Skip to content

artifact_exists can never pass for a dot-directory path: the worker's journaled artifacts list omits them #513

Description

@khaliqgant

Summary

An artifact_exists gate can never pass for a file under a dot-directory, because the worker's journaled artifacts list omits those paths entirely. The gate is correct by its own rules — it reads the journal — but the journal does not describe what the agent actually wrote.

.workflow-artifacts/ is the conventional artifact directory in AgentWorkforce/relay (every flow spec in that repo writes there), so in practice artifact_exists is unusable for the thing it exists to check.

Evidence

Run 01M2ZQP6P9ME3PRBWDXQA32MT3, CLI 2.0.22, macOS arm64, flows run --local-agent.

The run died at shadow-rust.gate with the file it was gating sitting on disk:

FAILED [step_failed] Step "shadow-rust.gate" (deterministic) completionReason: retries_exhausted exit=1.

$ ls -la .workflow-artifacts/migrate-native-delivery/phase-0-seam-20260920c/reviews/shadow-rust.md
-rw-r--r--  1 khaliqgant  staff  25257 Sep 20 08:57 ...

The gate was { type: 'artifact_exists', path: '.workflow-artifacts/migrate-native-delivery/phase-0-seam-20260920c/reviews/shadow-rust.md' }. shadow-rust journaled zero artifacts.

The preceding step makes the pattern unambiguous. implement-rust journaled 6,837 artifacts:

top-level prefixes: {'target': 6832, 'crates': 5}

target/ and crates/ only — and nothing under .workflow-artifacts/, despite that step provably having written evidence/mutation-proof.md there:

$ stat -f "%Sm %N" -t "%H:%M" .workflow-artifacts/.../evidence/mutation-proof.md
08:48 .workflow-artifacts/.../evidence/mutation-proof.md

So the exclusion is not .gitignore-driven: target/ is gitignored too and is included in full. The distinguishing property of the missing path is the leading dot.

Why it matters

artifact_exists is documented as the journal-honest way to check "the agent wrote X", and it is the gate an author naturally reaches for on a review or report step. Silently excluding a whole class of paths means:

  • the gate fails on a file that exists, with no indication why;
  • the failure is a bare retries_exhausted exit=1 (the lowered gate decides in-process, so there is no command output to inspect either);
  • agent-written evidence is invisible in the journal generally, not just to this gate — any consumer reading output.artifacts to find what a step produced will miss it.

What to change

Either include dot-directories in the worker's artifact scan, or — if they are excluded deliberately, which is defensible for .git/, .relayflowd/ and friends — make the exclusion explicit and inspectable:

  • document which prefixes are excluded;
  • have flows check refuse an artifact_exists gate whose path falls inside an excluded prefix, with a message naming the exclusion, rather than compiling a gate that cannot pass;
  • consider an opt-in (artifacts.include) so a flow can declare its own artifact directory.

A deny-list of exactly .git/ and the runtime's own state directories would cover the real hazard without swallowing every author-chosen artifact path.

Acceptance

  • Either an agent writing .workflow-artifacts/x/y.md has that path in its journaled artifacts, or flows check refuses the artifact_exists gate naming it, before the run starts.
  • A test pins a dot-directory artifact path either way.

Out of scope

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinggarden-readyScoped and ready for an agent to pick up

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions