You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[bug] The docs-drift tool count reads three files and reports "every doc claim" — the public /about page says ~67 tools while production serves 135 #555
"every doc claim" is a claim about the repo; the measurement is over three paths. That is the same shape as #536 and #531: a guard whose printed number is trusted because of how it is worded, taken over a subset.
The root of it is one layer up. docFiles() (scripts/docs-drift.mjs:49) opens with "Everything a reader or an agent is expected to trust" and then collects only platform-docs/*.md, store/llms.txt, store/llms-full.txt, README.md, AGENTS.md, SECURITY.md, and per-package README/AGENTS/CLAUDE.md. The store's own HTML — the marketing site, which workers/host builds and serves — is in none of it. Grepped: store/about/index.html is the only HTML page in the tree carrying a tool count, so the fix is small; but nothing was ever going to report it.
A second, independent stale claim in a file the guard DOES read
store/llms.txt:65:
Twelve tools require an exact confirm value, compared with ===. In eleven cases the value is the tool's own name: write_agent_file, batch_write_agent_files, unregister_instance_runtime, cancel_instance_task, cancel_instance, delete_instance_knowledge, delete_instance_memory, delete_instance_file, delete_instance_trigger, delete_instance_connector_grant, clear_instance_messages. The exception is remove_repo …
Counted from the code — every requireConfirmation(…) call site outside safety.ts and the tests — there are 13, twelve of which use the tool's own name. The missing one is delete_supervision (workers/mcp/src/instance-tools/composition.ts:97 declares the arg, :115 enforces confirm === "delete_supervision").
platform-docs/mcp.md:135-148 and workers/mcp/README.md:328 both list it correctly, so the drift is isolated to the LLM-facing file — which is precisely the reader that cannot ask. store/llms.txt is inside docFiles(), but the confirm-value list is not one of the eight checks, so nothing compares it to anything.
What to do, cheapest first
One line, fixes today's defect: correct store/about/index.html:179 to the real number, or better, drop the number ("the full tool surface — see the MCP docs") so a marketing page is not a second place the count has to be maintained.
Add the store HTML to claimFiles.store/**/*.html for the N tools regex. This is the smallest change that makes the guard's sentence true, and it would have failed on the line above.
Widen docFiles() to include the served HTML, so the removed-command and removed-identity checks cover the marketing site too. Grepped before proposing: cloudflared, --tunnel and the FAGS runtime-plane strings do not currently appear in any store/*.html (the only freeagentstore reference is a sibling-store profile link in store/developers/profile.html:206, which is the ecosystem cross-link, not a runtime-identity claim). So this widening lands green and holds new ground rather than opening a backlog.
Derive the confirm list.requireConfirmation(safety, toolName, confirm, expected, …) gives both halves; a check like the MCP tool-table one — every documented confirm pair equals a registration, and every registration is documented — turns store/llms.txt, platform-docs/mcp.md and workers/mcp/README.md into one derived table. That is the same construction that makes the tool-count check strong: tool-count.ts is asserted by index.test.ts running the REAL registration path, not by a regex over prose.
Make the success line say its denominator.✓ MCP tool count: 135 == constant == every claim in 4 files costs nothing and stops the next reader over-trusting it. Consider it a general rule for this script — see the systemic issue filed alongside this one.
Alternatives considered and rejected
Scan every file in the repo for N tools. Rejected: workers/mcp/CLAUDE.md:85 legitimately says "67 of those 86 tools until [standards][tracking] Split worst large files into testable modules #305" — a historical statement — and the per-file module-layout counts are already checked separately by their own rule. A blanket scan would fire on the prose that explains the rule, which is the failure mode usage-claims.test.ts and control-labels.ts both had to design around.
Assert the about page against /health at build time. Rejected: it makes the docs build depend on a deployed service, and the constant already exists locally.
After the fix, the live /about/ number equals MCP_TOOL_COUNT, or states no number at all.
store/llms.txt's confirm list names all 13 tools and the count says 13/12, and a check compares that list to the requireConfirmation call sites rather than to another document.
Each ✓ line in docs-drift.mjs names how many files it read.
Regression risk
Widening docFiles() to HTML risks the removed-command check firing on prose inside a <code> block. fencedLines() (scripts/docs-drift.mjs:81) is Markdown-fence-specific and has no HTML equivalent, so step 3 needs an HTML-aware "is this an instruction" rule or it will need its own exclusions. Step 2 alone (the N tools regex over HTML) has no such coupling and can ship first.
Verified vs inferred
Verified: the live /about/ string and the live /health count (both fetched today); store/about/index.html:179; claimFiles at scripts/docs-drift.mjs:307; docFiles() at :49; 13 requireConfirmation call sites; store/llms.txt:65 listing eleven; platform-docs/mcp.md:148 listing delete_supervision; node scripts/docs-drift.mjs green at cfe8ff7.
Inferred: that no other served HTML page carries a checkable numeric claim — grepped for N tools|agents|migrations across store/**/*.html and found only this one, but a claim phrased differently would not have matched.
The number a prospective user reads is half the real one
https://proagentstore.online/about/ — measured today:
https://mcp.proagentstore.online/health — measured the same minute:
{"ok":true,"service":"proagentstore-mcp","tools":135}Source:
store/about/index.html:179. The constant it disagrees with isworkers/mcp/src/tool-count.ts:23(MCP_TOOL_COUNT = 135).This is #210's own defect, in the one surface a person reads before they decide whether to use the product — and
pnpm docs:driftis green.Why the guard did not see it
scripts/docs-drift.mjs:307:Three files. The failure message and the success line both speak in a wider voice — the CI output reads:
"every doc claim" is a claim about the repo; the measurement is over three paths. That is the same shape as #536 and #531: a guard whose printed number is trusted because of how it is worded, taken over a subset.
The root of it is one layer up.
docFiles()(scripts/docs-drift.mjs:49) opens with "Everything a reader or an agent is expected to trust" and then collects onlyplatform-docs/*.md,store/llms.txt,store/llms-full.txt,README.md,AGENTS.md,SECURITY.md, and per-packageREADME/AGENTS/CLAUDE.md. The store's own HTML — the marketing site, whichworkers/hostbuilds and serves — is in none of it. Grepped:store/about/index.htmlis the only HTML page in the tree carrying a tool count, so the fix is small; but nothing was ever going to report it.A second, independent stale claim in a file the guard DOES read
store/llms.txt:65:Counted from the code — every
requireConfirmation(…)call site outsidesafety.tsand the tests — there are 13, twelve of which use the tool's own name. The missing one isdelete_supervision(workers/mcp/src/instance-tools/composition.ts:97declares the arg,:115enforcesconfirm === "delete_supervision").platform-docs/mcp.md:135-148andworkers/mcp/README.md:328both list it correctly, so the drift is isolated to the LLM-facing file — which is precisely the reader that cannot ask.store/llms.txtis insidedocFiles(), but the confirm-value list is not one of the eight checks, so nothing compares it to anything.What to do, cheapest first
store/about/index.html:179to the real number, or better, drop the number ("the full tool surface — see the MCP docs") so a marketing page is not a second place the count has to be maintained.claimFiles.store/**/*.htmlfor theN toolsregex. This is the smallest change that makes the guard's sentence true, and it would have failed on the line above.docFiles()to include the served HTML, so the removed-command and removed-identity checks cover the marketing site too. Grepped before proposing:cloudflared,--tunneland the FAGS runtime-plane strings do not currently appear in anystore/*.html(the onlyfreeagentstorereference is a sibling-store profile link instore/developers/profile.html:206, which is the ecosystem cross-link, not a runtime-identity claim). So this widening lands green and holds new ground rather than opening a backlog.requireConfirmation(safety, toolName, confirm, expected, …)gives both halves; a check like the MCP tool-table one — every documentedconfirmpair equals a registration, and every registration is documented — turnsstore/llms.txt,platform-docs/mcp.mdandworkers/mcp/README.mdinto one derived table. That is the same construction that makes the tool-count check strong:tool-count.tsis asserted byindex.test.tsrunning the REAL registration path, not by a regex over prose.✓ MCP tool count: 135 == constant == every claim in 4 filescosts nothing and stops the next reader over-trusting it. Consider it a general rule for this script — see the systemic issue filed alongside this one.Alternatives considered and rejected
N tools. Rejected:workers/mcp/CLAUDE.md:85legitimately says "67 of those 86 tools until [standards][tracking] Split worst large files into testable modules #305" — a historical statement — and the per-file module-layout counts are already checked separately by their own rule. A blanket scan would fire on the prose that explains the rule, which is the failure modeusage-claims.test.tsandcontrol-labels.tsboth had to design around./healthat build time. Rejected: it makes the docs build depend on a deployed service, and the constant already exists locally.Acceptance criteria
node scripts/docs-drift.mjsFAILS onstore/about/index.htmlas it stands today — demonstrate that before fixing the page, the way [bug] A "Runs on" tile claims "Attached · online" for a node the pin excludes — one line below "Status: Offline", and the invariant test only covers the pinned tile #531 proved its assertion by reverting the fix./about/number equalsMCP_TOOL_COUNT, or states no number at all.store/llms.txt's confirm list names all 13 tools and the count says 13/12, and a check compares that list to therequireConfirmationcall sites rather than to another document.✓line indocs-drift.mjsnames how many files it read.Regression risk
Widening
docFiles()to HTML risks the removed-command check firing on prose inside a<code>block.fencedLines()(scripts/docs-drift.mjs:81) is Markdown-fence-specific and has no HTML equivalent, so step 3 needs an HTML-aware "is this an instruction" rule or it will need its own exclusions. Step 2 alone (theN toolsregex over HTML) has no such coupling and can ship first.Verified vs inferred
Verified: the live
/about/string and the live/healthcount (both fetched today);store/about/index.html:179;claimFilesatscripts/docs-drift.mjs:307;docFiles()at:49; 13requireConfirmationcall sites;store/llms.txt:65listing eleven;platform-docs/mcp.md:148listingdelete_supervision;node scripts/docs-drift.mjsgreen atcfe8ff7.Inferred: that no other served HTML page carries a checkable numeric claim — grepped for
N tools|agents|migrationsacrossstore/**/*.htmland found only this one, but a claim phrased differently would not have matched.