diff --git a/.agents/pm/features/pm-nilh.toon b/.agents/pm/features/pm-nilh.toon index 56c777f71..2e59a42f6 100644 --- a/.agents/pm/features/pm-nilh.toon +++ b/.agents/pm/features/pm-nilh.toon @@ -6,7 +6,7 @@ status: closed priority: 2 tags[4]: agent-ux,"area:cli",gh-issue,token-efficiency created_at: "2026-07-06T08:03:03.701Z" -updated_at: "2026-07-31T14:16:08.723Z" +updated_at: "2026-08-01T00:35:36.460Z" closed_at: "2026-07-20T10:01:06.896Z" author: maintainer-agent estimated_minutes: 120 @@ -23,9 +23,10 @@ dependencies[4]{id,kind,created_at}: pm-g9xk,related,"2026-07-20T08:49:49.562Z" pm-xm7c,related,"2026-07-20T08:49:49.562Z" pm-mpbb,implements,"2026-07-26T17:21:13.002Z" -comments[2]{created_at,author,text}: +comments[3]{created_at,author,text}: "2026-07-20T09:59:55.002Z",codex-20260720,"Evidence: mutation commands now default to id/status/changed_field_count, --no-changed-fields preserves the compact legacy item envelope, --full-changed-fields restores the full delta, and --id-only retains precedence. Isolated packed creates measured 71-byte compact vs 583-byte full output (87.82% reduction). Token-budget consumer and manifest were updated intentionally." "2026-07-31T14:16:08.723Z","harness:claude-code","Closed-item conformance check 2026-07-31, filed as pm-awe3t6. No reopen proposed - the CLI half of this item shipped and holds - but the parity claim in the title is inverted at HEAD.\n\nMeasured in one sandbox tracker, same type, same fields, same second. CLI pm create --json returns 72 bytes: {id, status, changed_field_count}. MCP pm_create with identical arguments returns 373 bytes: a result wrapper containing the full ten-field item echo, an empty warnings array, a next_transition object, and changed_field_count. That is 5.2x, and it is the MCP default; the lean form on MCP requires idOnly:true, which returns 45 bytes, while the CLI needs no flag.\n\nSo this item made the CLI lean and the direction of parity reversed rather than converged: the surface that is now verbose is the one where tokens are unavoidable, because every MCP tool result enters the model context whether the agent needed it or not, whereas a CLI caller can pipe through jq and discard. The result wrapper is a second divergence - the CLI emits no such key - which is the shape difference the agent guidance warns about." + "2026-08-01T00:35:36.460Z","harness:codex","Conformance correction 2026-08-01: pm-awe3t6 restores the parity this closed item intended. An isolated identical create now serializes to 57 bytes on both the CLI default and the MCP structured result, with the same id/status/changed_field_count keys. MCP protocol framing still wraps structuredContent.result as documented, while the mutation result itself has one cross-surface accessor shape; fullChangedFields:true remains the explicit full-envelope opt-in." files[6]{path,scope,note}: scripts/release/token-budget-gate.mjs,project,Compact mutation consumer compatibility scripts/release/token-budgets.json,project,Intentional agent output budget update diff --git a/.agents/pm/history/pm-7hbfch.jsonl b/.agents/pm/history/pm-7hbfch.jsonl index 28173a6f4..ff4556922 100644 --- a/.agents/pm/history/pm-7hbfch.jsonl +++ b/.agents/pm/history/pm-7hbfch.jsonl @@ -17,3 +17,22 @@ {"ts":"2026-07-30T11:54:22.385Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"af9867eb30d01f2e6d661d1b","agent_provenance":{"model":null},"op":"comment_add","patch":[{"op":"add","path":"/metadata/comments/3","value":{"created_at":"2026-07-30T11:54:22.385Z","author":"harness:codex","text":"Review correction: intent receipts now honor the effective explicit tokenBudget override, and over-budget row sets fall back to a receipt-only envelope instead of dropping rows while retaining stale counts or cursors."}},{"op":"replace","path":"/metadata/updated_at","value":"2026-07-30T11:54:22.385Z"}],"before_hash":"ea04a9d349c4655ffe668a163c0483f805fecfd401ee8d434bd0f9ed30a5aa28","after_hash":"86d488ead2fc1e4b2957f89c0691232c805c37d9287333329354ec3c89cadb77"} {"ts":"2026-07-30T17:03:17.214Z","author":"harness:claude-code","author_source":"detected","agent_harness":"claude-code","agent_instance":"6682b76673432e27b62e2ad8","agent_provenance":{"model":null,"effort":{"value":"xhigh","source":"environment"}},"op":"update","patch":[{"op":"add","path":"/metadata/dependencies/6","value":{"id":"pm-yekkvt","kind":"blocked_by","created_at":"2026-07-30T17:03:17.017Z","author":"harness:claude-code","source_kind":"cli:update:dep","author_source":"detected"}},{"op":"replace","path":"/metadata/updated_at","value":"2026-07-30T17:03:17.214Z"}],"before_hash":"86d488ead2fc1e4b2957f89c0691232c805c37d9287333329354ec3c89cadb77","after_hash":"badbcdf3b2283d1ddc60e835f2c9401e6f9749fb4531b62cb3c06aab867d49b6","message":"Budget enforcement cannot honestly close while three of five declared budgets are below the smallest projection their command can emit"} {"ts":"2026-07-30T17:13:52.692Z","author":"harness:claude-code","author_source":"detected","agent_harness":"claude-code","agent_instance":"6682b76673432e27b62e2ad8","agent_provenance":{"model":null,"effort":{"value":"xhigh","source":"environment"}},"op":"comment_add","patch":[{"op":"add","path":"/metadata/comments/4","value":{"created_at":"2026-07-30T17:13:52.692Z","author":"harness:claude-code","text":"Conformance re-measure 2026-07-30 (evening), at HEAD after the context-budget bundle merged at 14:33Z. Enforcement shipped and works. The three intents this item measured as 43.8x, 19.7x and 2.45x over their declared budgets are now inside them: list triage 1,045 of 1,800 tokens in 6,250 bytes, get inspect 1,208 of 3,200 in 6,565 bytes, search discover 1,300 of 1,800 in 7,219 bytes. The receipt now carries the resolved budget, the measured estimate and the applied degradation, which closes the envelope half of the acceptance criteria.\n\nTwo of this item's own criteria are still open, and one of them is now falsified rather than merely unmet.\n\nThe criterion that list, get and search either declare the budget flag or the intent layer refuses to claim a budget it cannot apply, with no silent third option, is falsified. All three still exit 2 with unknown_option on --token-budget. All three nevertheless claim a budget in the receipt and enforce it at egress. That is precisely the silent third option the criterion forbids: the budget is claimed and applied on a command that offers no way to adjust it. It is reachable today, not latent. pm list --limit 200 --for triage returns budget_receipt_only with zero rows, and pm get --depth deep --for inspect does the same, and neither has any override.\n\nThe criterion that a negative control asserts an intent whose command lacks budget enforcement fails the build is still unmet, and the day showed the control was pointed at the wrong invariant. Enforcement presence was never the fragile part. Reachability of the declared number is, and that is now tracked separately as a blocking dependency on this item, since enforcement cannot honestly be called complete while three of five declared ceilings cannot be met by the commands that declare them.\n\nMethod note for whoever picks this up: measure with the flag on the two commands that accept it. The floor is only visible by raising the ceiling until rows appear. next execute yields nothing at 1200, nothing at 2000, and 1,438 tokens of content at 4000. context orient yields nothing at 2400, nothing at 8000, and 8,417 tokens at 40000."}},{"op":"replace","path":"/metadata/updated_at","value":"2026-07-30T17:13:52.692Z"}],"before_hash":"badbcdf3b2283d1ddc60e835f2c9401e6f9749fb4531b62cb3c06aab867d49b6","after_hash":"daf341e3be78d9bb37195a07d98931267edce7663a3184e91911fc2f17e9c98a"} +{"ts":"2026-07-31T23:03:51.614Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"claim","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:03:51.614Z"},{"op":"add","path":"/metadata/assignee","value":"harness:codex"},{"op":"add","path":"/metadata/claim_principal","value":"harness:codex#264406b88560fcdcbb17052e"}],"before_hash":"daf341e3be78d9bb37195a07d98931267edce7663a3184e91911fc2f17e9c98a","after_hash":"8226573ff21b3572449317d8f3d4e5dad63c138e5e1b443d618e90d6fa5ee535"} +{"ts":"2026-07-31T23:03:52.461Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"update","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:03:52.461Z"},{"op":"replace","path":"/metadata/status","value":"in_progress"}],"before_hash":"8226573ff21b3572449317d8f3d4e5dad63c138e5e1b443d618e90d6fa5ee535","after_hash":"ae9f7fe5a01cb7c902ab215de5aafad322ee0095f3298240cc04ee2313eee15c","message":"Start cohesive SDK/CLI context-output tranche: bounded cursor-chain metadata, reachable intent budgets, truthful delivery ledger, and lean MCP mutation parity."} +{"ts":"2026-07-31T23:32:33.463Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"files_add","patch":[{"op":"replace","path":"/metadata/files/1/note","value":"only next and context declare a --token-budget flag; list,get and search reject it as unknown"},{"op":"replace","path":"/metadata/files/1/path","value":"src/sdk/cli-contracts.ts"},{"op":"replace","path":"/metadata/files/0/note","value":"Cross-surface token-budget flag and schema parity"},{"op":"replace","path":"/metadata/files/0/path","value":"src/cli/register-list-query.ts"},{"op":"add","path":"/metadata/files/2","value":{"path":"src/sdk/context-intent-contracts.ts","scope":"project","note":"applyContextIntentProjection writes the declared token_budget into projected.tokenBudget at line 323 for all five intent commands"}},{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:32:33.463Z"}],"before_hash":"ae9f7fe5a01cb7c902ab215de5aafad322ee0095f3298240cc04ee2313eee15c","after_hash":"210ed5bf9cbfd9f0009de20b5a5fb980dfe076b943f56f6089f05cc9e55cf6bd","message":"Link implementation evidence for broad context-contract delivery"} +{"ts":"2026-07-31T23:32:34.318Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"files_add","patch":[{"op":"replace","path":"/metadata/files/2/note","value":"Cross-surface token-budget flag and schema parity"},{"op":"replace","path":"/metadata/files/2/path","value":"src/sdk/cli-contracts/flag-contracts.ts"},{"op":"add","path":"/metadata/files/3","value":{"path":"src/sdk/context-intent-contracts.ts","scope":"project","note":"applyContextIntentProjection writes the declared token_budget into projected.tokenBudget at line 323 for all five intent commands"}},{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:32:34.318Z"}],"before_hash":"210ed5bf9cbfd9f0009de20b5a5fb980dfe076b943f56f6089f05cc9e55cf6bd","after_hash":"b17ad8ad60c496ad8228589b8501d277b659c5e9982d379f91c4d071c2574eb3","message":"Link implementation evidence for broad context-contract delivery"} +{"ts":"2026-07-31T23:32:35.102Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"files_add","patch":[{"op":"replace","path":"/metadata/files/3/note","value":"Cross-surface token-budget flag and schema parity"},{"op":"replace","path":"/metadata/files/3/path","value":"src/sdk/cli-contracts/tool-option-contracts.ts"},{"op":"add","path":"/metadata/files/4","value":{"path":"src/sdk/context-intent-contracts.ts","scope":"project","note":"applyContextIntentProjection writes the declared token_budget into projected.tokenBudget at line 323 for all five intent commands"}},{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:32:35.102Z"}],"before_hash":"b17ad8ad60c496ad8228589b8501d277b659c5e9982d379f91c4d071c2574eb3","after_hash":"327977ff6aac532abb9f6cbcd564ff433816d114a17bd4af9b8453cffd9bd283","message":"Link implementation evidence for broad context-contract delivery"} +{"ts":"2026-07-31T23:32:35.906Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"files_add","patch":[{"op":"replace","path":"/metadata/files/4/note","value":"Cross-surface token-budget flag and schema parity"},{"op":"replace","path":"/metadata/files/4/path","value":"src/sdk/cli-contracts/tool-schema.ts"},{"op":"add","path":"/metadata/files/5","value":{"path":"src/sdk/context-intent-contracts.ts","scope":"project","note":"applyContextIntentProjection writes the declared token_budget into projected.tokenBudget at line 323 for all five intent commands"}},{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:32:35.906Z"}],"before_hash":"327977ff6aac532abb9f6cbcd564ff433816d114a17bd4af9b8453cffd9bd283","after_hash":"f20fe34d1ae5a22195e356427c6fdbbfe99c2284da97c81b4351c0905e6bd322","message":"Link implementation evidence for broad context-contract delivery"} +{"ts":"2026-07-31T23:32:36.682Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"files_add","patch":[{"op":"add","path":"/metadata/files/6","value":{"path":"tests/fixtures/contracts/full.json","scope":"project","note":"Cross-surface token-budget flag and schema parity"}},{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:32:36.682Z"}],"before_hash":"f20fe34d1ae5a22195e356427c6fdbbfe99c2284da97c81b4351c0905e6bd322","after_hash":"b4bd1ff1d06bfcb5be77dfb2268b8c1e19f6b0371479c15134edd91d4a176930","message":"Link implementation evidence for broad context-contract delivery"} +{"ts":"2026-07-31T23:32:37.434Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"files_add","patch":[{"op":"add","path":"/metadata/files/7","value":{"path":"tests/unit/cli/context-intent-registration.spec.ts","scope":"project","note":"Cross-surface token-budget flag and schema parity"}},{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:32:37.434Z"}],"before_hash":"b4bd1ff1d06bfcb5be77dfb2268b8c1e19f6b0371479c15134edd91d4a176930","after_hash":"1bd699ddb5c751c476f567c0990d0e37c10d82a1ca4313170eb818589f1fe877","message":"Link implementation evidence for broad context-contract delivery"} +{"ts":"2026-07-31T23:32:38.628Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"files_add","patch":[{"op":"replace","path":"/metadata/files/7/path","value":"tests/fixtures/contracts/full.json"},{"op":"replace","path":"/metadata/files/6/note","value":"applyContextIntentProjection writes the declared token_budget into projected.tokenBudget at line 323 for all five intent commands"},{"op":"replace","path":"/metadata/files/6/path","value":"src/sdk/context-intent-contracts.ts"},{"op":"replace","path":"/metadata/files/5/note","value":"Cross-surface token-budget flag and schema parity"},{"op":"replace","path":"/metadata/files/5/path","value":"src/sdk/cli-contracts/tool-schema.ts"},{"op":"replace","path":"/metadata/files/4/path","value":"src/sdk/cli-contracts/tool-option-contracts.ts"},{"op":"replace","path":"/metadata/files/3/path","value":"src/sdk/cli-contracts/flag-contracts.ts"},{"op":"replace","path":"/metadata/files/2/note","value":"only next and context declare a --token-budget flag; list,get and search reject it as unknown"},{"op":"replace","path":"/metadata/files/2/path","value":"src/sdk/cli-contracts.ts"},{"op":"replace","path":"/metadata/files/1/note","value":"Cross-surface token-budget flag and schema parity"},{"op":"replace","path":"/metadata/files/1/path","value":"src/cli/register-list-query.ts"},{"op":"replace","path":"/metadata/files/0/note","value":"Intent reachability release gate"},{"op":"replace","path":"/metadata/files/0/path","value":"scripts/release/token-budget-gate.mjs"},{"op":"add","path":"/metadata/files/8","value":{"path":"tests/unit/cli/context-intent-registration.spec.ts","scope":"project","note":"Cross-surface token-budget flag and schema parity"}},{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:32:38.628Z"}],"before_hash":"1bd699ddb5c751c476f567c0990d0e37c10d82a1ca4313170eb818589f1fe877","after_hash":"21f7651dc58b63a9d896f017fd3d5703fe389466e5766efc3d521eab8af55391","message":"Link implementation evidence for broad context-contract delivery"} +{"ts":"2026-07-31T23:32:40.278Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"files_add","patch":[{"op":"replace","path":"/metadata/files/8/path","value":"tests/fixtures/contracts/full.json"},{"op":"replace","path":"/metadata/files/7/note","value":"applyContextIntentProjection writes the declared token_budget into projected.tokenBudget at line 323 for all five intent commands"},{"op":"replace","path":"/metadata/files/7/path","value":"src/sdk/context-intent-contracts.ts"},{"op":"replace","path":"/metadata/files/6/note","value":"Cross-surface token-budget flag and schema parity"},{"op":"replace","path":"/metadata/files/6/path","value":"src/sdk/cli-contracts/tool-schema.ts"},{"op":"replace","path":"/metadata/files/5/path","value":"src/sdk/cli-contracts/tool-option-contracts.ts"},{"op":"replace","path":"/metadata/files/4/path","value":"src/sdk/cli-contracts/flag-contracts.ts"},{"op":"replace","path":"/metadata/files/3/note","value":"only next and context declare a --token-budget flag; list,get and search reject it as unknown"},{"op":"replace","path":"/metadata/files/3/path","value":"src/sdk/cli-contracts.ts"},{"op":"replace","path":"/metadata/files/2/note","value":"Cross-surface token-budget flag and schema parity"},{"op":"replace","path":"/metadata/files/2/path","value":"src/cli/register-list-query.ts"},{"op":"replace","path":"/metadata/files/1/note","value":"Measured intent corpus baseline"},{"op":"replace","path":"/metadata/files/1/path","value":"scripts/release/token-budgets.json"},{"op":"add","path":"/metadata/files/9","value":{"path":"tests/unit/cli/context-intent-registration.spec.ts","scope":"project","note":"Cross-surface token-budget flag and schema parity"}},{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:32:40.278Z"}],"before_hash":"21f7651dc58b63a9d896f017fd3d5703fe389466e5766efc3d521eab8af55391","after_hash":"aea6480bd9cd96e457886e80684754cd541aac9e51433e0dc2b0b7c203ed3d81","message":"Link implementation evidence for broad context-contract delivery"} +{"ts":"2026-07-31T23:32:41.540Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"docs_add","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:32:41.540Z"}],"before_hash":"aea6480bd9cd96e457886e80684754cd541aac9e51433e0dc2b0b7c203ed3d81","after_hash":"443c19e5266203e869091c55736a8e96e4bea122cdd009a28a85311285e96ac8","message":"Link documentation evidence for broad context-contract delivery"} +{"ts":"2026-07-31T23:32:42.479Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"tests_add","patch":[{"op":"replace","path":"/metadata/tests/1/timeout_seconds","value":300},{"op":"replace","path":"/metadata/tests/1/command","value":"node scripts/run-tests.mjs test -- tests/unit/cli/context-intent-registration.spec.ts tests/unit/sdk/tool-option-contracts.spec.ts"},{"op":"add","path":"/metadata/tests/2","value":{"command":"node scripts/run-tests.mjs test -- tests/unit/sdk/context-intent-contracts.spec.ts","scope":"project","timeout_seconds":240}},{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:32:42.479Z"}],"before_hash":"443c19e5266203e869091c55736a8e96e4bea122cdd009a28a85311285e96ac8","after_hash":"e7301c6bd582eca1526afdb4062750ffc1ee481199797387097a15e3807b8a9c","message":"Link sandbox-safe verification for broad context-contract delivery"} +{"ts":"2026-07-31T23:32:44.056Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"tests_add","patch":[{"op":"replace","path":"/metadata/tests/2/timeout_seconds","value":300},{"op":"replace","path":"/metadata/tests/2/command","value":"node scripts/run-tests.mjs test -- tests/unit/cli/context-intent-registration.spec.ts tests/unit/sdk/tool-option-contracts.spec.ts"},{"op":"replace","path":"/metadata/tests/1/timeout_seconds","value":240},{"op":"replace","path":"/metadata/tests/1/command","value":"node scripts/run-tests.mjs test -- tests/unit/cli/context-intent-registration.spec.ts tests/unit/sdk/context-packing-usage.spec.ts"},{"op":"replace","path":"/metadata/tests/0/timeout_seconds","value":300},{"op":"replace","path":"/metadata/tests/0/command","value":"node scripts/release/token-budget-gate.mjs"},{"op":"add","path":"/metadata/tests/3","value":{"command":"node scripts/run-tests.mjs test -- tests/unit/sdk/context-intent-contracts.spec.ts","scope":"project","timeout_seconds":240}},{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:32:44.056Z"}],"before_hash":"e7301c6bd582eca1526afdb4062750ffc1ee481199797387097a15e3807b8a9c","after_hash":"216586dcdf3e8573709cf40c83c854b716fbe7d51dc7820cce191ec3a2b9814a","message":"Link sandbox-safe verification for broad context-contract delivery"} +{"ts":"2026-07-31T23:36:22.702Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"files_add","patch":[{"op":"replace","path":"/metadata/files/9/path","value":"tests/fixtures/contracts/full.json"},{"op":"replace","path":"/metadata/files/8/note","value":"applyContextIntentProjection writes the declared token_budget into projected.tokenBudget at line 323 for all five intent commands"},{"op":"replace","path":"/metadata/files/8/path","value":"src/sdk/context-intent-contracts.ts"},{"op":"replace","path":"/metadata/files/7/note","value":"Cross-surface token-budget flag and schema parity"},{"op":"replace","path":"/metadata/files/7/path","value":"src/sdk/cli-contracts/tool-schema.ts"},{"op":"replace","path":"/metadata/files/6/path","value":"src/sdk/cli-contracts/tool-option-contracts.ts"},{"op":"replace","path":"/metadata/files/5/path","value":"src/sdk/cli-contracts/flag-contracts.ts"},{"op":"replace","path":"/metadata/files/4/note","value":"only next and context declare a --token-budget flag; list,get and search reject it as unknown"},{"op":"replace","path":"/metadata/files/4/path","value":"src/sdk/cli-contracts.ts"},{"op":"replace","path":"/metadata/files/3/note","value":"Cross-surface token-budget flag and schema parity"},{"op":"replace","path":"/metadata/files/3/path","value":"src/cli/register-list-query.ts"},{"op":"replace","path":"/metadata/files/2/note","value":"Tool schema 4.3.0 public surface snapshot"},{"op":"replace","path":"/metadata/files/2/path","value":"sdk/public-surface.json"},{"op":"add","path":"/metadata/files/10","value":{"path":"tests/unit/cli/context-intent-registration.spec.ts","scope":"project","note":"Cross-surface token-budget flag and schema parity"}},{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:36:22.702Z"}],"before_hash":"216586dcdf3e8573709cf40c83c854b716fbe7d51dc7820cce191ec3a2b9814a","after_hash":"13c9e609ccf433b928891d9f67bc4608fc067429446fee348a905cb590fc2d58","message":"Link SDK surface contract evidence"} +{"ts":"2026-08-01T00:02:05.895Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"files_add","patch":[{"op":"replace","path":"/metadata/files/10/path","value":"tests/fixtures/contracts/full.json"},{"op":"replace","path":"/metadata/files/9/note","value":"applyContextIntentProjection writes the declared token_budget into projected.tokenBudget at line 323 for all five intent commands"},{"op":"replace","path":"/metadata/files/9/path","value":"src/sdk/context-intent-contracts.ts"},{"op":"replace","path":"/metadata/files/8/note","value":"Cross-surface token-budget flag and schema parity"},{"op":"replace","path":"/metadata/files/8/path","value":"src/sdk/cli-contracts/tool-schema.ts"},{"op":"replace","path":"/metadata/files/7/path","value":"src/sdk/cli-contracts/tool-option-contracts.ts"},{"op":"replace","path":"/metadata/files/6/path","value":"src/sdk/cli-contracts/flag-contracts.ts"},{"op":"replace","path":"/metadata/files/5/note","value":"only next and context declare a --token-budget flag; list,get and search reject it as unknown"},{"op":"replace","path":"/metadata/files/5/path","value":"src/sdk/cli-contracts.ts"},{"op":"replace","path":"/metadata/files/4/note","value":"Cross-surface token-budget flag and schema parity"},{"op":"replace","path":"/metadata/files/4/path","value":"src/cli/register-list-query.ts"},{"op":"replace","path":"/metadata/files/3/note","value":"Tool schema 4.3.0 public surface snapshot"},{"op":"replace","path":"/metadata/files/3/path","value":"sdk/public-surface.json"},{"op":"replace","path":"/metadata/files/2/note","value":"Measured intent corpus baseline"},{"op":"replace","path":"/metadata/files/2/path","value":"scripts/release/token-budgets.json"},{"op":"replace","path":"/metadata/files/1/note","value":"Intent reachability release gate"},{"op":"replace","path":"/metadata/files/1/path","value":"scripts/release/token-budget-gate.mjs"},{"op":"replace","path":"/metadata/files/0/note","value":"Regenerated package-owned token surface baseline after the list/get/search budget option and current command surface additions"},{"op":"replace","path":"/metadata/files/0/path","value":"scripts/agent-token-surface-baseline.json"},{"op":"add","path":"/metadata/files/11","value":{"path":"tests/unit/cli/context-intent-registration.spec.ts","scope":"project","note":"Cross-surface token-budget flag and schema parity"}},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T00:02:05.895Z"}],"before_hash":"13c9e609ccf433b928891d9f67bc4608fc067429446fee348a905cb590fc2d58","after_hash":"93eec3049a4d04526e26744d1f75770e5e43e0eb2a36bd8e4e38a848bd47357b"} +{"ts":"2026-08-01T00:15:58.204Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"test_run_track","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T00:15:58.204Z"},{"op":"add","path":"/metadata/test_runs","value":[{"run_id":"test-local-ms9mewok-jsmdpi","kind":"test","status":"passed","started_at":"2026-08-01T00:15:13.819Z","finished_at":"2026-08-01T00:15:58.196Z","recorded_at":"2026-08-01T00:15:58.196Z","passed":4,"failed":0,"skipped":0}]}],"before_hash":"93eec3049a4d04526e26744d1f75770e5e43e0eb2a36bd8e4e38a848bd47357b","after_hash":"de5cd7441162460c53f8505a7f94818ef8ea81dbb5ea71d63d37e723e81cfcf4","message":"Track test run summary (test-local-ms9mewok-jsmdpi)"} +{"ts":"2026-08-01T00:37:51.707Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"comment_add","patch":[{"op":"add","path":"/metadata/comments/5","value":{"created_at":"2026-08-01T00:37:51.706Z","author":"harness:codex","text":"Delivery evidence 2026-08-01: list/get/search now expose --token-budget across CLI, SDK tool options, cursor semantics, contracts, and tool schema 4.3.0. The release gate checks 28 surfaces plus a 256-token infeasible declaration control. Live current-tracker receipts are delivered and within ceiling: context orient 1725/2400 with 11 useful rows; list triage 1703/3200 with 20 rows and a cursor; search discover 1562/1800 with 16 rows; next execute 1109/1200 with 3 ready rows; get inspect 2009/3200. Remaining acceptance before closure: add a generated corpus at least as large as the current tracker to the mandatory gate and a structural negative control that removes enforcement from one declared command."}},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T00:37:51.707Z"}],"before_hash":"de5cd7441162460c53f8505a7f94818ef8ea81dbb5ea71d63d37e723e81cfcf4","after_hash":"f4c2f7cb8b16e02fd73c668491edd0d7889a4e35558ba75d5d8beead7a2ee71f"} +{"ts":"2026-08-01T00:37:54.009Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"update","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T00:37:54.009Z"},{"op":"replace","path":"/metadata/status","value":"open"}],"before_hash":"f4c2f7cb8b16e02fd73c668491edd0d7889a4e35558ba75d5d8beead7a2ee71f","after_hash":"26826fafd06fd1fea26af5b6222c4d0d6f7bcd3a90b7162c7f0eae8e10f31330","message":"Pause after broad implementation; current-scale and structural-negative-control gate acceptance remains"} +{"ts":"2026-08-01T00:37:54.818Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"release","patch":[{"op":"remove","path":"/metadata/claim_principal"},{"op":"remove","path":"/metadata/assignee"},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T00:37:54.818Z"}],"before_hash":"26826fafd06fd1fea26af5b6222c4d0d6f7bcd3a90b7162c7f0eae8e10f31330","after_hash":"485261ebd05e312b9ff43eda36d3c390d70cbaa0a7b5720098dd0ba1ff21812d"} diff --git a/.agents/pm/history/pm-awe3t6.jsonl b/.agents/pm/history/pm-awe3t6.jsonl index eb1894e81..90ca32bda 100644 --- a/.agents/pm/history/pm-awe3t6.jsonl +++ b/.agents/pm/history/pm-awe3t6.jsonl @@ -2,3 +2,41 @@ {"ts":"2026-07-31T14:16:09.657Z","author":"harness:claude-code","author_source":"detected","agent_harness":"claude-code","agent_instance":"4cc69f82c87e6e8164c8f176","agent_provenance":{"model":null,"effort":{"value":"xhigh","source":"environment"}},"op":"update","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T14:16:09.657Z"},{"op":"add","path":"/metadata/dependencies","value":[{"id":"pm-5t33or","kind":"related","created_at":"2026-07-31T14:16:09.459Z","author":"harness:claude-code","source_kind":"cli:update:dep","author_source":"detected"},{"id":"pm-nilh","kind":"related","created_at":"2026-07-31T14:16:09.459Z","author":"harness:claude-code","source_kind":"cli:update:dep","author_source":"detected"}]}],"before_hash":"87089b772460a0c00637c16500077add015a593bd3c225f0ed6705dc0a7efdb8","after_hash":"6e437c3a31845e0a871553eaa0bba729ee487ddcfcd02e2d570bde9b89611514","message":"Link the closed parity item and the output-budget feature"} {"ts":"2026-07-31T14:20:57.270Z","author":"harness:claude-code","author_source":"detected","agent_harness":"claude-code","agent_instance":"4cc69f82c87e6e8164c8f176","agent_provenance":{"model":null,"effort":{"value":"xhigh","source":"environment"}},"op":"update","patch":[{"op":"add","path":"/metadata/dependencies/2","value":{"id":"pm-5k4v","kind":"implements","created_at":"2026-07-31T14:20:57.070Z","author":"harness:claude-code","source_kind":"cli:update:dep","author_source":"detected"}},{"op":"add","path":"/metadata/dependencies/3","value":{"id":"pm-9sui7t","kind":"related","created_at":"2026-07-31T14:20:57.070Z","author":"harness:claude-code","source_kind":"cli:update:dep","author_source":"detected"}},{"op":"add","path":"/metadata/dependencies/4","value":{"id":"pm-j82fd3","kind":"verifies","created_at":"2026-07-31T14:20:57.070Z","author":"harness:claude-code","source_kind":"cli:update:dep","author_source":"detected"}},{"op":"add","path":"/metadata/dependencies/5","value":{"id":"pm-mpbb","kind":"related","created_at":"2026-07-31T14:20:57.070Z","author":"harness:claude-code","source_kind":"cli:update:dep","author_source":"detected"}},{"op":"add","path":"/metadata/dependencies/6","value":{"id":"pm-n7rr","kind":"related","created_at":"2026-07-31T14:20:57.070Z","author":"harness:claude-code","source_kind":"cli:update:dep","author_source":"detected"}},{"op":"add","path":"/metadata/dependencies/7","value":{"id":"pm-sb0tns","kind":"related","created_at":"2026-07-31T14:20:57.070Z","author":"harness:claude-code","source_kind":"cli:update:dep","author_source":"detected"}},{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T14:20:57.270Z"}],"before_hash":"6e437c3a31845e0a871553eaa0bba729ee487ddcfcd02e2d570bde9b89611514","after_hash":"a0f4df1671ed2d87791775bfe87bc03b1976c77a5b7894151f4a6d49b09ba4df","message":"Typed graph placement: MCP capability epic parent, verifying the agent-legible-grammar milestone"} {"ts":"2026-07-31T14:28:27.142Z","author":"harness:claude-code","author_source":"detected","agent_harness":"claude-code","agent_instance":"4cc69f82c87e6e8164c8f176","agent_provenance":{"model":null,"effort":{"value":"xhigh","source":"environment"}},"op":"files_add","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T14:28:27.142Z"},{"op":"add","path":"/metadata/files","value":[{"path":"src/mcp/server.ts","scope":"project","note":"tool result envelope wraps in result and echoes the created item by default"}]}],"before_hash":"a0f4df1671ed2d87791775bfe87bc03b1976c77a5b7894151f4a6d49b09ba4df","after_hash":"6261250da24a62583be5a1a54a993d6d6ab34c687dac0d783c1cd86a3881abf3"} +{"ts":"2026-07-31T23:03:55.336Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"claim","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:03:55.336Z"},{"op":"add","path":"/metadata/assignee","value":"harness:codex"},{"op":"add","path":"/metadata/claim_principal","value":"harness:codex#264406b88560fcdcbb17052e"}],"before_hash":"6261250da24a62583be5a1a54a993d6d6ab34c687dac0d783c1cd86a3881abf3","after_hash":"149b59e1c7b78c46452e3f4f9909e56d25f1f66ccebdf1d891a7136b2b527bef"} +{"ts":"2026-07-31T23:03:56.667Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"update","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:03:56.667Z"},{"op":"replace","path":"/metadata/status","value":"in_progress"}],"before_hash":"149b59e1c7b78c46452e3f4f9909e56d25f1f66ccebdf1d891a7136b2b527bef","after_hash":"1c4cad7115be22a009d0353545e2609cefb860ec073663e3adef3a2a295422f5","message":"Start cohesive SDK/CLI context-output tranche: bounded cursor-chain metadata, reachable intent budgets, truthful delivery ledger, and lean MCP mutation parity."} +{"ts":"2026-07-31T23:32:56.825Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"files_add","patch":[{"op":"add","path":"/metadata/files/1","value":{"path":"src/sdk/runtime.ts","scope":"project","note":"CLI and MCP default mutation-envelope parity"}},{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:32:56.825Z"}],"before_hash":"1c4cad7115be22a009d0353545e2609cefb860ec073663e3adef3a2a295422f5","after_hash":"27197e2973118ebc9b7b9dbba735fb8057e14e6da5e91d7697b39e19ef0bba07","message":"Link implementation evidence for broad context-contract delivery"} +{"ts":"2026-07-31T23:32:57.874Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"files_add","patch":[{"op":"add","path":"/metadata/files/2","value":{"path":"tests/unit/mcp/mutation-envelope-parity.spec.ts","scope":"project","note":"CLI and MCP default mutation-envelope parity"}},{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:32:57.874Z"}],"before_hash":"27197e2973118ebc9b7b9dbba735fb8057e14e6da5e91d7697b39e19ef0bba07","after_hash":"2d6137008b572172efb21993cf1db3032bd8f359fae8943cb4dd9e3dede9ae7b","message":"Link implementation evidence for broad context-contract delivery"} +{"ts":"2026-07-31T23:32:58.743Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"docs_add","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:32:58.743Z"},{"op":"add","path":"/metadata/docs","value":[{"path":"docs/COMMANDS.md","scope":"project","note":"Documented MCP protocol wrapper and lean result"}]}],"before_hash":"2d6137008b572172efb21993cf1db3032bd8f359fae8943cb4dd9e3dede9ae7b","after_hash":"4aa39b83c58160aad8a12df5733d51518de911f96a8d8164338c5c348634314c","message":"Link documentation evidence for broad context-contract delivery"} +{"ts":"2026-07-31T23:32:59.712Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"tests_add","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:32:59.712Z"},{"op":"add","path":"/metadata/tests","value":[{"command":"node scripts/run-tests.mjs test -- tests/unit/mcp/mutation-envelope-parity.spec.ts tests/unit/core/output/mutation-projection.spec.ts","scope":"project","timeout_seconds":300}]}],"before_hash":"4aa39b83c58160aad8a12df5733d51518de911f96a8d8164338c5c348634314c","after_hash":"feeeb7762829d6eefc65f276e1562b309284cceac572d3d97985eec5f9815a43","message":"Link sandbox-safe verification for broad context-contract delivery"} +{"ts":"2026-07-31T23:45:20.168Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"files_add","patch":[{"op":"replace","path":"/metadata/files/2/note","value":"Updated consumers for lean default and explicit full opt-in"},{"op":"replace","path":"/metadata/files/2/path","value":"tests/integration/mcp-dynamic-package-actions.spec.ts"},{"op":"add","path":"/metadata/files/3","value":{"path":"tests/unit/mcp/mutation-envelope-parity.spec.ts","scope":"project","note":"CLI and MCP default mutation-envelope parity"}},{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:45:20.168Z"}],"before_hash":"feeeb7762829d6eefc65f276e1562b309284cceac572d3d97985eec5f9815a43","after_hash":"0b942fbf6efe3ffaf6dbbc36c16f21a388e56d2bbd3cb4b3065cace3cd60b15c","message":"Link repo-wide mutation parity regression coverage"} +{"ts":"2026-07-31T23:45:20.850Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"files_add","patch":[{"op":"replace","path":"/metadata/files/3/note","value":"Updated consumers for lean default and explicit full opt-in"},{"op":"replace","path":"/metadata/files/3/path","value":"tests/integration/sdk-cli-contract-integrity.integration.spec.ts"},{"op":"add","path":"/metadata/files/4","value":{"path":"tests/unit/mcp/mutation-envelope-parity.spec.ts","scope":"project","note":"CLI and MCP default mutation-envelope parity"}},{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:45:20.850Z"}],"before_hash":"0b942fbf6efe3ffaf6dbbc36c16f21a388e56d2bbd3cb4b3065cace3cd60b15c","after_hash":"80c81554280a7990784d0984ab887a8d255b3feec9053c2ca41e744aa9d18ef6","message":"Link repo-wide mutation parity regression coverage"} +{"ts":"2026-07-31T23:45:21.604Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"files_add","patch":[{"op":"add","path":"/metadata/files/5","value":{"path":"tests/unit/sdk/sdk-index.spec.ts","scope":"project","note":"Updated consumers for lean default and explicit full opt-in"}},{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:45:21.604Z"}],"before_hash":"80c81554280a7990784d0984ab887a8d255b3feec9053c2ca41e744aa9d18ef6","after_hash":"f5a3d2cb3d75d044482337bb5d0c36b240912c183eb53440a9989492ef3fd6e3","message":"Link repo-wide mutation parity regression coverage"} +{"ts":"2026-08-01T00:16:51.812Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"test_run_track","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T00:16:51.812Z"},{"op":"add","path":"/metadata/test_runs","value":[{"run_id":"test-local-ms9mg21p-sraa7s","kind":"test","status":"passed","started_at":"2026-08-01T00:16:40.080Z","finished_at":"2026-08-01T00:16:51.805Z","recorded_at":"2026-08-01T00:16:51.805Z","passed":1,"failed":0,"skipped":0}]}],"before_hash":"f5a3d2cb3d75d044482337bb5d0c36b240912c183eb53440a9989492ef3fd6e3","after_hash":"57fdcaf735dedc6578720d2d0540523fb0963fddab398f225962ea4499bc526b","message":"Track test run summary (test-local-ms9mg21p-sraa7s)"} +{"ts":"2026-08-01T00:35:37.292Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"comment_add","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T00:35:37.292Z"},{"op":"add","path":"/metadata/comments","value":[{"created_at":"2026-08-01T00:35:37.291Z","author":"harness:codex","text":"Implementation evidence 2026-08-01: raw SDK/MCP mutation actions create, copy, update, close, append, and restore now use the same lean id/status/changed_field_count default as the CLI, while typed PmClient convenience methods preserve full results through explicit fullChangedFields opt-in. Isolated identical creates measured 57 bytes on both CLI and MCP result versus the recorded 72/373-byte baseline. The MCP JSON-RPC structuredContent.result protocol wrapper remains documented, but both surfaces expose the same keys inside the result. Focused parity tests passed 22/22; the repo-wide suite passed 6631/6631 at 100/100/100/100 coverage."}]}],"before_hash":"57fdcaf735dedc6578720d2d0540523fb0963fddab398f225962ea4499bc526b","after_hash":"d21110c855559daf5e2883f68ec82b62b4f1285be4122a4d2b47acddbb6ea8d5"} +{"ts":"2026-08-01T00:35:38.049Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"update","patch":[{"op":"replace","path":"/metadata/actual_result","value":"An isolated identical create returns id/status/changed_field_count at 57 bytes on both CLI and MCP result; fullChangedFields restores the full envelope."},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T00:35:38.049Z"},{"op":"add","path":"/metadata/resolution","value":"Aligned raw SDK and MCP mutation defaults with the CLI lean envelope while preserving explicit fullChangedFields output and documenting protocol framing."}],"before_hash":"d21110c855559daf5e2883f68ec82b62b4f1285be4122a4d2b47acddbb6ea8d5","after_hash":"b10a8acd27cf7a22bc1ed65afeb582e501082775e9aec8673c993f87a5bbea85","message":"Record implemented mutation-envelope parity and measured acceptance evidence"} +{"ts":"2026-08-01T00:35:45.357Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"close","patch":[{"op":"remove","path":"/metadata/assignee"},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T00:35:45.357Z"},{"op":"replace","path":"/metadata/status","value":"closed"},{"op":"add","path":"/metadata/closed_at","value":"2026-08-01T00:35:45.350Z"},{"op":"add","path":"/metadata/completed_at","value":"2026-08-01T00:35:45.350Z"},{"op":"add","path":"/metadata/close_reason","value":"Implemented and verified CLI/MCP mutation-envelope parity: identical lean 57-byte create results, explicit full opt-in, protocol documentation, focused tests, and 100% repo coverage."}],"before_hash":"b10a8acd27cf7a22bc1ed65afeb582e501082775e9aec8673c993f87a5bbea85","after_hash":"71afd51fb613eaa4b4cf7e72ab60547e1ed84d1311ca27306df2857cea38e987"} +{"ts":"2026-08-01T00:35:46.234Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"release","patch":[{"op":"remove","path":"/metadata/claim_principal"},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T00:35:46.234Z"}],"before_hash":"71afd51fb613eaa4b4cf7e72ab60547e1ed84d1311ca27306df2857cea38e987","after_hash":"21d7798f48b366c95faa1cbe82d4fe8316b2b4617e82c1e00b2818c2a164e6ba"} +{"ts":"2026-08-01T00:38:51.296Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"files_add","patch":[{"op":"replace","path":"/metadata/files/5/note","value":"CLI and MCP default mutation-envelope parity"},{"op":"replace","path":"/metadata/files/5/path","value":"tests/unit/mcp/mutation-envelope-parity.spec.ts"},{"op":"replace","path":"/metadata/files/4/note","value":"Updated consumers for lean default and explicit full opt-in"},{"op":"replace","path":"/metadata/files/4/path","value":"tests/integration/sdk-cli-contract-integrity.integration.spec.ts"},{"op":"replace","path":"/metadata/files/3/path","value":"tests/integration/mcp-dynamic-package-actions.spec.ts"},{"op":"replace","path":"/metadata/files/2/note","value":"CLI and MCP default mutation-envelope parity"},{"op":"replace","path":"/metadata/files/2/path","value":"src/sdk/runtime.ts"},{"op":"replace","path":"/metadata/files/1/note","value":"tool result envelope wraps in result and echoes the created item by default"},{"op":"replace","path":"/metadata/files/1/path","value":"src/mcp/server.ts"},{"op":"replace","path":"/metadata/files/0/note","value":"Package-owned generated release entry"},{"op":"replace","path":"/metadata/files/0/path","value":"CHANGELOG.md"},{"op":"add","path":"/metadata/files/6","value":{"path":"tests/unit/sdk/sdk-index.spec.ts","scope":"project","note":"Updated consumers for lean default and explicit full opt-in"}},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T00:38:51.296Z"}],"before_hash":"21d7798f48b366c95faa1cbe82d4fe8316b2b4617e82c1e00b2818c2a164e6ba","after_hash":"99b0a5d58c7bdfe3ec08b533baa6912e1766cc28da5aebbdd4e761dcbe75d331"} +{"ts":"2026-08-01T01:08:45.057Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"update","patch":[{"op":"remove","path":"/metadata/close_reason"},{"op":"remove","path":"/metadata/completed_at"},{"op":"remove","path":"/metadata/closed_at"},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T01:08:45.057Z"},{"op":"replace","path":"/metadata/status","value":"open"}],"before_hash":"99b0a5d58c7bdfe3ec08b533baa6912e1766cc28da5aebbdd4e761dcbe75d331","after_hash":"586c0859997f960ec6b5c5911b4e98c68d0d8196bf446848174fd8df35fdfa46","message":"Reopen canonical mutation-parity work after exact-head CI found the Claude plugin smoke still consumed the retired verbose raw create envelope."} +{"ts":"2026-08-01T01:08:45.808Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"claim","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T01:08:45.808Z"},{"op":"add","path":"/metadata/assignee","value":"harness:codex"},{"op":"add","path":"/metadata/claim_principal","value":"harness:codex#264406b88560fcdcbb17052e"}],"before_hash":"586c0859997f960ec6b5c5911b4e98c68d0d8196bf446848174fd8df35fdfa46","after_hash":"8390750fde8bf5f5f634bfab409f1e5cce7016c3135a76191fd448fc8a51a257"} +{"ts":"2026-08-01T01:08:46.675Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"update","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T01:08:46.675Z"},{"op":"replace","path":"/metadata/status","value":"in_progress"}],"before_hash":"8390750fde8bf5f5f634bfab409f1e5cce7016c3135a76191fd448fc8a51a257","after_hash":"7621d0e9da42d6ea2187e39a1d9a620f805c65cc6a65e1befceccdf92ae349c8","message":"Actively updating the Claude plugin acceptance smoke and unit coverage for the lean default MCP mutation contract exposed by PR #849 CI."} +{"ts":"2026-08-01T01:09:44.869Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"files_add","patch":[{"op":"replace","path":"/metadata/files/6/note","value":"CLI and MCP default mutation-envelope parity"},{"op":"replace","path":"/metadata/files/6/path","value":"tests/unit/mcp/mutation-envelope-parity.spec.ts"},{"op":"replace","path":"/metadata/files/5/note","value":"Updated consumers for lean default and explicit full opt-in"},{"op":"replace","path":"/metadata/files/5/path","value":"tests/integration/sdk-cli-contract-integrity.integration.spec.ts"},{"op":"replace","path":"/metadata/files/4/path","value":"tests/integration/mcp-dynamic-package-actions.spec.ts"},{"op":"replace","path":"/metadata/files/3/note","value":"CLI and MCP default mutation-envelope parity"},{"op":"replace","path":"/metadata/files/3/path","value":"src/sdk/runtime.ts"},{"op":"replace","path":"/metadata/files/2/note","value":"tool result envelope wraps in result and echoes the created item by default"},{"op":"replace","path":"/metadata/files/2/path","value":"src/mcp/server.ts"},{"op":"replace","path":"/metadata/files/1/note","value":"Acceptance smoke enforces lean raw MCP create envelope"},{"op":"replace","path":"/metadata/files/1/path","value":"scripts/smoke-claude-plugin.mjs"},{"op":"add","path":"/metadata/files/7","value":{"path":"tests/unit/scripts/smoke-claude-plugin.spec.ts","scope":"project","note":"Regression coverage rejects verbose and malformed create envelopes"}},{"op":"add","path":"/metadata/files/8","value":{"path":"tests/unit/sdk/sdk-index.spec.ts","scope":"project","note":"Updated consumers for lean default and explicit full opt-in"}},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T01:09:44.869Z"}],"before_hash":"7621d0e9da42d6ea2187e39a1d9a620f805c65cc6a65e1befceccdf92ae349c8","after_hash":"e051b82aab739a1dd57a479071ac1156d4cab7f5368bed9b332e5b5c94114cb7"} +{"ts":"2026-08-01T01:09:46.072Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"tests_add","patch":[{"op":"add","path":"/metadata/tests/1","value":{"command":"node scripts/run-tests.mjs test -- tests/unit/scripts/smoke-claude-plugin.spec.ts tests/unit/mcp/mutation-envelope-parity.spec.ts","scope":"project","timeout_seconds":300,"note":"Lean mutation contract and Claude plugin smoke regression"}},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T01:09:46.072Z"}],"before_hash":"e051b82aab739a1dd57a479071ac1156d4cab7f5368bed9b332e5b5c94114cb7","after_hash":"d553555adfc37126846d1f0883f61b907cf0a2f1c68986e86edb188815a69d11"} +{"ts":"2026-08-01T01:10:09.272Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"test_run_track","patch":[{"op":"add","path":"/metadata/test_runs/1","value":{"run_id":"test-local-ms9ocl81-o0u486","kind":"test","status":"passed","started_at":"2026-08-01T01:09:47.417Z","finished_at":"2026-08-01T01:10:09.265Z","recorded_at":"2026-08-01T01:10:09.265Z","passed":2,"failed":0,"skipped":0}},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T01:10:09.272Z"}],"before_hash":"d553555adfc37126846d1f0883f61b907cf0a2f1c68986e86edb188815a69d11","after_hash":"ea8b11d6947a50b06dd0f718097046da678f7414b80b6cc3d80fd1dfc614b7ec","message":"Track test run summary (test-local-ms9ocl81-o0u486)"} +{"ts":"2026-08-01T01:10:10.296Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"comment_add","patch":[{"op":"add","path":"/metadata/comments/1","value":{"created_at":"2026-08-01T01:10:10.295Z","author":"harness:codex","text":"PR #849 exact-head CI correction: the Claude plugin smoke was the remaining consumer of the retired verbose raw pm_create result. It now requires the exact lean id/status/changed_field_count key set and a non-empty id; unit tests reject both verbose and malformed envelopes. Focused tests passed 19/19, the real MCP/plugin smoke passed all 31 tools and its full workflow, and ESLint passed."}},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T01:10:10.296Z"}],"before_hash":"ea8b11d6947a50b06dd0f718097046da678f7414b80b6cc3d80fd1dfc614b7ec","after_hash":"898d2de494879f496d7f134c15bb15ecf83fdc0818dc1e15ef98f4fdcde9017e"} +{"ts":"2026-08-01T01:10:16.046Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"close","patch":[{"op":"remove","path":"/metadata/assignee"},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T01:10:16.046Z"},{"op":"replace","path":"/metadata/status","value":"closed"},{"op":"add","path":"/metadata/closed_at","value":"2026-08-01T01:10:16.041Z"},{"op":"add","path":"/metadata/completed_at","value":"2026-08-01T01:10:16.041Z"},{"op":"add","path":"/metadata/close_reason","value":"Reclosed after exact-head CI compatibility correction: acceptance smoke now enforces the lean MCP create contract, focused regression tests and real 31-tool plugin workflow pass, and ESLint is clean."}],"before_hash":"898d2de494879f496d7f134c15bb15ecf83fdc0818dc1e15ef98f4fdcde9017e","after_hash":"74800b06fca7470e216223213d749e75d0c84f5b08ec177b3d0e2fb2f6c83e12"} +{"ts":"2026-08-01T01:10:16.844Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"release","patch":[{"op":"remove","path":"/metadata/claim_principal"},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T01:10:16.844Z"}],"before_hash":"74800b06fca7470e216223213d749e75d0c84f5b08ec177b3d0e2fb2f6c83e12","after_hash":"ae46f52b6518160f275f314ad71efdae4a94ca45fc1ed8623f2c0a97d4a7aae2"} +{"ts":"2026-08-01T01:20:14.916Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"update","patch":[{"op":"remove","path":"/metadata/close_reason"},{"op":"remove","path":"/metadata/completed_at"},{"op":"remove","path":"/metadata/closed_at"},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T01:20:14.916Z"},{"op":"replace","path":"/metadata/status","value":"open"}],"before_hash":"ae46f52b6518160f275f314ad71efdae4a94ca45fc1ed8623f2c0a97d4a7aae2","after_hash":"8c5809028fa4ceaf71db50df378add6a53e23334210352f02ec0b4d340d98091","message":"Reopen canonical mutation-parity item for verified review finding: pm_run append drops the idOnly projection flag."} +{"ts":"2026-08-01T01:20:15.603Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"claim","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T01:20:15.603Z"},{"op":"add","path":"/metadata/assignee","value":"harness:codex"},{"op":"add","path":"/metadata/claim_principal","value":"harness:codex#264406b88560fcdcbb17052e"}],"before_hash":"8c5809028fa4ceaf71db50df378add6a53e23334210352f02ec0b4d340d98091","after_hash":"407ac04eea0abfc6735589dd53a31d129992cef793068706ede2a93c49531bb7"} +{"ts":"2026-08-01T01:20:16.463Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"update","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T01:20:16.463Z"},{"op":"replace","path":"/metadata/status","value":"in_progress"}],"before_hash":"407ac04eea0abfc6735589dd53a31d129992cef793068706ede2a93c49531bb7","after_hash":"fdf4a8916ae9b3e1f21865ce265e45f36a75280903fd7ea7838a146d94438435","message":"Actively fixing and testing append idOnly parity from PR #849 review."} +{"ts":"2026-08-01T01:34:19.681Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"comment_add","patch":[{"op":"add","path":"/metadata/comments/2","value":{"created_at":"2026-08-01T01:34:19.681Z","author":"harness:codex","text":"PR #849 review evidence: runMcpAppendAction now propagates idOnly and disables compactEnvelope when idOnly is requested. A real MCP pm_run append regression returns exactly id/status with no changed_field_count. The focused MCP suite and repo-wide 6636-test 100/100/100/100 coverage pass."}},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T01:34:19.681Z"}],"before_hash":"fdf4a8916ae9b3e1f21865ce265e45f36a75280903fd7ea7838a146d94438435","after_hash":"4cb22f4dcffbc7c31dc16599c619e25838e366e96283025def458d1d3192309e"} +{"ts":"2026-08-01T01:34:27.585Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"close","patch":[{"op":"remove","path":"/metadata/assignee"},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T01:34:27.585Z"},{"op":"replace","path":"/metadata/status","value":"closed"},{"op":"add","path":"/metadata/closed_at","value":"2026-08-01T01:34:27.578Z"},{"op":"add","path":"/metadata/completed_at","value":"2026-08-01T01:34:27.578Z"},{"op":"add","path":"/metadata/close_reason","value":"Reclosed after review correction: pm_run append honors idOnly, real MCP regression coverage passes, and the full suite is 6636/6636 at exact 100/100/100/100."}],"before_hash":"4cb22f4dcffbc7c31dc16599c619e25838e366e96283025def458d1d3192309e","after_hash":"aa033ac31fcbb5281128069b990b0ed25d316cee153f4a6641aba754f400c503"} +{"ts":"2026-08-01T01:34:28.385Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"release","patch":[{"op":"remove","path":"/metadata/claim_principal"},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T01:34:28.385Z"}],"before_hash":"aa033ac31fcbb5281128069b990b0ed25d316cee153f4a6641aba754f400c503","after_hash":"006e6de79082d063119997624159095768b7175d30db53e86191bf5ca327c6f4"} +{"ts":"2026-08-01T02:14:24.225Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"update","patch":[{"op":"remove","path":"/metadata/close_reason"},{"op":"remove","path":"/metadata/completed_at"},{"op":"remove","path":"/metadata/closed_at"},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T02:14:24.225Z"},{"op":"replace","path":"/metadata/status","value":"in_progress"}],"before_hash":"006e6de79082d063119997624159095768b7175d30db53e86191bf5ca327c6f4","after_hash":"d8aa9eafa26c96b2a0b91f8a667bae5eeb8c4af22f931c5f0739c6966b7abdd8","message":"Reopen briefly to correct stale linked-file note identified in exact-head review."} +{"ts":"2026-08-01T02:14:25.007Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"claim","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T02:14:25.007Z"},{"op":"add","path":"/metadata/assignee","value":"harness:codex"},{"op":"add","path":"/metadata/claim_principal","value":"harness:codex#264406b88560fcdcbb17052e"}],"before_hash":"d8aa9eafa26c96b2a0b91f8a667bae5eeb8c4af22f931c5f0739c6966b7abdd8","after_hash":"e78839a7d01a8c77655c62b88d87ab66a23469e9bf3db49ecc8a0c02e486ade6"} +{"ts":"2026-08-01T02:14:27.324Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"files_add","patch":[{"op":"remove","path":"/metadata/files/8"},{"op":"replace","path":"/metadata/files/7/note","value":"Updated consumers for lean default and explicit full opt-in"},{"op":"replace","path":"/metadata/files/7/path","value":"tests/unit/sdk/sdk-index.spec.ts"},{"op":"replace","path":"/metadata/files/6/note","value":"Regression coverage rejects verbose and malformed create envelopes"},{"op":"replace","path":"/metadata/files/6/path","value":"tests/unit/scripts/smoke-claude-plugin.spec.ts"},{"op":"replace","path":"/metadata/files/5/note","value":"CLI and MCP default mutation-envelope parity"},{"op":"replace","path":"/metadata/files/5/path","value":"tests/unit/mcp/mutation-envelope-parity.spec.ts"},{"op":"replace","path":"/metadata/files/4/path","value":"tests/integration/sdk-cli-contract-integrity.integration.spec.ts"},{"op":"replace","path":"/metadata/files/3/note","value":"Updated consumers for lean default and explicit full opt-in"},{"op":"replace","path":"/metadata/files/3/path","value":"tests/integration/mcp-dynamic-package-actions.spec.ts"},{"op":"replace","path":"/metadata/files/2/note","value":"CLI and MCP default mutation-envelope parity"},{"op":"replace","path":"/metadata/files/2/path","value":"src/sdk/runtime.ts"},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T02:14:27.324Z"}],"before_hash":"e78839a7d01a8c77655c62b88d87ab66a23469e9bf3db49ecc8a0c02e486ade6","after_hash":"14f024a1c4adbbc78d081d5c86c953b2d2372b5502efd29d817d8d3f9d18895b","message":"Replace stale pre-fix MCP mutation-envelope note."} +{"ts":"2026-08-01T02:14:28.220Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"files_add","patch":[{"op":"replace","path":"/metadata/files/7/note","value":"Regression coverage rejects verbose and malformed create envelopes"},{"op":"replace","path":"/metadata/files/7/path","value":"tests/unit/scripts/smoke-claude-plugin.spec.ts"},{"op":"replace","path":"/metadata/files/6/note","value":"CLI and MCP default mutation-envelope parity"},{"op":"replace","path":"/metadata/files/6/path","value":"tests/unit/mcp/mutation-envelope-parity.spec.ts"},{"op":"replace","path":"/metadata/files/5/note","value":"Updated consumers for lean default and explicit full opt-in"},{"op":"replace","path":"/metadata/files/5/path","value":"tests/integration/sdk-cli-contract-integrity.integration.spec.ts"},{"op":"replace","path":"/metadata/files/4/path","value":"tests/integration/mcp-dynamic-package-actions.spec.ts"},{"op":"replace","path":"/metadata/files/3/note","value":"CLI and MCP default mutation-envelope parity"},{"op":"replace","path":"/metadata/files/3/path","value":"src/sdk/runtime.ts"},{"op":"replace","path":"/metadata/files/2/note","value":"MCP protocol wrapper exposes the lean default mutation result without an item echo"},{"op":"replace","path":"/metadata/files/2/path","value":"src/mcp/server.ts"},{"op":"add","path":"/metadata/files/8","value":{"path":"tests/unit/sdk/sdk-index.spec.ts","scope":"project","note":"Updated consumers for lean default and explicit full opt-in"}},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T02:14:28.220Z"}],"before_hash":"14f024a1c4adbbc78d081d5c86c953b2d2372b5502efd29d817d8d3f9d18895b","after_hash":"c6c92b63eea6ffa7b067196c474eaf8cd6d666ccb3f1c5ed8e2601986ffa3b9b","message":"Record current lean MCP mutation-envelope behavior."} +{"ts":"2026-08-01T02:15:20.872Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"comment_add","patch":[{"op":"add","path":"/metadata/comments/3","value":{"created_at":"2026-08-01T02:15:20.871Z","author":"harness:codex","text":"Exact-head CodeRabbit correction: replaced the stale src/mcp/server.ts linked-file note through pm files. The canonical record now states that the protocol wrapper exposes the lean default mutation result without an item echo; focused context/MCP regressions and ESLint pass."}},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T02:15:20.872Z"}],"before_hash":"c6c92b63eea6ffa7b067196c474eaf8cd6d666ccb3f1c5ed8e2601986ffa3b9b","after_hash":"c533c7dc6d3ef11196bb8faa228437d0eaf94c86a83d780bf6e0c9868695f6ed"} +{"ts":"2026-08-01T02:15:23.714Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"comment_add","patch":[{"op":"add","path":"/metadata/comments/4","value":{"created_at":"2026-08-01T02:15:23.713Z","author":"harness:codex","text":"Exact-head CodeRabbit correction: replaced the stale src/mcp/server.ts linked-file note through pm files. The canonical record now states that the protocol wrapper exposes the lean default mutation result without an item echo; focused context/MCP regressions pass 18/18."}},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T02:15:23.714Z"}],"before_hash":"c533c7dc6d3ef11196bb8faa228437d0eaf94c86a83d780bf6e0c9868695f6ed","after_hash":"6973889b7040fe2adcf568d292c959c0b8d4d3141b399ef642cbd97fd414ecfd"} +{"ts":"2026-08-01T02:15:28.132Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"close","patch":[{"op":"remove","path":"/metadata/assignee"},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T02:15:28.132Z"},{"op":"replace","path":"/metadata/status","value":"closed"},{"op":"add","path":"/metadata/closed_at","value":"2026-08-01T02:15:28.125Z"},{"op":"add","path":"/metadata/completed_at","value":"2026-08-01T02:15:28.125Z"},{"op":"add","path":"/metadata/close_reason","value":"Reclosed after correcting the stale linked-file note; canonical PM metadata now matches the lean MCP default and focused verification passes."}],"before_hash":"6973889b7040fe2adcf568d292c959c0b8d4d3141b399ef642cbd97fd414ecfd","after_hash":"5c72d7d17ec60f413d75a7bcd3143fc97db10af1ba46a8fea995ed92a02a0a44"} +{"ts":"2026-08-01T02:15:28.922Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"release","patch":[{"op":"remove","path":"/metadata/claim_principal"},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T02:15:28.922Z"}],"before_hash":"5c72d7d17ec60f413d75a7bcd3143fc97db10af1ba46a8fea995ed92a02a0a44","after_hash":"f5a8754fc55162e8315b07e5c4d56279b8658f35912e0e164df49cc48bc1e6b6"} diff --git a/.agents/pm/history/pm-nilh.jsonl b/.agents/pm/history/pm-nilh.jsonl index a6a1775c7..853b0f724 100644 --- a/.agents/pm/history/pm-nilh.jsonl +++ b/.agents/pm/history/pm-nilh.jsonl @@ -16,3 +16,4 @@ {"ts":"2026-07-26T16:52:59.224Z","author":"harness:claude-code","author_source":"detected","agent_harness":"claude-code","agent_instance":"ad0de54baae9cc12afd5a5a6","op":"update","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-07-26T16:52:59.224Z"},{"op":"add","path":"/metadata/release","value":"v2026.7.21"}],"before_hash":"a1417a03edfd1fb52e09c66cca36fe08d5ef2d285f00d7d1d4a739555ab28518","after_hash":"4cbab13de3d0da18dd9e4ae810b8a881ccac584806e1a4fe28c132dd65409303","message":"Historical release attribution backfill (pm-3j6it6): stamp the release tag whose window contains this item close event, derived from its immutable history stream, so changelog attribution stops depending on updated_at"} {"ts":"2026-07-26T17:21:13.320Z","author":"harness:claude-code","author_source":"detected","agent_harness":"claude-code","agent_instance":"ad0de54baae9cc12afd5a5a6","op":"update","patch":[{"op":"add","path":"/metadata/dependencies/3","value":{"id":"pm-mpbb","kind":"implements","created_at":"2026-07-26T17:21:13.002Z"}},{"op":"replace","path":"/metadata/updated_at","value":"2026-07-26T17:21:13.320Z"}],"before_hash":"4cbab13de3d0da18dd9e4ae810b8a881ccac584806e1a4fe28c132dd65409303","after_hash":"e422423c03f54290d0352ec9369dbf88216d23fe4c523d3d6c99bb1c819294eb","message":"Terminal graph backfill (pm-lnrk / pm-3j6it6 lane): add 1 evidence-derived relationship edge(s). Evidence classes used: typed hierarchy mirror so semantic traversal reaches the owning lineage (parent alone is not a traversable semantic kind). Release attribution is stamped, so this metadata write cannot re-bucket the item in the generated changelog."} {"ts":"2026-07-31T14:16:08.723Z","author":"harness:claude-code","author_source":"detected","agent_harness":"claude-code","agent_instance":"4cc69f82c87e6e8164c8f176","agent_provenance":{"model":null,"effort":{"value":"xhigh","source":"environment"}},"op":"comment_add","patch":[{"op":"add","path":"/metadata/comments/1","value":{"created_at":"2026-07-31T14:16:08.723Z","author":"harness:claude-code","text":"Closed-item conformance check 2026-07-31, filed as pm-awe3t6. No reopen proposed - the CLI half of this item shipped and holds - but the parity claim in the title is inverted at HEAD.\n\nMeasured in one sandbox tracker, same type, same fields, same second. CLI pm create --json returns 72 bytes: {id, status, changed_field_count}. MCP pm_create with identical arguments returns 373 bytes: a result wrapper containing the full ten-field item echo, an empty warnings array, a next_transition object, and changed_field_count. That is 5.2x, and it is the MCP default; the lean form on MCP requires idOnly:true, which returns 45 bytes, while the CLI needs no flag.\n\nSo this item made the CLI lean and the direction of parity reversed rather than converged: the surface that is now verbose is the one where tokens are unavoidable, because every MCP tool result enters the model context whether the agent needed it or not, whereas a CLI caller can pipe through jq and discard. The result wrapper is a second divergence - the CLI emits no such key - which is the shape difference the agent guidance warns about."}},{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T14:16:08.723Z"}],"before_hash":"e422423c03f54290d0352ec9369dbf88216d23fe4c523d3d6c99bb1c819294eb","after_hash":"0aeb07e988b0e76f0baa62b125d9df196f6a49ef700235d1fc8264e12c47cf9b"} +{"ts":"2026-08-01T00:35:36.460Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"comment_add","patch":[{"op":"add","path":"/metadata/comments/2","value":{"created_at":"2026-08-01T00:35:36.460Z","author":"harness:codex","text":"Conformance correction 2026-08-01: pm-awe3t6 restores the parity this closed item intended. An isolated identical create now serializes to 57 bytes on both the CLI default and the MCP structured result, with the same id/status/changed_field_count keys. MCP protocol framing still wraps structuredContent.result as documented, while the mutation result itself has one cross-surface accessor shape; fullChangedFields:true remains the explicit full-envelope opt-in."}},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T00:35:36.460Z"}],"before_hash":"0aeb07e988b0e76f0baa62b125d9df196f6a49ef700235d1fc8264e12c47cf9b","after_hash":"d2a03f14a4ce3a5403c09a9e64aacfa6366087722a642a2d01a00374944a4aa1"} diff --git a/.agents/pm/history/pm-sf31yl.jsonl b/.agents/pm/history/pm-sf31yl.jsonl index bc407ab8b..64a67460b 100644 --- a/.agents/pm/history/pm-sf31yl.jsonl +++ b/.agents/pm/history/pm-sf31yl.jsonl @@ -1,3 +1,26 @@ {"ts":"2026-07-30T17:01:49.124Z","author":"harness:claude-code","author_source":"detected","agent_harness":"claude-code","agent_instance":"6682b76673432e27b62e2ad8","agent_provenance":{"model":null,"effort":{"value":"xhigh","source":"environment"}},"op":"create","patch":[{"op":"add","path":"/metadata/id","value":"pm-sf31yl"},{"op":"add","path":"/metadata/title","value":"The bounded read costs 13.8 times the unbounded read to deliver the same set, because eight metadata blocks are re-emitted per page and the page carries two rows"},{"op":"add","path":"/metadata/description","value":"Measured at HEAD on the live tracker. pm list --json returns all 315 open items in 71,709 bytes, about 228 bytes per row. pm list --for triage returns 2 rows in 6,250 bytes, about 3,125 bytes per row, with has_more true and a resumable cursor. Walking the same 315 items through the triage intent therefore takes 158 pages and 987,500 bytes, which is 13.8 times the single unprojected call and about 247,000 tokens against about 18,000. The token-efficiency feature is anti-efficient at whole-set scope, and it is anti-efficient by construction rather than by accident. Every page re-emits eight metadata blocks that do not vary across the chain: context_intent, row_contract, projection, omission_receipt, filters, sorting, completeness and the pagination triple. On a 2-row page those blocks and the wider per-row field set dominate the payload, so the marginal cost of a row is small compared to the fixed cost of asking for it. Two independent levers exist and neither is applied. The metadata is chain-invariant, so it can be emitted once for the cursor chain and referenced by fingerprint on continuation pages, or suppressed by an explicit caller opt-out. The row count is chosen without reference to measured per-row cost, so a budget that admits 1,045 tokens of payload is spent mostly on envelope instead of being divided by the observed bytes-per-row to pick the largest feasible page. This is scoped to per-page metadata amortization and page-size derivation across the paginated read family. It is not the per-row resume cursor in pm events, which is pm-ez1dfg, and it is not the encoding study, which is pm-kvxqp1."},{"op":"add","path":"/metadata/type","value":"Issue"},{"op":"add","path":"/metadata/status","value":"open"},{"op":"add","path":"/metadata/priority","value":1},{"op":"add","path":"/metadata/tags","value":["context-management","pagination","token-budget"]},{"op":"add","path":"/metadata/created_at","value":"2026-07-30T17:01:49.124Z"},{"op":"add","path":"/metadata/updated_at","value":"2026-07-30T17:01:49.124Z"},{"op":"add","path":"/metadata/author","value":"harness:claude-code"},{"op":"add","path":"/metadata/estimated_minutes","value":360},{"op":"add","path":"/metadata/acceptance_criteria","value":"Chain-invariant envelope metadata is emitted once per cursor chain and referenced on continuation pages, or is suppressible by an explicit caller opt-out, and the reduction is measured; Page size is derived from the measured bytes-per-row of the projection against the remaining budget rather than from a fixed constant, so a larger budget yields more rows rather than the same two; A gate asserts that walking a full result set through any bounded intent costs no more total tokens than the unprojected single call for the same set, on a corpus at least the size of the current tracker; The published evidence table records bytes per row and total walk cost for every bounded read family member before and after, including the 315-item list case; A negative control proves the gate fails when per-page metadata is reintroduced on every page"},{"op":"add","path":"/metadata/parent","value":"pm-5t33or"},{"op":"add","path":"/metadata/risk","value":"high"},{"op":"add","path":"/metadata/confidence","value":"high"}],"before_hash":"3cc22dff72be7b14824654a7a64ea62b04799939b2fee54c1b5f52ca60bf6df0","after_hash":"a1b6a10cf2e86c69bfd202fe25976ab0aaa97381e9f01a411d4aaac1dfe8356d","message":""} {"ts":"2026-07-30T17:03:14.155Z","author":"harness:claude-code","author_source":"detected","agent_harness":"claude-code","agent_instance":"6682b76673432e27b62e2ad8","agent_provenance":{"model":null,"effort":{"value":"xhigh","source":"environment"}},"op":"update","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-07-30T17:03:14.155Z"},{"op":"add","path":"/metadata/dependencies","value":[{"id":"pm-7hbfch","kind":"discovered_from","created_at":"2026-07-30T17:03:13.975Z","author":"harness:claude-code","source_kind":"cli:update:dep","author_source":"detected"},{"id":"pm-ez1dfg","kind":"related","created_at":"2026-07-30T17:03:13.975Z","author":"harness:claude-code","source_kind":"cli:update:dep","author_source":"detected"},{"id":"pm-kvxqp1","kind":"related","created_at":"2026-07-30T17:03:13.975Z","author":"harness:claude-code","source_kind":"cli:update:dep","author_source":"detected"},{"id":"pm-o87av6","kind":"implements","created_at":"2026-07-30T17:03:13.975Z","author":"harness:claude-code","source_kind":"cli:update:dep","author_source":"detected"}]}],"before_hash":"a1b6a10cf2e86c69bfd202fe25976ab0aaa97381e9f01a411d4aaac1dfe8356d","after_hash":"3b160bddebc1ae46f7ae2fac10d3428ed480e3b29fb03c506f0129d9afa5ec98","message":"Wire per-page amortization issue to proven scale, to the budget-enforcement issue that exposed it, and to its two class siblings"} {"ts":"2026-07-30T17:21:52.248Z","author":"harness:claude-code","author_source":"detected","agent_harness":"claude-code","agent_instance":"6682b76673432e27b62e2ad8","agent_provenance":{"model":null,"effort":{"value":"xhigh","source":"environment"}},"op":"learning_add","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-07-30T17:21:52.248Z"},{"op":"add","path":"/metadata/learnings","value":[{"created_at":"2026-07-30T17:21:52.247Z","author":"harness:claude-code","text":"Measurement discipline this issue depends on, worth stating because the intuitive measurement hides the defect: judge a bounded read by the cost of the whole answer, never by the cost of one page. Per page the triage projection looks like a clear win at 6,250 bytes against 71,709 for the unprojected call. Multiplied by the pages needed to reach the same 315 rows it is 987,500 bytes, and the win becomes a 13.8-fold loss. The comparison that matters is total tokens to answer the question the caller actually asked.\n\nThe derived quantity to record for any paginated surface is bytes per row at the offered page size, because it exposes envelope amortisation directly: 228 bytes per row unprojected against 3,125 per row at a two-row page is the whole finding in one ratio, and it stays meaningful across corpus sizes in a way that a page byte count does not."}]}],"before_hash":"3b160bddebc1ae46f7ae2fac10d3428ed480e3b29fb03c506f0129d9afa5ec98","after_hash":"88a42a2fd3c5b783236a840f9ef4887ec248efea357eaa475eecbb0aa981a987"} +{"ts":"2026-07-31T23:03:47.956Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"claim","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:03:47.956Z"},{"op":"add","path":"/metadata/assignee","value":"harness:codex"},{"op":"add","path":"/metadata/claim_principal","value":"harness:codex#264406b88560fcdcbb17052e"}],"before_hash":"88a42a2fd3c5b783236a840f9ef4887ec248efea357eaa475eecbb0aa981a987","after_hash":"7272a10f8e78b3af8cf81c2f3773ac8af06667b578c536bbf8cdfa94b08407b5"} +{"ts":"2026-07-31T23:03:48.783Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"update","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:03:48.783Z"},{"op":"replace","path":"/metadata/status","value":"in_progress"}],"before_hash":"7272a10f8e78b3af8cf81c2f3773ac8af06667b578c536bbf8cdfa94b08407b5","after_hash":"bdfd4368e9d9c971ca93a5ea0fc8cbfb6a26e5f8a613688586983c1fbd26a10b","message":"Start cohesive SDK/CLI context-output tranche: bounded cursor-chain metadata, reachable intent budgets, truthful delivery ledger, and lean MCP mutation parity."} +{"ts":"2026-07-31T23:32:52.616Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"files_add","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:32:52.616Z"},{"op":"add","path":"/metadata/files","value":[{"path":"src/sdk/context-intent-contracts.ts","scope":"project","note":"Cursor-chain metadata reference and pagination integrity"}]}],"before_hash":"bdfd4368e9d9c971ca93a5ea0fc8cbfb6a26e5f8a613688586983c1fbd26a10b","after_hash":"545a9393d397edfd5c13d7cef8933bdce53d99d440eb81d036c14b6363942f5f","message":"Link implementation evidence for broad context-contract delivery"} +{"ts":"2026-07-31T23:32:53.432Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"files_add","patch":[{"op":"add","path":"/metadata/files/1","value":{"path":"tests/unit/sdk/context-intent-contracts.spec.ts","scope":"project","note":"Cursor-chain metadata reference and pagination integrity"}},{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:32:53.432Z"}],"before_hash":"545a9393d397edfd5c13d7cef8933bdce53d99d440eb81d036c14b6363942f5f","after_hash":"d56f1f1b98c5a0e7c4293c9c269b96f063d9858ff6adac87d67658fcdbf24dc8","message":"Link implementation evidence for broad context-contract delivery"} +{"ts":"2026-07-31T23:32:54.347Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"files_add","patch":[{"op":"replace","path":"/metadata/files/1/path","value":"tests/unit/commands/query-pagination.spec.ts"},{"op":"add","path":"/metadata/files/2","value":{"path":"tests/unit/sdk/context-intent-contracts.spec.ts","scope":"project","note":"Cursor-chain metadata reference and pagination integrity"}},{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:32:54.347Z"}],"before_hash":"d56f1f1b98c5a0e7c4293c9c269b96f063d9858ff6adac87d67658fcdbf24dc8","after_hash":"8fcc9c988111059bbf45556ebc6738a30ae022bef911bff36710ccecea876624","message":"Link implementation evidence for broad context-contract delivery"} +{"ts":"2026-07-31T23:32:55.177Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"docs_add","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:32:55.177Z"},{"op":"add","path":"/metadata/docs","value":[{"path":"docs/OUTPUT_PROJECTION_CONTRACTS.md","scope":"project","note":"Continuation-page metadata contract"}]}],"before_hash":"8fcc9c988111059bbf45556ebc6738a30ae022bef911bff36710ccecea876624","after_hash":"762a50a3dba498c568030a71a40df494f51e898d7e75669b9cf26726ec8ff3de","message":"Link documentation evidence for broad context-contract delivery"} +{"ts":"2026-07-31T23:32:55.979Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"tests_add","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:32:55.979Z"},{"op":"add","path":"/metadata/tests","value":[{"command":"node scripts/run-tests.mjs test -- tests/unit/commands/query-pagination.spec.ts tests/unit/sdk/context-intent-contracts.spec.ts","scope":"project","timeout_seconds":300}]}],"before_hash":"762a50a3dba498c568030a71a40df494f51e898d7e75669b9cf26726ec8ff3de","after_hash":"2968dfe5b23d109a23af7554bfc490bf9d0ecfe4b6da5177a0e2365e2d02d275","message":"Link sandbox-safe verification for broad context-contract delivery"} +{"ts":"2026-08-01T00:16:39.440Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"test_run_track","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T00:16:39.440Z"},{"op":"add","path":"/metadata/test_runs","value":[{"run_id":"test-local-ms9mfsi3-oh4vvc","kind":"test","status":"passed","started_at":"2026-08-01T00:16:29.855Z","finished_at":"2026-08-01T00:16:39.434Z","recorded_at":"2026-08-01T00:16:39.434Z","passed":1,"failed":0,"skipped":0}]}],"before_hash":"2968dfe5b23d109a23af7554bfc490bf9d0ecfe4b6da5177a0e2365e2d02d275","after_hash":"4663095d824032b00735081cb51e300650fda64f8c9651df969f78183b16db77","message":"Track test run summary (test-local-ms9mfsi3-oh4vvc)"} +{"ts":"2026-08-01T00:37:53.207Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"comment_add","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T00:37:53.207Z"},{"op":"add","path":"/metadata/comments","value":[{"created_at":"2026-08-01T00:37:53.206Z","author":"harness:codex","text":"Delivery evidence 2026-08-01: continuation pages now replace invariant filtering, sorting, projection, completeness, row, omission, pagination-summary, timestamp, and full intent-receipt blocks with a cursor-fingerprint reference while retaining only rows and the next cursor. List page size is budget-derived and the live tracker delivers 20 rows at 1703/3200 tokens; cursor integrity tests traverse list/search/context without duplicates. Remaining acceptance before closure: add a mandatory full-walk cost gate on a generated current-scale corpus, its repeated-metadata negative control, and publish the before/after whole-chain table."}]}],"before_hash":"4663095d824032b00735081cb51e300650fda64f8c9651df969f78183b16db77","after_hash":"2c79b9704ebf83e18a195a1bf47ed8e1d8883574d29d0999cd4b6fc3fe1bfa0d"} +{"ts":"2026-08-01T00:37:57.298Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"update","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T00:37:57.298Z"},{"op":"replace","path":"/metadata/status","value":"open"}],"before_hash":"2c79b9704ebf83e18a195a1bf47ed8e1d8883574d29d0999cd4b6fc3fe1bfa0d","after_hash":"eaaf43bac226d59b575ec8c19d930489528926dfc9295b16a5a2d69ebacb7c76","message":"Pause after continuation compaction and budget-derived paging; current-scale full-walk gate acceptance remains"} +{"ts":"2026-08-01T00:37:58.027Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"release","patch":[{"op":"remove","path":"/metadata/claim_principal"},{"op":"remove","path":"/metadata/assignee"},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T00:37:58.027Z"}],"before_hash":"eaaf43bac226d59b575ec8c19d930489528926dfc9295b16a5a2d69ebacb7c76","after_hash":"817f1e586928d0823c5f00f8f97bb4b7fa09b9ce83e9fd99acd08425e6e8bbfb"} +{"ts":"2026-08-01T01:34:20.523Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"comment_add","patch":[{"op":"add","path":"/metadata/comments/1","value":{"created_at":"2026-08-01T01:34:20.523Z","author":"harness:codex","text":"PR #849 review reconciliation: CodeRabbit asked that the full-walk gate, repeated-metadata negative control, and before/after chain table be linked before closure. The item is intentionally still open, its existing delivery comment explicitly names those three remaining artifacts, and it has not been claimed or closed in this review pass. No unsupported artifact links were fabricated."}},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T01:34:20.523Z"}],"before_hash":"817f1e586928d0823c5f00f8f97bb4b7fa09b9ce83e9fd99acd08425e6e8bbfb","after_hash":"324d18e349b8575b82b775fae2be8e9f051f892b73e22d6148d1d0b34c672ea4"} +{"ts":"2026-08-01T01:36:33.023Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"claim","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T01:36:33.023Z"},{"op":"add","path":"/metadata/assignee","value":"harness:codex"},{"op":"add","path":"/metadata/claim_principal","value":"harness:codex#264406b88560fcdcbb17052e"}],"before_hash":"324d18e349b8575b82b775fae2be8e9f051f892b73e22d6148d1d0b34c672ea4","after_hash":"c94a0b60d64a564ea404de0f95e80aafd2f054563689b83f0d89a9b249073b30"} +{"ts":"2026-08-01T01:36:33.825Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"update","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T01:36:33.825Z"},{"op":"replace","path":"/metadata/status","value":"in_progress"}],"before_hash":"c94a0b60d64a564ea404de0f95e80aafd2f054563689b83f0d89a9b249073b30","after_hash":"a9931e4ec1cbda4d2ca0331bf3dd13038237512bb179b8e2255d9a31f615e925","message":"Actively correcting post-projection row compaction so paginated read families never drop unrecoverable rows."} +{"ts":"2026-08-01T01:45:28.919Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"comment_add","patch":[{"op":"add","path":"/metadata/comments/2","value":{"created_at":"2026-08-01T01:45:28.919Z","author":"harness:codex","text":"Review-fix evidence: post-projection row reduction is now restricted to next:execute, whose contract has a scalar primary recommendation; list/get/search/context instead fall back to receipt-only output rather than silently dropping paginated or otherwise retrievable rows. Added a no-cursor list regression and a 2,000-row serialization-efficiency regression. Focused review tests and the complete sandboxed coverage suite pass at 6637/6637 with 100% statements, branches, functions, and lines. Remaining full-walk current-scale cost-gate and before/after chain artifacts stay open and are not claimed as delivered."}},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T01:45:28.919Z"}],"before_hash":"a9931e4ec1cbda4d2ca0331bf3dd13038237512bb179b8e2255d9a31f615e925","after_hash":"bec993661ef6b0a34a1cf67fcb02f5d1c2dfbb665703cc879548b92af9b3cffc"} +{"ts":"2026-08-01T01:45:31.079Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"update","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T01:45:31.079Z"},{"op":"replace","path":"/metadata/status","value":"open"}],"before_hash":"bec993661ef6b0a34a1cf67fcb02f5d1c2dfbb665703cc879548b92af9b3cffc","after_hash":"37cb0e33cfefec7c5312f3858d31dc299f688b208b75683e4d8242c0f48e126c","message":"Review corrections implemented and evidenced; returning the uncompleted full-walk cost and chain acceptance to open."} +{"ts":"2026-08-01T01:45:31.812Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"release","patch":[{"op":"remove","path":"/metadata/claim_principal"},{"op":"remove","path":"/metadata/assignee"},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T01:45:31.812Z"}],"before_hash":"37cb0e33cfefec7c5312f3858d31dc299f688b208b75683e4d8242c0f48e126c","after_hash":"6ac8439dbfb2a9aab01223c8a691230bd3d545480c50c9844efe1748f5bf7bf5"} +{"ts":"2026-08-01T02:14:25.787Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"claim","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T02:14:25.787Z"},{"op":"add","path":"/metadata/assignee","value":"harness:codex"},{"op":"add","path":"/metadata/claim_principal","value":"harness:codex#264406b88560fcdcbb17052e"}],"before_hash":"6ac8439dbfb2a9aab01223c8a691230bd3d545480c50c9844efe1748f5bf7bf5","after_hash":"587003f6e9ab6d24cd1474b739e8ff0df8916ae6928081f485ca21fa3c58e8f4"} +{"ts":"2026-08-01T02:14:26.587Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"update","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T02:14:26.587Z"},{"op":"replace","path":"/metadata/status","value":"in_progress"}],"before_hash":"587003f6e9ab6d24cd1474b739e8ff0df8916ae6928081f485ca21fa3c58e8f4","after_hash":"a39f9e48c9483ff9b2dc048da1dd001758ec1966dc257f257100c32cf012c00c","message":"Remove non-discriminating compaction assertions identified in exact-head review."} +{"ts":"2026-08-01T02:15:21.645Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"comment_add","patch":[{"op":"add","path":"/metadata/comments/3","value":{"created_at":"2026-08-01T02:15:21.645Z","author":"harness:codex","text":"Exact-head CodeRabbit cleanup: removed two non-discriminating absence assertions from the row-compaction regression; the test now asserts only compaction behavior driven by its fixture. Focused context/MCP regressions and ESLint pass. Remaining full-walk acceptance remains open."}},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T02:15:21.645Z"}],"before_hash":"a39f9e48c9483ff9b2dc048da1dd001758ec1966dc257f257100c32cf012c00c","after_hash":"ef9d361a178ec7b9b58f1d01f368c54f4ef6f06be7dd476e390587392221bb17"} +{"ts":"2026-08-01T02:15:24.601Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"comment_add","patch":[{"op":"add","path":"/metadata/comments/4","value":{"created_at":"2026-08-01T02:15:24.601Z","author":"harness:codex","text":"Exact-head CodeRabbit cleanup: removed two non-discriminating absence assertions from the row-compaction regression; the test now asserts only compaction behavior driven by its fixture. Focused context/MCP regressions pass 18/18. Remaining full-walk acceptance remains open."}},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T02:15:24.601Z"}],"before_hash":"ef9d361a178ec7b9b58f1d01f368c54f4ef6f06be7dd476e390587392221bb17","after_hash":"1f0538307865f742ef1421e7d291dd74eb95859d016ee82618444e8a1daacc12"} +{"ts":"2026-08-01T02:15:29.671Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"update","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T02:15:29.671Z"},{"op":"replace","path":"/metadata/status","value":"open"}],"before_hash":"1f0538307865f742ef1421e7d291dd74eb95859d016ee82618444e8a1daacc12","after_hash":"80f6512d84574b5394330bc571ed6b1c4f262b151b8deb172e55b1ba33b3673d","message":"Review-test cleanup complete; remaining full-walk acceptance stays open."} +{"ts":"2026-08-01T02:15:30.407Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"release","patch":[{"op":"remove","path":"/metadata/claim_principal"},{"op":"remove","path":"/metadata/assignee"},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T02:15:30.407Z"}],"before_hash":"80f6512d84574b5394330bc571ed6b1c4f262b151b8deb172e55b1ba33b3673d","after_hash":"319a93b272acdcc211905cf0b7ad5b61bedd49f11cb4af08f0ddc9d9e21098ee"} diff --git a/.agents/pm/history/pm-wv47pf.jsonl b/.agents/pm/history/pm-wv47pf.jsonl index e8ad3032f..8f0e4eab5 100644 --- a/.agents/pm/history/pm-wv47pf.jsonl +++ b/.agents/pm/history/pm-wv47pf.jsonl @@ -1,3 +1,8 @@ {"ts":"2026-07-30T17:02:34.169Z","author":"harness:claude-code","author_source":"detected","agent_harness":"claude-code","agent_instance":"6682b76673432e27b62e2ad8","agent_provenance":{"model":null,"effort":{"value":"xhigh","source":"environment"}},"op":"create","patch":[{"op":"add","path":"/metadata/id","value":"pm-wv47pf"},{"op":"add","path":"/metadata/title","value":"A read whose result was omitted for budget still records those items as served and included, so the usage-affinity signal learns from context the agent never received"},{"op":"add","path":"/metadata/description","value":"The usage-affinity signal treats a recorded serve as evidence that an item was placed in front of an agent, and that evidence feeds relevance scoring. Enforcement of intent budgets can now delete the whole payload at egress, and the ledger write happens independently of that decision, so the two disagree. Measured at HEAD with controls run back to back. pm next --for execute emitted zero rows to the caller because its budget is infeasible, and the ledger recorded 200 candidate rows with 35 of them marked included true. The control pm next emitted six rows and recorded 200 candidates with 21 marked included true. pm context --for orient emitted zero and recorded 315 rows with 77 included, against 53 included on the served control. The omitted response therefore recorded more inclusions than the response that actually served content, and nothing in the entry distinguishes the two cases. Three consequences follow. The affinity signal is trained on serves that never happened, which is a silent data-quality fault in the input to relevance scoring rather than a visible failure. The served-then-acted-on outcome that the feedback signal is built around becomes unmeasurable, because a non-action after a phantom serve is indistinguishable from a non-action after a real one. And the fault appears precisely when the agent got nothing, so the corpus of phantom serves grows fastest for exactly the intents that are most broken. This is the correctness of the recorded signal. The cost and scaling of the same ledger are tracked separately."},{"op":"add","path":"/metadata/type","value":"Issue"},{"op":"add","path":"/metadata/status","value":"open"},{"op":"add","path":"/metadata/priority","value":2},{"op":"add","path":"/metadata/tags","value":["context-management","data-quality"]},{"op":"add","path":"/metadata/created_at","value":"2026-07-30T17:02:34.169Z"},{"op":"add","path":"/metadata/updated_at","value":"2026-07-30T17:02:34.169Z"},{"op":"add","path":"/metadata/author","value":"harness:claude-code"},{"op":"add","path":"/metadata/estimated_minutes","value":180},{"op":"add","path":"/metadata/acceptance_criteria","value":"A response that omits its result records no serve, or records one whose rows are all marked not included and whose entry states that the response was omitted; The ledger entry carries the egress decision, so a consumer can separate a delivered assembly from a suppressed one without re-deriving the budget; Inclusion is recorded from what the response actually emitted rather than from the packing decision that preceded enforcement, proved by a test that asserts recorded inclusions equal emitted rows for both a served and an omitted response; Any existing phantom serves are either identifiable by a recorded marker or the affinity reader documents that entries written before the fix cannot be trusted for inclusion; A negative control proves the assertion fails when inclusion is taken from the pre-enforcement packing set"},{"op":"add","path":"/metadata/parent","value":"pm-4k6b"},{"op":"add","path":"/metadata/risk","value":"medium"},{"op":"add","path":"/metadata/confidence","value":"high"}],"before_hash":"3cc22dff72be7b14824654a7a64ea62b04799939b2fee54c1b5f52ca60bf6df0","after_hash":"657548f9c06dda7b365552879a5408cf5b2a7501eb8e0803124a26bcbd394985","message":""} {"ts":"2026-07-30T17:03:16.220Z","author":"harness:claude-code","author_source":"detected","agent_harness":"claude-code","agent_instance":"6682b76673432e27b62e2ad8","agent_provenance":{"model":null,"effort":{"value":"xhigh","source":"environment"}},"op":"update","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-07-30T17:03:16.220Z"},{"op":"add","path":"/metadata/dependencies","value":[{"id":"pm-o87av6","kind":"implements","created_at":"2026-07-30T17:03:16.021Z","author":"harness:claude-code","source_kind":"cli:update:dep","author_source":"detected"},{"id":"pm-rtn5h6","kind":"related","created_at":"2026-07-30T17:03:16.021Z","author":"harness:claude-code","source_kind":"cli:update:dep","author_source":"detected"},{"id":"pm-uwfs","kind":"discovered_from","created_at":"2026-07-30T17:03:16.021Z","author":"harness:claude-code","source_kind":"cli:update:dep","author_source":"detected"}]}],"before_hash":"657548f9c06dda7b365552879a5408cf5b2a7501eb8e0803124a26bcbd394985","after_hash":"15662b5e1967e051268d28949cbaab99629e9b44ec9e78b9b05ad19ff990e985","message":"Wire phantom-serve issue to proven scale, to the closed feedback-signal feature, and to the defect-escape ratchet that should have caught it"} {"ts":"2026-07-30T17:18:11.301Z","author":"harness:claude-code","author_source":"detected","agent_harness":"claude-code","agent_instance":"6682b76673432e27b62e2ad8","agent_provenance":{"model":null,"effort":{"value":"xhigh","source":"environment"}},"op":"update","patch":[{"op":"add","path":"/metadata/dependencies/3","value":{"id":"pm-bab3gb","kind":"related","created_at":"2026-07-30T17:18:11.070Z","author":"harness:claude-code","source_kind":"cli:update:dep","author_source":"detected"}},{"op":"replace","path":"/metadata/updated_at","value":"2026-07-30T17:18:11.301Z"}],"before_hash":"15662b5e1967e051268d28949cbaab99629e9b44ec9e78b9b05ad19ff990e985","after_hash":"3e0b1dc618e99dcb590cd505c499141ac098aecf03000aaa7974c1da3102dac0","message":"Class siblings on the same usage ledger, one owning what is recorded and the other owning what the recording costs"} +{"ts":"2026-07-31T23:03:53.324Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"claim","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:03:53.324Z"},{"op":"add","path":"/metadata/assignee","value":"harness:codex"},{"op":"add","path":"/metadata/claim_principal","value":"harness:codex#264406b88560fcdcbb17052e"}],"before_hash":"3e0b1dc618e99dcb590cd505c499141ac098aecf03000aaa7974c1da3102dac0","after_hash":"66434755888030f309c46d60332b5cb4f314bd20c0ac5b9aba7d31252629d60c"} +{"ts":"2026-07-31T23:03:54.150Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"update","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:03:54.150Z"},{"op":"replace","path":"/metadata/status","value":"in_progress"}],"before_hash":"66434755888030f309c46d60332b5cb4f314bd20c0ac5b9aba7d31252629d60c","after_hash":"618bfef4e17392ad830e77bae90f43b0256f88447349e02bb25912642e9dbcbb","message":"Start cohesive SDK/CLI context-output tranche: bounded cursor-chain metadata, reachable intent budgets, truthful delivery ledger, and lean MCP mutation parity."} +{"ts":"2026-07-31T23:07:57.955Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"comment_add","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:07:57.955Z"},{"op":"add","path":"/metadata/comments","value":[{"created_at":"2026-07-31T23:07:57.955Z","author":"harness:codex","text":"Scope disposition 2026-08-01: this tranche is implementing the upstream budget reachability, cursor-chain amortization, and egress receipt semantics first. The usage-ledger correction requires the SDK-owned context/next extraction still open on pm-z5pmf8 so it can consume the exact post-egress delivered rows without adding a second projection pass inside CLI commands. Leaving this distinct data-quality item open and unclaimed; no source edit is being made for it in this PR."}]}],"before_hash":"618bfef4e17392ad830e77bae90f43b0256f88447349e02bb25912642e9dbcbb","after_hash":"2a67c737f9b8255f6d8043f1c3dfff582bda0f4e9a056e02e3060f763730fbcb"} +{"ts":"2026-07-31T23:07:58.770Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"update","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:07:58.770Z"},{"op":"replace","path":"/metadata/status","value":"open"}],"before_hash":"2a67c737f9b8255f6d8043f1c3dfff582bda0f4e9a056e02e3060f763730fbcb","after_hash":"ec327975b0d0ee1160d4ccc30746d032680f11df42e405e18521ec8d2d77166e","message":"Not actively edited in this tranche; preserve for post-egress ledger integration."} +{"ts":"2026-07-31T23:07:59.633Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"release","patch":[{"op":"remove","path":"/metadata/claim_principal"},{"op":"remove","path":"/metadata/assignee"},{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:07:59.633Z"}],"before_hash":"ec327975b0d0ee1160d4ccc30746d032680f11df42e405e18521ec8d2d77166e","after_hash":"9f2343dbbcbcfa98e61b180dffa96222a62fb933cd44a6dec6f00e59ad8e8b63"} diff --git a/.agents/pm/history/pm-yekkvt.jsonl b/.agents/pm/history/pm-yekkvt.jsonl index dc15739dc..f53122825 100644 --- a/.agents/pm/history/pm-yekkvt.jsonl +++ b/.agents/pm/history/pm-yekkvt.jsonl @@ -3,3 +3,37 @@ {"ts":"2026-07-30T17:18:10.348Z","author":"harness:claude-code","author_source":"detected","agent_harness":"claude-code","agent_instance":"6682b76673432e27b62e2ad8","agent_provenance":{"model":null,"effort":{"value":"xhigh","source":"environment"}},"op":"update","patch":[{"op":"add","path":"/metadata/dependencies/2","value":{"id":"pm-sf31yl","kind":"blocked_by","created_at":"2026-07-30T17:18:10.164Z","author":"harness:claude-code","source_kind":"cli:update:dep","author_source":"detected"}},{"op":"replace","path":"/metadata/updated_at","value":"2026-07-30T17:18:10.348Z"}],"before_hash":"225d8e188a3507bac8ed159426fbcc0cb7565fa949453bb2bbdb12547d74c033","after_hash":"624fe1c88d40ca2434ebb6edc9383a828ce27116be9d3e498f0d0f339c46143c","message":"Calibrating a reachable ceiling depends on the final envelope cost, so per-page amortisation lands first or the calibration is done twice against two different envelopes"} {"ts":"2026-07-30T17:21:51.508Z","author":"harness:claude-code","author_source":"detected","agent_harness":"claude-code","agent_instance":"6682b76673432e27b62e2ad8","agent_provenance":{"model":null,"effort":{"value":"xhigh","source":"environment"}},"op":"learning_add","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-07-30T17:21:51.508Z"},{"op":"add","path":"/metadata/learnings","value":[{"created_at":"2026-07-30T17:21:51.507Z","author":"harness:claude-code","text":"Method that found this, reusable for any declared bound: run the identical invocation against a two-item workspace and against the real tracker, and diff the verdicts rather than the outputs. A bound that is satisfied on the small corpus and violated on the large one is a scalar that should have been a function, and the small corpus is the one the number was authored against. A bound violated on both is an ordinary miscalibration. A bound satisfied on both is genuinely scale-invariant and can be left alone.\n\nSecond technique, for the same class: a floor is invisible from the default. Raising the ceiling in steps until content first appears is the only way to measure the smallest form a command can emit, because at the default the response contains no rows to measure. next execute yielded nothing at 1200 and 2000 and content at 4000, which located the floor between 2000 and 4000 and then exactly at 1438 from the receipt. Doing this in the other direction, lowering a working ceiling until output disappears, gives the same number and is cheaper when the default already works."}]}],"before_hash":"624fe1c88d40ca2434ebb6edc9383a828ce27116be9d3e498f0d0f339c46143c","after_hash":"6edacc5b531f6c95a6fa4cab70e12ed2bdf440a4ad84d7ba12dba4ae3f52d78b"} {"ts":"2026-07-31T06:14:40.384Z","author":"harness:claude-code","author_source":"detected","agent_harness":"claude-code","agent_instance":"bbccd5ce4f6ac18346c324e7","agent_provenance":{"model":null,"effort":{"value":"xhigh","source":"environment"}},"op":"comment_add","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T06:14:40.384Z"},{"op":"add","path":"/metadata/comments","value":[{"created_at":"2026-07-31T06:14:40.384Z","author":"harness:claude-code","text":"Still live at HEAD 2026.7.31, verified 2026-07-31. `pm next --for execute` emits budget_exceeded.omitted_result: true alongside within_budget: true in one envelope, with token_budget 1200 and estimated_tokens 79 — the receipt reports the omitted-result payload as within budget, so the two keys in the same envelope assert opposite things. The recovery instruction \"Repeat the original command without --for\" costs 9,259 bytes against the 320-byte refusal."}]}],"before_hash":"6edacc5b531f6c95a6fa4cab70e12ed2bdf440a4ad84d7ba12dba4ae3f52d78b","after_hash":"493357eadd8626f28d8b902626550c931b2e149f9c3a69fd9e9cf140f8953f6c"} +{"ts":"2026-07-31T23:03:49.745Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"claim","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:03:49.745Z"},{"op":"add","path":"/metadata/assignee","value":"harness:codex"},{"op":"add","path":"/metadata/claim_principal","value":"harness:codex#264406b88560fcdcbb17052e"}],"before_hash":"493357eadd8626f28d8b902626550c931b2e149f9c3a69fd9e9cf140f8953f6c","after_hash":"46ed7ae8046baeab885106503156bdb87d8de7ab1a8328f675091fdd53febaa4"} +{"ts":"2026-07-31T23:03:50.633Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"update","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:03:50.633Z"},{"op":"replace","path":"/metadata/status","value":"in_progress"}],"before_hash":"46ed7ae8046baeab885106503156bdb87d8de7ab1a8328f675091fdd53febaa4","after_hash":"12cca58aa4ea93c7de316ac9e29870937e49a9890618d7fea72d37d85bc39a78","message":"Start cohesive SDK/CLI context-output tranche: bounded cursor-chain metadata, reachable intent budgets, truthful delivery ledger, and lean MCP mutation parity."} +{"ts":"2026-07-31T23:32:45.141Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"files_add","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:32:45.141Z"},{"op":"add","path":"/metadata/files","value":[{"path":"src/sdk/context-intent-contracts.ts","scope":"project","note":"Feasible intent projection and truthful receipt implementation"}]}],"before_hash":"12cca58aa4ea93c7de316ac9e29870937e49a9890618d7fea72d37d85bc39a78","after_hash":"a2c1c72dbdd71412e4e663aa595fdb634cf4d45a621ab888f3bbe664922cd049","message":"Link implementation evidence for broad context-contract delivery"} +{"ts":"2026-07-31T23:32:46.377Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"files_add","patch":[{"op":"add","path":"/metadata/files/1","value":{"path":"tests/unit/sdk/context-intent-contracts.spec.ts","scope":"project","note":"Feasible intent projection and truthful receipt implementation"}},{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:32:46.377Z"}],"before_hash":"a2c1c72dbdd71412e4e663aa595fdb634cf4d45a621ab888f3bbe664922cd049","after_hash":"4590e24309e54a4decf6e65aa7bf371f4e33421585a18946db51b79e612a692c","message":"Link implementation evidence for broad context-contract delivery"} +{"ts":"2026-07-31T23:32:47.294Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"files_add","patch":[{"op":"replace","path":"/metadata/files/1/path","value":"tests/unit/cli/context-intent-registration.spec.ts"},{"op":"add","path":"/metadata/files/2","value":{"path":"tests/unit/sdk/context-intent-contracts.spec.ts","scope":"project","note":"Feasible intent projection and truthful receipt implementation"}},{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:32:47.294Z"}],"before_hash":"4590e24309e54a4decf6e65aa7bf371f4e33421585a18946db51b79e612a692c","after_hash":"549ca69e94251a1c536b2c05b0d911f53c8ee8042485d4ced19141fb5c08a0d2","message":"Link implementation evidence for broad context-contract delivery"} +{"ts":"2026-07-31T23:32:48.152Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"files_add","patch":[{"op":"replace","path":"/metadata/files/2/path","value":"tests/unit/cli/context-intent-registration.spec.ts"},{"op":"replace","path":"/metadata/files/1/path","value":"src/sdk/context-intent-contracts.ts"},{"op":"replace","path":"/metadata/files/0/path","value":"scripts/release/token-budget-gate.mjs"},{"op":"add","path":"/metadata/files/3","value":{"path":"tests/unit/sdk/context-intent-contracts.spec.ts","scope":"project","note":"Feasible intent projection and truthful receipt implementation"}},{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:32:48.152Z"}],"before_hash":"549ca69e94251a1c536b2c05b0d911f53c8ee8042485d4ced19141fb5c08a0d2","after_hash":"e314576c5bb7555843310b75f83c29442d3de868b17b302703f7780fd7ed58d5","message":"Link implementation evidence for broad context-contract delivery"} +{"ts":"2026-07-31T23:32:49.112Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"files_add","patch":[{"op":"replace","path":"/metadata/files/3/path","value":"tests/unit/cli/context-intent-registration.spec.ts"},{"op":"replace","path":"/metadata/files/2/path","value":"src/sdk/context-intent-contracts.ts"},{"op":"replace","path":"/metadata/files/1/path","value":"scripts/release/token-budgets.json"},{"op":"add","path":"/metadata/files/4","value":{"path":"tests/unit/sdk/context-intent-contracts.spec.ts","scope":"project","note":"Feasible intent projection and truthful receipt implementation"}},{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:32:49.112Z"}],"before_hash":"e314576c5bb7555843310b75f83c29442d3de868b17b302703f7780fd7ed58d5","after_hash":"a86b3146497a1b017added4dccc5294c04cf726f06aea63b513fe572ef587d4f","message":"Link implementation evidence for broad context-contract delivery"} +{"ts":"2026-07-31T23:32:50.020Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"docs_add","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:32:50.020Z"},{"op":"add","path":"/metadata/docs","value":[{"path":"docs/OUTPUT_PROJECTION_CONTRACTS.md","scope":"project","note":"Intent degradation and receipt semantics"}]}],"before_hash":"a86b3146497a1b017added4dccc5294c04cf726f06aea63b513fe572ef587d4f","after_hash":"d82a62065c6e0de620b300415d397dd12ab49d0a4a36673effbb607ca5b4d623","message":"Link documentation evidence for broad context-contract delivery"} +{"ts":"2026-07-31T23:32:50.885Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"tests_add","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:32:50.885Z"},{"op":"add","path":"/metadata/tests","value":[{"command":"node scripts/run-tests.mjs test -- tests/unit/sdk/context-intent-contracts.spec.ts tests/unit/cli/context-intent-registration.spec.ts","scope":"project","timeout_seconds":300}]}],"before_hash":"d82a62065c6e0de620b300415d397dd12ab49d0a4a36673effbb607ca5b4d623","after_hash":"b73e6f16eb15b9cdb70fd69fdc39da74de0c82c1bce5858efbdd003685dd8099","message":"Link sandbox-safe verification for broad context-contract delivery"} +{"ts":"2026-07-31T23:32:51.756Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"tests_add","patch":[{"op":"replace","path":"/metadata/tests/0/command","value":"node scripts/release/token-budget-gate.mjs"},{"op":"add","path":"/metadata/tests/1","value":{"command":"node scripts/run-tests.mjs test -- tests/unit/sdk/context-intent-contracts.spec.ts tests/unit/cli/context-intent-registration.spec.ts","scope":"project","timeout_seconds":300}},{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:32:51.756Z"}],"before_hash":"b73e6f16eb15b9cdb70fd69fdc39da74de0c82c1bce5858efbdd003685dd8099","after_hash":"522f7ac00393555e61d88d8f9168356bf2357d9692e793d3eedaab900d5059a4","message":"Link sandbox-safe verification for broad context-contract delivery"} +{"ts":"2026-07-31T23:36:21.982Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"files_add","patch":[{"op":"replace","path":"/metadata/files/4/path","value":"tests/unit/cli/context-intent-registration.spec.ts"},{"op":"replace","path":"/metadata/files/3/path","value":"src/sdk/context-intent-contracts.ts"},{"op":"replace","path":"/metadata/files/2/note","value":"Versioned public receipt contract and breaking acknowledgement"},{"op":"replace","path":"/metadata/files/2/path","value":"sdk/public-surface.json"},{"op":"add","path":"/metadata/files/5","value":{"path":"tests/unit/sdk/context-intent-contracts.spec.ts","scope":"project","note":"Feasible intent projection and truthful receipt implementation"}},{"op":"replace","path":"/metadata/updated_at","value":"2026-07-31T23:36:21.982Z"}],"before_hash":"522f7ac00393555e61d88d8f9168356bf2357d9692e793d3eedaab900d5059a4","after_hash":"e0ef47c3552c7ade29f8d527ba9a89876d4a032ed5a576d806ee957822b16e50","message":"Link SDK surface contract evidence"} +{"ts":"2026-08-01T00:16:29.195Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"test_run_track","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T00:16:29.195Z"},{"op":"add","path":"/metadata/test_runs","value":[{"run_id":"test-local-ms9mfklb-2y4mp4","kind":"test","status":"passed","started_at":"2026-08-01T00:15:58.982Z","finished_at":"2026-08-01T00:16:29.183Z","recorded_at":"2026-08-01T00:16:29.183Z","passed":2,"failed":0,"skipped":0}]}],"before_hash":"e0ef47c3552c7ade29f8d527ba9a89876d4a032ed5a576d806ee957822b16e50","after_hash":"3c9e29cff58e86cd2fdda3c8ff15951b5f4fc716d813b0faff210f1b8d1ea665","message":"Track test run summary (test-local-ms9mfklb-2y4mp4)"} +{"ts":"2026-08-01T00:37:52.411Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"comment_add","patch":[{"op":"add","path":"/metadata/comments/1","value":{"created_at":"2026-08-01T00:37:52.411Z","author":"harness:codex","text":"Delivery evidence 2026-08-01: receipts now distinguish declaration_feasible and result_omitted, omitted results always report within_budget:false, recovery never recommends an unprojected retry, and deterministic string then row compaction retains useful rows before receipt-only fallback. The checked 27-item fixture and all five live 2243-item tracker probes deliver feasible results; an explicit 256-token control proves truthful omission. Remaining acceptance before closure: publish and gate the required two-item versus current-scale calibration table rather than relying on the current small committed fixture plus manual live evidence."}},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T00:37:52.411Z"}],"before_hash":"3c9e29cff58e86cd2fdda3c8ff15951b5f4fc716d813b0faff210f1b8d1ea665","after_hash":"2a2133ea6308f7de43155be6d606b70a63a6760fb0b6404e4601dbf59bc9c340"} +{"ts":"2026-08-01T00:37:55.617Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"update","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T00:37:55.617Z"},{"op":"replace","path":"/metadata/status","value":"open"}],"before_hash":"2a2133ea6308f7de43155be6d606b70a63a6760fb0b6404e4601dbf59bc9c340","after_hash":"2be5ed2d9c6ffdf6652100bfacb2dff9785cbc89b60c6918843b8a87b2623c00","message":"Pause after truthful feasible receipt implementation; dual-scale calibration gate acceptance remains"} +{"ts":"2026-08-01T00:37:56.475Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"release","patch":[{"op":"remove","path":"/metadata/claim_principal"},{"op":"remove","path":"/metadata/assignee"},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T00:37:56.475Z"}],"before_hash":"2be5ed2d9c6ffdf6652100bfacb2dff9785cbc89b60c6918843b8a87b2623c00","after_hash":"bcb46c4de10da369428f437f8a5340c9c4f1d07adcaf9e23d03b54cbe7c67caf"} +{"ts":"2026-08-01T01:20:13.348Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"claim","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T01:20:13.348Z"},{"op":"add","path":"/metadata/assignee","value":"harness:codex"},{"op":"add","path":"/metadata/claim_principal","value":"harness:codex#264406b88560fcdcbb17052e"}],"before_hash":"bcb46c4de10da369428f437f8a5340c9c4f1d07adcaf9e23d03b54cbe7c67caf","after_hash":"fa2f61bc419239529c9e3886f4201ce9e573661b89513d27b7251fab90ecf2c7"} +{"ts":"2026-08-01T01:20:14.144Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"update","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T01:20:14.144Z"},{"op":"replace","path":"/metadata/status","value":"in_progress"}],"before_hash":"fa2f61bc419239529c9e3886f4201ce9e573661b89513d27b7251fab90ecf2c7","after_hash":"05bce4084d3c6dfc571cff815ce998f33428d93702a1ac00db7619c4de1da3db","message":"Addressing verified PR #849 review findings in intent option validation, compaction scalability, and generated token-budget contract wording."} +{"ts":"2026-08-01T01:34:17.175Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"files_add","patch":[{"op":"replace","path":"/metadata/files/5/note","value":"Regenerated token-budget contract descriptions"},{"op":"replace","path":"/metadata/files/5/path","value":"tests/fixtures/contracts/full.json"},{"op":"replace","path":"/metadata/files/4/path","value":"src/sdk/context-intent-contracts.ts"},{"op":"replace","path":"/metadata/files/3/note","value":"Action-correct token-budget schema descriptions"},{"op":"replace","path":"/metadata/files/3/path","value":"src/sdk/cli-contracts/tool-parameter-tables.ts"},{"op":"add","path":"/metadata/files/6","value":{"path":"tests/unit/cli/context-intent-registration.spec.ts","scope":"project","note":"Feasible intent projection and truthful receipt implementation"}},{"op":"add","path":"/metadata/files/7","value":{"path":"tests/unit/sdk/context-intent-contracts.spec.ts","scope":"project","note":"Feasible intent projection and truthful receipt implementation"}},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T01:34:17.175Z"}],"before_hash":"05bce4084d3c6dfc571cff815ce998f33428d93702a1ac00db7619c4de1da3db","after_hash":"663000ac54eaea2cd1f6f70ff4de318b2f975e2f23e5c3b636d1582aa92cd5ce"} +{"ts":"2026-08-01T01:34:18.024Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"tests_add","patch":[{"op":"replace","path":"/metadata/tests/1/timeout_seconds","value":600},{"op":"replace","path":"/metadata/tests/1/command","value":"node scripts/run-tests.mjs coverage"},{"op":"add","path":"/metadata/tests/1/note","value":"Repo-wide 100/100/100/100 review-fix verification"},{"op":"add","path":"/metadata/tests/2","value":{"command":"node scripts/run-tests.mjs test -- tests/unit/sdk/context-intent-contracts.spec.ts tests/unit/cli/context-intent-registration.spec.ts","scope":"project","timeout_seconds":300}},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T01:34:18.024Z"}],"before_hash":"663000ac54eaea2cd1f6f70ff4de318b2f975e2f23e5c3b636d1582aa92cd5ce","after_hash":"f68321f197cba554c284184872e069a3c8b1f20f0ecd8e5b8dfe59dfc50d329a"} +{"ts":"2026-08-01T01:34:18.885Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"comment_add","patch":[{"op":"add","path":"/metadata/comments/2","value":{"created_at":"2026-08-01T01:34:18.884Z","author":"harness:codex","text":"PR #849 review evidence: list/get/search now reject tokenBudget without a selected intent while context/next retain their established standalone budget semantics; 2,000-row compaction uses batch estimation and completed with fewer than 20 JSON serializations; duplicate terminal estimation was removed; generated schemas now use generic wording except the deps-scoped override. Focused regression tests passed 111/111 after narrowing the validation, and the repo-wide suite passed 6636/6636 at exact 100/100/100/100 coverage. Remaining original closure acceptance is unchanged: the current-scale calibration table and mandatory gate are still outstanding, so this item returns to open."}},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T01:34:18.885Z"}],"before_hash":"f68321f197cba554c284184872e069a3c8b1f20f0ecd8e5b8dfe59dfc50d329a","after_hash":"8d84e462e084c7f145178e498125913f556cb7d44d06fef17b0447581191772a"} +{"ts":"2026-08-01T01:34:21.272Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"update","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T01:34:21.272Z"},{"op":"replace","path":"/metadata/status","value":"open"}],"before_hash":"8d84e462e084c7f145178e498125913f556cb7d44d06fef17b0447581191772a","after_hash":"c0f084313ac2234b4fe78ff4218725641adbce8af1b3039cf9c8c69c602a7506","message":"Review fixes delivered and verified; preserve open status for the original current-scale calibration-table and mandatory-gate acceptance work."} +{"ts":"2026-08-01T01:34:22.080Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"release","patch":[{"op":"remove","path":"/metadata/claim_principal"},{"op":"remove","path":"/metadata/assignee"},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T01:34:22.080Z"}],"before_hash":"c0f084313ac2234b4fe78ff4218725641adbce8af1b3039cf9c8c69c602a7506","after_hash":"95641977f01415006f30a6bf0c5067d249b6fec70583642c1c675457da264def"} +{"ts":"2026-08-01T01:36:31.501Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"claim","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T01:36:31.501Z"},{"op":"add","path":"/metadata/assignee","value":"harness:codex"},{"op":"add","path":"/metadata/claim_principal","value":"harness:codex#264406b88560fcdcbb17052e"}],"before_hash":"95641977f01415006f30a6bf0c5067d249b6fec70583642c1c675457da264def","after_hash":"8806e97f6e9c31efcdb81000a30534552750eed99c3e4cd770a956161d440609"} +{"ts":"2026-08-01T01:36:32.311Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"update","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T01:36:32.311Z"},{"op":"replace","path":"/metadata/status","value":"in_progress"}],"before_hash":"8806e97f6e9c31efcdb81000a30534552750eed99c3e4cd770a956161d440609","after_hash":"5d6b7849c6184e1e9c3be58d7e442a2dba77f1aad63e902b0710f8dbe9e1e725","message":"Continuing verified Cubic review fixes for delivered-byte budget proof, token_budget alias normalization, and truthful discover metadata."} +{"ts":"2026-08-01T01:45:28.140Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"comment_add","patch":[{"op":"add","path":"/metadata/comments/3","value":{"created_at":"2026-08-01T01:45:28.140Z","author":"harness:codex","text":"Review-fix evidence: exact token budgets now normalize token_budget to tokenBudget, reject ambiguous get/list/search usage without --for while preserving context/next standalone behavior, and use truthful budget-derived search guidance. The release gate independently measures serialized stdout, requires finite numeric receipt fields, and rejects actual output above the declared receipt budget. Focused review tests and the complete sandboxed coverage suite pass; latest full result is 6637/6637 tests with 100% statements, branches, functions, and lines. Remaining current-scale calibration-table acceptance stays open and is not claimed as delivered."}},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T01:45:28.140Z"}],"before_hash":"5d6b7849c6184e1e9c3be58d7e442a2dba77f1aad63e902b0710f8dbe9e1e725","after_hash":"d48ff3953082ab994b095fe76a336c0127849142c12a0688b34c3aca9927c2e9"} +{"ts":"2026-08-01T01:45:29.641Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"update","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T01:45:29.641Z"},{"op":"replace","path":"/metadata/status","value":"open"}],"before_hash":"d48ff3953082ab994b095fe76a336c0127849142c12a0688b34c3aca9927c2e9","after_hash":"936c9854f4b3e7e32ffd639aade8341eb9a197bf22bff01d64157d7c0fd676e3","message":"Review corrections implemented and evidenced; returning the uncompleted current-scale calibration acceptance to open."} +{"ts":"2026-08-01T01:45:30.324Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"release","patch":[{"op":"remove","path":"/metadata/claim_principal"},{"op":"remove","path":"/metadata/assignee"},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T01:45:30.324Z"}],"before_hash":"936c9854f4b3e7e32ffd639aade8341eb9a197bf22bff01d64157d7c0fd676e3","after_hash":"8c79e6ec1b5c695aa4a8dd6d1030bd0ce6f48b0850ae8f9027b5a5910f8c1970"} +{"ts":"2026-08-01T01:56:15.853Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"comment_add","patch":[{"op":"add","path":"/metadata/comments/4","value":{"created_at":"2026-08-01T01:56:15.853Z","author":"harness:codex","text":"Exact local release-gate evidence before the review-fix push: static quality and 100% docstring gates passed; package boundary, SDK contract parity, 28-surface token budget, gate registry, SDK surface, benchmarks, context/retrieval evaluations, and the 96-surface agent-token gate passed; 410 files and 6637 tests passed at exact 100/100/100/100 coverage; secret scan, packed npx smoke, and the 88-command isolated package-first dogfood run passed. The only terminal release:gates failure was the hosted Greptile adapter reporting free_reviews_limit_reached after all local gates completed; this is external review capacity, not a product/test failure."}},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T01:56:15.853Z"}],"before_hash":"8c79e6ec1b5c695aa4a8dd6d1030bd0ce6f48b0850ae8f9027b5a5910f8c1970","after_hash":"db94043beb27770e9dafff693b567a796ab3de82a6619e9c2a6e6e53ce8a847b"} +{"ts":"2026-08-01T02:03:22.765Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"claim","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T02:03:22.765Z"},{"op":"add","path":"/metadata/assignee","value":"harness:codex"},{"op":"add","path":"/metadata/claim_principal","value":"harness:codex#264406b88560fcdcbb17052e"}],"before_hash":"db94043beb27770e9dafff693b567a796ab3de82a6619e9c2a6e6e53ce8a847b","after_hash":"e9bb7ec8d88b4fcc54d23d9fe76952c40e39c8eec5d8867642935c7bf5b33eac"} +{"ts":"2026-08-01T02:03:23.563Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"update","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T02:03:23.563Z"},{"op":"replace","path":"/metadata/status","value":"in_progress"}],"before_hash":"e9bb7ec8d88b4fcc54d23d9fe76952c40e39c8eec5d8867642935c7bf5b33eac","after_hash":"f415ef03f99b474e91277b7d3214bf004e1076005779e7fb68004f91a226f2c1","message":"Fix exact-head CI generated error-code catalog drift."} +{"ts":"2026-08-01T02:03:36.755Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"files_add","patch":[{"op":"replace","path":"/metadata/files/7/path","value":"tests/unit/cli/context-intent-registration.spec.ts"},{"op":"replace","path":"/metadata/files/6/note","value":"Regenerated token-budget contract descriptions"},{"op":"replace","path":"/metadata/files/6/path","value":"tests/fixtures/contracts/full.json"},{"op":"replace","path":"/metadata/files/5/note","value":"Generated structured usage-error source inventory"},{"op":"replace","path":"/metadata/files/5/path","value":"src/sdk/generated-error-code-catalog.ts"},{"op":"add","path":"/metadata/files/8","value":{"path":"tests/unit/sdk/context-intent-contracts.spec.ts","scope":"project","note":"Feasible intent projection and truthful receipt implementation"}},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T02:03:36.755Z"}],"before_hash":"f415ef03f99b474e91277b7d3214bf004e1076005779e7fb68004f91a226f2c1","after_hash":"68d7c82d762929777baed805cc2db64e2e17cbce3acb917141f983c15181e38c"} +{"ts":"2026-08-01T02:04:45.101Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"comment_add","patch":[{"op":"add","path":"/metadata/comments/5","value":{"created_at":"2026-08-01T02:04:45.101Z","author":"harness:codex","text":"Exact-head CI static correction: the structured missing_required_option path added in sdk/context-intent-contracts.ts is now present in the generated error-code catalog and full contracts fixture. pnpm contracts:check, security:scan, lint, and the focused generator/context tests pass. This fixes the only Actions failure on 6b0e063d5; the original current-scale calibration acceptance remains open."}},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T02:04:45.101Z"}],"before_hash":"68d7c82d762929777baed805cc2db64e2e17cbce3acb917141f983c15181e38c","after_hash":"aa201e8a904eb123a593910baeefd8c1db824a190aa82d677dc4c548a50875c8"} +{"ts":"2026-08-01T02:04:45.962Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"update","patch":[{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T02:04:45.962Z"},{"op":"replace","path":"/metadata/status","value":"open"}],"before_hash":"aa201e8a904eb123a593910baeefd8c1db824a190aa82d677dc4c548a50875c8","after_hash":"71eafb261b9a79cc5804f492f4fc58de472c3a5b168ac8ee9da77a9c0e0dd7c8","message":"Generated contract drift fixed; returning remaining calibration acceptance to open."} +{"ts":"2026-08-01T02:04:46.790Z","author":"harness:codex","author_source":"detected","agent_harness":"codex","agent_instance":"264406b88560fcdcbb17052e","agent_provenance":{"model":null,"effort":null,"role":null},"op":"release","patch":[{"op":"remove","path":"/metadata/claim_principal"},{"op":"remove","path":"/metadata/assignee"},{"op":"replace","path":"/metadata/updated_at","value":"2026-08-01T02:04:46.790Z"}],"before_hash":"71eafb261b9a79cc5804f492f4fc58de472c3a5b168ac8ee9da77a9c0e0dd7c8","after_hash":"0ec43c637ef8c7efa5a196aa59046ae4a1983b7db7f7c31c53d7a0afc2261ee5"} diff --git a/.agents/pm/issues/pm-7hbfch.toon b/.agents/pm/issues/pm-7hbfch.toon index 45a2ecc48..31a61ab4b 100644 --- a/.agents/pm/issues/pm-7hbfch.toon +++ b/.agents/pm/issues/pm-7hbfch.toon @@ -6,7 +6,7 @@ status: open priority: 1 tags[6]: agent-ux,"area:cli","area:contracts","area:sdk",conformance-gap,token-efficiency created_at: "2026-07-30T09:12:36.920Z" -updated_at: "2026-07-30T17:13:52.692Z" +updated_at: "2026-08-01T00:37:54.818Z" author: "harness:claude-code" estimated_minutes: 480 acceptance_criteria: "Every declared intent budget is enforced at one response egress point rather than by a per-command flag, so no intent can overrun its own declaration; list, get and search either declare --token-budget or the intent layer refuses to claim a budget it cannot apply, with no silent third option; the response envelope of every intent-projected read carries the resolved budget, the measured estimate and the degradation actually applied, so a consumer can detect an overrun without measuring bytes itself; a negative-control test asserts that an intent whose command lacks budget enforcement fails the build rather than shipping; the published evidence table records observed versus declared tokens per intent on a corpus of at least the current tracker size" @@ -29,18 +29,33 @@ dependencies[7]{id,kind,created_at,author,source_kind,author_source}: pm-sb0tns,related,"2026-07-30T09:13:11.911Z","harness:claude-code","cli:update:dep",detected pm-o87av6,implements,"2026-07-30T09:28:37.564Z","harness:claude-code","cli:update:dep",detected pm-yekkvt,blocked_by,"2026-07-30T17:03:17.017Z","harness:claude-code","cli:update:dep",detected -comments[5]{created_at,author,text}: +comments[6]{created_at,author,text}: "2026-07-30T10:27:23.385Z","harness:codex","Implementation evidence: every built-in intent now emits resolved budget, measured tokens, within-budget verdict, and degradation; oversized context/next results compact deterministically and all six live tracker probes remained within ceiling." "2026-07-30T11:24:13.871Z","harness:codex","Delivery boundary: enforced intent receipts and deterministic degradation are implemented and exact 100% coverage plus token-budget gates pass. The canonical issue remains open until the current-tracker per-intent observed-versus-declared evidence table is published and its negative control is explicitly tied to the release gate." "2026-07-30T11:30:54.844Z","harness:codex","PR evidence: https://github.com/unbraind/pm-cli/pull/829 reviews cohesive SDK context budgets, universal row contracts, bounded graph/health diagnostics, quality ratchets, and exact-head commit e53544cd1." "2026-07-30T11:54:22.385Z","harness:codex","Review correction: intent receipts now honor the effective explicit tokenBudget override, and over-budget row sets fall back to a receipt-only envelope instead of dropping rows while retaining stale counts or cursors." "2026-07-30T17:13:52.692Z","harness:claude-code","Conformance re-measure 2026-07-30 (evening), at HEAD after the context-budget bundle merged at 14:33Z. Enforcement shipped and works. The three intents this item measured as 43.8x, 19.7x and 2.45x over their declared budgets are now inside them: list triage 1,045 of 1,800 tokens in 6,250 bytes, get inspect 1,208 of 3,200 in 6,565 bytes, search discover 1,300 of 1,800 in 7,219 bytes. The receipt now carries the resolved budget, the measured estimate and the applied degradation, which closes the envelope half of the acceptance criteria.\n\nTwo of this item's own criteria are still open, and one of them is now falsified rather than merely unmet.\n\nThe criterion that list, get and search either declare the budget flag or the intent layer refuses to claim a budget it cannot apply, with no silent third option, is falsified. All three still exit 2 with unknown_option on --token-budget. All three nevertheless claim a budget in the receipt and enforce it at egress. That is precisely the silent third option the criterion forbids: the budget is claimed and applied on a command that offers no way to adjust it. It is reachable today, not latent. pm list --limit 200 --for triage returns budget_receipt_only with zero rows, and pm get --depth deep --for inspect does the same, and neither has any override.\n\nThe criterion that a negative control asserts an intent whose command lacks budget enforcement fails the build is still unmet, and the day showed the control was pointed at the wrong invariant. Enforcement presence was never the fragile part. Reachability of the declared number is, and that is now tracked separately as a blocking dependency on this item, since enforcement cannot honestly be called complete while three of five declared ceilings cannot be met by the commands that declare them.\n\nMethod note for whoever picks this up: measure with the flag on the two commands that accept it. The floor is only visible by raising the ceiling until rows appear. next execute yields nothing at 1200, nothing at 2000, and 1,438 tokens of content at 4000. context orient yields nothing at 2400, nothing at 8000, and 8,417 tokens at 40000." -files[2]{path,scope,note}: + "2026-08-01T00:37:51.706Z","harness:codex","Delivery evidence 2026-08-01: list/get/search now expose --token-budget across CLI, SDK tool options, cursor semantics, contracts, and tool schema 4.3.0. The release gate checks 28 surfaces plus a 256-token infeasible declaration control. Live current-tracker receipts are delivered and within ceiling: context orient 1725/2400 with 11 useful rows; list triage 1703/3200 with 20 rows and a cursor; search discover 1562/1800 with 16 rows; next execute 1109/1200 with 3 ready rows; get inspect 2009/3200. Remaining acceptance before closure: add a generated corpus at least as large as the current tracker to the mandatory gate and a structural negative control that removes enforcement from one declared command." +files[12]{path,scope,note}: + scripts/agent-token-surface-baseline.json,project,Regenerated package-owned token surface baseline after the list/get/search budget option and current command surface additions + scripts/release/token-budget-gate.mjs,project,Intent reachability release gate + scripts/release/token-budgets.json,project,Measured intent corpus baseline + sdk/public-surface.json,project,Tool schema 4.3.0 public surface snapshot + src/cli/register-list-query.ts,project,Cross-surface token-budget flag and schema parity src/sdk/cli-contracts.ts,project,"only next and context declare a --token-budget flag; list,get and search reject it as unknown" + src/sdk/cli-contracts/flag-contracts.ts,project,Cross-surface token-budget flag and schema parity + src/sdk/cli-contracts/tool-option-contracts.ts,project,Cross-surface token-budget flag and schema parity + src/sdk/cli-contracts/tool-schema.ts,project,Cross-surface token-budget flag and schema parity src/sdk/context-intent-contracts.ts,project,applyContextIntentProjection writes the declared token_budget into projected.tokenBudget at line 323 for all five intent commands -tests[2]{command,scope,timeout_seconds}: + tests/fixtures/contracts/full.json,project,Cross-surface token-budget flag and schema parity + tests/unit/cli/context-intent-registration.spec.ts,project,Cross-surface token-budget flag and schema parity +tests[4]{command,scope,timeout_seconds}: + node scripts/release/token-budget-gate.mjs,project,300 node scripts/run-tests.mjs test -- tests/unit/cli/context-intent-registration.spec.ts tests/unit/sdk/context-packing-usage.spec.ts,project,240 + node scripts/run-tests.mjs test -- tests/unit/cli/context-intent-registration.spec.ts tests/unit/sdk/tool-option-contracts.spec.ts,project,300 node scripts/run-tests.mjs test -- tests/unit/sdk/context-intent-contracts.spec.ts,project,240 +test_runs[1]{run_id,kind,status,started_at,finished_at,recorded_at,passed,failed,skipped}: + test-local-ms9mewok-jsmdpi,test,passed,"2026-08-01T00:15:13.819Z","2026-08-01T00:15:58.196Z","2026-08-01T00:15:58.196Z",4,0,0 docs[1]{path,scope,note}: docs/OUTPUT_PROJECTION_CONTRACTS.md,project,Budget enforcement and degradation contract body: "" diff --git a/.agents/pm/issues/pm-awe3t6.toon b/.agents/pm/issues/pm-awe3t6.toon index e297411a7..475640972 100644 --- a/.agents/pm/issues/pm-awe3t6.toon +++ b/.agents/pm/issues/pm-awe3t6.toon @@ -2,19 +2,22 @@ id: pm-awe3t6 title: "Mutation echo parity reversed after pm-nilh closed: the MCP surface now returns 5.2x the CLI default for an identical create" description: "pm-nilh closed as 'GH-437: make lean mutation output the CLI default (parity with MCP compact envelope)'. The CLI side shipped and is now the lean surface. The MCP side did not follow, and the parity the closed item claims is inverted at HEAD.\n\nMeasured 2026-07-31 in one sandbox tracker, same item type, same fields, same second.\n\nCLI: pm create --title ... --type Task --status open --json returns {\"id\":\"...\",\"status\":\"open\",\"changed_field_count\":10} at 72 bytes.\n\nMCP: pm_create with the same arguments returns {\"result\":{\"item\":{ten fields},\"warnings\":[],\"next_transition\":{...},\"changed_field_count\":10}} at 373 bytes. That is 5.2x the CLI default, and it is the default: leanness on MCP requires passing idOnly:true, which drops it to 45 bytes, while the CLI needs no flag at all.\n\nTwo distinct problems sit inside that ratio. The MCP default echoes the full created item, which the caller already knows because it just supplied every field, and pm-nilh's whole argument was that this echo is redundant. And the MCP envelope wraps every response in a result key that the CLI does not emit, so an agent parsing both surfaces needs two accessor paths for the same data - the shape divergence that AGENTS.md's guidance about the CLI having no result wrapper exists to warn about.\n\nThe direction of the regression is what makes it worth a separate item rather than a comment on the closed one. MCP is the surface where tokens are most expensive, because every tool result enters the model's context whether the agent needed it or not, whereas a CLI caller can pipe through jq and discard. Optimizing the cheap surface to parity with the expensive one, and then leaving the expensive one unchanged, spends the effort on the wrong side of the ratio.\n\nThis also belongs to the growth pattern measured across the agent-facing surface this week: pm context --limit 10 is 9,218 bytes against a recorded 7.6 KB baseline on 2026-07-24, pm list-open --limit 20 is 4,734 bytes against 3.6 KB, and pm contracts --flags-only is 124,288 bytes against 117,070 on 2026-07-26. Payload size on the real corpus is trending up while the token-efficiency work is open." type: Issue -status: open +status: closed priority: 2 tags[5]: agent-ux,closed-item-conformance,contracts,mcp,token-efficiency created_at: "2026-07-31T14:13:13.147Z" -updated_at: "2026-07-31T14:28:27.142Z" +updated_at: "2026-08-01T02:15:28.922Z" +closed_at: "2026-08-01T02:15:28.125Z" +completed_at: "2026-08-01T02:15:28.125Z" author: "harness:claude-code" estimated_minutes: 120 acceptance_criteria: "The MCP default mutation echo matches the CLI default in both content and size, so neither surface requires a flag to obtain the lean form; The result wrapper divergence is resolved or documented as a protocol requirement with one accessor path stated for agents parsing both surfaces; A test asserts the byte-size relationship between the two surfaces for a representative mutation, so the ratio cannot silently invert again; The parity claim in the closed pm-nilh is corrected by a comment on that item pointing at this one, so the closed record does not continue to assert a parity that HEAD does not have; The measured CLI 72 bytes versus MCP 373 bytes baseline is recorded, and the post-fix numbers are reported against it" parent: pm-5k4v risk: medium confidence: 96 +resolution: Aligned raw SDK and MCP mutation defaults with the CLI lean envelope while preserving explicit fullChangedFields output and documenting protocol framing. expected_result: An identical create returns the same lean envelope on both surfaces without a flag. -actual_result: "CLI returns 72 bytes by default; MCP returns 373 bytes by default and requires idOnly:true to reach 45." +actual_result: An isolated identical create returns id/status/changed_field_count at 57 bytes on both CLI and MCP result; fullChangedFields restores the full envelope. dependencies[8]{id,kind,created_at,author,source_kind,author_source}: pm-5t33or,related,"2026-07-31T14:16:09.459Z","harness:claude-code","cli:update:dep",detected pm-nilh,related,"2026-07-31T14:16:09.459Z","harness:claude-code","cli:update:dep",detected @@ -24,6 +27,34 @@ dependencies[8]{id,kind,created_at,author,source_kind,author_source}: pm-mpbb,related,"2026-07-31T14:20:57.070Z","harness:claude-code","cli:update:dep",detected pm-n7rr,related,"2026-07-31T14:20:57.070Z","harness:claude-code","cli:update:dep",detected pm-sb0tns,related,"2026-07-31T14:20:57.070Z","harness:claude-code","cli:update:dep",detected -files[1]{path,scope,note}: - src/mcp/server.ts,project,tool result envelope wraps in result and echoes the created item by default +comments[5]{created_at,author,text}: + "2026-08-01T00:35:37.291Z","harness:codex","Implementation evidence 2026-08-01: raw SDK/MCP mutation actions create, copy, update, close, append, and restore now use the same lean id/status/changed_field_count default as the CLI, while typed PmClient convenience methods preserve full results through explicit fullChangedFields opt-in. Isolated identical creates measured 57 bytes on both CLI and MCP result versus the recorded 72/373-byte baseline. The MCP JSON-RPC structuredContent.result protocol wrapper remains documented, but both surfaces expose the same keys inside the result. Focused parity tests passed 22/22; the repo-wide suite passed 6631/6631 at 100/100/100/100 coverage." + "2026-08-01T01:10:10.295Z","harness:codex","PR #849 exact-head CI correction: the Claude plugin smoke was the remaining consumer of the retired verbose raw pm_create result. It now requires the exact lean id/status/changed_field_count key set and a non-empty id; unit tests reject both verbose and malformed envelopes. Focused tests passed 19/19, the real MCP/plugin smoke passed all 31 tools and its full workflow, and ESLint passed." + "2026-08-01T01:34:19.681Z","harness:codex","PR #849 review evidence: runMcpAppendAction now propagates idOnly and disables compactEnvelope when idOnly is requested. A real MCP pm_run append regression returns exactly id/status with no changed_field_count. The focused MCP suite and repo-wide 6636-test 100/100/100/100 coverage pass." + "2026-08-01T02:15:20.871Z","harness:codex","Exact-head CodeRabbit correction: replaced the stale src/mcp/server.ts linked-file note through pm files. The canonical record now states that the protocol wrapper exposes the lean default mutation result without an item echo; focused context/MCP regressions and ESLint pass." + "2026-08-01T02:15:23.713Z","harness:codex","Exact-head CodeRabbit correction: replaced the stale src/mcp/server.ts linked-file note through pm files. The canonical record now states that the protocol wrapper exposes the lean default mutation result without an item echo; focused context/MCP regressions pass 18/18." +files[9]{path,scope,note}: + CHANGELOG.md,project,Package-owned generated release entry + scripts/smoke-claude-plugin.mjs,project,Acceptance smoke enforces lean raw MCP create envelope + src/mcp/server.ts,project,MCP protocol wrapper exposes the lean default mutation result without an item echo + src/sdk/runtime.ts,project,CLI and MCP default mutation-envelope parity + tests/integration/mcp-dynamic-package-actions.spec.ts,project,Updated consumers for lean default and explicit full opt-in + tests/integration/sdk-cli-contract-integrity.integration.spec.ts,project,Updated consumers for lean default and explicit full opt-in + tests/unit/mcp/mutation-envelope-parity.spec.ts,project,CLI and MCP default mutation-envelope parity + tests/unit/scripts/smoke-claude-plugin.spec.ts,project,Regression coverage rejects verbose and malformed create envelopes + tests/unit/sdk/sdk-index.spec.ts,project,Updated consumers for lean default and explicit full opt-in +tests[2]: + - command: node scripts/run-tests.mjs test -- tests/unit/mcp/mutation-envelope-parity.spec.ts tests/unit/core/output/mutation-projection.spec.ts + scope: project + timeout_seconds: 300 + - command: node scripts/run-tests.mjs test -- tests/unit/scripts/smoke-claude-plugin.spec.ts tests/unit/mcp/mutation-envelope-parity.spec.ts + scope: project + timeout_seconds: 300 + note: Lean mutation contract and Claude plugin smoke regression +test_runs[2]{run_id,kind,status,started_at,finished_at,recorded_at,passed,failed,skipped}: + test-local-ms9mg21p-sraa7s,test,passed,"2026-08-01T00:16:40.080Z","2026-08-01T00:16:51.805Z","2026-08-01T00:16:51.805Z",1,0,0 + test-local-ms9ocl81-o0u486,test,passed,"2026-08-01T01:09:47.417Z","2026-08-01T01:10:09.265Z","2026-08-01T01:10:09.265Z",2,0,0 +docs[1]{path,scope,note}: + docs/COMMANDS.md,project,Documented MCP protocol wrapper and lean result +close_reason: Reclosed after correcting the stale linked-file note; canonical PM metadata now matches the lean MCP default and focused verification passes. body: "" diff --git a/.agents/pm/issues/pm-sf31yl.toon b/.agents/pm/issues/pm-sf31yl.toon index da08a1d92..1d46f55c3 100644 --- a/.agents/pm/issues/pm-sf31yl.toon +++ b/.agents/pm/issues/pm-sf31yl.toon @@ -6,7 +6,7 @@ status: open priority: 1 tags[3]: context-management,pagination,token-budget created_at: "2026-07-30T17:01:49.124Z" -updated_at: "2026-07-30T17:21:52.248Z" +updated_at: "2026-08-01T02:15:30.407Z" author: "harness:claude-code" estimated_minutes: 360 acceptance_criteria: "Chain-invariant envelope metadata is emitted once per cursor chain and referenced on continuation pages, or is suppressible by an explicit caller opt-out, and the reduction is measured; Page size is derived from the measured bytes-per-row of the projection against the remaining budget rather than from a fixed constant, so a larger budget yields more rows rather than the same two; A gate asserts that walking a full result set through any bounded intent costs no more total tokens than the unprojected single call for the same set, on a corpus at least the size of the current tracker; The published evidence table records bytes per row and total walk cost for every bounded read family member before and after, including the 315-item list case; A negative control proves the gate fails when per-page metadata is reintroduced on every page" @@ -18,6 +18,22 @@ dependencies[4]{id,kind,created_at,author,source_kind,author_source}: pm-ez1dfg,related,"2026-07-30T17:03:13.975Z","harness:claude-code","cli:update:dep",detected pm-kvxqp1,related,"2026-07-30T17:03:13.975Z","harness:claude-code","cli:update:dep",detected pm-o87av6,implements,"2026-07-30T17:03:13.975Z","harness:claude-code","cli:update:dep",detected +comments[5]{created_at,author,text}: + "2026-08-01T00:37:53.206Z","harness:codex","Delivery evidence 2026-08-01: continuation pages now replace invariant filtering, sorting, projection, completeness, row, omission, pagination-summary, timestamp, and full intent-receipt blocks with a cursor-fingerprint reference while retaining only rows and the next cursor. List page size is budget-derived and the live tracker delivers 20 rows at 1703/3200 tokens; cursor integrity tests traverse list/search/context without duplicates. Remaining acceptance before closure: add a mandatory full-walk cost gate on a generated current-scale corpus, its repeated-metadata negative control, and publish the before/after whole-chain table." + "2026-08-01T01:34:20.523Z","harness:codex","PR #849 review reconciliation: CodeRabbit asked that the full-walk gate, repeated-metadata negative control, and before/after chain table be linked before closure. The item is intentionally still open, its existing delivery comment explicitly names those three remaining artifacts, and it has not been claimed or closed in this review pass. No unsupported artifact links were fabricated." + "2026-08-01T01:45:28.919Z","harness:codex","Review-fix evidence: post-projection row reduction is now restricted to next:execute, whose contract has a scalar primary recommendation; list/get/search/context instead fall back to receipt-only output rather than silently dropping paginated or otherwise retrievable rows. Added a no-cursor list regression and a 2,000-row serialization-efficiency regression. Focused review tests and the complete sandboxed coverage suite pass at 6637/6637 with 100% statements, branches, functions, and lines. Remaining full-walk current-scale cost-gate and before/after chain artifacts stay open and are not claimed as delivered." + "2026-08-01T02:15:21.645Z","harness:codex","Exact-head CodeRabbit cleanup: removed two non-discriminating absence assertions from the row-compaction regression; the test now asserts only compaction behavior driven by its fixture. Focused context/MCP regressions and ESLint pass. Remaining full-walk acceptance remains open." + "2026-08-01T02:15:24.601Z","harness:codex","Exact-head CodeRabbit cleanup: removed two non-discriminating absence assertions from the row-compaction regression; the test now asserts only compaction behavior driven by its fixture. Focused context/MCP regressions pass 18/18. Remaining full-walk acceptance remains open." learnings[1]{created_at,author,text}: "2026-07-30T17:21:52.247Z","harness:claude-code","Measurement discipline this issue depends on, worth stating because the intuitive measurement hides the defect: judge a bounded read by the cost of the whole answer, never by the cost of one page. Per page the triage projection looks like a clear win at 6,250 bytes against 71,709 for the unprojected call. Multiplied by the pages needed to reach the same 315 rows it is 987,500 bytes, and the win becomes a 13.8-fold loss. The comparison that matters is total tokens to answer the question the caller actually asked.\n\nThe derived quantity to record for any paginated surface is bytes per row at the offered page size, because it exposes envelope amortisation directly: 228 bytes per row unprojected against 3,125 per row at a two-row page is the whole finding in one ratio, and it stays meaningful across corpus sizes in a way that a page byte count does not." +files[3]{path,scope,note}: + src/sdk/context-intent-contracts.ts,project,Cursor-chain metadata reference and pagination integrity + tests/unit/commands/query-pagination.spec.ts,project,Cursor-chain metadata reference and pagination integrity + tests/unit/sdk/context-intent-contracts.spec.ts,project,Cursor-chain metadata reference and pagination integrity +tests[1]{command,scope,timeout_seconds}: + node scripts/run-tests.mjs test -- tests/unit/commands/query-pagination.spec.ts tests/unit/sdk/context-intent-contracts.spec.ts,project,300 +test_runs[1]{run_id,kind,status,started_at,finished_at,recorded_at,passed,failed,skipped}: + test-local-ms9mfsi3-oh4vvc,test,passed,"2026-08-01T00:16:29.855Z","2026-08-01T00:16:39.434Z","2026-08-01T00:16:39.434Z",1,0,0 +docs[1]{path,scope,note}: + docs/OUTPUT_PROJECTION_CONTRACTS.md,project,Continuation-page metadata contract body: "" diff --git a/.agents/pm/issues/pm-wv47pf.toon b/.agents/pm/issues/pm-wv47pf.toon index 63006b4aa..55fccec6a 100644 --- a/.agents/pm/issues/pm-wv47pf.toon +++ b/.agents/pm/issues/pm-wv47pf.toon @@ -6,7 +6,7 @@ status: open priority: 2 tags[2]: context-management,data-quality created_at: "2026-07-30T17:02:34.169Z" -updated_at: "2026-07-30T17:18:11.301Z" +updated_at: "2026-07-31T23:07:59.633Z" author: "harness:claude-code" estimated_minutes: 180 acceptance_criteria: "A response that omits its result records no serve, or records one whose rows are all marked not included and whose entry states that the response was omitted; The ledger entry carries the egress decision, so a consumer can separate a delivered assembly from a suppressed one without re-deriving the budget; Inclusion is recorded from what the response actually emitted rather than from the packing decision that preceded enforcement, proved by a test that asserts recorded inclusions equal emitted rows for both a served and an omitted response; Any existing phantom serves are either identifiable by a recorded marker or the affinity reader documents that entries written before the fix cannot be trusted for inclusion; A negative control proves the assertion fails when inclusion is taken from the pre-enforcement packing set" @@ -18,4 +18,6 @@ dependencies[4]{id,kind,created_at,author,source_kind,author_source}: pm-rtn5h6,related,"2026-07-30T17:03:16.021Z","harness:claude-code","cli:update:dep",detected pm-uwfs,discovered_from,"2026-07-30T17:03:16.021Z","harness:claude-code","cli:update:dep",detected pm-bab3gb,related,"2026-07-30T17:18:11.070Z","harness:claude-code","cli:update:dep",detected +comments[1]{created_at,author,text}: + "2026-07-31T23:07:57.955Z","harness:codex","Scope disposition 2026-08-01: this tranche is implementing the upstream budget reachability, cursor-chain amortization, and egress receipt semantics first. The usage-ledger correction requires the SDK-owned context/next extraction still open on pm-z5pmf8 so it can consume the exact post-egress delivered rows without adding a second projection pass inside CLI commands. Leaving this distinct data-quality item open and unclaimed; no source edit is being made for it in this PR." body: "" diff --git a/.agents/pm/issues/pm-yekkvt.toon b/.agents/pm/issues/pm-yekkvt.toon index 0a28802fa..0d22f5bf2 100644 --- a/.agents/pm/issues/pm-yekkvt.toon +++ b/.agents/pm/issues/pm-yekkvt.toon @@ -6,7 +6,7 @@ status: open priority: 1 tags[3]: conformance,context-management,token-budget created_at: "2026-07-30T17:01:25.178Z" -updated_at: "2026-07-31T06:14:40.384Z" +updated_at: "2026-08-01T02:04:46.790Z" author: "harness:claude-code" estimated_minutes: 300 acceptance_criteria: "Every declared intent budget is greater than or equal to the measured minimum bounded projection of its own command on a corpus at least the size of the current tracker, and a gate fails the build when it is not; Budget enforcement offers at least one intermediate tier that still carries rows before omission is permitted, and the receipt names the tier actually applied; A response that omits its result never reports within_budget true, and the receipt distinguishes an infeasible declaration from an exceeded one; Recovery guidance for an infeasible budget never instructs a caller to re-run the unprojected command when that form emits more tokens than the projection it replaces; The published evidence table records declared budget, measured minimum projection and applied degradation per intent on both a two-item corpus and the current tracker, so calibration against a toy corpus is visible in review" @@ -17,8 +17,38 @@ dependencies[3]{id,kind,created_at,author,source_kind,author_source}: pm-cxr0jb,discovered_from,"2026-07-30T17:03:13.062Z","harness:claude-code","cli:update:dep",detected pm-o87av6,implements,"2026-07-30T17:03:13.062Z","harness:claude-code","cli:update:dep",detected pm-sf31yl,blocked_by,"2026-07-30T17:18:10.164Z","harness:claude-code","cli:update:dep",detected -comments[1]{created_at,author,text}: +comments[6]{created_at,author,text}: "2026-07-31T06:14:40.384Z","harness:claude-code","Still live at HEAD 2026.7.31, verified 2026-07-31. `pm next --for execute` emits budget_exceeded.omitted_result: true alongside within_budget: true in one envelope, with token_budget 1200 and estimated_tokens 79 — the receipt reports the omitted-result payload as within budget, so the two keys in the same envelope assert opposite things. The recovery instruction \"Repeat the original command without --for\" costs 9,259 bytes against the 320-byte refusal." + "2026-08-01T00:37:52.411Z","harness:codex","Delivery evidence 2026-08-01: receipts now distinguish declaration_feasible and result_omitted, omitted results always report within_budget:false, recovery never recommends an unprojected retry, and deterministic string then row compaction retains useful rows before receipt-only fallback. The checked 27-item fixture and all five live 2243-item tracker probes deliver feasible results; an explicit 256-token control proves truthful omission. Remaining acceptance before closure: publish and gate the required two-item versus current-scale calibration table rather than relying on the current small committed fixture plus manual live evidence." + "2026-08-01T01:34:18.884Z","harness:codex","PR #849 review evidence: list/get/search now reject tokenBudget without a selected intent while context/next retain their established standalone budget semantics; 2,000-row compaction uses batch estimation and completed with fewer than 20 JSON serializations; duplicate terminal estimation was removed; generated schemas now use generic wording except the deps-scoped override. Focused regression tests passed 111/111 after narrowing the validation, and the repo-wide suite passed 6636/6636 at exact 100/100/100/100 coverage. Remaining original closure acceptance is unchanged: the current-scale calibration table and mandatory gate are still outstanding, so this item returns to open." + "2026-08-01T01:45:28.140Z","harness:codex","Review-fix evidence: exact token budgets now normalize token_budget to tokenBudget, reject ambiguous get/list/search usage without --for while preserving context/next standalone behavior, and use truthful budget-derived search guidance. The release gate independently measures serialized stdout, requires finite numeric receipt fields, and rejects actual output above the declared receipt budget. Focused review tests and the complete sandboxed coverage suite pass; latest full result is 6637/6637 tests with 100% statements, branches, functions, and lines. Remaining current-scale calibration-table acceptance stays open and is not claimed as delivered." + "2026-08-01T01:56:15.853Z","harness:codex","Exact local release-gate evidence before the review-fix push: static quality and 100% docstring gates passed; package boundary, SDK contract parity, 28-surface token budget, gate registry, SDK surface, benchmarks, context/retrieval evaluations, and the 96-surface agent-token gate passed; 410 files and 6637 tests passed at exact 100/100/100/100 coverage; secret scan, packed npx smoke, and the 88-command isolated package-first dogfood run passed. The only terminal release:gates failure was the hosted Greptile adapter reporting free_reviews_limit_reached after all local gates completed; this is external review capacity, not a product/test failure." + "2026-08-01T02:04:45.101Z","harness:codex","Exact-head CI static correction: the structured missing_required_option path added in sdk/context-intent-contracts.ts is now present in the generated error-code catalog and full contracts fixture. pnpm contracts:check, security:scan, lint, and the focused generator/context tests pass. This fixes the only Actions failure on 6b0e063d5; the original current-scale calibration acceptance remains open." learnings[1]{created_at,author,text}: "2026-07-30T17:21:51.507Z","harness:claude-code","Method that found this, reusable for any declared bound: run the identical invocation against a two-item workspace and against the real tracker, and diff the verdicts rather than the outputs. A bound that is satisfied on the small corpus and violated on the large one is a scalar that should have been a function, and the small corpus is the one the number was authored against. A bound violated on both is an ordinary miscalibration. A bound satisfied on both is genuinely scale-invariant and can be left alone.\n\nSecond technique, for the same class: a floor is invisible from the default. Raising the ceiling in steps until content first appears is the only way to measure the smallest form a command can emit, because at the default the response contains no rows to measure. next execute yielded nothing at 1200 and 2000 and content at 4000, which located the floor between 2000 and 4000 and then exactly at 1438 from the receipt. Doing this in the other direction, lowering a working ceiling until output disappears, gives the same number and is cheaper when the default already works." +files[9]{path,scope,note}: + scripts/release/token-budget-gate.mjs,project,Feasible intent projection and truthful receipt implementation + scripts/release/token-budgets.json,project,Feasible intent projection and truthful receipt implementation + sdk/public-surface.json,project,Versioned public receipt contract and breaking acknowledgement + src/sdk/cli-contracts/tool-parameter-tables.ts,project,Action-correct token-budget schema descriptions + src/sdk/context-intent-contracts.ts,project,Feasible intent projection and truthful receipt implementation + src/sdk/generated-error-code-catalog.ts,project,Generated structured usage-error source inventory + tests/fixtures/contracts/full.json,project,Regenerated token-budget contract descriptions + tests/unit/cli/context-intent-registration.spec.ts,project,Feasible intent projection and truthful receipt implementation + tests/unit/sdk/context-intent-contracts.spec.ts,project,Feasible intent projection and truthful receipt implementation +tests[3]: + - command: node scripts/release/token-budget-gate.mjs + scope: project + timeout_seconds: 300 + - command: node scripts/run-tests.mjs coverage + scope: project + timeout_seconds: 600 + note: Repo-wide 100/100/100/100 review-fix verification + - command: node scripts/run-tests.mjs test -- tests/unit/sdk/context-intent-contracts.spec.ts tests/unit/cli/context-intent-registration.spec.ts + scope: project + timeout_seconds: 300 +test_runs[1]{run_id,kind,status,started_at,finished_at,recorded_at,passed,failed,skipped}: + test-local-ms9mfklb-2y4mp4,test,passed,"2026-08-01T00:15:58.982Z","2026-08-01T00:16:29.183Z","2026-08-01T00:16:29.183Z",2,0,0 +docs[1]{path,scope,note}: + docs/OUTPUT_PROJECTION_CONTRACTS.md,project,Intent degradation and receipt semantics body: "" diff --git a/CHANGELOG.md b/CHANGELOG.md index 46759c78a..3cfc2baab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Fixed +- Mutation echo parity reversed after pm-nilh closed: the MCP surface now returns 5.2x the CLI default for an identical create ([pm-awe3t6](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/issues/pm-awe3t6.toon)) - The bunx release gate passes with an arbitrary token in the executable position, so the only Bun coverage in the pipeline cannot fail for the reason it exists ([pm-lpqln4](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/issues/pm-lpqln4.toon)) - The published-artifact gate never executes pm-mcp: two of three declared bins resolve to the same file and the third — which already shipped dead once — has zero release coverage ([pm-u0oz2k](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/issues/pm-u0oz2k.toon)) - One governance rule, two terminal-transition paths, opposite answers: pm close refuses a reasonless close while pm update --status closed invents a reason and writes it into the immutable record unmarked ([pm-2ew0w3](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/issues/pm-2ew0w3.toon)) diff --git a/docs/COMMANDS.md b/docs/COMMANDS.md index a12a4f59e..2000aee8d 100644 --- a/docs/COMMANDS.md +++ b/docs/COMMANDS.md @@ -506,7 +506,13 @@ Every transition into a terminal status stamps two distinct ISO timestamps: `clo When closing a blocker, `pm close` scans reverse `blocked_by` edges and auto-unblocks dependent items only when every resolvable blocker is now terminal. Each unblocked item is updated through the normal audited mutation path, gets an `unblock_note`, and the close result reports compact `auto_unblocked::resolved_blockers=` warnings. Items with another active blocker remain blocked. -Over MCP the mutation tools (`pm_create`/`pm_update`/`pm_close`/`pm_run` append/update-many) are compact by default; pass `fullChangedFields=true` to restore the full `changed_fields` delta, or `idOnly=true` for single-item id/status output. +Over MCP, single-item mutations (`pm_create`, `pm_update`, `pm_close`, and +`pm_run` append) default to the same lean result as the CLI: `id`, `status`, +and `changed_field_count`. The MCP transport still wraps that result in +`structuredContent.result`, as required by the protocol. Pass +`fullChangedFields=true` to restore the full item echo and `changed_fields` +delta, or `idOnly=true` for id/status output. Bulk mutations remain compact +row summaries. See tracker item [pm-awe3t6](../.agents/pm/issues/pm-awe3t6.toon). ### Atomic heterogeneous mutation batches diff --git a/docs/OUTPUT_PROJECTION_CONTRACTS.md b/docs/OUTPUT_PROJECTION_CONTRACTS.md index 08381cbf9..ba5af97bd 100644 --- a/docs/OUTPUT_PROJECTION_CONTRACTS.md +++ b/docs/OUTPUT_PROJECTION_CONTRACTS.md @@ -6,7 +6,11 @@ Tracker references: [pm-p258tx](../.agents/pm/features/pm-p258tx.toon), intent-budget contracts are tracked by [pm-sb0tns](../.agents/pm/issues/pm-sb0tns.toon), [pm-cxr0jb](../.agents/pm/features/pm-cxr0jb.toon), and -[pm-5t33or](../.agents/pm/features/pm-5t33or.toon). Trustworthy collection +[pm-5t33or](../.agents/pm/features/pm-5t33or.toon). Reachable budgets and +cursor-chain amortization are tracked by +[pm-7hbfch](../.agents/pm/issues/pm-7hbfch.toon), +[pm-yekkvt](../.agents/pm/issues/pm-yekkvt.toon), and +[pm-sf31yl](../.agents/pm/issues/pm-sf31yl.toon). Trustworthy collection selectors are tracked by [pm-x710qm](../.agents/pm/issues/pm-x710qm.toon). @@ -151,10 +155,12 @@ resolved contract in `context_intent`: "context_intent": { "command": "list", "intent": "triage", - "token_budget": 1800, + "token_budget": 3200, "estimated_tokens": 1416, "within_budget": true, - "degradation": "bounded_fields_and_rows" + "degradation": "bounded_fields_and_rows", + "declaration_feasible": true, + "result_omitted": false } } ``` @@ -164,21 +170,33 @@ Use `context --for orient|handoff`, `get --for inspect`, `search --for discover`. Explicit caller projection options win over intent defaults, while the intent ceiling still applies. Selecting an intent is an explicit request for its bounded shape: `get --for inspect` defaults to -standard depth, `list --for triage` defaults to two compact rows, and -`search --for discover` defaults to fifteen compact rows. Callers that need a -different depth or page size can pass `--depth` or `--limit`; list and search -retain their ordinary completeness and continuation metadata when bounded. -If a selected result exceeds -its budget, long explanatory strings are compacted deterministically without -dropping rows. If the complete row set still cannot fit, the result is replaced -by a `budget_receipt_only` envelope instead of retaining stale counts or -pagination cursors. The receipt's `token_budget` is the effective ceiling after -any explicit caller override. Explicit overrides below 256 tokens are rejected -because the minimum machine-readable receipt cannot fit; malformed or absent -overrides retain the declared intent budget. A receipt-only response directs -callers to repeat their original invocation without `--for`, avoiding -non-runnable recovery strings for positional commands such as `get` and -`search`. Calls +standard depth. List and search derive their default page size from the +effective token ceiling and a conservative per-row cost, so raising +`--token-budget` increases useful rows instead of paying the same fixed envelope +cost for every page. Context applies the same principle to its focus and +activity limits so the built-in orientation declaration remains feasible on a +large tracker. All five intent commands accept the same +`--token-budget` override. Explicit `--depth` and `--limit` controls still win. + +If a selected result exceeds its budget, long explanatory strings compact +first, followed by deterministic root-row reduction that retains at least one +useful row and reports `budget_row_compaction`. Only a result whose minimum +useful projection cannot fit becomes `budget_receipt_only`. That receipt sets +`declaration_feasible: false`, `result_omitted: true`, and +`within_budget: false`; fitting the refusal envelope does not make the omitted +result truthful. Recovery recommends increasing the ceiling or narrowing the +request and never sends an agent to a potentially larger unprojected retry. +Explicit overrides below 256 tokens are rejected because the minimum +machine-readable receipt cannot fit; malformed or absent overrides retain the +declared intent budget. + +The first cursor page carries the complete projection, filtering, sorting, +completeness, row, and omission contracts. Continuation pages replace those +chain-invariant blocks with `continuation_contract`, which carries the cursor's +query fingerprint and a compact restore instruction. Continuations retain only +the rows and next cursor needed to advance the chain; page counts, total, +truncation, timestamps, and the full intent receipt are referenced from the +first page instead of being re-emitted. Calls without `--for` remain byte-compatible with the ordinary projection path apart from the universal row contract. diff --git a/scripts/agent-token-surface-baseline.json b/scripts/agent-token-surface-baseline.json index 9d311073a..cf0c5aaa9 100644 --- a/scripts/agent-token-surface-baseline.json +++ b/scripts/agent-token-surface-baseline.json @@ -3,16 +3,16 @@ "metric": "utf8_bytes", "headroom": 1.1, "surfaces": { - "root_help": 14385, - "per_command_total": 221421, - "full_help_surface": 235805, + "root_help": 15041, + "per_command_total": 225719, + "full_help_surface": 240760, "contracts": { - "summary_toon": 9851, - "summary_json": 13465, - "json": 13465, - "full": 934984 + "summary_toon": 10672, + "summary_json": 14744, + "json": 14744, + "full": 1027133 }, - "mcp_tools_list": 39125, + "mcp_tools_list": 40002, "required_commands": [ "activity", "aggregate", @@ -88,47 +88,47 @@ "update": 9335, "create": 8601, "close-many": 7875, - "list": 7254, - "list-all": 7047, - "list-blocked": 6970, - "list-in-progress": 6921, - "list-draft": 6917, - "list-closed": 6904, - "list-open": 6899, - "list-canceled": 6892, + "list": 7473, + "list-all": 7266, + "list-blocked": 7189, + "list-in-progress": 7140, + "list-draft": 7136, + "list-closed": 7123, + "list-open": 7118, + "list-canceled": 7111, + "search": 6948, "package": 6825, - "search": 6729, "extension": 6685, "validate": 4870, "config": 4787, - "search-advanced": 4386, + "search-advanced": 4594, "test": 3963, - "schema": 3488, - "context": 2726, + "schema": 3504, + "context": 2805, "graph": 2670, "test-all": 2633, + "health": 2304, "init": 2204, "files": 2204, - "health": 2153, "close": 2077, "calendar": 2011, "cal": 2006, + "next": 1996, "learnings": 1973, - "next": 1917, "normalize": 1872, "aggregate": 1828, "claim": 1818, - "notes": 1770, "comments": 1729, "history-compact": 1668, + "notes": 1659, "docs": 1633, "merge": 1589, + "get": 1552, "deps": 1534, "event": 1443, "stats": 1437, "meet": 1429, "upgrade": 1367, - "get": 1333, "history": 1303, "events": 1269, "contracts": 1252, @@ -142,7 +142,7 @@ "reindex": 927, "test-runs": 852, "history-redact": 850, - "append": 844, + "append": 832, "close-task": 831, "gc": 812, "telemetry": 786, @@ -152,20 +152,25 @@ "release": 709, "restore": 693, "delete": 684, - "history-author-acknowledge": 642, + "completion": 648, "profile": 638, "pause-task": 611, "start-task": 608, "focus": 547, "duplicates": 535, + "history-author-acknowledge": 524, "copy": 508, + "guide": 508, "workspace": 483, "templates": 416, "changelog": 381, "item": 336, "command-kit": 313, "todos": 311, - "beads": 235 + "beads": 235, + "completion-statuses": 228, + "completion-types": 225, + "completion-tags": 211 } } } diff --git a/scripts/release/token-budget-gate.mjs b/scripts/release/token-budget-gate.mjs index cf569fd70..3424ae760 100644 --- a/scripts/release/token-budget-gate.mjs +++ b/scripts/release/token-budget-gate.mjs @@ -319,6 +319,46 @@ function commandCorpus(ids) { scale_tier: "medium", args: ["search", "status:all Alpha", "--json"], }, + { + id: "context-intent-orient", + kind: "answer", + command: "context", + intent: true, + scale_tier: "medium", + args: ["context", "--for", "orient", "--json"], + }, + { + id: "get-intent-inspect", + kind: "answer", + command: "get", + intent: true, + scale_tier: "linked", + args: ["get", ids.childId, "--for", "inspect", "--json"], + }, + { + id: "list-intent-triage", + kind: "answer", + command: "list", + intent: true, + scale_tier: "medium", + args: ["list", "--for", "triage", "--json"], + }, + { + id: "next-intent-execute", + kind: "answer", + command: "next", + intent: true, + scale_tier: "medium", + args: ["next", "--for", "execute", "--json"], + }, + { + id: "search-intent-discover", + kind: "answer", + command: "search", + intent: true, + scale_tier: "medium", + args: ["search", "Alpha", "--for", "discover", "--json"], + }, ]; } @@ -369,6 +409,9 @@ function measureCorpus(cliPath) { ? {} : { contract_max_estimated_tokens: contractMaxEstimatedTokens }), ...measureOutput(stdout), + ...(entry.intent + ? { intent_receipt: JSON.parse(stdout).context_intent } + : {}), }; }); const negativeControl = { @@ -383,7 +426,12 @@ function measureCorpus(cliPath) { ), contract_max_estimated_tokens: contractBudgets.get("activity"), }; - return { measurements, negativeControl }; + const intentNegativeControl = runCliJson( + cliPath, + ["list", "--for", "triage", "--token-budget", "256", "--json"], + options, + ).context_intent; + return { measurements, negativeControl, intentNegativeControl }; } finally { cleanupTempRoot(workspaceRoot); } @@ -392,7 +440,9 @@ function measureCorpus(cliPath) { export function budgetForMeasurement(measurement, multiplier) { return { id: measurement.id, - args: measurement.args, + args: measurement.args.map((argument) => + /^pm-[a-z0-9]+$/u.test(argument) ? "" : argument, + ), kind: measurement.kind ?? "discovery", scale_tier: measurement.scale_tier ?? "static", baseline_bytes: measurement.bytes, @@ -452,6 +502,21 @@ function isMalformedBudget(budget) { } function measurementViolation(measurement, budget) { + if (measurement.intent) { + const receipt = measurement.intent_receipt; + if ( + !receipt || + receipt.declaration_feasible !== true || + receipt.result_omitted !== false || + receipt.within_budget !== true || + !Number.isFinite(receipt.estimated_tokens) || + !Number.isFinite(receipt.token_budget) || + measurement.estimated_tokens > receipt.token_budget || + receipt.estimated_tokens > receipt.token_budget + ) { + return `${measurement.id}: intent receipt did not prove a feasible delivered result (${measurement.args.join(" ")})`; + } + } if ( measurement.kind === "answer" && measurement.estimated_tokens > measurement.contract_max_estimated_tokens @@ -495,6 +560,29 @@ export function compareBudgets(measurements, manifest) { return violations; } +/** Verify controls that prove bounded defaults differ from explicit escape hatches and infeasible declarations remain truthful. */ +function compareNegativeControls(negativeControl, intentNegativeControl) { + const violations = []; + if ( + negativeControl.estimated_tokens <= + negativeControl.contract_max_estimated_tokens + ) { + violations.push( + `negative-control: explicit unbounded activity produced ${negativeControl.estimated_tokens} estimated tokens, expected more than its ${negativeControl.contract_max_estimated_tokens}-token default contract`, + ); + } + if ( + intentNegativeControl?.declaration_feasible !== false || + intentNegativeControl?.result_omitted !== true || + intentNegativeControl?.within_budget !== false + ) { + violations.push( + "intent-negative-control: infeasible 256-token list declaration did not return an explicit omitted-result receipt", + ); + } + return violations; +} + export function main() { const { flags } = parseFlags(process.argv.slice(2)); const update = flags.has("update"); @@ -518,7 +606,8 @@ export function main() { ); } const manifest = update ? undefined : readManifest(manifestPath); - const { measurements, negativeControl } = measureCorpus(cliPath); + const { measurements, negativeControl, intentNegativeControl } = + measureCorpus(cliPath); if (update) { const nextManifest = buildManifest(measurements, multiplier); writeFileSync(manifestPath, `${JSON.stringify(nextManifest, null, 2)}\n`); @@ -527,22 +616,17 @@ export function main() { ); return; } - const violations = compareBudgets(measurements, manifest); - if ( - negativeControl.estimated_tokens <= - negativeControl.contract_max_estimated_tokens - ) { - violations.push( - `negative-control: explicit unbounded activity produced ${negativeControl.estimated_tokens} estimated tokens, expected more than its ${negativeControl.contract_max_estimated_tokens}-token default contract`, - ); - } + const violations = [ + ...compareBudgets(measurements, manifest), + ...compareNegativeControls(negativeControl, intentNegativeControl), + ]; if (violations.length > 0) { fail( `Token budget gate failed:\n${violations.join("\n")}\nRun node scripts/release/token-budget-gate.mjs --update after intentional output changes.`, ); } console.log( - `Token budget gate passed (${measurements.length} surfaces checked; unbounded negative control ${negativeControl.estimated_tokens} tokens).`, + `Token budget gate passed (${measurements.length} surfaces checked; unbounded negative control ${negativeControl.estimated_tokens} tokens; infeasible intent receipt verified).`, ); } diff --git a/scripts/release/token-budgets.json b/scripts/release/token-budgets.json index 8457cb1bb..2f174e85c 100644 --- a/scripts/release/token-budgets.json +++ b/scripts/release/token-budgets.json @@ -7,27 +7,35 @@ "budgets": [ { "id": "root-help", - "args": ["--help"], + "args": [ + "--help" + ], "kind": "discovery", "scale_tier": "static", - "baseline_bytes": 11090, - "baseline_estimated_tokens": 2773, - "max_bytes": 12200, - "max_estimated_tokens": 3051 + "baseline_bytes": 11210, + "baseline_estimated_tokens": 2803, + "max_bytes": 12332, + "max_estimated_tokens": 3084 }, { "id": "search-help", - "args": ["search", "--help"], + "args": [ + "search", + "--help" + ], "kind": "discovery", "scale_tier": "static", - "baseline_bytes": 6117, - "baseline_estimated_tokens": 1530, - "max_bytes": 6729, - "max_estimated_tokens": 1684 + "baseline_bytes": 6316, + "baseline_estimated_tokens": 1579, + "max_bytes": 6948, + "max_estimated_tokens": 1737 }, { "id": "create-help", - "args": ["create", "--help"], + "args": [ + "create", + "--help" + ], "kind": "discovery", "scale_tier": "static", "baseline_bytes": 7768, @@ -37,71 +45,92 @@ }, { "id": "update-help", - "args": ["update", "--help"], + "args": [ + "update", + "--help" + ], "kind": "discovery", "scale_tier": "static", - "baseline_bytes": 7972, - "baseline_estimated_tokens": 1993, - "max_bytes": 8770, - "max_estimated_tokens": 2193 + "baseline_bytes": 8196, + "baseline_estimated_tokens": 2049, + "max_bytes": 9016, + "max_estimated_tokens": 2254 }, { "id": "contracts-summary-json", - "args": ["contracts", "--summary", "--json"], + "args": [ + "contracts", + "--summary", + "--json" + ], "kind": "discovery", "scale_tier": "static", - "baseline_bytes": 9753, - "baseline_estimated_tokens": 2439, - "max_bytes": 10729, - "max_estimated_tokens": 2683 + "baseline_bytes": 10632, + "baseline_estimated_tokens": 2658, + "max_bytes": 11696, + "max_estimated_tokens": 2924 }, { "id": "contracts-flags-json", - "args": ["contracts", "--flags-only", "--json"], + "args": [ + "contracts", + "--flags-only", + "--json" + ], "kind": "discovery", "scale_tier": "static", - "baseline_bytes": 118453, - "baseline_estimated_tokens": 29614, - "max_bytes": 130299, - "max_estimated_tokens": 32576 + "baseline_bytes": 130366, + "baseline_estimated_tokens": 32592, + "max_bytes": 143403, + "max_estimated_tokens": 35852 }, { "id": "list-default", - "args": ["list"], + "args": [ + "list" + ], "kind": "answer", "scale_tier": "medium", - "baseline_bytes": 3198, - "baseline_estimated_tokens": 800, + "baseline_bytes": 3635, + "baseline_estimated_tokens": 909, "command": "list", "contract_max_estimated_tokens": 4000 }, { "id": "list-open-default", - "args": ["list-open"], + "args": [ + "list-open" + ], "kind": "answer", "scale_tier": "medium", - "baseline_bytes": 2468, - "baseline_estimated_tokens": 617, + "baseline_bytes": 2905, + "baseline_estimated_tokens": 727, "command": "list", "contract_max_estimated_tokens": 4000 }, { "id": "list-json", - "args": ["list", "--json"], + "args": [ + "list", + "--json" + ], "kind": "answer", "scale_tier": "medium", - "baseline_bytes": 4245, - "baseline_estimated_tokens": 1062, + "baseline_bytes": 4783, + "baseline_estimated_tokens": 1196, "command": "list", "contract_max_estimated_tokens": 4000 }, { "id": "get-default", - "args": ["get", "pm-yo5x"], + "args": [ + "get", + "" + ], "kind": "answer", "scale_tier": "linked", - "baseline_bytes": 646, - "baseline_estimated_tokens": 162, + "baseline_bytes": 876, + "baseline_estimated_tokens": 219, "command": "get", "contract_max_estimated_tokens": 4000 }, @@ -109,91 +138,119 @@ "id": "get-json-compact-fields", "args": [ "get", - "pm-yo5x", + "", "--json", "--fields", "id,title,status,type,priority,tags,dependencies" ], "kind": "answer", "scale_tier": "linked", - "baseline_bytes": 458, - "baseline_estimated_tokens": 115, + "baseline_bytes": 971, + "baseline_estimated_tokens": 243, "command": "get", "contract_max_estimated_tokens": 4000 }, { "id": "context-default", - "args": ["context"], + "args": [ + "context" + ], "kind": "answer", "scale_tier": "medium", - "baseline_bytes": 3134, - "baseline_estimated_tokens": 784, + "baseline_bytes": 4748, + "baseline_estimated_tokens": 1187, "command": "context", "contract_max_estimated_tokens": 4000 }, { "id": "next-default", - "args": ["next"], + "args": [ + "next" + ], "kind": "answer", "scale_tier": "medium", - "baseline_bytes": 3092, - "baseline_estimated_tokens": 773, + "baseline_bytes": 3459, + "baseline_estimated_tokens": 865, "command": "next", "contract_max_estimated_tokens": 4000 }, { "id": "activity-default", - "args": ["activity", "--json"], + "args": [ + "activity", + "--json" + ], "kind": "answer", "scale_tier": "medium", - "baseline_bytes": 2929, - "baseline_estimated_tokens": 733, + "baseline_bytes": 3540, + "baseline_estimated_tokens": 885, "command": "activity", "contract_max_estimated_tokens": 4000 }, { "id": "deps-tree-default", - "args": ["deps", "pm-5qpl"], + "args": [ + "deps", + "" + ], "kind": "answer", "scale_tier": "linked", - "baseline_bytes": 197, - "baseline_estimated_tokens": 50, + "baseline_bytes": 567, + "baseline_estimated_tokens": 142, "command": "deps", "contract_max_estimated_tokens": 4000 }, { "id": "deps-tree-json", - "args": ["deps", "pm-5qpl", "--json"], + "args": [ + "deps", + "", + "--json" + ], "kind": "answer", "scale_tier": "linked", - "baseline_bytes": 289, - "baseline_estimated_tokens": 73, + "baseline_bytes": 800, + "baseline_estimated_tokens": 200, "command": "deps", "contract_max_estimated_tokens": 4000 }, { "id": "graph-audit-summary", - "args": ["graph", "audit", "--summary", "--json"], + "args": [ + "graph", + "audit", + "--summary", + "--json" + ], "kind": "answer", "scale_tier": "medium", - "baseline_bytes": 872, - "baseline_estimated_tokens": 218, + "baseline_bytes": 1440, + "baseline_estimated_tokens": 360, "command": "graph", "contract_max_estimated_tokens": 4000 }, { "id": "duplicates-default", - "args": ["duplicates", "--limit", "20", "--json"], + "args": [ + "duplicates", + "--limit", + "20", + "--json" + ], "kind": "answer", "scale_tier": "medium", - "baseline_bytes": 314, - "baseline_estimated_tokens": 79, + "baseline_bytes": 650, + "baseline_estimated_tokens": 163, "command": "duplicates", "contract_max_estimated_tokens": 4000 }, { "id": "events-default", - "args": ["events", "--limit", "20"], + "args": [ + "events", + "--limit", + "20" + ], "kind": "answer", "scale_tier": "medium", "baseline_bytes": 6411, @@ -203,41 +260,131 @@ }, { "id": "health-default", - "args": ["health", "--check-only"], + "args": [ + "health", + "--check-only" + ], "kind": "answer", "scale_tier": "medium", - "baseline_bytes": 7604, - "baseline_estimated_tokens": 1901, + "baseline_bytes": 1014, + "baseline_estimated_tokens": 254, "command": "health", "contract_max_estimated_tokens": 6000 }, { "id": "validate-counts", - "args": ["validate", "--counts"], + "args": [ + "validate", + "--counts" + ], "kind": "answer", "scale_tier": "medium", - "baseline_bytes": 5241, - "baseline_estimated_tokens": 1311, + "baseline_bytes": 5508, + "baseline_estimated_tokens": 1377, "command": "validate", "contract_max_estimated_tokens": 6000 }, { "id": "search-inline-default", - "args": ["search", "status:all Alpha"], + "args": [ + "search", + "status:all Alpha" + ], "kind": "answer", "scale_tier": "medium", - "baseline_bytes": 501, - "baseline_estimated_tokens": 126, + "baseline_bytes": 943, + "baseline_estimated_tokens": 236, "command": "search", "contract_max_estimated_tokens": 4000 }, { "id": "search-inline-json", - "args": ["search", "status:all Alpha", "--json"], + "args": [ + "search", + "status:all Alpha", + "--json" + ], + "kind": "answer", + "scale_tier": "medium", + "baseline_bytes": 1216, + "baseline_estimated_tokens": 304, + "command": "search", + "contract_max_estimated_tokens": 4000 + }, + { + "id": "context-intent-orient", + "args": [ + "context", + "--for", + "orient", + "--json" + ], + "kind": "answer", + "scale_tier": "medium", + "baseline_bytes": 5430, + "baseline_estimated_tokens": 1358, + "command": "context", + "contract_max_estimated_tokens": 4000 + }, + { + "id": "get-intent-inspect", + "args": [ + "get", + "", + "--for", + "inspect", + "--json" + ], + "kind": "answer", + "scale_tier": "linked", + "baseline_bytes": 1670, + "baseline_estimated_tokens": 418, + "command": "get", + "contract_max_estimated_tokens": 4000 + }, + { + "id": "list-intent-triage", + "args": [ + "list", + "--for", + "triage", + "--json" + ], + "kind": "answer", + "scale_tier": "medium", + "baseline_bytes": 7041, + "baseline_estimated_tokens": 1761, + "command": "list", + "contract_max_estimated_tokens": 4000 + }, + { + "id": "next-intent-execute", + "args": [ + "next", + "--for", + "execute", + "--json" + ], + "kind": "answer", + "scale_tier": "medium", + "baseline_bytes": 2553, + "baseline_estimated_tokens": 639, + "command": "next", + "contract_max_estimated_tokens": 4000 + }, + { + "id": "search-intent-discover", + "args": [ + "search", + "Alpha", + "--for", + "discover", + "--json" + ], "kind": "answer", "scale_tier": "medium", - "baseline_bytes": 673, - "baseline_estimated_tokens": 169, + "baseline_bytes": 1603, + "baseline_estimated_tokens": 401, "command": "search", "contract_max_estimated_tokens": 4000 } diff --git a/scripts/smoke-claude-plugin.mjs b/scripts/smoke-claude-plugin.mjs index 651278023..9e45954da 100644 --- a/scripts/smoke-claude-plugin.mjs +++ b/scripts/smoke-claude-plugin.mjs @@ -166,7 +166,17 @@ try { createMode: "progressive", }, }); - const id = created.item.id; + const createKeys = Object.keys(created).sort(); + const expectedCreateKeys = ["changed_field_count", "id", "status"]; + if (createKeys.join(",") !== expectedCreateKeys.join(",")) { + throw new Error( + `pm_create default must use the lean mutation envelope (${expectedCreateKeys.join(", ")}); got ${createKeys.join(", ")}`, + ); + } + const id = created.id; + if (typeof id !== "string" || id.length === 0) { + throw new Error("pm_create lean mutation envelope is missing a non-empty id"); + } console.log(`pm_create: ok (${id})`); await callTool("pm_claim", { cwd: tmpRoot, id, author: "claude-smoke" }); diff --git a/sdk/public-surface.json b/sdk/public-surface.json index 21dbbcd28..26ad2e588 100644 --- a/sdk/public-surface.json +++ b/sdk/public-surface.json @@ -435,6 +435,16 @@ ], "package_version": "2026.7.31", "reason": "Expand universal SDK context primitives with typed runtime containers, merge-safe structured events, init target provenance, and actionable author diagnostics." + }, + { + "changes": [ + "signature ./sdk:PM_TOOL_PARAMETERS_SCHEMA_VERSION", + "signature ./sdk:PmContextIntentReceipt", + "signature ./sdk/contracts:PM_TOOL_PARAMETERS_SCHEMA_VERSION", + "signature ./sdk/contracts:PmContextIntentReceipt" + ], + "package_version": "2026.7.31", + "reason": "Intent receipts now require truthful feasibility and omission state; tool schema 4.3.0 adds tokenBudget to list get and search" } ], "entrypoints": { @@ -6991,7 +7001,7 @@ "classification": "contract_data", "kind": "value", "name": "PM_TOOL_PARAMETERS_SCHEMA_VERSION", - "signature": "\"4.2.0\"" + "signature": "\"4.3.0\"" }, { "classification": "advanced_export", @@ -7147,7 +7157,7 @@ "classification": "contract_data", "kind": "interface", "name": "PmContextIntentReceipt", - "signature": "export interface PmContextIntentReceipt { command: string; intent: string; source: PmContextIntentSource; included_field_groups: string[]; token_budget: number; estimated_tokens: number; within_budget: boolean; degradation: \"bounded_fields_and_rows\" | \"bounded_ranked_rows\" | \"bounded_sections\" | \"recursive_budget_compaction\" | \"budget_receipt_only\" | \"standard_item\" | \"none\"; }" + "signature": "export interface PmContextIntentReceipt { command: string; intent: string; source: PmContextIntentSource; included_field_groups: string[]; token_budget: number; estimated_tokens: number; within_budget: boolean; degradation: \"bounded_fields_and_rows\" | \"bounded_ranked_rows\" | \"bounded_sections\" | \"budget_row_compaction\" | \"recursive_budget_compaction\" | \"budget_receipt_only\" | \"standard_item\" | \"none\"; declaration_feasible: boolean; result_omitted: boolean; }" }, { "classification": "contract_data", @@ -13963,7 +13973,7 @@ "classification": "contract_data", "kind": "value", "name": "PM_TOOL_PARAMETERS_SCHEMA_VERSION", - "signature": "\"4.2.0\"" + "signature": "\"4.3.0\"" }, { "classification": "contract_data", @@ -14023,7 +14033,7 @@ "classification": "contract_data", "kind": "interface", "name": "PmContextIntentReceipt", - "signature": "export interface PmContextIntentReceipt { command: string; intent: string; source: PmContextIntentSource; included_field_groups: string[]; token_budget: number; estimated_tokens: number; within_budget: boolean; degradation: \"bounded_fields_and_rows\" | \"bounded_ranked_rows\" | \"bounded_sections\" | \"recursive_budget_compaction\" | \"budget_receipt_only\" | \"standard_item\" | \"none\"; }" + "signature": "export interface PmContextIntentReceipt { command: string; intent: string; source: PmContextIntentSource; included_field_groups: string[]; token_budget: number; estimated_tokens: number; within_budget: boolean; degradation: \"bounded_fields_and_rows\" | \"bounded_ranked_rows\" | \"bounded_sections\" | \"budget_row_compaction\" | \"recursive_budget_compaction\" | \"budget_receipt_only\" | \"standard_item\" | \"none\"; declaration_feasible: boolean; result_omitted: boolean; }" }, { "classification": "contract_data", diff --git a/src/cli/register-list-query.ts b/src/cli/register-list-query.ts index aaeb53bee..f234e947a 100644 --- a/src/cli/register-list-query.ts +++ b/src/cli/register-list-query.ts @@ -345,6 +345,10 @@ function registerListCommand( } command .option("--for ", "Apply a declared context intent projection") + .option( + "--token-budget ", + "Override the selected intent's maximum estimated output tokens", + ) .option("--type ", "Filter by item type") .option( "--tag ", @@ -474,6 +478,11 @@ function registerListCommand( "Alias for --assignee-filter", ); addHiddenOption(command, "--tree_depth ", "Alias for --tree-depth"); + addHiddenOption( + command, + "--token_budget ", + "Alias for --token-budget", + ); addHiddenOption( command, "--all", @@ -1129,6 +1138,10 @@ export function registerListQueryCommands( "(tag:/status:/type:/priority:) in the query are parsed as filters, e.g. 'auth tag:area:search status:open'.", ) .option("--for ", "Apply a declared context intent projection") + .option( + "--token-budget ", + "Override the selected intent's maximum estimated output tokens", + ) .option( "--mode ", "Search mode: keyword|semantic|hybrid (default: keyword)", @@ -1226,6 +1239,11 @@ export function registerListQueryCommands( registerContentAndGovernanceFilters(searchCommand); searchCommand.action(runSearchAction); addHiddenOption(searchCommand, "--tags ", "Alias for --tag"); + addHiddenOption( + searchCommand, + "--token_budget ", + "Alias for --token-budget", + ); } if (shouldRegister("eval")) { @@ -1257,6 +1275,10 @@ export function registerListQueryCommands( .command("get") .argument("", "Item id") .option("--for ", "Apply a declared context intent projection") + .option( + "--token-budget ", + "Override the selected intent's maximum estimated output tokens", + ) .option( "--depth ", "Detail depth: brief|standard|deep|full (full aliases deep; default: standard)", @@ -1282,6 +1304,11 @@ export function registerListQueryCommands( .description("Show item details by ID.") .action(runGetAction); addHiddenOption(getCommand, "--tree_depth ", "Alias for --tree-depth"); + addHiddenOption( + getCommand, + "--token_budget ", + "Alias for --token-budget", + ); } if (shouldRegister("history")) { diff --git a/src/sdk/cli-contracts/flag-contracts.ts b/src/sdk/cli-contracts/flag-contracts.ts index 81bb958d9..227bd4442 100644 --- a/src/sdk/cli-contracts/flag-contracts.ts +++ b/src/sdk/cli-contracts/flag-contracts.ts @@ -186,6 +186,7 @@ export const LIST_FILTER_FLAG_CONTRACTS: CliFlagContract[] = withCursorSemantics( [ { flag: "--for", value_name: "intent" }, + { flag: "--token-budget", aliases: ["--token_budget"] }, { flag: "--status", list: true }, { flag: "--type" }, { flag: "--tag", aliases: ["--tags"] }, @@ -233,6 +234,7 @@ export const LIST_FILTER_FLAG_CONTRACTS: CliFlagContract[] = ], new Set([ "--limit", + "--token-budget", "--offset", "--after", "--no-truncate", @@ -1483,6 +1485,7 @@ export const CONTEXT_FLAG_CONTRACTS: CliFlagContract[] = withCursorSemantics( /** Public contract for get flag contracts, shared by SDK and presentation-layer consumers. */ export const GET_FLAG_CONTRACTS: CliFlagContract[] = [ { flag: "--for", value_name: "intent" }, + { flag: "--token-budget", aliases: ["--token_budget"] }, { flag: "--depth" }, { flag: "--full" }, { flag: "--fields", list: true }, @@ -1577,6 +1580,7 @@ export const NEXT_FLAG_CONTRACTS: CliFlagContract[] = [ export const SEARCH_FLAG_CONTRACTS: CliFlagContract[] = withCursorSemantics( [ { flag: "--for", value_name: "intent" }, + { flag: "--token-budget", aliases: ["--token_budget"] }, { flag: "--mode" }, { flag: "--semantic" }, { flag: "--hybrid" }, @@ -1617,6 +1621,7 @@ export const SEARCH_FLAG_CONTRACTS: CliFlagContract[] = withCursorSemantics( "--fields", "--format", "--limit", + "--token-budget", "--after", ]), ); diff --git a/src/sdk/cli-contracts/tool-option-contracts.ts b/src/sdk/cli-contracts/tool-option-contracts.ts index b1b29ae31..d5a9c732c 100644 --- a/src/sdk/cli-contracts/tool-option-contracts.ts +++ b/src/sdk/cli-contracts/tool-option-contracts.ts @@ -106,6 +106,7 @@ const TOOL_CONTENT_PRESENCE_OPTION_CONTRACTS: readonly SharedToolOptionFlagContr /** Public contract for tool list filter option contracts, shared by SDK and presentation-layer consumers. */ export const TOOL_LIST_FILTER_OPTION_CONTRACTS: ToolOptionFlagContract[] = [ { param: "for", flag: "--for" }, + { param: "tokenBudget", flag: "--token-budget" }, ...cloneOptionContracts(TOOL_ITEM_BASE_FILTER_OPTION_CONTRACTS), ...cloneOptionContracts(TOOL_LIST_WINDOW_FILTER_OPTION_CONTRACTS), { param: "ids", flag: "--ids" }, @@ -134,6 +135,7 @@ export const TOOL_AGGREGATE_OPTION_CONTRACTS: ToolOptionFlagContract[] = [ /** Public contract for tool search filter option contracts, shared by SDK and presentation-layer consumers. */ export const TOOL_SEARCH_FILTER_OPTION_CONTRACTS: ToolOptionFlagContract[] = [ { param: "for", flag: "--for" }, + { param: "tokenBudget", flag: "--token-budget" }, { param: "matchMode", flag: "--match-mode" }, { param: "minScore", flag: "--min-score" }, { param: "count", flag: "--count", booleanish: true }, diff --git a/src/sdk/cli-contracts/tool-parameter-tables.ts b/src/sdk/cli-contracts/tool-parameter-tables.ts index 4b2ed3bb2..c146287c6 100644 --- a/src/sdk/cli-contracts/tool-parameter-tables.ts +++ b/src/sdk/cli-contracts/tool-parameter-tables.ts @@ -1594,7 +1594,7 @@ export const PM_TOOL_PARAMETER_METADATA: Record< examples: [20, "40"], }, tokenBudget: { - description: "Maximum estimated output tokens for deps --format context.", + description: "Maximum estimated output tokens for the command output.", examples: [600, "1200"], }, cursor: { @@ -1730,6 +1730,12 @@ export const PM_TOOL_ACTION_SCOPED_PARAMETER_METADATA: Partial< Record > > = { + deps: { + tokenBudget: { + description: "Maximum estimated output tokens for deps --format context.", + examples: [600, "1200"], + }, + }, notes: { since: { description: diff --git a/src/sdk/cli-contracts/tool-schema.ts b/src/sdk/cli-contracts/tool-schema.ts index 4df7c5353..776f7aa08 100644 --- a/src/sdk/cli-contracts/tool-schema.ts +++ b/src/sdk/cli-contracts/tool-schema.ts @@ -516,6 +516,7 @@ const PM_TOOL_ACTION_SCHEMA_CONTRACTS: Record = required: ["id"], optional: [ "for", + "tokenBudget", "at", "depth", "full", @@ -1424,7 +1425,7 @@ function createLazyContractSchema( } /** Canonical version of the action-scoped strict MCP tool-parameters schema (`PM_TOOL_PARAMETERS_SCHEMA`). Exported as the single source of truth so the MCP server, the `pm contracts` command, SDK consumers, and the contract tests all bind to one constant instead of re-typing the `"4.0.2"` literal (pm-r9sz). Bump the patch/minor for additive, backward-compatible schema changes; bump the MAJOR for breaking changes — the major also drives the `$id` `tool-parameters-v{major}` slug, so the two never drift. */ -export const PM_TOOL_PARAMETERS_SCHEMA_VERSION = "4.2.0" as const; +export const PM_TOOL_PARAMETERS_SCHEMA_VERSION = "4.3.0" as const; /** * Major component of {@link PM_TOOL_PARAMETERS_SCHEMA_VERSION}, used to build the diff --git a/src/sdk/context-intent-contracts.ts b/src/sdk/context-intent-contracts.ts index 1e0555fbc..3bd365172 100644 --- a/src/sdk/context-intent-contracts.ts +++ b/src/sdk/context-intent-contracts.ts @@ -57,10 +57,15 @@ export interface PmContextIntentReceipt { | "bounded_fields_and_rows" | "bounded_ranked_rows" | "bounded_sections" + | "budget_row_compaction" | "recursive_budget_compaction" | "budget_receipt_only" | "standard_item" | "none"; + /** Whether the declared ceiling can carry at least one useful result row. */ + declaration_feasible: boolean; + /** True only when no useful result survived the declared ceiling. */ + result_omitted: boolean; } /** Built-in intent projections shared by CLI, SDK, MCP, and package authors. */ @@ -109,14 +114,14 @@ export const PM_CONTEXT_INTENT_CONTRACTS: readonly PmContextIntentContract[] = command: "list", intent: "triage", description: - "The first two compact governance, ownership, priority, and blocker rows for triage.", + "A budget-derived page of compact governance, ownership, priority, and blocker rows for triage.", included_field_groups: [ "identity", "governance", "ownership", "dependencies", ], - token_budget: 1800, + token_budget: 3200, source: "core", }, { @@ -132,7 +137,7 @@ export const PM_CONTEXT_INTENT_CONTRACTS: readonly PmContextIntentContract[] = command: "search", intent: "discover", description: - "The first fifteen ranked canonical lineage candidates with compact match evidence.", + "A budget-derived page of ranked canonical lineage candidates with compact match evidence.", included_field_groups: ["identity", "status", "lineage", "match"], token_budget: 1800, source: "core", @@ -331,13 +336,24 @@ const CONTEXT_INTENT_DEFAULT_APPLIERS: Readonly< ? ["activity", "progress", "blockers"] : ["hierarchy", "blockers", "activity"]; } + const tokenBudget = resolveIntentTokenBudget( + projected.tokenBudget, + contract.token_budget, + ); + const derivedLimit = String( + Math.max(1, Math.min(20, Math.floor((tokenBudget - 800) / 500))), + ); + if (projected.limit === undefined) projected.limit = derivedLimit; + if (projected.activityLimit === undefined) { + projected.activityLimit = derivedLimit; + } }, get: (projected) => { if (projected.depth === undefined && projected.fields === undefined) { projected.depth = "standard"; } }, - list: (projected) => { + list: (projected, contract) => { if ( projected.brief === undefined && projected.compact === undefined && @@ -345,14 +361,22 @@ const CONTEXT_INTENT_DEFAULT_APPLIERS: Readonly< projected.fields === undefined ) { projected.fields = - "id,title,status,type,priority,parent,assignee,reviewer,risk,confidence,sprint,release,blocked_by,blocked_reason,dependencies,updated_at"; + "id,title,status,type,priority,parent,assignee,risk,blocked_by"; + } + if (projected.limit === undefined) { + const tokenBudget = resolveIntentTokenBudget( + projected.tokenBudget, + contract.token_budget, + ); + projected.limit = String( + Math.max(2, Math.min(100, Math.floor((tokenBudget - 520) / 128))), + ); } - if (projected.limit === undefined) projected.limit = "2"; }, next: (projected) => { if (projected.readyOnly === undefined) projected.readyOnly = true; }, - search: (projected) => { + search: (projected, contract) => { if ( projected.compact === undefined && projected.full === undefined && @@ -360,7 +384,15 @@ const CONTEXT_INTENT_DEFAULT_APPLIERS: Readonly< ) { projected.compact = true; } - if (projected.limit === undefined) projected.limit = "15"; + if (projected.limit === undefined) { + const tokenBudget = resolveIntentTokenBudget( + projected.tokenBudget, + contract.token_budget, + ); + projected.limit = String( + Math.max(2, Math.min(100, Math.floor((tokenBudget - 480) / 80))), + ); + } }, }; @@ -369,9 +401,37 @@ export function applyContextIntentProjection( command: "context" | "get" | "list" | "next" | "search", options: Record, ): Record { - if (typeof options.for !== "string") return options; + const tokenBudget = options.tokenBudget ?? options.token_budget; + if (typeof options.for !== "string") { + if ( + tokenBudget !== undefined && + (command === "get" || command === "list" || command === "search") + ) { + throw new PmCliError( + "--token-budget requires a declared context intent selected with --for", + EXIT_CODE.USAGE, + { + code: "missing_required_option", + field: "for", + required: "Select a context intent with --for when setting --token-budget.", + why: "A token-budget override has no projection contract to constrain without a selected intent.", + nextSteps: ["Retry with --for --token-budget , or omit --token-budget."], + }, + ); + } + if (options.tokenBudget !== undefined || options.token_budget === undefined) { + return options; + } + const projected: Record = { ...options, tokenBudget }; + delete projected.token_budget; + return projected; + } const contract = resolveContextIntentContract(command, options.for)!; const projected = { ...options }; + if (projected.tokenBudget === undefined && tokenBudget !== undefined) { + projected.tokenBudget = tokenBudget; + } + delete projected.token_budget; if (projected.tokenBudget === undefined) { projected.tokenBudget = String(contract.token_budget); } @@ -455,6 +515,82 @@ function updateContextIntentEstimate( } } +const CONTEXT_INTENT_ROW_KEYS: Readonly< + Record +> = { + context: [ + "high_level", + "low_level", + "blocked_fallback", + "recently_created", + "unparented", + "hierarchy", + "activity", + "blockers", + ], + get: ["children"], + list: ["items"], + next: ["ready", "decision_needed", "blocked", "held_by_others"], + search: ["items"], +}; + +/** Reduce root row collections deterministically while retaining at least one useful row. */ +function compactContextIntentRows( + command: BuiltInContextIntentCommand, + projected: Record, + receipt: PmContextIntentReceipt, +): boolean { + if ( + command !== "next" || + typeof projected.next_cursor === "string" + ) { + return false; + } + let compacted = false; + for (;;) { + updateContextIntentEstimate(projected, receipt); + if (receipt.estimated_tokens <= receipt.token_budget) return compacted; + const candidate = CONTEXT_INTENT_ROW_KEYS[command] + .map((key) => ({ + key, + rows: Array.isArray(projected[key]) ? projected[key] : [], + })) + .filter(({ rows }) => rows.length > 0) + .sort( + (left, right) => + right.rows.length - left.rows.length || + left.key.localeCompare(right.key), + )[0]; + if (candidate === undefined) return compacted; + const retainedTotal = CONTEXT_INTENT_ROW_KEYS[command].reduce( + (total, key) => + total + (Array.isArray(projected[key]) ? projected[key].length : 0), + 0, + ); + if (retainedTotal <= 1) return compacted; + const removableRows = Math.min( + candidate.rows.length, + retainedTotal - 1, + ); + const candidateBytes = Buffer.byteLength( + JSON.stringify(candidate.rows), + "utf8", + ); + const estimatedBytesPerRow = Math.max( + 1, + Math.ceil(candidateBytes / candidate.rows.length), + ); + const excessBytes = + (receipt.estimated_tokens - receipt.token_budget) * 4; + const removalCount = Math.min( + removableRows, + Math.max(1, Math.ceil(excessBytes / estimatedBytesPerRow)), + ); + candidate.rows.splice(-removalCount, removalCount); + compacted = true; + } +} + /** Attach budget and degradation evidence for a selected built-in read intent. */ export function attachContextIntentReceipt< Result extends Record, @@ -480,6 +616,8 @@ export function attachContextIntentReceipt< estimated_tokens: 0, within_budget: true, degradation: CONTEXT_INTENT_DEGRADATIONS[builtInCommand], + declaration_feasible: true, + result_omitted: false, }; let projected: Record = { ...result, @@ -494,23 +632,77 @@ export function attachContextIntentReceipt< }; updateContextIntentEstimate(projected, receipt); } + if ( + receipt.estimated_tokens > receipt.token_budget && + compactContextIntentRows(builtInCommand, projected, receipt) + ) { + receipt.degradation = "budget_row_compaction"; + updateContextIntentEstimate(projected, receipt); + } if (receipt.estimated_tokens > receipt.token_budget) { receipt.degradation = "budget_receipt_only"; + receipt.declaration_feasible = false; + receipt.result_omitted = true; + receipt.within_budget = false; projected = { budget_exceeded: { omitted_result: true, - restore_with: "Repeat the original command without --for.", + reason: "declared_budget_infeasible", + restore_with: + "Increase --token-budget or narrow the request; the unprojected command may be larger.", }, context_intent: receipt, }; updateContextIntentEstimate(projected, receipt); } - receipt.within_budget = receipt.estimated_tokens <= receipt.token_budget; - updateContextIntentEstimate(projected, receipt); - receipt.within_budget = receipt.estimated_tokens <= receipt.token_budget; return projected as Result & { context_intent: PmContextIntentReceipt }; } +function collapseContinuationMetadata( + options: Record, + result: Record, +): Record { + if (typeof options.after !== "string" || options.after.length === 0) { + return result; + } + let fingerprint = "opaque_cursor"; + try { + const decoded = JSON.parse( + Buffer.from(options.after, "base64url").toString("utf8"), + ) as { fingerprint?: unknown }; + if (typeof decoded.fingerprint === "string") { + fingerprint = decoded.fingerprint; + } + } catch { + // Command-level cursor validation owns malformed cursors. The disclosure + // layer remains total for package-authored or opaque cursor formats. + } + const projected = { ...result }; + for (const key of [ + "applied_limit", + "completeness", + "context_intent", + "count", + "filters", + "has_more", + "now", + "omission_receipt", + "projection", + "row_contract", + "sorting", + "total", + "truncated", + ]) { + delete projected[key]; + } + projected.continuation_contract = { + fingerprint, + metadata: "reference", + restore_with: "omit --after", + }; + return projected; +} + /** Attach universal row, omission, and optional intent-budget contracts in rendering order. */ export function attachReadOutputContracts( command: string | undefined, @@ -521,10 +713,13 @@ export function attachReadOutputContracts( return typeof disclosedResult === "object" && disclosedResult !== null && !Array.isArray(disclosedResult) - ? attachContextIntentReceipt( - command ?? "", + ? collapseContinuationMetadata( options, - disclosedResult as Record, + attachContextIntentReceipt( + command ?? "", + options, + disclosedResult as Record, + ), ) : disclosedResult; } diff --git a/src/sdk/generated-error-code-catalog.ts b/src/sdk/generated-error-code-catalog.ts index 7f0b0359e..d959cd739 100644 --- a/src/sdk/generated-error-code-catalog.ts +++ b/src/sdk/generated-error-code-catalog.ts @@ -908,6 +908,7 @@ export const PM_ERROR_CODE_CATALOG = definePmErrorCodeCatalog([ "cli/commands/plan.ts", "cli/error-guidance.ts", "core/telemetry/observability.ts", + "sdk/context-intent-contracts.ts", ], }, { diff --git a/src/sdk/runtime.ts b/src/sdk/runtime.ts index 0c6332692..394e99953 100644 --- a/src/sdk/runtime.ts +++ b/src/sdk/runtime.ts @@ -2974,7 +2974,11 @@ async function runMcpCreateAction( ); return projectMutationResult( await runCreate(runnerOptions as never, ctx.global), - { changedFields, idOnly }, + { + changedFields, + compactEnvelope: changedFields === "compact" && !idOnly, + idOnly, + }, ); } @@ -3003,6 +3007,7 @@ async function runMcpCopyAction( ), { changedFields, + compactEnvelope: changedFields === "compact" && !idOnly, idOnly, }, ); @@ -3023,6 +3028,7 @@ async function runMcpUpdateAction( ), { changedFields, + compactEnvelope: changedFields === "compact" && !idOnly, idOnly, }, ); @@ -3047,7 +3053,11 @@ async function runMcpCloseAction( runnerOptions as never, ctx.global, ), - { changedFields, idOnly }, + { + changedFields, + compactEnvelope: changedFields === "compact" && !idOnly, + idOnly, + }, ); } @@ -3484,7 +3494,7 @@ function runMcpStatsAction(ctx: McpActionDispatchContext): Promise { async function runMcpAppendAction( ctx: McpActionDispatchContext, ): Promise { - const { changedFields, runnerOptions } = withMutationCompaction( + const { changedFields, idOnly, runnerOptions } = withMutationCompaction( ctx.args, ctx.options, ); @@ -3496,6 +3506,8 @@ async function runMcpAppendAction( ), { changedFields, + compactEnvelope: changedFields === "compact" && !idOnly, + idOnly, }, ); } @@ -3556,6 +3568,7 @@ async function runMcpRestoreAction( ), { changedFields, + compactEnvelope: changedFields === "compact" && !idOnly, idOnly, }, ); diff --git a/tests/fixtures/contracts/full.json b/tests/fixtures/contracts/full.json index fda92aaec..8cde4d77d 100644 --- a/tests/fixtures/contracts/full.json +++ b/tests/fixtures/contracts/full.json @@ -2592,6 +2592,12 @@ "flag": "--for", "value_name": "intent" }, + { + "aliases": [ + "--token_budget" + ], + "flag": "--token-budget" + }, { "flag": "--depth" }, @@ -3013,6 +3019,13 @@ "flag": "--for", "value_name": "intent" }, + { + "aliases": [ + "--token_budget" + ], + "cursor_semantics": "presentation", + "flag": "--token-budget" + }, { "flag": "--status", "list": true @@ -3237,6 +3250,13 @@ "flag": "--for", "value_name": "intent" }, + { + "aliases": [ + "--token_budget" + ], + "cursor_semantics": "presentation", + "flag": "--token-budget" + }, { "flag": "--status", "list": true @@ -3461,6 +3481,13 @@ "flag": "--for", "value_name": "intent" }, + { + "aliases": [ + "--token_budget" + ], + "cursor_semantics": "presentation", + "flag": "--token-budget" + }, { "flag": "--status", "list": true @@ -3685,6 +3712,13 @@ "flag": "--for", "value_name": "intent" }, + { + "aliases": [ + "--token_budget" + ], + "cursor_semantics": "presentation", + "flag": "--token-budget" + }, { "flag": "--status", "list": true @@ -3909,6 +3943,13 @@ "flag": "--for", "value_name": "intent" }, + { + "aliases": [ + "--token_budget" + ], + "cursor_semantics": "presentation", + "flag": "--token-budget" + }, { "flag": "--status", "list": true @@ -4133,6 +4174,13 @@ "flag": "--for", "value_name": "intent" }, + { + "aliases": [ + "--token_budget" + ], + "cursor_semantics": "presentation", + "flag": "--token-budget" + }, { "flag": "--status", "list": true @@ -4357,6 +4405,13 @@ "flag": "--for", "value_name": "intent" }, + { + "aliases": [ + "--token_budget" + ], + "cursor_semantics": "presentation", + "flag": "--token-budget" + }, { "flag": "--status", "list": true @@ -4581,6 +4636,13 @@ "flag": "--for", "value_name": "intent" }, + { + "aliases": [ + "--token_budget" + ], + "cursor_semantics": "presentation", + "flag": "--token-budget" + }, { "flag": "--status", "list": true @@ -6236,6 +6298,13 @@ "flag": "--for", "value_name": "intent" }, + { + "aliases": [ + "--token_budget" + ], + "cursor_semantics": "presentation", + "flag": "--token-budget" + }, { "flag": "--mode" }, @@ -9116,7 +9185,7 @@ }, { "command": "list", - "description": "The first two compact governance, ownership, priority, and blocker rows for triage.", + "description": "A budget-derived page of compact governance, ownership, priority, and blocker rows for triage.", "included_field_groups": [ "identity", "governance", @@ -9125,7 +9194,7 @@ ], "intent": "triage", "source": "core", - "token_budget": 1800 + "token_budget": 3200 }, { "command": "next", @@ -9139,7 +9208,7 @@ }, { "command": "search", - "description": "The first fifteen ranked canonical lineage candidates with compact match evidence.", + "description": "A budget-derived page of ranked canonical lineage candidates with compact match evidence.", "included_field_groups": [ "identity", "status", @@ -10144,7 +10213,8 @@ "cli/commands/create.ts", "cli/commands/plan.ts", "cli/error-guidance.ts", - "core/telemetry/observability.ts" + "core/telemetry/observability.ts", + "sdk/context-intent-contracts.ts" ], "stability": "stable" }, @@ -12493,7 +12563,7 @@ "type": "integer" } ], - "description": "Maximum estimated output tokens for deps --format context.", + "description": "Maximum estimated output tokens for the command output.", "examples": [ 600, "1200" @@ -14185,6 +14255,22 @@ ], "type": "number" }, + "tokenBudget": { + "anyOf": [ + { + "type": "string" + }, + { + "minimum": 1, + "type": "integer" + } + ], + "description": "Maximum estimated output tokens for the command output.", + "examples": [ + 600, + "1200" + ] + }, "tree": { "description": "When true for list/get actions, render recursive parent/child tree ordering.", "type": "boolean" @@ -15157,6 +15243,22 @@ "description": "When true for list actions, include only items updated since local midnight today.", "type": "boolean" }, + "tokenBudget": { + "anyOf": [ + { + "type": "string" + }, + { + "minimum": 1, + "type": "integer" + } + ], + "description": "Maximum estimated output tokens for the command output.", + "examples": [ + 600, + "1200" + ] + }, "tree": { "description": "When true for list/get actions, render recursive parent/child tree ordering.", "type": "boolean" @@ -17550,6 +17652,22 @@ "description": "For search action, require exact normalized title match for the full query string.", "type": "boolean" }, + "tokenBudget": { + "anyOf": [ + { + "type": "string" + }, + { + "minimum": 1, + "type": "integer" + } + ], + "description": "Maximum estimated output tokens for the command output.", + "examples": [ + 600, + "1200" + ] + }, "type": { "description": "Alias for options.type.", "type": "string" @@ -23593,6 +23711,22 @@ "description": "When true for list actions, include only items updated since local midnight today.", "type": "boolean" }, + "tokenBudget": { + "anyOf": [ + { + "type": "string" + }, + { + "minimum": 1, + "type": "integer" + } + ], + "description": "Maximum estimated output tokens for the command output.", + "examples": [ + 600, + "1200" + ] + }, "tree": { "description": "When true for list/get actions, render recursive parent/child tree ordering.", "type": "boolean" @@ -24100,6 +24234,22 @@ "description": "When true for list actions, include only items updated since local midnight today.", "type": "boolean" }, + "tokenBudget": { + "anyOf": [ + { + "type": "string" + }, + { + "minimum": 1, + "type": "integer" + } + ], + "description": "Maximum estimated output tokens for the command output.", + "examples": [ + 600, + "1200" + ] + }, "tree": { "description": "When true for list/get actions, render recursive parent/child tree ordering.", "type": "boolean" @@ -24607,6 +24757,22 @@ "description": "When true for list actions, include only items updated since local midnight today.", "type": "boolean" }, + "tokenBudget": { + "anyOf": [ + { + "type": "string" + }, + { + "minimum": 1, + "type": "integer" + } + ], + "description": "Maximum estimated output tokens for the command output.", + "examples": [ + 600, + "1200" + ] + }, "tree": { "description": "When true for list/get actions, render recursive parent/child tree ordering.", "type": "boolean" @@ -25114,6 +25280,22 @@ "description": "When true for list actions, include only items updated since local midnight today.", "type": "boolean" }, + "tokenBudget": { + "anyOf": [ + { + "type": "string" + }, + { + "minimum": 1, + "type": "integer" + } + ], + "description": "Maximum estimated output tokens for the command output.", + "examples": [ + 600, + "1200" + ] + }, "tree": { "description": "When true for list/get actions, render recursive parent/child tree ordering.", "type": "boolean" @@ -25621,6 +25803,22 @@ "description": "When true for list actions, include only items updated since local midnight today.", "type": "boolean" }, + "tokenBudget": { + "anyOf": [ + { + "type": "string" + }, + { + "minimum": 1, + "type": "integer" + } + ], + "description": "Maximum estimated output tokens for the command output.", + "examples": [ + 600, + "1200" + ] + }, "tree": { "description": "When true for list/get actions, render recursive parent/child tree ordering.", "type": "boolean" @@ -26128,6 +26326,22 @@ "description": "When true for list actions, include only items updated since local midnight today.", "type": "boolean" }, + "tokenBudget": { + "anyOf": [ + { + "type": "string" + }, + { + "minimum": 1, + "type": "integer" + } + ], + "description": "Maximum estimated output tokens for the command output.", + "examples": [ + 600, + "1200" + ] + }, "tree": { "description": "When true for list/get actions, render recursive parent/child tree ordering.", "type": "boolean" @@ -26635,6 +26849,22 @@ "description": "When true for list actions, include only items updated since local midnight today.", "type": "boolean" }, + "tokenBudget": { + "anyOf": [ + { + "type": "string" + }, + { + "minimum": 1, + "type": "integer" + } + ], + "description": "Maximum estimated output tokens for the command output.", + "examples": [ + 600, + "1200" + ] + }, "tree": { "description": "When true for list/get actions, render recursive parent/child tree ordering.", "type": "boolean" @@ -27142,6 +27372,22 @@ "description": "When true for list actions, include only items updated since local midnight today.", "type": "boolean" }, + "tokenBudget": { + "anyOf": [ + { + "type": "string" + }, + { + "minimum": 1, + "type": "integer" + } + ], + "description": "Maximum estimated output tokens for the command output.", + "examples": [ + 600, + "1200" + ] + }, "tree": { "description": "When true for list/get actions, render recursive parent/child tree ordering.", "type": "boolean" @@ -27617,7 +27863,7 @@ "type": "integer" } ], - "description": "Maximum estimated output tokens for deps --format context.", + "description": "Maximum estimated output tokens for the command output.", "examples": [ 600, "1200" @@ -27894,7 +28140,7 @@ "type": "integer" } ], - "description": "Maximum estimated output tokens for deps --format context.", + "description": "Maximum estimated output tokens for the command output.", "examples": [ 600, "1200" @@ -28029,6 +28275,22 @@ ], "type": "number" }, + "tokenBudget": { + "anyOf": [ + { + "type": "string" + }, + { + "minimum": 1, + "type": "integer" + } + ], + "description": "Maximum estimated output tokens for the command output.", + "examples": [ + 600, + "1200" + ] + }, "tree": { "description": "When true for list/get actions, render recursive parent/child tree ordering.", "type": "boolean" @@ -28423,6 +28685,22 @@ "description": "For search action, require exact normalized title match for the full query string.", "type": "boolean" }, + "tokenBudget": { + "anyOf": [ + { + "type": "string" + }, + { + "minimum": 1, + "type": "integer" + } + ], + "description": "Maximum estimated output tokens for the command output.", + "examples": [ + 600, + "1200" + ] + }, "type": { "description": "Item type name from the active runtime type registry.", "examples": [ @@ -35961,10 +36239,10 @@ ], "title": "pm-cli tool parameters (action-scoped strict schema)", "type": "object", - "x-schema-version": "4.2.0" + "x-schema-version": "4.3.0" }, "schema_id": "https://schema.unbrained.dev/pm-cli/tool-parameters-v4.schema.json", - "schema_version": "4.2.0", + "schema_version": "4.3.0", "selected": { "action": null, "availability_only": false, diff --git a/tests/integration/mcp-dynamic-package-actions.spec.ts b/tests/integration/mcp-dynamic-package-actions.spec.ts index 53780a21d..dd38cbc33 100644 --- a/tests/integration/mcp-dynamic-package-actions.spec.ts +++ b/tests/integration/mcp-dynamic-package-actions.spec.ts @@ -528,6 +528,7 @@ describe("MCP dynamic package actions", () => { path: context.pmPath, id, author: "mcp-agent", + fullChangedFields: true, options: { comment: "scalar comment from MCP", note: "scalar note from MCP", @@ -639,7 +640,7 @@ describe("MCP dynamic package actions", () => { }); }, 60_000); - it("compacts mutation changed_fields by default and restores them with options.full", async () => { + it("compacts mutation envelopes by default and restores full changed fields explicitly", async () => { await withTempPmPath(async (context) => { const compactCreate = await handleRequest({ jsonrpc: "2.0", @@ -660,12 +661,13 @@ describe("MCP dynamic package actions", () => { }); expect(compactCreate?.isError).not.toBe(true); const compactResult = (compactCreate?.structuredContent as { - result?: { item?: { id?: string }; changed_fields?: unknown; changed_field_count?: number }; + result?: { id?: string; item?: unknown; changed_fields?: unknown; changed_field_count?: number }; } | undefined)?.result; + expect(compactResult?.item).toBeUndefined(); expect(compactResult?.changed_fields).toBeUndefined(); expect(typeof compactResult?.changed_field_count).toBe("number"); expect(compactResult?.changed_field_count ?? 0).toBeGreaterThan(0); - const id = compactResult?.item?.id as string; + const id = compactResult?.id as string; expect(id).toBeTruthy(); const fullUpdate = await handleRequest({ @@ -725,6 +727,7 @@ describe("MCP dynamic package actions", () => { arguments: { path: context.pmPath, allowMissingParent: true, + fullChangedFields: true, options: { title: "MCP allow missing parent target", description: "MCP allow missing parent description", diff --git a/tests/integration/sdk-cli-contract-integrity.integration.spec.ts b/tests/integration/sdk-cli-contract-integrity.integration.spec.ts index 9884597b9..179c8e881 100644 --- a/tests/integration/sdk-cli-contract-integrity.integration.spec.ts +++ b/tests/integration/sdk-cli-contract-integrity.integration.spec.ts @@ -390,9 +390,10 @@ describe("SDK and CLI contract integrity", () => { priority: "2", message: "tool contract identity parity", }, - })) as { item: { id: string } }; + })) as { id: string; item?: unknown }; - expect(created.item.id).toBe("pm-tool-explicit-id"); + expect(created).toMatchObject({ id: "pm-tool-explicit-id" }); + expect(created.item).toBeUndefined(); }); }); @@ -408,6 +409,7 @@ describe("SDK and CLI contract integrity", () => { author: "mcp-copy-author", message: "top-level copy message", path: context.pmPath, + fullChangedFields: true, })) as { item: { id: string; title: string } }; expect(copied.item.title).toBe("Top-level copy title"); @@ -425,6 +427,7 @@ describe("SDK and CLI contract integrity", () => { author: "top-level-author", options: { author: "nested-option-author" }, path: context.pmPath, + fullChangedFields: true, })) as { item: { id: string } }; const optionAuthorHistory = context.runCli( ["history", optionAuthorCopy.item.id, "--full", "--json"], diff --git a/tests/unit/cli/context-intent-registration.spec.ts b/tests/unit/cli/context-intent-registration.spec.ts index 15f3f25f6..e380cfd7d 100644 --- a/tests/unit/cli/context-intent-registration.spec.ts +++ b/tests/unit/cli/context-intent-registration.spec.ts @@ -14,6 +14,8 @@ describe("read command context intent registration", () => { ).toMatchObject({ depth: "standard", section: ["hierarchy", "blockers", "activity"], + limit: "3", + activityLimit: "3", tokenBudget: "2400", }); expect( @@ -27,9 +29,9 @@ describe("read command context intent registration", () => { }), ).toMatchObject({ fields: - "id,title,status,type,priority,parent,assignee,reviewer,risk,confidence,sprint,release,blocked_by,blocked_reason,dependencies,updated_at", - limit: "2", - tokenBudget: "1800", + "id,title,status,type,priority,parent,assignee,risk,blocked_by", + limit: "20", + tokenBudget: "3200", }); expect( applyContextIntentProjection("next", { @@ -40,7 +42,7 @@ describe("read command context intent registration", () => { applyContextIntentProjection("search", { for: "discover", }), - ).toMatchObject({ compact: true, limit: "15", tokenBudget: "1800" }); + ).toMatchObject({ compact: true, limit: "16", tokenBudget: "1800" }); }); it("preserves explicit projection and token options", () => { @@ -112,7 +114,7 @@ describe("read command context intent registration", () => { context_intent: { command: "list", intent: "triage", - token_budget: 1800, + token_budget: 3200, within_budget: true, degradation: "bounded_fields_and_rows", }, @@ -136,7 +138,9 @@ describe("read command context intent registration", () => { ); expect(result.context_intent).toMatchObject({ degradation: "budget_receipt_only", - within_budget: true, + declaration_feasible: false, + result_omitted: true, + within_budget: false, }); expect(result.context_intent!.estimated_tokens).toBeLessThanOrEqual(1_200); expect(result).not.toHaveProperty("recommended"); diff --git a/tests/unit/commands/query-pagination.spec.ts b/tests/unit/commands/query-pagination.spec.ts index 2cdbca11a..482ed7f35 100644 --- a/tests/unit/commands/query-pagination.spec.ts +++ b/tests/unit/commands/query-pagination.spec.ts @@ -8,6 +8,10 @@ interface PageResult { next_cursor?: string; has_more?: boolean; truncated?: boolean; + continuation_contract?: { + fingerprint: string; + metadata: "reference"; + }; } function createPaginationItems( @@ -75,6 +79,10 @@ describe("query cursor pagination", () => { ); const secondList = secondListRun.json as PageResult; expect(secondListRun.code).toBe(0); + expect(secondList.continuation_contract).toMatchObject({ + fingerprint: expect.any(String), + metadata: "reference", + }); expect( secondList.items?.some((item) => firstList.items?.some((first) => first.id === item.id), @@ -102,6 +110,10 @@ describe("query cursor pagination", () => { ); const secondSearch = secondSearchRun.json as PageResult; expect(secondSearchRun.code).toBe(0); + expect(secondSearch.continuation_contract).toMatchObject({ + fingerprint: expect.any(String), + metadata: "reference", + }); expect( secondSearch.items?.some((item) => firstSearch.items?.some((first) => first.id === item.id), @@ -130,6 +142,10 @@ describe("query cursor pagination", () => { ); const secondContext = secondContextRun.json as PageResult; expect(secondContextRun.code).toBe(0); + expect(secondContext.continuation_contract).toMatchObject({ + fingerprint: expect.any(String), + metadata: "reference", + }); expect( focusIds(secondContext).some((id) => focusIds(firstContext).includes(id)), ).toBe(false); diff --git a/tests/unit/mcp/mutation-envelope-parity.spec.ts b/tests/unit/mcp/mutation-envelope-parity.spec.ts new file mode 100644 index 000000000..9adf30671 --- /dev/null +++ b/tests/unit/mcp/mutation-envelope-parity.spec.ts @@ -0,0 +1,125 @@ +import { describe, expect, it } from "vitest"; +import { handleRequest } from "../../../src/mcp/server.js"; +import { withTempPmPath } from "../../helpers/withTempPmPath.js"; + +/** Verifies that the unavoidable MCP tool result uses the same lean mutation contract as the CLI default. */ +describe("MCP mutation envelope parity", () => { + it("returns the CLI default create shape without an opt-in flag", async () => { + await withTempPmPath(async (context) => { + const cli = context.runCli( + [ + "create", + "--json", + "--title", + "CLI parity", + "--type", + "Task", + "--status", + "open", + ], + { expectJson: true, preserveDefaultMutationOutput: true }, + ); + expect(cli.code).toBe(0); + const cliResult = cli.json as Record; + + const response = (await handleRequest({ + jsonrpc: "2.0", + id: 1, + method: "tools/call", + params: { + name: "pm_create", + arguments: { + path: context.pmPath, + title: "MCP parity", + type: "Task", + status: "open", + }, + }, + })) as { + structuredContent: { result: Record }; + }; + const mcpResult = response.structuredContent.result; + + expect(Object.keys(mcpResult).sort()).toEqual( + Object.keys(cliResult).sort(), + ); + expect(mcpResult).toMatchObject({ + id: expect.stringMatching(/^pm-/), + status: "open", + changed_field_count: 10, + }); + expect(mcpResult).not.toHaveProperty("item"); + expect(Buffer.byteLength(JSON.stringify(mcpResult))).toBeLessThanOrEqual( + Buffer.byteLength(JSON.stringify(cliResult)), + ); + }); + }); + + it("preserves the full mutation envelope only when explicitly requested", async () => { + await withTempPmPath(async (context) => { + const response = (await handleRequest({ + jsonrpc: "2.0", + id: 2, + method: "tools/call", + params: { + name: "pm_create", + arguments: { + path: context.pmPath, + title: "Full MCP mutation", + type: "Task", + status: "open", + fullChangedFields: true, + }, + }, + })) as { + structuredContent: { result: Record }; + }; + expect(response.structuredContent.result).toMatchObject({ + item: { title: "Full MCP mutation", status: "open" }, + changed_fields: expect.any(Array), + }); + expect(response.structuredContent.result).not.toHaveProperty( + "changed_field_count", + ); + }); + }); + + it("honors idOnly for append through the aggregated pm_run surface", async () => { + await withTempPmPath(async (context) => { + const created = (await handleRequest({ + jsonrpc: "2.0", + id: 3, + method: "tools/call", + params: { + name: "pm_create", + arguments: { + path: context.pmPath, + title: "Append id-only parity", + type: "Task", + status: "open", + }, + }, + })) as { structuredContent: { result: { id: string } } }; + const response = (await handleRequest({ + jsonrpc: "2.0", + id: 4, + method: "tools/call", + params: { + name: "pm_run", + arguments: { + action: "append", + path: context.pmPath, + id: created.structuredContent.result.id, + body: "Appended through pm_run.", + idOnly: true, + }, + }, + })) as { structuredContent: { result: Record } }; + + expect(response.structuredContent.result).toEqual({ + id: created.structuredContent.result.id, + status: "open", + }); + }); + }); +}); diff --git a/tests/unit/scripts/release/token-budget-gate.spec.ts b/tests/unit/scripts/release/token-budget-gate.spec.ts index 242a4f047..ec89d4b5c 100644 --- a/tests/unit/scripts/release/token-budget-gate.spec.ts +++ b/tests/unit/scripts/release/token-budget-gate.spec.ts @@ -17,6 +17,14 @@ type TokenBudgetMeasurement = { scale_tier?: string; command?: string; contract_max_estimated_tokens?: number; + intent?: boolean; + intent_receipt?: { + declaration_feasible: boolean; + result_omitted: boolean; + within_budget: boolean; + estimated_tokens: number; + token_budget: number; + }; }; type TokenBudgetManifest = { @@ -89,6 +97,11 @@ const CORPUS_IDS = [ "validate-counts", "search-inline-default", "search-inline-json", + "context-intent-orient", + "get-intent-inspect", + "list-intent-triage", + "next-intent-execute", + "search-intent-discover", ]; function manifestForBudget(maxBytes: number): string { @@ -110,6 +123,11 @@ function manifestForBudget(maxBytes: number): string { ["validate-counts", "validate"], ["search-inline-default", "search"], ["search-inline-json", "search"], + ["context-intent-orient", "context"], + ["get-intent-inspect", "get"], + ["list-intent-triage", "list"], + ["next-intent-execute", "next"], + ["search-intent-discover", "search"], ]); return JSON.stringify({ version: 2, @@ -161,6 +179,28 @@ function commandStdout(args: string[]): string { if (joined.includes("activity --json --full --unbounded")) { return "x".repeat(20_000); } + if (joined.includes("--for") && joined.includes("--token-budget 256")) { + return JSON.stringify({ + context_intent: { + declaration_feasible: false, + result_omitted: true, + within_budget: false, + estimated_tokens: 280, + token_budget: 256, + }, + }); + } + if (joined.includes("--for")) { + return JSON.stringify({ + context_intent: { + declaration_feasible: true, + result_omitted: false, + within_budget: true, + estimated_tokens: 100, + token_budget: 1_200, + }, + }); + } return `output for ${joined}`; } @@ -410,6 +450,127 @@ describe("scripts/release/token-budget-gate", () => { ).toEqual([ "context-answer: 5 estimated tokens exceeds context contract 4 tokens (context)", ]); + + expect( + mod.compareBudgets( + [ + { + id: "context-intent", + args: ["context", "--for", "orient"], + kind: "answer", + command: "context", + contract_max_estimated_tokens: 4_000, + bytes: 400, + estimated_tokens: 100, + intent: true, + intent_receipt: { + declaration_feasible: false, + result_omitted: true, + within_budget: false, + estimated_tokens: 100, + token_budget: 2_400, + }, + }, + ], + { + ...manifest, + budgets: [ + { + id: "context-intent", + args: ["context", "--for", "orient"], + kind: "answer", + scale_tier: "medium", + baseline_bytes: 400, + baseline_estimated_tokens: 100, + command: "context", + contract_max_estimated_tokens: 4_000, + }, + ], + }, + ), + ).toEqual([ + "context-intent: intent receipt did not prove a feasible delivered result (context --for orient)", + ]); + + const intentManifest = { + ...manifest, + budgets: [ + { + id: "context-intent", + args: ["context", "--for", "orient"], + kind: "answer", + scale_tier: "medium", + baseline_bytes: 400, + baseline_estimated_tokens: 100, + command: "context", + contract_max_estimated_tokens: 4_000, + }, + ], + }; + for (const intentReceipt of [ + { + declaration_feasible: true, + result_omitted: false, + within_budget: true, + estimated_tokens: "100", + token_budget: 2_400, + }, + { + declaration_feasible: true, + result_omitted: false, + within_budget: true, + estimated_tokens: 100, + token_budget: Number.NaN, + }, + ]) { + expect( + mod.compareBudgets( + [ + { + id: "context-intent", + args: ["context", "--for", "orient"], + kind: "answer", + command: "context", + contract_max_estimated_tokens: 4_000, + bytes: 400, + estimated_tokens: 100, + intent: true, + intent_receipt: intentReceipt, + }, + ], + intentManifest, + ), + ).toEqual([ + "context-intent: intent receipt did not prove a feasible delivered result (context --for orient)", + ]); + } + + expect( + mod.compareBudgets( + [ + { + id: "context-intent", + args: ["context", "--for", "orient"], + kind: "answer", + command: "context", + contract_max_estimated_tokens: 4_000, + bytes: 10_000, + estimated_tokens: 2_500, + intent: true, + intent_receipt: { + declaration_feasible: true, + result_omitted: false, + within_budget: true, + estimated_tokens: 100, + token_budget: 2_400, + }, + }, + ], + intentManifest, + ), + ).toEqual([ + "context-intent: intent receipt did not prove a feasible delivered result (context --for orient)", + ]); }); it("runs direct update mode against a deterministic fixture corpus", async () => { @@ -432,7 +593,7 @@ describe("scripts/release/token-budget-gate", () => { "scripts/release/token-budget-gate.mjs", ); - expect(runtime.runCommand).toHaveBeenCalledTimes(65); + expect(runtime.runCommand).toHaveBeenCalledTimes(71); const runOptions = runtime.runCommand.mock.calls[0]?.[2] as | { env?: Record } | undefined; @@ -464,7 +625,7 @@ describe("scripts/release/token-budget-gate", () => { mod.main(); expect(log).toHaveBeenCalledWith( - "Token budget gate passed (23 surfaces checked; unbounded negative control 5000 tokens).", + "Token budget gate passed (28 surfaces checked; unbounded negative control 5000 tokens; infeasible intent receipt verified).", ); }); @@ -480,7 +641,7 @@ describe("scripts/release/token-budget-gate", () => { path.join("/repo", "scripts", "release", "token-budgets.json"), ); expect(log).toHaveBeenCalledWith( - "Token budget gate passed (23 surfaces checked; unbounded negative control 5000 tokens).", + "Token budget gate passed (28 surfaces checked; unbounded negative control 5000 tokens; infeasible intent receipt verified).", ); }); @@ -571,6 +732,25 @@ describe("scripts/release/token-budget-gate", () => { ); }); + it("fails when the infeasible intent control claims success", async () => { + mockRuntime({ + manifestText: manifestForBudget(10_000), + stdout: (args) => + args.join(" ").includes("--for triage --token-budget 256") + ? JSON.stringify({ + context_intent: { + declaration_feasible: true, + result_omitted: false, + within_budget: true, + }, + }) + : commandStdout(args), + }); + await expect(loadModule().then((mod) => mod.main())).rejects.toThrow( + "intent-negative-control: infeasible 256-token list declaration", + ); + }); + it("fails when an answer command has no declared contract ceiling", async () => { mockRuntime({ manifestText: manifestForBudget(10_000), diff --git a/tests/unit/scripts/smoke-claude-plugin.spec.ts b/tests/unit/scripts/smoke-claude-plugin.spec.ts index 41282031c..4e8c67cd7 100644 --- a/tests/unit/scripts/smoke-claude-plugin.spec.ts +++ b/tests/unit/scripts/smoke-claude-plugin.spec.ts @@ -47,6 +47,7 @@ interface SmokeOverrides { pluginJson?: unknown; initResult?: unknown; tools?: string[]; + createResult?: unknown; getResult?: unknown; existsSync?: () => boolean; execSync?: () => string; @@ -64,7 +65,9 @@ function setupSmoke(overrides: SmokeOverrides = {}) { return {}; }); const callTool = vi.fn(async (toolName: string) => { - if (toolName === "pm_create") return { item: { id: "pm-claude-smoke" } }; + if (toolName === "pm_create") { + return overrides.createResult ?? { id: "pm-claude-smoke", status: "open", changed_field_count: 10 }; + } if (toolName === "pm_get") { return ( overrides.getResult ?? { @@ -157,6 +160,16 @@ describe("smoke-claude-plugin", () => { overrides: { tools: [...REQUIRED_TOOLS, "pm_extra"] } as SmokeOverrides, expected: /tools but the smoke expects/, }, + { + name: "verbose create envelope", + overrides: { createResult: { item: { id: "pm-claude-smoke" } } } as SmokeOverrides, + expected: /pm_create default must use the lean mutation envelope/, + }, + { + name: "create missing id", + overrides: { createResult: { id: "", status: "open", changed_field_count: 10 } } as SmokeOverrides, + expected: /missing a non-empty id/, + }, { name: "status not in_progress", overrides: { getResult: { item: { status: "open" }, linked: { files: [{}], tests: [{}] } } } as SmokeOverrides, diff --git a/tests/unit/sdk/context-intent-contracts.spec.ts b/tests/unit/sdk/context-intent-contracts.spec.ts index bfe1bf9f0..a64bf70de 100644 --- a/tests/unit/sdk/context-intent-contracts.spec.ts +++ b/tests/unit/sdk/context-intent-contracts.spec.ts @@ -1,10 +1,11 @@ -import { describe, expect, it } from "vitest"; +import { describe, expect, it, vi } from "vitest"; import { EXIT_CODE } from "../../../src/core/shared/constants.js"; import { PmCliError } from "../../../src/core/shared/errors.js"; import { PM_CONTEXT_INTENT_CONTRACTS, applyContextIntentProjection, attachContextIntentReceipt, + attachReadOutputContracts, composeContextIntentContracts, resolveContextIntentContract, } from "../../../src/sdk/context-intent-contracts.js"; @@ -173,11 +174,15 @@ describe("context intent contracts", () => { for: "handoff", depth: "full", section: ["decisions"], + limit: "7", + activityLimit: "6", tokenBudget: "9999", }), ).toMatchObject({ depth: "full", section: ["decisions"], + limit: "7", + activityLimit: "6", tokenBudget: "9999", }); expect( @@ -185,6 +190,8 @@ describe("context intent contracts", () => { ).toMatchObject({ depth: "deep", section: ["activity", "progress", "blockers"], + limit: "2", + activityLimit: "2", }); expect( applyContextIntentProjection("list", { @@ -200,6 +207,27 @@ describe("context intent contracts", () => { limit: "8", }), ).toMatchObject({ full: true, limit: "8" }); + expect( + applyContextIntentProjection("list", { + for: "triage", + tokenBudget: "1800", + }), + ).toMatchObject({ limit: "10" }); + expect( + applyContextIntentProjection("list", { + for: "triage", + token_budget: "1800", + }), + ).toMatchObject({ limit: "10", tokenBudget: "1800" }); + expect( + applyContextIntentProjection("context", { token_budget: "900" }), + ).toEqual({ tokenBudget: "900" }); + expect( + applyContextIntentProjection("list", { + for: "triage", + tokenBudget: "3000", + }), + ).toMatchObject({ limit: "19" }); expect( attachContextIntentReceipt("list-open", { for: "triage" }, { items: [] }), ).toMatchObject({ @@ -237,6 +265,21 @@ describe("context intent contracts", () => { ).toEqual({}); }); + it("rejects a token-budget override without a selected intent", () => { + for (const override of [ + { tokenBudget: "1200" }, + { token_budget: "1200" }, + ]) { + expect(() => applyContextIntentProjection("list", override)).toThrow( + expect.objectContaining>({ + code: "missing_required_option", + exitCode: EXIT_CODE.USAGE, + context: expect.objectContaining({ field: "for" }), + }), + ); + } + }); + it("falls back to a bounded receipt when recursive compaction cannot fit", () => { const oversized = Object.fromEntries( Array.from({ length: 2500 }, (_, index) => [`field_${index}`, index]), @@ -249,11 +292,13 @@ describe("context intent contracts", () => { expect(projected).toMatchObject({ budget_exceeded: { omitted_result: true, - restore_with: "Repeat the original command without --for.", + reason: "declared_budget_infeasible", }, context_intent: { degradation: "budget_receipt_only", - within_budget: true, + declaration_feasible: false, + result_omitted: true, + within_budget: false, }, }); expect(projected.context_intent!.estimated_tokens).toBeLessThanOrEqual( @@ -302,7 +347,7 @@ describe("context intent contracts", () => { ); }); - it("returns invocation-safe recovery guidance for positional reads", () => { + it("returns bounded recovery guidance instead of recommending an unprojected retry", () => { const oversized = Object.fromEntries( Array.from({ length: 2500 }, (_, index) => [`field_${index}`, index]), ); @@ -314,13 +359,14 @@ describe("context intent contracts", () => { attachContextIntentReceipt(command, { for: intent }, oversized), ).toMatchObject({ budget_exceeded: { - restore_with: "Repeat the original command without --for.", + restore_with: + "Increase --token-budget or narrow the request; the unprojected command may be larger.", }, }); } }); - it("never drops result rows while compacting explanatory strings", () => { + it("retains useful rows through an intermediate budget-compaction tier", () => { const recommended = Array.from({ length: 20 }, (_, index) => ({ id: `pm-${index}`, explanation: "x".repeat(2_000), @@ -328,17 +374,184 @@ describe("context intent contracts", () => { const projected = attachContextIntentReceipt( "next", { for: "execute" }, - { recommended, count: recommended.length, has_more: false }, + { + recommended: recommended[0], + ready: recommended.slice(1), + blocked: recommended.slice(1, 6), + decision_needed: recommended.slice(6, 11), + count: recommended.length, + has_more: false, + }, + ); + expect(projected.context_intent).toMatchObject({ + degradation: "budget_row_compaction", + declaration_feasible: true, + result_omitted: false, + within_budget: true, + }); + expect(projected.recommended).toMatchObject({ id: "pm-0" }); + expect(projected.ready.length).toBeGreaterThanOrEqual(1); + expect(projected.ready.length).toBeLessThan(recommended.length - 1); + expect(projected).toMatchObject({ has_more: false }); + }); + + it("batches large row compaction without serializing the full result once per removed row", () => { + const stringify = vi.spyOn(JSON, "stringify"); + let projected: ReturnType; + try { + projected = attachContextIntentReceipt( + "next", + { for: "execute", tokenBudget: 1_200 }, + { + recommended: { id: "pm-recommended" }, + ready: Array.from({ length: 2_000 }, (_, index) => ({ + id: `pm-${index}`, + title: `Item ${index}`, + status: "open", + })), + has_more: false, + truncated: false, + }, + ); + expect(stringify.mock.calls.length).toBeLessThan(20); + } finally { + stringify.mockRestore(); + } + expect(projected.context_intent).toMatchObject({ + degradation: "budget_row_compaction", + within_budget: true, + }); + expect(projected.recommended).toEqual({ id: "pm-recommended" }); + expect(projected.ready.length).toBeGreaterThanOrEqual(1); + expect(projected.ready.length).toBeLessThan(2_000); + }); + + it("never drops paginated command rows without a recovery cursor", () => { + const projected = attachContextIntentReceipt( + "list", + { for: "triage", tokenBudget: 1_200 }, + { + items: Array.from({ length: 200 }, (_, index) => ({ + id: `pm-${index}`, + title: `Item ${index}`, + status: "open", + })), + }, + ); + expect(projected).toMatchObject({ + budget_exceeded: { omitted_result: true }, + context_intent: { + degradation: "budget_receipt_only", + result_omitted: true, + }, + }); + expect(projected).not.toHaveProperty("items"); + expect(projected).not.toHaveProperty("next_cursor"); + }); + + it("does not drop rows behind an already-issued pagination cursor", () => { + const projected = attachContextIntentReceipt( + "list", + { for: "triage" }, + { + items: Array.from({ length: 20 }, (_, index) => ({ + id: `pm-${index}`, + title: "x".repeat(2_000), + metadata: Object.fromEntries( + Array.from({ length: 100 }, (_, field) => [ + `field_${field}`, + field, + ]), + ), + })), + next_cursor: "opaque-cursor", + has_more: true, + }, + ); + expect(projected).toMatchObject({ + budget_exceeded: { omitted_result: true }, + context_intent: { + degradation: "budget_receipt_only", + result_omitted: true, + within_budget: false, + }, + }); + expect(projected).not.toHaveProperty("items"); + expect(projected).not.toHaveProperty("next_cursor"); + }); + + it("retains the final useful row when unrelated payload fields exceed the budget", () => { + const projected = attachContextIntentReceipt( + "next", + { for: "execute" }, + { + ready: [{ id: "pm-anchor" }], + ...Object.fromEntries( + Array.from({ length: 2500 }, (_, index) => [`field_${index}`, index]), + ), + }, ); expect(projected).toMatchObject({ budget_exceeded: { omitted_result: true }, context_intent: { degradation: "budget_receipt_only", - within_budget: true, + declaration_feasible: false, + }, + }); + }); + + it("references cursor-chain metadata instead of repeating invariant blocks", () => { + const cursor = Buffer.from( + JSON.stringify({ fingerprint: "chain-fingerprint", after_index: 1 }), + ).toString("base64url"); + const projected = attachReadOutputContracts( + "list", + { for: "triage", after: cursor }, + { + items: [{ id: "pm-2", title: "Second" }], + filters: { status: "open" }, + sorting: { sort: "priority" }, + completeness: { status: "complete" }, + projection: { mode: "fields" }, + row_contract: { command: "list", row_keys: ["items"] }, + }, + ) as Record; + expect(projected).toMatchObject({ + continuation_contract: { + fingerprint: "chain-fingerprint", + metadata: "reference", }, }); - expect(projected).not.toHaveProperty("recommended"); - expect(projected).not.toHaveProperty("count"); - expect(projected).not.toHaveProperty("has_more"); + for (const key of [ + "applied_limit", + "completeness", + "context_intent", + "count", + "filters", + "has_more", + "now", + "omission_receipt", + "projection", + "row_contract", + "sorting", + "total", + "truncated", + ]) { + expect(projected).not.toHaveProperty(key); + } + + for (const after of [ + Buffer.from(JSON.stringify({ fingerprint: 42 })).toString("base64url"), + "not-json", + ]) { + expect( + attachReadOutputContracts("list", { after }, { items: [] }), + ).toMatchObject({ + continuation_contract: { + fingerprint: "opaque_cursor", + metadata: "reference", + }, + }); + } }); }); diff --git a/tests/unit/sdk/sdk-index.spec.ts b/tests/unit/sdk/sdk-index.spec.ts index 26cf2d993..56c7f7913 100644 --- a/tests/unit/sdk/sdk-index.spec.ts +++ b/tests/unit/sdk/sdk-index.spec.ts @@ -1178,6 +1178,7 @@ console.log(JSON.stringify(payload));`, type: "Task", status: "open", createMode: "progressive", + fullChangedFields: true, })) as { item?: { id?: string; title?: string } }; expect(runCreated.item?.id).toMatch(/^pm-/); expect(runCreated.item?.title).toBe("SDK structured run item"); @@ -1395,6 +1396,7 @@ console.log(JSON.stringify(payload));`, cwd: path.dirname(pmPath), noExtensions: true, author: "sdk-client-test", + fullChangedFields: true, target: "1", options: { message: "SDK restore to created version" }, })) as { item?: { id?: string; status?: string }; restored_from?: { target?: string } };