Skip to content

AM-1321 - Make context economy a single-copy rule and cut /sy:spec's duplicate summary comment - #22

Merged
bretttully merged 16 commits into
mainfrom
AM-1321/context-economy
Aug 7, 2026
Merged

AM-1321 - Make context economy a single-copy rule and cut /sy:spec's duplicate summary comment#22
bretttully merged 16 commits into
mainfrom
AM-1321/context-economy

Conversation

@bretttully

@bretttully bretttully commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

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, and validate.py enforces 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.

  • New single-copy 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-issue refuse an over-limit body client-side, naming measured length, limit and overflow.
  • Each limit is pinned by validate.py to 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.limit is 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 each ADAPTER.md rather 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.

bretttully and others added 2 commits August 6, 2026 22:01
…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>
@bretttully

Copy link
Copy Markdown
Collaborator Author

Acceptance evidence — AM-1321

Base ca26977 → head f22919b. Commands run in the branch worktree; full output under the task's scratch dir.

Check Result
pixi run validate PASS — final-validate.log
pixi run pytest PASS 650 passed (base baseline 642; +8 new) — final-pytest.log
pixi run ruff check sy_tools/ PASS — final-ruff-check-sy_tools-.log
pixi run ty check sy_tools/ PASS — final-ty-check-sy_tools-.log

pixi run ruff format --check reports 37 files would be reformatted — byte-identical at base ca26977 (format-baseline.log), and CI does not run it (.github/workflows/validate.yml runs validate / ruff check / ty check / pytest). Not a regression, not addressed.

Per-obligation evidence

Single-copy drift — the cut-test phrasing exists in exactly one file. validate.py asserts each of spec, plan, pr, handoff-accounting, CONTRIBUTING.md contains context-economy.md and contains neither cut-test literal (the three-way present-in-reference / absent-from-every-consumer shape). All six new assertions were negative-tested by perturbing the source and confirming each fires — negative-tests.log.

Dead-instruction removal — no instruction anywhere still directs the deleted summary comment. Repo-wide grep for step.1 summary|summary as a comment|summary comment returns only validate.py's own new guards (staleness-sweep.log). validate.py:745's pre-existing "never writes the Task body" assertion still passes: the phrase moved into Step 2's lead-in. §7 Step 2 now lists exactly 4 items, none a summary comment.

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 JiraAdapter/GithubAdapter instances (real-limit-runner.log):

JiraAdapter    post-comment  body= 32847 limit= 32767 -> REFUSED naming measured length + limit
JiraAdapter    create-issue  body= 32768 limit= 32767 -> REFUSED naming measured length + limit
JiraAdapter    update-issue  body= 32768 limit= 32767 -> REFUSED naming measured length + limit
GithubAdapter  post-comment  body= 65616 limit= 65536 -> REFUSED naming measured length + limit
GithubAdapter  create-issue  body= 65537 limit= 65536 -> REFUSED naming measured length + limit
GithubAdapter  update-issue  body= 65537 limit= 65536 -> REFUSED naming measured length + limit

Test-double drifttracker/test_canonical.py passes unmodified. Verified empirically, not by inference: body_limit in vars(TrackerAdapter) is False, the annotation is present in __annotations__, and the pinned verb set is still 15.

Guard is best-effort, not a contract — the body_limit docstring names both sources and both uncertainties (ADF unit undocumented; established for comments, applied to descriptions as a deliberate unverified assumption), matched in CONTRACT.md and both ADAPTER.md.

Sourcing integrity — every claim in context-economy.md carries a primary-source URL, each confirmed against the publisher's own page: Anthropic's context-engineering guidance (attention budget; "smallest possible set of high-signal tokens"), Chroma's Context Rot (18 LLMs, 194,480 calls), Liu et al. arXiv:2307.03172, IFScale arXiv:2507.11538 (68% at 500 instructions). One correction made against the primary source: IFScale's bias runs the other way from a loose reading — later instructions are dropped more often, earlier ones survive — and the reference states that direction.

Docs obligations

Doc Disposition
docs/usage.md updated — 19b680a
CONTRIBUTING.md:14 updated — 19b680a
skills/tracker/CONTRACT.md updated — f22919b
skills/tracker/jira/ADAPTER.md updated — f22919b
skills/tracker/github/ADAPTER.md updated — f22919b
README.md (plan: no change needed) inspected, confirmed accurate — README.md:58 describes the sign-off summary and the single ACTIVE plan, neither of which this alters, and does not enumerate the shared references

