Skip to content

fix(ship): looksComplete no longer flags wrapped list-item continuations as truncated - #46

Merged
teragrid merged 2 commits into
mainfrom
fix/looks-complete-wrapped-list-continuation
Sep 13, 2026
Merged

teragrid merged 2 commits into
mainfrom
fix/looks-complete-wrapped-list-continuation

Conversation

@teragrid

Copy link
Copy Markdown
Owner

Summary

  • Root cause (dogfooding on ai-marketing-platfrom, forge ship --agent-mode, 2026-09-13): a complete, well-formed spec.md answer was submitted via forge agent submit, but its last physical line was an indented continuation of a - [x] ... checklist item (the bullet's text wrapped onto a second, hanging-indented line). isListItem only recognizes a bullet's own first physical line, so looksComplete misclassified the continuation line as truncated, and the checkpoint silently discarded the real answer, re-serving a stub on every subsequent forge ship --agent-mode re-entry.
  • Fix: looksComplete now also recognizes an indented continuation of an earlier list item (isWrappedListContinuation), by walking backward over consecutively-indented lines to find the bullet's own first line — same "normal, intentional document ending" rationale the existing isListItem check already uses. Guarded in both directions: plain indented prose (not under a list item) is unaffected, and a continuation line cut off mid-word inside an unclosed inline code span is still flagged truncated (the existing unclosed-backtick check runs first, unconditionally).
  • Second, unrelated bug found while trying to push the fix above: the repo's .githooks/pre-push stage 1 (gofmt -s -l . / goimports -l .) chokes on tests/fixtures/hygiene-corpus's intentionally-invalid Go scratch-file fixtures (.forge/scratch/plan3.go, _scratch_idea.go) — unlike go build/go vet/go list ./..., which already skip dot/underscore-prefixed paths per Go's own package-discovery convention, gofmt/goimports have no such rule. This blocked every push in the repo through the real hook. Fixed by building the file list via git ls-files filtered through the same dot/underscore-prefix exclusion, so this stage checks exactly the same files the rest of the hook (./...-based stages) already does.

Test plan

  • New regression tests: TestLooksComplete_EndsOnWrappedListContinuation_NotTruncated (3 cases: checklist item, ordered list, unordered list), plus two false-positive guards (TestLooksComplete_IndentedProseNotUnderListItem_StillTruncated, TestLooksComplete_WrappedListContinuationCutMidWord_StillTruncated)
  • Reproduced the exact real-world incident content and confirmed it now passes looksComplete
  • go build ./..., go vet ./..., golangci-lint run ./... — clean
  • go test ./... — full repo suite green
  • Pushed through the real (fixed) .githooks/pre-push gate end-to-end — all 13 stages passed, including the QA real-command suite and ship dry-run scenarios

🤖 Generated with Claude Code

vietking and others added 2 commits September 13, 2026 10:51
…ons as truncated

Root cause (dogfooding on ai-marketing-platfrom, forge ship --agent-mode,
2026-09-13): a complete, well-formed spec.md answer was submitted via
`forge agent submit`, but its last physical line was an indented
continuation of a "- [x] ..." checklist item — the bullet's text wrapped
onto a second, hanging-indented line, e.g.:

    - [x] Migration applied and verified against local Postgres test DB (real
          RPC call: idempotency + P0002 unknown-subscription path confirmed)

isListItem only recognizes a bullet's own first physical line (the one
starting with "- "/"1. "/etc.), so the continuation line — ending in
ordinary prose with no terminal punctuation, heading, or list marker of its
own — was misclassified as truncated by looksComplete. The checkpoint then
silently discarded the answer and kept re-serving a stub on every
subsequent `forge ship --agent-mode` re-entry, with no visible error beyond
the "spec review truncated/incomplete after retry" digest line.

Fix: looksComplete now also checks whether the last line is an indented
continuation of an earlier list item (isWrappedListContinuation) by walking
backward over consecutively-indented lines to find the bullet's own first
line. Same rationale as the existing isListItem terminal-shape check — this
is a normal, intentional document ending, not a truncation signal.

Guarded against over-broadening in both directions:
- an indented continuation of plain prose (not under an actual list item)
  is still judged on its own terminal shape, unchanged from before
- a wrapped continuation line that is itself cut off mid-word inside an
  unclosed inline code span is still flagged truncated (the unclosed-
  backtick check runs unconditionally, earlier in the function)

Verified against the exact real-world content that triggered the incident.

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

Discovered while pushing the looksComplete fix in this same session: stage
1 (`gofmt -s -l .` / `goimports -l .`) walks every .go file under the repo
root, including tests/fixtures/hygiene-corpus/'s deliberately-invalid Go
scratch-file fixtures (DEV-M0-32) — e.g. .forge/scratch/plan3.go and
scratch-files/_scratch_idea.go, which are intentionally not valid Go source
since they exist only to test forge's own hygiene/scratch-file scanner
against realistic-looking junk.

Unlike gofmt/goimports, `go build`/`go vet`/`go list ./...` already skip
these paths, because Go's own package-discovery convention ignores any
directory or file whose name starts with "." or "_" (see `go help
packages`). gofmt/goimports have no equivalent rule and simply try to parse
every .go file they're given, so this stage failed unconditionally for
every contributor on every push — the exact case makes it hard to notice
locally if a previous formatting/import issue is masking it, or if
SKIP_PRE_PUSH is already habitual for other reasons.

Fix: build the file list via `git ls-files` filtered through the same
dot/underscore-prefix exclusion Go's own tools already apply, and pass that
explicit list to gofmt/goimports instead of a bare directory — matching
what every other stage in this hook (go vet/build/test, golangci-lint, all
of which use `./...`) already effectively checks.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@teragrid
teragrid merged commit fa4a170 into main Sep 13, 2026
26 checks passed
@teragrid
teragrid deleted the fix/looks-complete-wrapped-list-continuation branch September 13, 2026 04:15
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