[AAASM-5750] 📝 (types): Point the §6 Planned referent at the capability ticket - #364
Merged
Merged
Conversation
ADR 0033 §6 scopes `Planned` to "decided but not implemented — a ticket reference". Both sites referenced AAASM-5681, which measured the absence of an SDK-side audit sink but never intended to build one. Unlike go-sdk and python-sdk — whose referent already points at a closed ticket — 5681 is still open, so node is not yet broken. It would be the moment 5681 closes. AAASM-5750 owns the capability. `with-assembly.ts`'s "tracked as" line is the same kind of forward reference and moves with it. References citing AAASM-5681 as the ticket that *measured* the drop are left alone; those are still true.
The referent lives in a comment, and a comment is the one artifact in a source file with no mechanical check on it. Scope is narrower here than in the sibling SDKs, and the header says why: the scan keys on the §6 term, and node-sdk currently describes one state with two different terms — `Planned` in `gateway-governance.ts`, `Unmeasured` in `with-assembly.ts` and the quickstart control. go-sdk and python-sdk both reason explicitly that `Unmeasured` is wrong for a state whose stopping point has been measured. Reconciling that is a claim change, not a referent change, so it is filed as AAASM-5755; when it lands, those sites acquire the term and this scan covers them with no change here. A floor guards the scan itself: an empty walk and a clean tree otherwise report the same result.
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Independent review broke the first version three ways, and all three came from one design mistake: the gate scanned its own file. Its header names AAASM-5750, so the floor was partly satisfied by the gate quoting itself — in node it was satisfied ENTIRELY that way, and deleting the only real site left the suite green. Four changes: * **Exclude the gate file from its own scan.** Verified with a positive control: the same stale-referent line fails when placed in any other file. * **Assert the expected SET of guarded paths, not a count.** A count can be held up by an unrelated site appearing as a real one is deleted; naming the paths makes that substitution visible. * **Pair the claim with a ticket on its line OR the next.** Coverage was decided by where a comment happened to wrap — python's quickstart control split `Planned` from its ticket across two lines and was silently unchecked while the PR claimed it was covered. Reflowing a comment now cannot hide a stale referent. * **Stop asserting that every `Planned` names AAASM-5750.** §6 scopes the term to any decided-but-unbuilt capability with any ticket, so the first version would have failed CI on the next unrelated roadmap row. The invariant is now the narrow one that is actually true: AAASM-5731 and AAASM-5681 measured the absence and will not fix it, so neither may ever be a forward referent. The rule is also now attributed correctly. It comes from AAASM-5750's own description, not from ADR 0033 §6 — §6 requires *a* ticket reference and says nothing about which. A failure message citing an ADR for a rule the ADR does not contain sends the next reader to the wrong document.
…the stale ones
Round-2 review: narrowing the invariant to a two-element denylist stopped the
gate asserting the thing the change actually made true. Repointing a guarded
site to ANY non-stale ticket passed green — including a real sibling ticket:
ffi_governance_client.go:169 AAASM-5750 -> AAASM-5749 -> ok
The likeliest drift — AAASM-5750 gets split or superseded and someone updates
the referent — was undetected. Round 1 was too broad, round 2 too narrow.
Two tiers, so neither failure mode returns:
* a **guarded** site (one of the named audit-sink deferrals) must name
AAASM-5750 exactly;
* **any other** site must merely not name a stale referent, so an unrelated
roadmap row is still legitimate.
The positive assertion is scoped to a named set, so it carries none of round
1's repo-wide over-breadth.
Also fixed: the one-line lookahead had no directionality, and created a new
false-positive class the same-line rule could not. A line of forward-looking
prose inserted above a correct BACKWARD citation was blamed for it:
153: // Streaming record delivery is Planned for a later release.
154: // RecordResult discards the record and reports success (AAASM-5731).
FAIL: ...:153 defers to AAASM-5731
The window now extends only when the claim line carries no ticket of its own
AND does not end a sentence. There are 81 backward citations across the three
SDKs — go 30, python 33, node 18 — each a landmine for any adjacent claim
prose. Zero are adjacent today, so this was green by luck of layout.
Two residual limits are disclosed in the header rather than papered over: the
reachability check is per file rather than per site, and the excluded gate file
is a hiding place. Both measured as currently unreachable.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Target
Task summary:
Repoints the two ADR 0033 §6
Plannedreferent sites from AAASM-5681 to AAASM-5750, and adds a source scan that keeps them pointed correctly.§6 scopes
Plannedto "decided but not implemented — a ticket reference; no capability claim." AAASM-5681 measured the absence of an SDK-side audit sink; it never intended to build one. Unlike go-sdk and python-sdk, node is not broken yet — AAASM-5681 is still open, so the reference still resolves to live work. It breaks the moment 5681 closes, which is why it is corrected now rather than after.This is AAASM-5750's own "Until then" step. The capability itself — actually wiring a sink — stays open.
Task tickets:
ai-agent-assembly/go-sdk#199andai-agent-assembly/python-sdk#316— the same change in the sibling SDKs. Independent; no merge ordering required.Key point change:
Sites repointed (2)
src/types/gateway-governance.ts:23ADR 0033 §6: recording here is **Planned** (…), not *Observed*.src/wrappers/with-assembly.ts:166Supplying a sink that retains it is tracked as …The second carries no §6 term but is the same kind of forward reference — a pointer to the remedy — so it goes stale the same way.
Deliberately NOT repointed. Stated so the boundary is reviewable. Each cites AAASM-5681 as the ticket that measured the drop, which is still true:
src/gateway/client.ts:23,50,183,src/core/init-assembly.ts:92,104,123,140,837,src/types/assembly-context.ts:89,src/types/gateway-governance.ts:3tests/audit-sink-disposition.test.tsheaders,tests/quickstart-negative-control.test.ts:268README.mdanddocs/**proseinitAssembly, and the test constant asserting itThe gate. Nothing tests a comment — it is the one artifact in a source file with no mechanical check on it.
tests/planned-referent.test.tswalks the repo, pairs each §6Plannedwith a ticket reference on the same line, and asserts the referent. Two controls, both run:gateway-governance.ts:23to AAASM-5681scan found 0 …, floor is 1 … passing over nothingThe second matters as much as the first: an empty scan and a clean tree otherwise report the same result.
Found while doing this — filed, not fixed here. node-sdk describes one state with two conflicting §6 terms:
src/types/gateway-governance.ts:23src/wrappers/with-assembly.ts:165tests/quickstart-negative-control.test.ts:268go-sdk (
tool_wrapper.go:111-116) and python-sdk (core/audit_sink.py:24-26) both reason this out explicitly and reach the opposite conclusion: §6 reservesUnmeasuredfor an action nothing inspected, where nothing is known — and here exactly where the record stops has been measured, by this repo's ownaudit-sink-disposition.test.ts. That is a claim change, not a referent change, so it is AAASM-5755 rather than scope creep in this PR.Consequence for the gate, recorded in its header rather than left to be discovered: the scan keys on the §6 term, so today it reaches one of those three sites. When 5755 lands and the term is applied uniformly, the scan covers all three with no change to the scan.
src/types/assembly-context.ts:18,33,36also saysUnmeasured, about a different subject (whether a call is evaluated or blocked at all) — not disputed, and must not be swept.Effecting Scope
Test Result
pnpm testpnpm typecheckpnpm lintprettier --checkon changed filesvitest run tests/planned-referent.test.tsComment-only change plus one new test file; no runtime behaviour changes.
Review round 2 — the gate was broken, and it was broken the way it was built to prevent
Independent review found three ways the first gate could not fail. All three had one cause: the gate scanned its own file, whose header names AAASM-5750. That padded the site count with the gate quoting itself.
test_quickstart_negative_control.pysplitsPlannedand its ticket across two lines. The same-line-only scan never saw it — the PR claimed coverage it did not have.Plannedin the repo names AAASM-5750. §6 scopes the term to any decided-but-unbuilt capability with any ticket, so the next unrelated roadmap row would have broken CI for a reason no reader could guess.What the gate asserts now
Two assertions, each narrow enough to be true:
Plannedortracked as, paired with a ticket on its own line or the next, must not name AAASM-5731 or AAASM-5681. Those measured the absence; neither will build the sink. This never false-positives on an unrelatedPlanned.The gate file is excluded from its own scan, with a positive control proving the exclusion is scoped: the identical stale-referent line fails when placed in any other file.
Every probe that previously passed, re-run against the rebuilt gate
tracked aslinePlanned (AAASM-9999)The reviewer also disputed the AAASM-5755 rationale, and the dispute holds up: capability-manifest row G10 (
governance/capability-manifest.yaml:5123-5168) files a measured audit drop ascoverage: unmeasured, andgovernance/README.md:417-419is normative — "If none fits, the answer isunmeasured, not a twelfth term." That is precedent pointing the other way. AAASM-5755 has been re-scoped from a directive into an adjudication: it now asks which term is right, and lists the outcome where go-sdk and python-sdk are the ones that get corrected. No claim in this PR depends on the answer.Review round 3 — round 2 was too narrow, in the opposite direction
Round 2 replaced an over-broad assertion with a two-element denylist. Review found that this stopped the gate asserting the thing the change made true: repointing a guarded site to any non-stale ticket passed green, including a real sibling ticket.
The likeliest drift — AAASM-5750 gets split or superseded and someone updates the referent — was undetected. Round 1 was too broad; round 2 too narrow. Both directions are now covered by splitting the assertion:
AAASM-5750exactlyThe positive assertion is scoped to a named set, so it carries none of round 1's repo-wide over-breadth — the roadmap-row probe still passes.
A second defect round 2 introduced
The one-line lookahead had no directionality, and created a false-positive class the same-line rule could not produce. Forward-looking prose inserted above a correct backward citation was blamed for it:
There are 81 backward citations across the three SDKs — go 30, python 33, node 18 — each a landmine for adjacent claim prose. None is adjacent today, so this was green by luck of layout rather than by construction.
The window now extends only when the claim line carries no ticket of its own and does not end a sentence. The reviewer's suggested fix (extend only within the same comment block) would not have worked — in the example above both lines are in one block. The sentence terminator is the discriminator that actually separates the two cases: the inserted line ends in
., python's genuinely wrapped site ends in§6.Disclosed rather than fixed
tool_wrapper.go:115("which is what Planned names") is legitimate prose with no ticket and would fail. Needs two coordinated edits; no file carries more than one site today.Both are written into each gate's header.
Gates re-run
0 issues