Content-QA grep over all 8 shipped prose artifacts: no </content>, </invoke>, antml:, or internal identifiers (agent ids, scratch/worktree/transcript paths) on any added line — content-qa.log.

@bretttully

Copy link
Copy Markdown
Collaborator Author

Review coverage
REVIEW_BASE_SHA: ca26977
REVIEWED_SHA: f22919b
REVIEW_MODEL_REQUESTED: opus
REVIEW_EFFORT: max

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.
@bretttully
bretttully marked this pull request as ready for review August 6, 2026 12:37
@bretttully
bretttully requested a review from Copilot August 6, 2026 12:38

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.md as the single canonical reference and wire/cross-reference it from relevant skills/docs; update scripts/validate.py to 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_limit and enforce a shared whole-write size refusal in create-issue, update-issue, post-comment, and post-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.

@bretttully

Copy link
Copy Markdown
Collaborator Author

Gate fix cycle — AM-1321

Full sy:gate review (opus, max effort) over ca26977..f22919b: PASS, nothing blocking. Two items dispositioned:

  • Fixed (4c1d6f0): skills/spec/SKILL.md:111 restated context-economy.md's "write to the actor" rule instead of only pointing at it — cut the restating sentence, leaving the pointer.
  • Fixed (4c1d6f0): context-economy.md:5 closed the Chroma Context Rot quote as if complete when the source sentence continues — added an ellipsis to signal truncation.
  • Rejected: nit that "later instructions dropped more often" omits IFScale's density curve. The measured ratio is ≥1.0 across the whole tested range and the abstract's own headline finding is the later-bias direction; a density caveat would not change what a Shipyard author does when trimming a brief (cut test 1), so it stays out.

Focused delta re-review (opus, max effort) over f22919b..4c1d6f0 (docs-only, 2 lines): PASS, no new finding, both fixes confirmed correctly resolved against primary sources, pixi run validate green.

4c1d6f07e25f0f656e1bf6ed73128a0d99d82af6 is CI-green and is the reviewed head. Automated reviewer (Copilot) explicitly requested after marking ready, request confirmed via GraphQL reviewRequests, and its review at commit 4c1d6f0 generated zero comments.

REVIEW_BASE_SHA: ca26977
REVIEWED_SHA: 4c1d6f0
CI_GREEN_SHA: 4c1d6f0

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.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 18 out of 18 changed files in this pull request and generated no new comments.

@bretttully

Copy link
Copy Markdown
Collaborator Author

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:

  1. 4c1d6f0 — cut a cross-part restatement in spec/SKILL.md; closed a truncated Chroma quote.
  2. 85348f6 — corrected two sourcing defects the parent's handoff doc-accuracy check found: an incompletely-quoted Liu et al. citation, and a false "Jira's 32,767-char limit is comments-only" claim.
  3. 08514d591d9dfe — three successive gate-found citation-accuracy corrections on the Jira body_limit provenance (a DC-only source mistakenly cited as Cloud-documenting; a ticket cited for a claim it didn't attest; a "confirming" verb overclaiming what Atlassian's response actually said). Every claim in the final wording is now verified against a primary Atlassian source fetched directly (JCMA migration KB, JRACLOUD-59124/63007/68949).
  4. 7fe13ef — cosmetic docstring rewrap, zero semantic change (word-diff and normalized-text hash confirmed identical).

Final gate pass (base ca2697713045697e771843ab8d22d366249d9a27, head 7fe13ef2a3ef377cca44e0d76db2286d074fd12c): PASS, nothing actionable outstanding.

Automated reviewer (Copilot) re-requested at this head per cadence (its prior review sat at 4c1d6f0, and every round since fixed gate findings, not Copilot threads). Its review at 7fe13ef generated zero new comments.

CI green at 7fe13ef (all 5 checks). This is the reviewed and CI-green SHA.

REVIEW_BASE_SHA: ca26977
REVIEWED_SHA: 7fe13ef
CI_GREEN_SHA: 7fe13ef
REVIEW_MODEL_REQUESTED: opus (frontier, max effort, every round)

bretttully and others added 5 commits August 7, 2026 09:29
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>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_limit docstring 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 is len(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.

bretttully and others added 3 commits August 7, 2026 10:46
…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>
@bretttully
bretttully merged commit e14bcd9 into main Aug 7, 2026
5 checks passed
@bretttully
bretttully deleted the AM-1321/context-economy branch August 7, 2026 01:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants