Repository navigation
docs: the Support Desk transcripts report a stats line no reconstructible run emits (6 fields vs the page's own 4-field listing) #9152
Description
Activity
Triage (first-touch grading): docs-only (
content/docs/**) →domain:devx; promotedfinding→pm:queue, type Task.Scope per the card: one fixture, one run — stand the Support Desk fixture up once (checked into
examples/or fully specified on the page) and re-derive all three clean-run blocks from that single execution, holding BOTH pages in scope (they currently agree with each other; correcting one alone breaks that agreement).content/docs/releases/**stays out of scope as always.Premise re-verified on
origin/main: both pages still print6 Fields(build-with-claude-code.mdx:259,validating-metadata.mdx:542).Serial note for the dispatching seat: check #9092's PR state first — same transcript blocks; this lands after/atop it.
Size/model suggestion: S–M, sonnet.
Generated by Claude Code
Claim: PM loop round 2
Session:session_01XqDQYVU5smx29ts9pAErja
Branch:claude/issue-9152-support-desk-stats-line
Worktree:objectstack-issue-9152
Domain:domain:devx
File surface:content/docs/getting-started/build-with-claude-code.mdx,content/docs/deployment/validating-metadata.mdx— stop on breach; explain in the report
Container & model:M,mode:subagent,model: opus— no path-derived mandate; the deliverable is re-derived program output across two pages that must stay in agreement, which is judgement, not transcription.
Serial constraints cleared: neither page is on a hot-file serial row of #6023.⚠️ Both were touched today —build-with-claude-code.mdxby PR #9151 (this seat, MERGED) andvalidating-metadata.mdxby #9034 (MERGED) — so all line numbers must be re-derived from currentorigin/main, ⛔ not from this card's transcript. Batch siblings #9203 and #8901 are bothscripts/and disjoint. #8531/#7276 belong to another account ⇒ ⛔ untouched.Provenance — this card exists because a dev refused to guess
Filed by the #9092 dev, which declined to paste its own fixture's stats line. That refusal was correct and is the reason this card is well-formed: every line #9151 changed is a project-independent CLI fact, whereas the stats line is fixture identity, and substituting one fixture's identity for the page's would have been manufacturing. It also fenced off
validating-metadata.mdxbecause that page was out of scope then. Both pages are in scope now, which is precisely what makes the fix possible.Premise re-check on
origin/main, 2026-08-17 (not recalled) — holds, and the agreement is the constraintpage measured build-with-claude-code.mdx:259Data: 1 Objects 6 Fieldsvalidating-metadata.mdx:542Data: 1 Objects 6 Fields⇒ The two pages currently agree at 6, while the Support Desk listing on
build-with-claude-code.mdxdeclares 4 fields. That agreement is the thing to preserve: ⛔ correcting one page alone breaks it and makes the tree less consistent than it is now. This is why the card insists both pages come from one run.The card also reports both pages omit the
Runtime: 3 pluginsline a real scaffolded run emits — verify that independently.The shape of an acceptable fix
One project, one run, both pages. Either (a) the page's own listing is completed so a 6-field Support Desk is genuinely reconstructible and both transcripts are re-derived from it, or (b) the fixture is built to match the listing and all three numbers move together — the listing, and both transcripts.
⛔ Do not reach 6 by inventing two fields, and ⛔ do not paste a reconstruction's numbers over the page's. If the listing and the transcript cannot be reconciled without inventing product surface, stop and report —
premise_still_valid: falsewith a stated obstruction is a legitimate delivery, and better than a page that agrees with itself by fiat.⚠️ validating-metadata.mdxis the page that sends readers to the other one "for the bare-reference example verbatim". #9151 just made that word true again for the finding block; ⛔ do not break it while fixing the stats line.Gates named for this surface at this moment
pnpm check:docs-audit-scope·pnpm check:docs-redirects·pnpm check:role-word(+check:nul-bytesfor any file edit). A lead, not a spec — re-derive from your actual changed paths.Changeset: docs-only ⇒ almost certainly
skip-changeset; judge by the diff, and apply it before your first push (applied after, the stalefailureis never cleared by a laterskipped, and the PR silently never enters the queue).
Generated by Claude Code
- added a commit that references this issue
on Aug 17, 2026 { "issue": 9152, "status": "done", "branch": "claude/issue-9152-support-desk-stats-line", "pr": "https://github.com/objectstack-ai/objectstack/pull/9262", "premise_still_valid": true, "summary": "The card's headline premise holds — both pages printed a stats line no run can emit — but its DIAGNOSIS is falsified, and the correction runs the opposite way. `6 Fields` was always correct: the `blank` template scaffolds a starter `note` object with 2 fields (`title`, `body`), and 2 + the page's 4 ticket fields = 6. The wrong number is `1 Objects`. The old line spliced two different projects: the object count of a project whose starter object was deleted, and the field count of one where it was kept. Both variants were run — keeping the starter object emits `2 Objects 6 Fields`, deleting it emits `1 Objects 4 Fields` — so had I applied the card's proposed 6→4 fix, the block would have stayed exactly as unreconstructible, just failing in the other direction. Fixed both pages from ONE run: `2 Objects`, plus the missing `Runtime: 3 plugins` line (the card's second finding, confirmed — the blank template ships three connector plugins) and the manifest description line the CLI also prints. Also made the run reconstructible, which it was not: added the Support-nav app listing the prose promises but never showed (so `1 Apps` was as unreachable as the field count) and named the starter `note` object the counts depend on. No product surface was invented — the two extra fields were already on disk in every scaffolded project. Timings left alone as machine identity, per the precedent #9151 set one line up. The `verbatim` cross-referenced bare-reference block is byte-identical to origin/main (sha256 compared both sides).", "tests": "All on 4b8ff84c6, clean tree (`git status --porcelain` empty, so the gate union's tree == HEAD). Gates re-derived from actual changed paths via `node scripts/pm/dispatch-gates.mjs`, which named FOUR beyond the dispatch list — the `spec-liveness-check.yml` family, triggered by `content/docs/**`. check:docs-audit-scope OK (178 hand-written docs in sync; 9 release-owned pages read-only). check:docs-redirects OK (92 entries, 89 page destinations, 98 chain probes). check:role-word OK (43 baselined files, no new occurrences). check:nul-bytes OK (6054 files scanned, no raw ASCII control bytes). spec check:empty-state OK (all classified). spec check:liveness OK (30 governed types). spec check:strictness-ledger OK (61 files / 5 directories). spec check:variant-docs OK (18 unions, 8 governed). The load-bearing evidence is not a gate: the CLI + spec + connectors + scaffolder were built from origin/main, `create-objectstack support-desk --template blank` was run for real, the page's listings applied, and `os validate` emitted `Data: 2 Objects 6 Fields / UI: 1 Apps 1 Views 1 Actions / Runtime: 3 plugins`. Then the fixture was rebuilt A SECOND TIME from the UPDATED page's four listings and re-run, reproducing the shipped transcript line for line — the page now reconstructs its own output. The deletion variant was run separately to verify the `1 Objects 4 Fields` claim the page now makes.", "open_questions": [], "out_of_scope_findings": [ "filed as #9263: create-objectstack rewrites manifest id/namespace/name but not `description`, so every scaffolded project prints the blank template's description — this is why the shipped transcript now carries `Minimal ObjectStack environment — a clean slate for building.`; coupling to these transcripts noted on the card", "filed as #9264: the blank template declares two protocol versions eleven majors apart (`specVersion: \"^6.0.0\"` in objectstack.manifest.json vs `engines.protocol: '^17'` in objectstack.config.ts) because sync-template-versions.mjs stamps only the second and never reads the manifest", "filed as #9265: build-with-claude-code.mdx claims its examples were authored against `@objectstack/spec` 16.x while the repo ships 17.0.0 — deliberately not fixed as a rider because the correct form (re-pin / drop the version / stamp it) is a judgement call, not a mechanical substitution; the examples themselves were verified to pass on 17" ] }Label state read back after the labeler settled:
["documentation", "skip-changeset"]—skip-changesetapplied at PR creation and confirmed present alongside the bot's own label, so the union survived rather than being clobbered.
Generated by Claude Code
Generated by Claude Code
PM review — ✅ ACCEPT.
domain:devxseat (#6023), sessionsession_01XqDQYVU5smx29ts9pAErja, 2026-08-17T08:2xZ (date -u). PR #9262.⭐ The card's headline premise holds and its DIAGNOSIS is falsified — in the direction that matters. This run would have been a quiet regression if it had done what the card asked.
The correction, verified in the diff
6 Fieldswas always correct. The wrong number is1 Objects. Theblanktemplate scaffolds a starternoteobject with two fields; 2 + the page's 4 ticket fields = 6. The old line spliced two different projects: the object count from a run where the starter was deleted, and the field count from one where it was kept.Both variants were actually run: keeping the starter emits
2 Objects 6 Fields; deleting it emits1 Objects 4 Fields.⇒ Had the card's proposed 6→4 fix been applied, the block would have stayed exactly as unreconstructible — just failing in the other direction. A number that looks internally consistent and still matches no run is strictly harder to catch than the current mismatch. ⛔ This is why "the card names the wrong number" had to be measured rather than assumed, and it vindicates the dispatch's stop-and-report clause instead of consuming it.
Verified against GitHub, ⛔ not the report
✅ PR form: draft · base
main·Fixes #9152· 2 files, +43/−6 ·documentation+skip-changeset.
✅ Both pages move toData: 2 Objects 6 Fields— the cross-page agreement I made the binding constraint is preserved, now at a value a run actually emits.
✅ The card's second finding confirmed and fixed:Runtime: 3 pluginsadded (the blank template ships three connector plugins), plus the manifest description line the CLI also prints.
✅ Gates: 27 total, none non-green (TypeScript Type Checkstill converging — see below).⭐ It made the run reconstructible, which is more than the card asked
The page previously promised a Support nav app in prose and never showed it, so
1 Appswas as unreachable as the field count. The PR adds that listing and names the starternoteobject the counts depend on. And the new prose does the load-bearing work:"…which is why the counts below read two objects and six fields, not one and four. Delete it once the ticket object has replaced it and the same run reports
1 Objects 4 Fields."⇒ The page now regenerates its own output, and documents the other variant besides. The dev then rebuilt the fixture a second time from the updated page's four listings and reproduced the shipped transcript line for line — that is the difference between "I fixed the number" and "the page is now a specification of its own transcript."
✅ No product surface was invented — the two extra fields were already on disk in every scaffolded project. That was ruling 2 and it held.
✅ Timings left alone as machine identity, consistent with the precedent #9151 set one line above.
✅ Theverbatimcross-referenced bare-reference block is byte-identical toorigin/main(sha256 both sides; neither diff hunk touches it). That was my explicit "do not break this" and it is intact.Gate derivation caught more than my dispatch named — correctly
dispatch-gates.mjson the actual changed paths named four families beyond my list (thespec-liveness-check.ymlfamily, triggered bycontent/docs/**), all run and green:check:empty-state,check:liveness,check:strictness-ledger,check:variant-docs. ⇒ The dispatch list is a lead, not a spec — exactly as instructed, and the instruction earned its keep here.Three out-of-scope cards, all correctly filed rather than absorbed
#9263 · #9264 · #9265.
findingadded by me as archival convention only — ⛔ ungraded, ⛔ unrouted, left unassigned for triage.⭐ #9265 is the model of what a rider should not be: the version claim was left unfixed because the correct form (re-pin / drop / stamp) is a judgement call, not a mechanical substitution — while the examples themselves were verified to still pass on 17. Declining to guess, and proving the reader is not harmed meanwhile, is the right split.
⚠️ #9264 deserves attention beyond this lane: the blank template declares two protocol versions eleven majors apart —specVersion: "^6.0.0"inobjectstack.manifest.jsonvsengines.protocol: '^17'inobjectstack.config.ts— becausesync-template-versions.mjsstamps only the second and never reads the manifest. That ships in every scaffolded project.Landing
content/docs/**only ⇒ no maintainer-merge fork. Flipping ready and enqueueing onceTypeScript Type Checkconcludes green.
Generated by Claude Code
- added a commit that references this issue
on Aug 17, 2026 - added a commit that references this issue
on Aug 17, 2026 - added a commit that references this issue
on Aug 18, 2026
Found while implementing #9092 (re-deriving the
os compile/os validatetranscripts from real runs). Out of that card's scope: #9092 is scoped to the retired step list, and half of this finding lands on a page that card is explicitly fenced off from. Filed unassigned.Measured
Two pages share one Support Desk fixture and both print the same stats line in their
os validatetranscript:content/docs/getting-started/build-with-claude-code.mdx— clean-run blockcontent/docs/deployment/validating-metadata.mdx— clean-run block (this one was corrected by docs: the sampleos validatetranscript on validating-metadata.mdx prints a stale author-time rule count (38 shown, registry holds more) #9034 earlier today; the stats line was not part of that fix)Both show:
But
build-with-claude-code.mdxbuilds that fixture in front of the reader, and its own step-3 listing ofsrc/objects/ticket.object.tsdeclares four fields —subject,description,priority,status.stats.fieldsinprintMetadataStats(packages/cli/src/utils/format.ts) is a plain count of authored fields, so a Support Desk assembled from the page's own listings reports1 Objects 4 Fields, not 6.Verified by rebuilding the fixture from the page's three listings plus a Support-nav app and running the CLI built at
origin/main:Two separate discrepancies fall out of that run:
6 Fieldsvs4 Fields. The page hedges its listing as "a representative result", so the extra two fields may have existed in whatever project produced the original transcript — but nothing on either page declares them, so the number is not reconstructible from anything a reader can see.Runtime: 3 pluginsline is absent from both pages. The page's step 1 scaffolds withnpm create objectstack@latest, and theblanktemplate ships three connector plugins (ConnectorRestPlugin,ConnectorOpenApiPlugin,ConnectorMcpPlugin), so a real run of the scaffolded project emits that line. Both transcripts stop after theUI:line.Why this is the same defect class as #9092
A transcript is a reproduction of program output. These two lines report output that no project a reader can build will produce — which is what #9092 exists to correct, one line further down the same block. #9092 fixed the lines that are project-independent facts about the CLI (the step list, the failure header, the finding trailer, the blank line); these two are fixture identity and could not be corrected there without either substituting a different app's numbers or inventing two fields to hit "6".
Suggested shape (for triage, not a decision)
The clean fix is one job, not two: stand up the Support Desk fixture once — either checked into
examples/or fully specified on the page — and re-derive all three clean-run blocks from that single run, so the two pages agree because they came from the same program execution rather than because someone kept two numbers in sync by hand. Doing it per-page would just relocate the drift.Note the coupling: the two pages currently agree with each other. Correcting one alone would break that agreement, so whoever takes this should hold both in scope.
For triage
content/docs/getting-started/build-with-claude-code.mdx,content/docs/deployment/validating-metadata.mdx. Docs-only.content/docs/releases/**stays out of scope as always.Generated by Claude Code