docs(spec): cite the cloud decision as cloud ADR-0025, not a bare number that resolves to the plugin-packaging ADR - #18754
Conversation
…umber `ToolExecutionContext.userMessageText`'s docblock said the agent route is owned by cloud "post-ADR-0025" — cloud context, bare id. A bare id resolves against THIS registry, where ADR-0025 is Plugin Package Distribution: a real record about `.osplugin` artifacts and marketplace install, which decides nothing about the agent route. An id that resolves to the wrong page is worse than one that resolves to nothing: a dangling number stops the reader, a live one lets them believe they read the right decision. Prime Directive 13: an ADR "lives in the repository whose code it governs", and a cloud decision is cited as `cloud ADR-NNNN`, never as a bare number. The line now reads `(cloud, post-cloud ADR-0025)` — verbatim what the sibling member `confirmedBlueprintIdentity` already says two declarations below, so the two neighbouring lines are consistent again. Docblock prose only: no type change, no export added or removed. Co-Authored-By: Claude <[email protected]> Claude-Session: https://claude.ai/code/session_01JbZnqu8bt6YqfJsr9vaFb3
📓 Docs Drift CheckThis PR changes 1 package(s): 1 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 2 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 136 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 470189f8b31a757128eb3afa14e049774a6b4288 && git checkout 470189f8b31a757128eb3afa14e049774a6b4288
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 09e16a5745b66ca4e5cdddb6248551d1761f0ddd edcbcda2548d8a23d9147adf4dd59ffa3fb87add && git checkout -B drift-repro 09e16a5745b66ca4e5cdddb6248551d1761f0ddd && git merge --no-ff edcbcda2548d8a23d9147adf4dd59ffa3fb87add
node scripts/docs-audit/affected-docs.mjs --json 09e16a5745b66ca4e5cdddb6248551d1761f0ddd
|
Clause-②: no
Fixes #18685
What changed
One docblock line in
packages/spec/src/contracts/ai-service.ts, plus a changeset.ToolExecutionContext.userMessageTextread:The parenthetical names cloud as the owning layer; the id was spelled bare. A bare id resolves against this registry, where
ADR-0025isdocs/adr/0025-plugin-package-distribution.md— a real record about.ospluginartifacts, plugin trust tiers and marketplace install, which decides nothing about who owns the agent route.AGENTS.md Prime Directive 13, verbatim: an ADR "lives in the repository whose code it governs", and cloud decisions are cited as
cloud ADR-NNNN— "never as a bare number".The line now reads
(cloud, post-cloud ADR-0025): byte-for-byte the phrase the sibling memberconfirmedBlueprintIdentityalready carries seven lines below. The two were knowingly inconsistent while the card was open; they agree again.Premise re-verified before editing. The card asked the taker to falsify two things. (1) This repo's ADR-0025 really is unrelated to the agent route — it contains exactly one case-insensitive
agenthit, at line 408, whereagentis one of the plugin contribution kinds a manifest may declare. Nothing in it decides route ownership. (2) Whether cloud has an ADR-0025 at all stays NOT MEASURED — thecloudrepo is outside this session's scope, and nothing here asserts what the bare number was meant to point at. What is measured is where the bare number did land: this repo's plugin-packaging record.Acceptance controls
cloud ADR-0025inai-service.ts(cloud, post-ADR-0025)underpackages/spec/src/**ADR-0025references to this repo's plugin-packaging ADRDARK b is the proof there was no blanket replace, and it is stronger than a file count: the
ADR-0025token total is unchanged at 326. The edit inserted the wordcloudin front of exactly one of them and removed none.The seat's two questions, answered by measurement
1. Does
scripts/check-adr-anchors.mjschange its verdict on this line?No — and it never had one. Both readings taken on the real gate:
0e2ebce37b)OK (53 anchored file(s) … 36082 citation(s) across 4628 file(s) resolve …)ai-service.tsis named zero times in either run. The gate's citation audit exempts a cross-repo qualifier and otherwise only asks that the number resolve;0025resolves here either way, so the gate is blind to this defect in both directions. That is what the card predicted, now measured rather than assumed.One thing the measurement turned up that the prediction did not — reported, not folded in. The exemption is an exact-token test against
CROSS_REPO_QUALIFIERS = {objectui, object-ui, cloud}, and the token is whatever[A-Za-z0-9_./-]+sits immediately before the id, on the same line. Probed with five throwaway spellings, each run against the real gate:cloud ADR-9911post-cloud ADR-9912objectstack-ai/cloud ADR-9913`objectstack-ai/cloud` ADR-9914ADR-9915So the spelling this PR lands,
post-cloud ADR-0025, is not recognised as cross-repo; it stays green only because this repo also owns anADR-0025. The same is true of the backticked prose form used indocs/adr/0135-*anddocs/adr/0133-*. Handed back as a finding rather than acted on — changing the qualifier set or the idiom is a different defect class from this card's, so the bounded in-place-fix exemption does not open.2. How many other bare numbers sit in cloud context?
Surface swept: the gate's own corpus, taken with the gate's own command (
git grep --untracked -IonE '([A-Za-z0-9_./-]+[ \t]+)?ADR-[0-9]{4}') and parsed with the gate's own regex and qualifier set, so the surface swept equals the surface that gate reads.CROSS_REPO_QUALIFIERS)cloudgoverns the same clause — within 48 chars before the id, same line, no.;)]betweenA loose first pass (
cloudanywhere within ±2 lines) returned 1105 and was discarded as too noisy to be a predicate — reported because the number is the honest cost of the tighter one.The 40 tier-C hits were triaged by hand. Most are false positives in which the cited number genuinely is ours and the word
cloudmerely sits nearby (packages/runtime/src/cloud/as a directory;cloud-only (ADR-0025)where ADR-0025 really is the distribution decision). Two are the same defect class as this card and are handed back in the report rather than folded in here. Details, dedupe words and the triage verdict for every ambiguous hit are in theos-dev-reportcomment on #18685.Acceptance notes
Out-of-scope observations, noted and deliberately not filed:
packages/spec/src/api/ai-agents-envelope.test.ts:112citescloud#816 / ADR-0057.0057is one of the three allowlisted collision numbers, and neither of this repo's two0057records (ERP authorization core; system-data lifecycle) is about agent capabilities — so this may be a cloud number spelled bare. I could not settle which registry it means without reading the cloud repo, which is out of session scope, so it is recorded as ambiguous rather than asserted. Next toucher: whoever does the#5992route-B slug-qualification pass over the0057pair, which has to read every0057citation anyway.content/docs/releases/v16.mdx:879—went cloud-only (ADR-0025). Reads as a legitimate reference to this repo's distribution ADR, and release notes are a frozen surface no PR edits. Taker: none.Verification
All on the final commit
edcbcda254.pnpm lint(eslint . --no-inline-config, the whole repo, not a narrowing) — exit 0.pnpm --filter @objectstack/spec typecheck && pnpm --filter @objectstack/spec test— exit 0, 486 test files / 13964 tests passed.node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack(75 commands) — 74 green.pnpm check:dual-build-cjs-loadsexits 3 —PREREQUISITE NOT MET, it reads built output for 87 packages and asks for a fullpnpm build. That is CI's run, not a finding; the gate states in its own words that "nothing was measured".check:lean-entry-closureandcheck:doc-formula-expressionsrefused the same way, were cleared with a targetedturbo run build --filter=@objectstack/objectql --filter=@objectstack/formula --filter=@objectstack/lint, and then both passed.pnpm check:nul-bytesgreen, plus a direct control-character scan over both changed files.Why a changeset, given the diff is prose. Measured rather than assumed:
packages/specshipsdistin itsfiles[], and after building the package the edited sentence is present indist/contracts/index.d.tsanddist/contracts/index.d.mts— 2 published files, with the untouched neighbouring sentences of the same docblock as the positive control (also 2). Published bytes move, soskip-changesetdoes not apply and this lands as apatch.Draft on purpose; landing is the seat's.
🤖 Generated with Claude Code
https://claude.ai/code/session_01JbZnqu8bt6YqfJsr9vaFb3
Generated by Claude Code