Skip to content

fix(cli): make os init's rendered template comments self-contained - #11192

Merged
os-elon merged 2 commits into
mainfrom
claude/issue-11023-init-template-adr-refs
Aug 23, 2026
Merged

fix(cli): make os init's rendered template comments self-contained#11192
os-elon merged 2 commits into
mainfrom
claude/issue-11023-init-template-adr-refs

Conversation

@os-elon

@os-elonos-elon commented Aug 23, 2026

Copy link
Copy Markdown
Collaborator

Fixes#11023

Premise check

Re-measured at origin/main before editing: the card's line numbers had drifted (as the claim comment already flagged), but the mechanism was intact. Located by text, confirmed at:

TextLine
// Protocol major this app is authored against (ADR-0087 load-time check).:397
// Org-wide default (OWD): who can see records they do NOT own. ADR-0090 D1:433
// Protocol major this plugin is authored against (ADR-0087 load-time check).:477
// Org-wide default (OWD): who can see records they do NOT own. ADR-0090 D1:499
// Protocol major this app is authored against (ADR-0087 load-time check).:540

:488's (now :572) #10499 is confirmed to be an ordinary in-repo JSDoc comment on printCreatedFilesSummary — outside every configContent/srcFiles function, so it never reaches fs.writeFileSync and does not ship. Premise holds in full.

The ships-vs-source boundary

init.ts writes to the user's project through exactly two paths: template.configContent(name, namespace)objectstack.config.ts, and writeTemplateSrcFiles(template.srcFiles, ...) → everything under src/. Both are called from TEMPLATES[key]. Anything inside those functions' template-literal bodies ships; anything outside them (helper functions, their own JSDoc, module-level comments) is init.ts's own source and never leaves this repo. All five hits sit inside the app/plugin/emptyconfigContent/srcFiles bodies; the #10499 JSDoc does not.

The fix

Rewrote each comment self-contained, keeping the rationale, using the wording #10324 settled on:

  • protocol range → https://objectstack.ai/docs/upgrading
  • org-wide default → https://objectstack.ai/docs/permissions/sharing-rules

Both routes verified to resolve against content/docs before committing (content/docs/upgrading.mdx, content/docs/permissions/sharing-rules.mdx both exist) and re-asserted by the pin's own assertion 3.

The pin

packages/cli/test/init-template-comments-self-contained.test.ts. Per the card's own warning, the population is template literals rendered by init.ts, not the source file — a wholesale grep of init.ts would also match its legitimate own comments (e.g. the #10499 JSDoc) and report on the wrong population. The pin reaches the real population directly: it calls template.configContent(...) and writeTemplateSrcFiles(...) — the exact functions init's command handler calls — and writes them to real files in a throwaway dir, exactly mirroring init-scaffold-authoring-rules.test.ts's existing generate() pattern. It then scans only what those functions produced.

Two-sided, matching #10324's shape:

  • assertion 1 — nothing in the rendered output matches MONOREPO_ONLY (ADR id / bare issue / script path / package path), reused verbatim from starter-comments-self-contained.test.ts.
  • assertion 2 — the fact each removed reference carried is still stated (protocol-refusal rationale, OWD rationale), matched loosely so rewording stays free.
  • assertion 3 — every canonical-origin docs URL in the rendered output resolves against content/docs the way Fumadocs routes it.

Vacuity guards throughout: a template-count / file-presence check before assertion 1, a non-empty object-file-list check before assertion 2, and a non-zero-URL-count check before assertion 3 (so an extractor that silently stopped matching would fail loud instead of vacuously passing).

Reverse-verification performed: committed the fix, then git checkout origin/main -- packages/cli/src/commands/init.ts to restore the pre-fix text on top of the new pin. Result: 9 of 15 cases went red, each for the intended reason — assertion 1 caught all 5 ADR identifiers by name (app, plugin, empty configs + both OWD object files), assertion 2 correctly failed to find the new wording, and assertion 3's own non-vacuity guard reported "no canonical docs URLs found" (there weren't any pre-fix). Then git checkout HEAD -- packages/cli/src/commands/init.ts restored the fix (git status --porcelain clean against HEAD), and the full 15/15 green again.

Real-thing verification: built the CLI and ran the init command for real against a temp directory, with --no-install, once per built-in template (app, plugin, empty). Swept the generated projects on disk with the same MONOREPO_ONLY pattern set — zero matches — and confirmed both docs URLs appear verbatim in the generated files (5 occurrences total, matching the 5 original hits).

Gate verdicts (derived via node scripts/pm/dispatch-gates.mjs at commit 6ff5a4345d)

  • pnpm --filter @objectstack/cli testTest Files 160 passed (160), Tests 1757 passed (1757) (full package suite); pin file alone re-verified at final HEAD: Test Files 3 passed (3), Tests 76 passed (76).
  • pnpm --filter @objectstack/cli typecheck — clean (tsc --noEmit, no output).
  • pnpm --filter @objectstack/cli build — clean.
  • pnpm check:cross-package-test-inputsOK: 13 package(s) read outside themselves, all declared, and turbo.json hashes every declared glob. (Note: an earlier draft of the pin's docblock backtick-quoted a scripts/*.mjs path in prose; the gate's literal collector reads a backtick-quoted path the same as a real specifier. Reworded to match the established convention — no scripts/ prefix, no quoting — rather than widening the package's declared turbo glob for a path nothing reads.)
  • pnpm check:slot-lookupslot-lookup ratchet holds: 107 unswept site(s) in 25 file(s), none new.
  • pnpm check:test-source-aliascheck-test-source-alias OK.
  • pnpm check:type-source-resolutioncheck-type-source-resolution OK.
  • node scripts/check-ci-filter-parity.mjsOK: all 86 declared cross-package glob(s) ... covered.
  • node scripts/check-cross-package-test-inputs.mjs — same OK as above (root-level invocation).
  • node scripts/check-plugin-teardown-shape.mjs0 known-unreached, SHRINK-ONLY, baseline fully burned down.
  • node scripts/docs-audit/check-affected-docs.mjs — self-test + scan both clean (exit 0).
  • pnpm check:query-options-erasureratchet holds ... none new.
  • pnpm check:engine-double-contractOK: 384 pinned, 133 in the DEBT ledger, 2 exempt (no new doubles from this PR).
  • pnpm check:where-matcher0 silently-wrong and 0 unjudged matcher(s) ... none new.
  • pnpm check:type-check-coverage / pnpm check:type-check-debt — required a full workspace-closure build first (pnpm exec turbo run build --filter='./packages/*' --filter='./packages/*/*', ~5m24s); re-measured clean: check-type-check-coverage --re-measure: OK — 33 ledger entr(ies) re-measured ... none above its recorded number.
  • Changeset-triggered: check:changeset-gate-self-tests, check:objectui-changeset self-tests all pass; check-adr-0087-registration: this PR adds no declared-breaking changeset; check-changeset-no-major: This diff introduces no major bump; check-empty-changeset: No empty-frontmatter changeset introduced.

All commands run through scripts/pm/os-verify-lock.sh.

Out of scope

Nothing found outside this card's surface during this pass.

Generated by Claude Code

packages/cli/src/commands/init.ts renders its templates as string
literals and writes them into the user's project. Five of those
literals carried ADR identifiers (ADR-0087, ADR-0090 D1) addressed to
a reader with this monorepo open; a project scaffolded by `os init`
ships no docs/adr/, so the identifier named something unfollowable.
Rewrite each self-contained, keeping the rationale, and link the same
public docs routes #10324 verified for create-objectstack:
- protocol range -> https://objectstack.ai/docs/upgrading
- org-wide default -> https://objectstack.ai/docs/permissions/sharing-rules
Add a pin that renders every TEMPLATES entry through init's own
emitter (configContent / writeTemplateSrcFiles) and scans the
rendered output -- not the source file -- so it cannot be confused by
init.ts's own ordinary source comments that legitimately cite ADRs
and issue numbers.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019bmVFqoQPq63zhKrxdYG1r
…n a comment mention
The pin's docblock backtick-quoted a scripts/*.mjs path, which the
cross-package-test-inputs gate's literal collector reads the same as
a real quoted specifier. Reword to match the established convention
(no scripts/ prefix, no quoting) instead of widening the package's
declared turbo glob for a path nothing actually reads.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019bmVFqoQPq63zhKrxdYG1r
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/cli, touching 1 documentable anchor(s).

3 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:

  • content/docs/deployment/cli.mdx(via os init (command))
  • content/docs/getting-started/examples.mdx(via os init (command))
  • content/docs/getting-started/your-first-project.mdx(via os init (command))

1 release-owned page(s) also name something this change touched. These are read-only:

  • content/docs/releases/v17.mdx(via os init (command))

content/docs/releases/ is RELEASE-OWNED (AGENTS.md "Documentation Guardrails"): release
notes are written centrally at release time, and a code PR that edits them is the exact PR
that guardrail exists to stop. They are still audited — read-only. If one of them is actually
wrong, file an issue or open a dedicated docs-only PR; do not edit it here.

What this run could not see

Coarse fallback — 23 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 2b5a7ce59b57231e6702e63b876ae335a8e71f24packageMentionDocs.

Which tree this was computed on

This run read content/docs from 95e7c43afd9569e64662d6de74e282a56a5e19a7 — the merge of head 6ff5a4345d4794a1eb14804eea73b46818894195 into base 2b5a7ce59b57231e6702e63b876ae335a8e71f24, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 95e7c43afd9569e64662d6de74e282a56a5e19a7 && git checkout 95e7c43afd9569e64662d6de74e282a56a5e19a7
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 2b5a7ce59b57231e6702e63b876ae335a8e71f24 6ff5a4345d4794a1eb14804eea73b46818894195 && git checkout -B drift-repro 2b5a7ce59b57231e6702e63b876ae335a8e71f24 && git merge --no-ff 6ff5a4345d4794a1eb14804eea73b46818894195
node scripts/docs-audit/affected-docs.mjs --json 2b5a7ce59b57231e6702e63b876ae335a8e71f24

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs 2b5a7ce59b57231e6702e63b876ae335a8e71f24 → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation tests tooling labels Aug 23, 2026
@os-elon
os-elon marked this pull request as ready for review August 23, 2026 02:26
@os-elon
os-elon added this pull request to the merge queueAug 23, 2026
Merged via the queue into main with commit 18d5fecAug 23, 2026
35 checks passed
@os-elon
os-elon deleted the claude/issue-11023-init-template-adr-refs branch August 23, 2026 02:38
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/mteststooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

os init writes ADR identifiers into the user's project too — the same defect #10324 fixed in create-objectstack, in the other scaffolder

2 participants

@os-elon@claude