Skip to content

fix(ship): agent-mode pipeline blockers found dogfooding on a real repo - #45

Merged
teragrid merged 4 commits into
mainfrom
fix/ship-agent-mode-issues-2026-09-07
Sep 7, 2026
Merged

teragrid merged 4 commits into
mainfrom
fix/ship-agent-mode-issues-2026-09-07

Conversation

@teragrid

@teragrid teragrid commented Sep 7, 2026

Copy link
Copy Markdown
Owner

Nine issues that stopped forge ship --agent-mode from certifying a feature end-to-end on a large Next.js/Supabase repo (found 2026-09-07 driving the pipeline by hand). After these fixes the same feature's pipeline reports ship pipeline ready (all checkpoints validated) — spec/arch/test/breakdown/ship all ✓.

# Problem Fix
7 forge clean flagged ~465 git-ignored files (.playwright-mcp/*.log, sibling .claude/worktrees/*) as "unmanaged scratch"; the ship hygiene gate hard-failed and told the user to forge clean --apply, which would delete other tools'/sessions' ignored files. clean now skips git-ignored paths outside .forge/ by default (still tidies forge's own ignored scratch). --include-ignored restores the old behaviour.
8 self-review-gate / spec-completeness / adr-quality / tdd-gate / security-hygiene / qa-coverage / manual-test-plan / four-stage-testing resolved the spec dir with slugify(description), ignoring the --name/-n override agent-mode always sets → every gate reported "artefact not found / UNVERIFIED" while the files sat under .forge/specs/<name>/. All use HookContext.SpecName via new ctxSpecSlug(ctx); testingPipelineEvidencePath accepts a resolved slug.
8 Same gates only looked for the canonical filename; agent-mode writes test.md / code-plan.md / etc. readSpecArtefact() aliases: arch.md↔adr.md, test.md↔tests.md↔test-stubs.md, code-plan.md↔impl-notes.md.
8b Once gate 8 made the scan actually run, a bare strings.Contains(content,"...") in self-review-gate flagged prose elisions, P1-01 … P1-09 ranges and { ... } code as "hedging". Removed bare "..."; a per-line check still catches a line that is only dots or a key: ... / = ... stub, skipping fenced code.
8c tdd-gate only accepted Gherkin or func Test* as a "test scenario". Also accepts it() / test() / describe() (Jest/Vitest/Jasmine/Mocha); reads test-stubs.md before forge's thin test.md.
6 checkCode reported "N modified file(s)" + status ok by counting every dirty git status line (docs, .forge ledgers, another session's screenshots) — the known "✓ Code with zero code" gap. countChangedSourceFiles() counts only source extensions, excluding .forge/ docs/ growth/. A plan with no source change now reports warning — implement then rerun + "(N other working-tree change(s) not attributed to this checkpoint)".
5 Test artefacts always written to <root>/tests, invisible to a runner whose roots are src; the reachability check then swept the whole repo and flagged the project's pre-existing tests/e2e/* / tests/staging/* suites as "unreachable". pickTestsDir() prefers an existing collected dir (src/test, …); allTestArtifactsExist / missingTestArtifacts check both; reachability now runs only against the artefacts forge wrote for this slug.
4 ship:test:integration prompt (and the ship-test template) hard-coded "Jest + supertest"; on a repo without supertest / a single HTTP entrypoint the stub couldn't compile. Prompts now tell the model to follow the project's own integration-test convention and not import a package the project lacks.
2 forge agent submit --file failed on a path with .. or mixed separators (FORGE-6900 … cannot find the path specified) even when the file existed. readAnswer filepath.FromSlash + Cleans the path and resolves a relative one against cwd.

Not fixed (noted for follow-up): npm shim resolving a nested forge.exe copy (#1), pending.json needing an explicit UTF-8 read on Windows (#3), -n vs --session desync footgun (#9).

Tests: go test ./internal/... green (76 packages); two TestCheckCode assertions updated to the corrected "a plan is not an implementation" contract.

🤖 Generated with Claude Code

vietking and others added 4 commits September 7, 2026 20:49
Seven issues that stopped `forge ship --agent-mode` from certifying a feature
end-to-end on a large Next.js/Supabase repo (2026-09-07):

1. forge clean flagged git-ignored files (~450 .playwright-mcp/*.log, sibling
   .claude/worktrees) as "unmanaged scratch" and the ship hygiene gate
   hard-failed on them, telling the user to run `forge clean --apply` which
   would delete other tools'/sessions' ignored working files. clean now skips
   git-ignored paths *outside* .forge/ by default (forge still tidies its own
   ignored scratch); `--include-ignored` restores the old behaviour.

2. self-review-gate / spec-completeness / adr-quality / tdd-gate /
   security-hygiene resolved the spec dir with slugify(description), ignoring
   the --name/-n override that agent-mode always uses — so every gate reported
   "spec.md not found / UNVERIFIED" while the artefacts sat in
   .forge/specs/<name>/. They now use HookContext.SpecName via ctxSpecSlug().

3. Same gates only looked for the canonical filename; agent-mode writes
   test.md / code-plan.md / etc. Added readSpecArtefact() aliases
   (arch.md↔adr.md, test.md↔tests.md, code-plan.md↔impl-notes.md).

4. The Code checkpoint reported "N modified file(s)" + status ok by counting
   every dirty line in `git status` — unrelated docs, .forge ledgers, another
   session's screenshots. Added countChangedSourceFiles() (source extensions,
   excludes .forge/ docs/ growth/); a plan with no source change now reports
   "warning — implement then rerun", not a green "code written".

5. Test artefacts were always written to <root>/tests, invisible to a runner
   whose roots are "src"; the reachability check then swept the whole repo and
   flagged the project's pre-existing e2e/staging suites as "unreachable".
   pickTestsDir() prefers an existing collected dir (src/test, …);
   reachability now checks only the artefacts forge wrote for this slug.

6. ship:test:integration hard-coded "Jest + supertest"; on a repo without
   supertest or an HTTP entrypoint the stub could not compile. Prompt now
   tells the model to follow the project's own integration-test convention.

7. `forge agent submit --file` failed on a path containing ".." or mixed
   separators ("cannot find the path specified") even when the file existed;
   the path is now cleaned and resolved against cwd.

Tests: cmdship/cmdclean/cmdagent suites green; two TestCheckCode assertions
updated to the corrected (plan != implementation) contract.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…acts

Removing bare "..." from the contains-scan (it hit prose elisions, "P1-01 …
P1-09" ranges and code snippets). Unfilled ellipsis placeholders are still
caught by a per-line check — a line that is only dots, or a "key: ..." / "= ..."
stub — which skips fenced code blocks and does not fire on real content.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
testingPipelineEvidencePath slugified ctx.Description, so on an agent-mode run
(which always sets --name/-n) the gate looked for testing-pipeline.md under a
truncated description slug and reported it missing even when it existed under
.forge/specs/<name>/. Now resolves via ctxSpecSlug(ctx); the path helper also
accepts an already-resolved slug.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- tdd-gate now accepts it()/test()/describe() (Jest/Vitest/Jasmine/Mocha) as a
  test scenario, not only Gherkin or `func Test*`, and reads test-stubs.md in
  preference to forge's thin test.md summary for the quality check.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@teragrid
teragrid merged commit feff0ee into main Sep 7, 2026
26 checks passed
@teragrid
teragrid deleted the fix/ship-agent-mode-issues-2026-09-07 branch September 7, 2026 15:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants