Skip to content

Make the scaffolded starter comments followable by a stranger - #11024

Merged
os-elon merged 2 commits into
mainfrom
claude/issue-10324-template-monorepo-only-references
Aug 22, 2026
Merged

Make the scaffolded starter comments followable by a stranger#11024
os-elon merged 2 commits into
mainfrom
claude/issue-10324-template-monorepo-only-references

Conversation

@os-elon

Copy link
Copy Markdown
Collaborator

Fixes#10324

The two files a newcomer opens first after scaffolding — objectstack.config.ts and src/objects/note.object.ts — carried six references addressed to a reader with this monorepo open: four ADR identifiers, one bare issue number, and the path of a release-time script. None of docs/adr/, the issue tracker, or that script ships in a scaffolded project, so // per ADR-0097 read as a reference the newcomer was failing to follow rather than as the context it was meant to be.

Per triage, the comments' explanatory value is kept and only the dead ends are gone. Every rewrite states the fact the identifier stood for, in terms the reader can act on, and points at a public docs page where one covers the material.

What each rewrite says instead

WasNow says, self-contained
ADR-0087 D1 + scripts/sync-template-versions.mjsthe runtime checks the range before it loads anything and refuses the app at the boundary with the migration command; the value was stamped to match the ObjectStack version you installed — change it when you deliberately move to a new protocol major, not to silence a mismatch
per ADR-0097 (on requires)unchanged rationale, identifier dropped — the comment already said the whole thing (without automation the executors have nowhere to register and boot fails)
ADR-0022/0023/0024 + ADR-0097what the executors do and that zero-arg means "contribute the provider factory only"
Security (#3055)a declarative mcp stdio transport spawns a local process from metadata, so it is denied by default, with the per-host opt-in spelled out
security posture gate (ADR-0090)what the org-wide default means, and that objectstack buildrefuses an object declaring no OWD, so the baseline is always an authored decision

The sync-template-versions.mjs line is the worked example of the judgement: it was telling the reader the range is machine-maintained rather than hand-tuned. That fact is now stated; the script the reader does not have is not named.

Sweep of the rest of the template tree (the card's rider)

One more hit outside the two starter files, and it is in scope — Dockerfile:23 pointed at docker/README.md in the framework repo. It now points at the self-hosting guide the file already links four lines above, so the "there is more detail" affordance survives without the dead pointer. This file is named here deliberately: it is an addition to the file surface declared in the claim comment, and the claim was amended in the same round.

⚠️Dockerfile:10 and docker-compose.yml:7 were left untouched — those docs.objectstack.ai host lines are #10990's, and this diff stays off them so the two cards cannot collide.

Verified against public docs, not assumed

Each URL introduced here was resolved with this repo's own link gate rather than a second hand-rolled resolver — checkDocument() from scripts/check-published-readme-links.mjs, over a synthetic document carrying the three links plus a deliberate control route that does not exist:

CANONICAL_DOCS_ORIGIN = https://objectstack.ai
stats: {"links":5,"docs-site":4,"relative":1,"resolved":3,...}
FINDING: {"kind":"dead-page",...,"dest":"https://objectstack.ai/docs/this-page-does-not-exist-10324",...}
VERDICT control-link-flagged=YES (must be YES, else the probe is blind)
VERDICT under-test-links-flagged=0 (must be 0)

The control link is what makes that green mean something: the probe demonstrably can fail.

The pin, and why it has two halves

packages/create-objectstack/src/starter-comments-self-contained.test.ts scans every file the scaffolder copies into a user's project:

  1. No unfollowable reference — no ADR identifier, bare issue number, repo script path or monorepo package path.
  2. The rationale still stated — each fact a removed reference was carrying must still be findable in the file.

Half 2 is the load-bearing one. The cheap way to make the references disappear is to delete the comments, which would be a worse project than the one with the dead references — so a one-way "no ADR identifiers" grep would rot in exactly the direction triage warned about, staying green while the explanation is deleted out from under it.

  1. Canonical docs links resolve against content/docs the way Fumadocs routes them, because a link that 404s is the same defect one level out.

blank/README.md is excluded — it still carries an ADR identifier of its own and is owned by other cards in this family. The exclusion is self-retiring rather than permanent: a final assertion fails the moment that README stops needing it, telling whoever cleans the file to delete the entry so it is scanned like everything else. A silent exemption over the most-read file in the tree is the failure that shape exists to avoid.

Reverse-verification — three ablations, each observed red, then restored green

Run from a committed state, so restoring was a git checkout rather than a hope. These are plain fs.readFileSync source-text reads inside one package — no dist/, no exports resolution — so no rebuild leg applies to any of them.

AblationObserved
reintroduce per ADR-0097redcites an ADR identifier ("ADR-0097"); 1 failed / 20 passed
delete the mcp rationale, adding no referenceredno longer explains that a declarative mcp stdio transport is denied by default; 1 failed / 20 passed
repoint a docs URL at a plausible-but-absent routeredlinks https://objectstack.ai/docs/automation/connector-authoring, which content/docs serves from none of …; 1 failed / 20 passed
restoredgreenTest Files 1 passed (1) · Tests 21 passed (21)

Read as a newcomer, not as a diff

The point of this card is what a stranger sees, so the CLI was rebuilt and a real project scaffolded from it (node dist/index.js acme-notes -t blank --skip-install --skip-skills). Sweeping the generated project for anything unfollowable leaves two hits, both in the fenced README, both reported rather than touched (see below).

Reading the generated output also caught something the diff alone did not: the OWD comment originally said `npm run build`, while the generated README uses pnpm throughout. Naming the underlying objectstack build instead is correct whichever package manager invoked it.

Fenced files — swept, reported, not touched

FileFoundOwner
templates/blank/README.md:77ADR-0097filed as #11022 (PR #11013 does not reach this line)
templates/blank/README.md:134"the ObjectStack framework repo"filed as #11022
templates/blank/README.md:102`AGENTS.md`not a defect: the scaffolder really does write that file into the project
templates/AGENTS.mdno ADR/issue/script references; its wrong-TLD link is #10990'suntouched
scaffolder src/index.tsbanner is #10325'suntouched

Also filed from the sweep: #11023packages/cli/src/commands/init.ts writes ADR identifiers into the user's project through the other scaffolder, same defect class, out of this card's package.

Gates

All run at e6a31555b0 (the final commit), gate set derived from the real change set with node scripts/pm/dispatch-gates.mjs rather than the dispatch list — it named five families the dispatch did not, all run below.

create-objectstack test Test Files 10 passed (10) · Tests 123 passed (123)
create-objectstack typecheck tsc --noEmit, exit 0
eslint packages/create-objectstack --no-inline-config exit 0
check:cross-package-test-inputs OK: 13 package(s) read outside themselves, all declared,
and turbo.json hashes every declared glob.
check:template-version-sync ✓ 40 assertions over temp fixtures, running the real CLI
check:nul-bytes OK (scanned 6377 text file(s); no raw ASCII control bytes)
check:slot-lookup ✓ ratchet holds: none new
check:where-matcher ✓ 276 matcher(s); 0 silently-wrong; none new
check:engine-double-contract OK — 377 pinned, 133 in the DEBT ledger, 2 exempt
check:query-options-erasure ✓ ratchet holds: none new
check:type-check-coverage OK — 65/78 workspace packages type-checked
check:test-source-alias OK — 72 packages with tests scanned
check:type-source-resolution OK — 77 packages with a tsconfig.json scanned
check:changeset-gate-self-tests ✓ (446 assertions across three gates)
check:objectui-changeset ✓ objectui-range --self-test: all checks passed
check-empty-changeset ✓ No empty-frontmatter changeset (1 declaring changeset added)
check-adr-0087-registration ✓ adds no declared-breaking changeset
check-changeset-no-major ✓ introduces no `major` bump
check-ci-filter-parity OK: all 82 declared cross-package glob(s) covered
check-plugin-teardown-shape ✓ 61 Plugin implementation(s); baseline fully burned down
docs-audit/check-affected-docs exit 0

check:cross-package-test-inputs is called out because the new test reads content/docs: that read lands inside the content/** glob this package already declares, so the gate stays green with no declaration change. pnpm --filter 'create-objectstack^...' build matched no projects — a genuine no-op, since create-objectstack has no workspace dependencies (only chalk and commander), not a silently skipped build. check:type-check-debt has nothing to re-measure here: this package carries no test-typecheck-debt.json, and its tsconfig.json puts the new test file inside the program that typecheck runs (confirmed with tsc --listFiles).

CI convergence is left to review rather than waited on here.


Generated by Claude Code

…tranger
The two files a newcomer opens first after scaffolding cited four ADR
identifiers, a bare issue number and a release-time script path — none of
which ship in a scaffolded project. Rewrite them self-contained, keeping
what they explain and pointing at public docs pages, and pin both halves:
no unfollowable reference, and the rationale still stated.
Fixes#10324
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019bmVFqoQPq63zhKrxdYG1r
…rally
The scaffolded README uses pnpm throughout, so a hardcoded `npm run build`
in the starter object contradicted the project's own docs. Name the
underlying `objectstack build` instead, which is what the project's build
script runs whichever package manager invoked it.
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

Nothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 1 changed package(s)), so this run has no opinion about the docs.

What this run could not see
  • 2 changed file(s) yielded no anchor (packages/create-objectstack/src/templates/blank/Dockerfile, packages/create-objectstack/src/templates/blank/objectstack.config.ts) — pages documenting those are invisible to this run
  • 1 name(s) were too generic to anchor anything (single lowercase words)

Coarse fallback — 1 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 f334d662ef3c2543d6add14b9140ab9350041cb2packageMentionDocs.

@github-actions

Copy link
Copy Markdown
Contributor

⛔ merge queue 构建失败 — 先分诊,再决定要不要重排

队列构建 32566894495 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集),
所以失败的测试可能在本 PR 没碰过的包里 —— 那不是重排能修的。每次盲目重排都会让排在后面的所有 PR 重建一轮。

失败的 job(日志抽取,best effort):

  • Console Pin Gate — 失败步骤: Build the Console SPA at the pinned objectui SHA

    ✗ Build failed in 6.14s
    

↳ 失败原因 是判读的关键:超时Test timed out in … / Hook timed out in …)多半是负载/时序,不是本 PR 的回归;
断言AssertionError: …)才指向真实的行为改变。两者的 FAIL 行长得一模一样,只有这一行能区分。

跨 PR 相同签名(24h,按失败测试文件聚合):

  • ⚠️本次没有可用的聚合签名(日志里没有能解析出测试文件名的 FAIL 行)—— 这不是「没有同签名的其他 PR」,是这一轮没测到。跨 PR 聚合本次不可用,请手工比对其他 PR 的同类评论。
  • ⚠️ 24h 评论账本没读完(超过 5 页仍未读到窗口尽头),所以上面的「不同 PR 数」是下界,不是全量。

历史信号:

  • 本 PR 过去 24h 无队列失败记录(首次)。
  • 过去 24h 队列共有 93 个失败构建(不含本次)。

分诊清单:

  1. 失败测试在本 PR 改动的包里 → 真回归,修 PR。
  2. 失败测试与本 PR 无关 → 看上面的「跨 PR 相同签名」;已有汇总 issue ⇒ flaky/环境问题实锤,去那张 issue 上谈,修好前重排只会再烧一轮全队列。
  3. 两者都不是 → 可能与同组 PR 语义冲突;等前面的 PR 落地或失败出队后再重排一次即可,不要连续重排。

Generated by Claude Code · merge-queue-triage workflow (#4859)

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.

[finding] The two starter files a newcomer opens first cite ADR numbers, an issue number and a monorepo script that do not exist in their project

2 participants

@os-elon@claude