AM-1321 - Make context economy a single-copy rule and cut /sy:spec's duplicate summary comment - #22
Conversation
…ec summary comment New skills/shared/references/context-economy.md is the one place the attention-budget principle, the two cut tests, write-to-the-actor, no-cross-part-restatement, and evidence-vs-instruction are stated; every authoring surface carries a pointer only. /sy:spec §7 Step 2 no longer posts the Step-1 summary back as a second comment restating a plan the user just approved, and Step 1's auto-mode consent sentence no longer authorizes that write. "never writes the Task body" moves into Step 2's lead-in so validate.py's existing assertion stays satisfiable. spec-gate's Simplicity axis gains two objective prose triggers; no seventh axis. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The four writers that already share the machine-log gate now share a body-size gate too: a body past the selected adapter's limit is refused whole, naming the measured length, the limit and the overflow, so a caller knows how much to cut rather than retrying blind into the tracker's own rejection. The limit lives on the adapter because it differs per tracker and neither figure is firm — Jira's 32,767 is documented for comments only and in an undocumented unit under ADF, GitHub's 65,536 is attested by its API error string alone — so both are stated as best-effort with their provenance, in the protocol and in each ADAPTER.md. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Acceptance evidence — AM-1321Base
Per-obligation evidenceSingle-copy drift — the cut-test phrasing exists in exactly one file. Dead-instruction removal — no instruction anywhere still directs the deleted summary comment. Repo-wide grep for Tracker write integrity — over-limit bodies refused client-side, before the network, naming measured size. 8 new pytest cases: 4 writers × (one over / exactly at) a stubbed limit, each sizing the assembled body (post-comment's separator, post-log's heading + fenced JSON) and asserting the adapter was never reached. Beyond the stub, a runner exercised the guard against the real adapter limits end to end with real Test-double drift — Guard is best-effort, not a contract — the Sourcing integrity — every claim in Docs obligations
Content-QA grep over all 8 shipped prose artifacts: no |
Gate review AM-1321: drop the paraphrase of context-economy.md's write-to-the-actor rule from spec/SKILL.md sec7 (it duplicated the cited reference, violating single-copy/pointer-only); add an ellipsis to the truncated Chroma quote in context-economy.md.
There was a problem hiding this comment.
Pull request overview
This PR formalizes “context economy” as a single-source rule across Shipyard’s agent-facing authoring surfaces, removes /sy:spec’s duplicate Step‑2 summary comment, and adds a shared client-side body-size refusal across the four tracker write verbs to prevent oversized plan/record writes.
Changes:
- Add
skills/shared/references/context-economy.mdas the single canonical reference and wire/cross-reference it from relevant skills/docs; updatescripts/validate.pyto enforce “pointer, not restatement” for the cut tests. - Update
/sy:spec§7 to post only the full ACTIVE plan after approval (no extra summary comment) and align the sign-off consent sentence with the actual mutations performed. - Introduce per-adapter
body_limitand enforce a shared whole-write size refusal increate-issue,update-issue,post-comment, andpost-log, with tests covering boundary behavior.
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| sy_tools/tracker/jira/adapter.py | Adds Jira adapter body_limit constant (32,767) for shared size-guard enforcement. |
| sy_tools/tracker/github/adapter.py | Adds GitHub adapter body_limit constant (65,536) for shared size-guard enforcement. |
| sy_tools/tracker/init.py | Extends the TrackerAdapter protocol with a body_limit attribute used by the shared server guard. |
| sy_tools/server.py | Enforces _validate_body_size on the four write tools, before attempting tracker writes. |
| sy_tools/tests/test_server.py | Adds boundary tests ensuring oversized bodies are refused pre-adapter and exact-limit bodies still write. |
| skills/tracker/jira/ADAPTER.md | Documents Jira’s best-effort body limit and its provenance/uncertainty. |
| skills/tracker/github/ADAPTER.md | Documents GitHub’s best-effort body limit as observed (undocumented) behavior. |
| skills/tracker/CONTRACT.md | Adds body-size as a second shared “whole-write refusal” guard across the four writers. |
| skills/spec/SKILL.md | Removes §7 Step‑2 summary-comment write; updates consent language and adds context-economy pointer. |
| skills/ship/references/handoff-accounting.md | Adds context-economy pointer for handoff/state brief record authoring. |
| skills/shared/references/spec-gate.md | Extends Simplicity axis with objective prose-economy triggers referencing context-economy. |
| skills/shared/references/context-economy.md | Introduces the single canonical “context economy” rule + cut tests and supporting sources. |
| skills/pr/SKILL.md | Adds pointer to context-economy for deciding what belongs in description vs durable PR comment. |
| skills/plan/SKILL.md | Adds pointer to context-economy for roadmap/SEAMS and other authored artifacts. |
| scripts/validate.py | Enforces single-copy rule for cut-test phrasing + ensures required pointers exist. |
| docs/usage.md | Updates user-facing description to reflect the “one comment, not two” behavior post-approval. |
| CONTRIBUTING.md | Adds pointer to context-economy (and avoids duplicating the cut-test phrasing). |
| .claude-plugin/plugin.json | Bumps plugin version to 1.19.0. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Gate fix cycle — AM-1321Full sy:gate review (opus, max effort) over
Focused delta re-review (opus, max effort) over
REVIEW_BASE_SHA: ca26977 |
Handoff doc-accuracy check found two real sourcing defects:
- context-economy.md's Liu et al. quote closed as complete but the
source sentence continues with a material qualifier
('of long contexts, even for explicitly long-context models');
extend the quote rather than truncate it.
- the Jira body_limit provenance claimed the 32,767 figure is
established for comments only, applying it to descriptions as an
unverified assumption. Atlassian documents the limit for both via
the site-wide jira.text.field.character.limit property
(JRACLOUD-59124, JRACLOUD-68949); only the ADF unit stays
undocumented. Corrected at all four sites: the shared body_limit
docstring, the Jira adapter's body_limit comment, and
skills/tracker/jira/ADAPTER.md.
The prior sourcing fix cited JRACLOUD-59124 (a low-vote, property-silent feature suggestion) and JRACLOUD-68949 (a Won't-Fix report, not an Atlassian doc) as evidence the jira.text.field.character.limit property is Atlassian-documented for Cloud. Neither ticket names the property, and the property is only exposed for tuning in Data Center per JRACLOUD-63007's own resolution. Reworded to attribute the documented per-text-field validation to the Jira Cloud KB article, and demote the two tickets to what they actually attest: Cloud customers observing the same 32,767 figure on both description and comment fields.
… source The previous round's fix cited a KB article stamped 'Data Center only' (never mentioning comments) as documenting the both-fields Cloud coverage, and cited JRACLOUD-63007 as attesting a field it never names. Fetched Atlassian's JCMA migration KB (platform: Cloud and Data Center), which states verbatim that on Cloud 'it's not possible to bypass the 32,767 character limit for both description and comments' and itself cites JRACLOUD-59124. Reattributed: the both-fields Cloud claim to that KB; the property's Data-Center-only tunability and the Cloud-default confirmation to JRACLOUD-63007; the description-specific corroboration to JRACLOUD-68949.
adapter.py:102 still bound JRACLOUD-68949 (a description-UI-hint Won't-Fix report) to a Data-Center-tunability claim it never attests, inconsistent with the two prose sites that already split the roles correctly. Also softened 'while confirming the same default applies there' to 'without disputing the reporter's premise that' at both prose sites: Atlassian's 2023 panel response never states the Cloud default figure itself, only declines to expose the property, so 'confirming' overclaimed what the source says.
Cosmetic-only: the prior edit left a 22-char mid-sentence orphan line. No wording change.
Gate convergence — AM-1321 (final)Review-remediation loop closed. Six fix rounds landed after the initial full review, all frontier-tier (opus, max effort) sy:gate coverage, narrowing scope per the trivial-diff (docs/docstring-only) path without lowering model/effort/coverage:
Final gate pass (base Automated reviewer (Copilot) re-requested at this head per cadence (its prior review sat at CI green at REVIEW_BASE_SHA: ca26977 |
The limit lived in three unbound copies per adapter (constant, ADAPTER.md prose, Protocol docstring), so editing the constant left two agent-facing docs asserting the old number with every check green. `check_invariants` now reads each adapter's declared `body_limit` out of source and requires the matching ADAPTER.md to state it, in either the bare or comma-grouped spelling. Also tightens two overclaims in the same area: refusing an oversized body is not proof the tracker would have refused it (Shipyard measures the Markdown it sends, not the converted body the tracker counts), and the limit's unit is characters of that Markdown body. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ants too The third copy of each limit is the `body_limit` docstring on `TrackerAdapter`, which names both figures in prose. The per-adapter loop now checks that file alongside the matching ADAPTER.md, so editing a constant fails validation until every copy of its figure moves. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…t gaps `plugin.json` claimed 1.19.0, which main already published; `claude plugin update` gates on that string alone, so a duplicate leaves installed copies pinned to stale content at their old version-keyed cache path. main has since published 1.20.0 (AM-1320), so this goes to 1.21.0. The body_limit assertion now also reads the comment block directly above each declaration — a fourth copy of the Jira figure that the declaration regex skipped — and refuses a declared limit under 8_192, because file-scoped containment lets a deleted leading digit (`32_767` -> `2_767`) pass on every target with all docs stale. CONTRACT.md's body-size clause ends at its conclusion: the Markdown-vs-converted-body mechanism is Jira-only inside a shared contract, and the sentence already delegates provenance to the adapter docs.
…ment shape AM-1320 replaced post-comment's flat two-part separator with a collapsed captioned section, removing _TWO_PART_SEPARATOR that the new body-size guard test measured against. Re-point it at _AGENT_DETAIL_OPEN/CLOSE. Resolves two conflicts: plugin.json keeps 1.21.0, one minor above main's 1.20.0, since writing 1.20.0 would recreate the invisible collision this run just fixed. spec/SKILL.md keeps AM-1320's send-the-summary-as-direct- text rule while dropping the summary-comment authorization, which this branch's Step 2 no longer performs. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 18 out of 18 changed files in this pull request and generated no new comments.
Suppressed comments (1)
sy_tools/tracker/init.py:123
- The
body_limitdocstring says the limit is measured in characters of the Markdown body Shipyard sends, but the Jira adapter converts Markdown to ADF before sending (adf.markdown_to_adf(body)), so this is not strictly a Markdown-on-the-wire limit. Clarifying that the measurement islen(body)on the pre-adapter string (and that Jira’s is pre-conversion) avoids overstating what the guard represents.
"""The largest body this tracker is believed to take, in characters of the Markdown body Shipyard
sends. Best-effort, not a guarantee.
…de-vacuify its binding legs The `body_limit` docstring in `sy_tools/tracker/__init__.py` named Jira, Atlassian, JCMA, three JRACLOUD ids, `jira.text.field.character.limit`, Data Center, ADF and GitHub, which CONTRIBUTING.md forbids in a core module outside its adapter zone. It was green only because the seam test exempts the whole `sy_tools/tracker/` subtree. The docstring now states the contract alone; every figure and every provenance uncertainty already lives in each adapter's source comment and its own ADAPTER.md. The binding loop in `scripts/validate.py` drops its Protocol-docstring leg with the figures, and closes three holes in what remains: - The doc leg matched raw substrings, so a limit whose digits appear inside unrelated prose satisfied it vacuously — `59_124` passed with both docs stale, since that is a JRACLOUD id. It now requires a whole numeric token, reusing the staleness leg's extractor. - The staleness leg's anchor only reaches a comment block immediately above the declaration, so one blank line emptied the note and passed on a stale figure. An empty note is now a failure naming the shape required. - `declared_body_limit` returned a `0` sentinel that fell through into the floor leg and reported a second, fabricated fault. It returns `None` and the adapter is skipped.
…actor The body_limit docstring said 'this module names no tracker', which is false of its own module: adapter() names both. It is the Protocol that names none. numeric_tokens' trailing (?![\\w-]) made hyphenated figures invisible, so a provenance comment stating '32,767-character' read as figure-free and the staleness leg passed on stale prose. (?!\\w|-\\d) recovers those while still excluding JRACLOUD-59124 and date-shaped runs. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
CONTRIBUTING.md:22 asks for a comment wherever a reader would otherwise simplify something and break it invisibly. Making these two lookarounds symmetric is exactly that: it silently reopens the vacuity the previous commit closed, and every gate stays green. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Ticket: AM-1321
Agent-facing text spends a finite, measured resource, and Shipyard had no single place saying so — so the rule was applied inconsistently and the most visible symptom was
/sy:spec§7 Step 2 posting the Step-1 summary back to the ticket as a second comment restating a plan the user had just read and approved.The principle now lives in exactly one file,
skills/shared/references/context-economy.md, with every claim carrying its primary source; every authoring surface carries a pointer rather than a copy, andvalidate.pyenforces both halves of that (the citation is present, the cut-test phrasing is not). Separately, the four tracker writers that already share the machine-log gate now share a body-size gate, since an oversized plan comment is the failure mode this ticket's own "one comment, not two" decision makes more likely.context-economy.md: attention budget, two cut tests, write-to-the-actor, no cross-part restatement, evidence-vs-instruction./sy:spec§7 posts one comment, not two; Step 1's auto-mode consent sentence no longer authorizes a write the run doesn't perform.sy:spec-gate's Simplicity axis gains two objective prose triggers — no seventh axis, no length budget.post-log/post-comment/create-issue/update-issuerefuse an over-limit body client-side, naming measured length, limit and overflow.validate.pyto every prose copy of its figure, so moving a constant without updating its documentation fails the build.The two body limits are deliberately best-effort, not spec. Jira's 32,767 is documented for both descriptions and comments — Atlassian's JCMA migration KB states it directly, citing JRACLOUD-59124, and
jira.text.field.character.limitis admin-tunable in Data Center only — but the unit is undocumented for an ADF body, and Shipyard measures the Markdown it sends rather than the converted body Jira counts. GitHub's 65,536 is attested by its API error string alone. Both are stated that way in eachADAPTER.mdrather than presented as a bound the tracker promises.An earlier revision of this description said Jira's figure was "documented for comments only"; that was wrong and is corrected above, as it was in the shipped text.