Repository navigation
Pass Claude's structured answer to the plan parser unchanged (#166) - #169
Merged
Merged
Conversation
Every version in schema/versions.json is now compiled from its retained snapshots, and plans and edit replies are checked by the version they declare. The loader refuses a registry that disagrees with the snapshots or validators, and treats a version with no validator as unsupported. Pin the released v1 files by SHA-256, keep them LF on checkout, and add the remaining #6 tests: path identity and Git mode mapping, hostile text in every authoring prompt, and output limits at the exact byte. Runtime gaps move to #162-#166. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
parseClaudeOutput re-encoded structured_output with JSON.parse and JSON.stringify, so a duplicate key or an inexact integer reached parseV1 already resolved. Cut the exact text of structured_output from the envelope with a length-bounded scanner instead, and refuse a planning envelope that repeats a top-level key before classifying it. Whether the Claude API or CLI resolves duplicates before writing the envelope is not verified; the docs say so. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Resolves the test/review.test.ts import conflict by keeping both imports. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nto feat/166-claude-structured-parse
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ctured-parse Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s at once Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
🟢 Approval recommended
The bounded extraction and targeted regressions support the parsing contract, with no unresolved findings.
No open issues 🎉
What changed in this PR
Fixes #166 by preserving Claude’s structured answer unchanged so the existing plan parser can reject duplicate keys and inexact integers.
Changes:
- Extracts exact
structured_outputtext and rejects repeated envelope keys. - Adds parsing and raw-byte limit regressions.
- Documents preservation guarantees and unverified upstream behavior.
| File | Description |
|---|---|
| test/planning-extraction.test.ts | Avoids expensive diffs for megabyte assertions. |
| test/agent-adapter.test.ts | Covers exact extraction, malformed envelopes, and parser limits. |
| docs/implementation/plan-library-alignment.md | Records the #166 fix and updated limit behavior. |
| docs/implementation/agent-isolation.md | Clarifies extraction guarantees and upstream limitations. |
| agents/adapters/claude.ts | Preserves structured answer text without re-encoding. |
Review effort: Balanced
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #166.
Built on #168 (merged as
dd35566), which added the agent-adapter test that described the old re-encoding; this PR replaces it.Summary
parseClaudeOutputread Claude's envelope withJSON.parseand returnedJSON.stringify(structured_output). That round trip resolved duplicate keys (last wins) and rounded inexact integers beforeparseV1saw the text, which bypassed the v1 parsing contract (schema/versions/1/semantics.md, "Deterministic input parsing").agents/adapters/claude.ts: afterJSON.parsevalidates the envelope,topLevelMemberscuts the exact source text of each top-level member. Planning answers return the exact text ofstructured_output, soparseV1refuses a duplicate key or an inexact integer the envelope holds.is_errorcannot turn a refusal into a provider failure.structured_outputin the envelope, not to a re-encoding.Limit
The Claude API and CLI may resolve duplicates or number spellings before writing the envelope. That is not verified: the real-CLI probes need credentials and do not run in CI. The docs (
docs/implementation/agent-isolation.md) and the code comment say so. This PR guarantees that codeboost itself no longer normalizes the answer.The recorded planning fixtures need no re-recording: their staleness hash covers the recorded repository files and argv only, and their text remains valid validator input.
Validation
Base
maindd3556640b005bac0d47fa94f4ab55bb1bc4fdb9(#168's squash; its tree equals #168's final head6b42931, soe9ba497merged it with-s oursafter checking), heade9ba497bcafd6b14491974467808d141c04296e1(current head). The tree ofe9ba497is identical to952a200's, where the full suite ran.vitest --project parallel)952a200, the same tree ase9ba497real-dockeris the gatetest,real-docker(required onmain)e9ba497Five tests fail against the base decoder: exact text, duplicate key, inexact integer, repeated top-level key, and the 1 MiB limit on the raw bytes of
structured_output. Deliberate breaks of escape skipping, string skipping in nested values, the repeat refusal, its ordering before classification, key decoding, whitespace handling and the non-object guard each fail a test, within seconds: comparisons of megabyte answers check the length and then use===, so a broken decoder never stalls in a long vitest diff.Earlier validated head
083d916on basef9c2e6b: typecheck pass; 2034/2034 without Docker.Load-related failure, separate from product results: one full run at load average ~150 had a timing failure in
pre-merge.test.ts("stops an active command check when the operation-wide deadline expires"), a file this PR does not touch. It passed 3/3 alone and in the full rerun.Review record
is_errorclassified before the repeat check; untested spacing, key spellings and raw-byte limit; assertion wording; doc precision; long linesTypeErroron anullenvelope (unchanged from the base); question answers keeping last-wins (plain text, never parsed byparseV1)main7fd4dfe) with no conflictsb3b028b(diff-free comparison)952a200mainmain's tree equals6b42931, so merged with-s ours; PR diff unchangedReview-lesson audit
No new AGENTS.md rule is needed.
🤖 Generated with Claude Code