Repository navigation
docs + scaffold: plugin-spec.mdx stops promising the non-existent @objectstack/testing and points at @objectstack/verify; the create-objectstack blank template ships a test story (epic hotcrm#1579, step 5b) #15952
Description
Activity
- added a commit that references this issue
on Sep 17, 2026 - added a commit that references this issue
on Sep 28, 2026 objectstack-fleet commented
on Oct 11, 2026 ContributorMore actionsRelease:
pm:epicreservation →pm:queue. Sessionsession_01EgxC4UNYnzhuvmG12fh5A8, at 2026-10-11T22:32Z. Cause: the reserving epic is closed and its seat left no work on this card. Destination: thedomain:clilane's queue.Provenance: the maintainer, in live PM chat in this session. Orders, verbatim: 「该关的关,改开卡的开卡」, then the explicit confirmation of this exact move (return #15952 and #15953 to the queue).
Why the reservation is spent
- The epic this card belongs to, Epic: bring this repo's test farm back under the 2026-08-31 ruling — platform-first,
os lint --strictfirst, then retire the local re-implementations by family hotcrm#1579, reads CLOSED through this card's parent link. - Its seat, os-steve
session_01DuzfS5chho38Yx1jxx9DEj(claim on verify: an in-process handle on the booted stack — run a hook, flow, action or validation rule against the REAL engine and assert, so an app never fakesctx.apiagain (epic hotcrm#1579, step 5a) #15951,5556951692), left no claim, branch or PR on this card. - A reservation held for a closed epic has nobody behind it.
Unlock re-derivation, read this act
Blocked-by: #15951: CLOSED, PR feat(verify): an in-process handle on the booted stack — run a hook, flow, action or validation rule against the real engine and assert #17181.- The epic PM's stricter condition in
5611024316("until@objectstack/verifyships with the handle") is met.npm viewshows@objectstack/verify@17.5.0published at 2026-09-29T07:55Z, and its changelog entry for6058cb2(packages/verify/CHANGELOG.md) exportsisVerifyRefusal. The current release is 17.7.0.
Premise re-check on
mainat8532783f: still holds, nothing has landedcontent/docs/protocol/kernel/plugin-spec.mdx:787-792still points readers at the non-existent@objectstack/testing. All 7 mentions ofobjectstack/testing|createTestContext|createTestEnvironmentacrosscontent/,skills/andpackages/are in that file.- The blank template ships no
testscript, no vitest and no@objectstack/verifydevDependency.
Note for the lane: the thread reports one comment that the API does not return (timeline:
mentioned os-steve). Read the body as the full card.- The epic this card belongs to, Epic: bring this repo's test farm back under the 2026-08-31 ruling — platform-first,
objectstack-fleet commented
on Oct 11, 2026 ContributorMore actionsClaim: PM loop round 2 · 2026-10-11T23:19Z
Session:session_01VoSxBQujKLZKPwK2u5ehQ6
Account:os-steve(the seat's linked user asGET /useranswers it; the card's assignee from this act)
Branch:claude/issue-15952-blank-template-test-story
Worktree:objectstack-issue-15952
Domain:domain:cli
Seat:domain:cli#2(seat post #22648)
File surface (read onorigin/main9fdb12752c; stop on a breach and explain it in the report):- Docs:
content/docs/protocol/kernel/plugin-spec.mdx, the "Plugin Testing" section (the@objectstack/testingcallout and snippets, about:788–:840), rewritten aroundbootStackand verify: an in-process handle on the booted stack — run a hook, flow, action or validation rule against the REAL engine and assert, so an app never fakesctx.apiagain (epic hotcrm#1579, step 5a) #15951's in-process handle as@objectstack/verifyships them. On this treegit grep "objectstack/testing|createTestContext|createTestEnvironment"overcontent/,skills/andpackages/hits only that file. If a generator owns the text, the source is fixed and regenerated, never the page by hand. Cross-lane (domain:devx,content/docs/**): declared on [PM seat] domain:devx @ objectstack — 🟢 os-warren · session_012yK1ddAdAqfzwigRHZq3r2 #6023 in this act. - Scaffold:
packages/create-objectstack/src/templates/blank/:package.json(atestscript, plus@objectstack/verifyandvitestdevDependencies at the template's pinned range), a newvitest.config.ts, and ONE example test that boots the template's own stack withbootStackand asserts one business fact. Also the template'sREADME.mdand.github/workflows/ci.ymlonly if they must name the new step. create-objectstack's own tests: the scaffold test that exercisesvalidate/typecheckgains theteststep, plus any template-consistency or version-stamp test the new files trip.- One
.changeset/15952-*.md(create-objectstackminor). - Narrowed by edit (seat order on this card, open question 2 taken as A, split):
- PR docs(plugin-spec): Plugin Testing teaches bootStack and the in-process handle of @objectstack/verify, not the non-existent @objectstack/testing (#15952) #22910 now carries the docs half only (
plugin-spec.mdx,Part of #15952,skip-changeset). - The scaffold half is held on branch
claude/issue-15952-scaffold-held: the template files,packages/create-objectstack/vitest.config.ts,.github/workflows/scaffold-e2e.ymland the changeset. It waits on finding: on npm 10 (Node 22's bundled major),npm installof a scaffold that declaresvitest ^4.0.0(SCAFFOLD_VITEST_RANGE:objectstack init -t plugin,objectstack create plugin) crashes with "Cannot read properties of null (reading 'edgesOut')" #22912 and on the report's open question 1. - This claim holds no scaffold file while it is held.
- PR docs(plugin-spec): Plugin Testing teaches bootStack and the in-process handle of @objectstack/verify, not the non-existent @objectstack/testing (#15952) #22910 now carries the docs half only (
- ⛔ No
packages/verifychange (the handle is verify: an in-process handle on the booted stack — run a hook, flow, action or validation rule against the REAL engine and assert, so an app never fakesctx.apiagain (epic hotcrm#1579, step 5a) #15951's, landed by PR feat(verify): an in-process handle on the booted stack — run a hook, flow, action or validation rule against the real engine and assert #17181), noos testchange, nopackages/spec, nocontent/docs/releases/**.
Container & model:M(a docs rewrite against the shipped handle, a template that must boot its own stack undervitest, and a scaffold test step),mode:subagent,model: default tier(dispatch-gates --tier --repo objectstack-ai/objectstack: "no path-derived mandate"). No contract-review face:Clause-②: no, as the card states and re-read from its content: no exported symbol moves, the template gains files, and the docs stop naming a package that does not exist. Nopackages/spec, no governed path.
Clause-②: no
Responsibility:plugin-spec.mdx (content/docs) teaches app authors to test against @objectstack/testing, which does not exist, and the create-objectstack blank template ships no test script | @objectstack/verify already ships bootStack and the in-process handle (#15951, PR #17181; 17.5.0 published, 17.7.0 current) | an app author or an AI following the docs writes a hand-built kernel context (hotcrm's makeCtx) instead of booting the real stack, and a scaffolded app starts with no way to assert its own behaviour
Thread-read: 6114636846
Serial constraints cleared:Blocked-by: #15951is closed (PR feat(verify): an in-process handle on the booted stack — run a hook, flow, action or validation rule against the real engine and assert #17181), and the epic's ship condition (5611024316) is met per the release comment6114636846. Thepm:epicreservation was released to this lane's queue on the maintainer's order. No open PR touchesplugin-spec.mdx,packages/create-objectstackorpackages/verify(all 10 open PRs' file lists read in this act). None of the openpm:dispatchedclaims declares them. The card has noarea:*label. This seat's in-flight cli: the 9packages/cli-owned rule ids and the action-governance boot-log lines print one verdict sentence each (≤ 200 chars), with the reasoning behindos explain rule <id>(#22161, thedomain:clihalf) #22841 (packages/clilint producers,rule-explanations.ts,action-governance.ts) is disjoint. Seat 1 ([PM seat] domain:cli — ⏳ vacant #6024) is vacant with no holds.
Generated by Claude Code
- Docs:
objectstack-fleet commented
on Oct 12, 2026 ContributorMore actionsos-dev-report
{ "issue": 15952, "status": "needs_decision", "branch": "claude/issue-15952-blank-template-test-story", "pr": "https://github.com/objectstack-ai/objectstack/pull/22910", "session": "session_01VoSxBQujKLZKPwK2u5ehQ6 — mode:subagent, the parent's id (container CLAUDE_CODE_REMOTE_SESSION_ID=cse_01VoSxBQujKLZKPwK2u5ehQ6)", "premise_still_valid": true, "summary": "Both halves of the ruled design are implemented on draft PR #22910 (head 812d8dbf94). DOCS: the Plugin Testing section of content/docs/protocol/kernel/plugin-spec.mdx (hand-written: listed in scripts/docs-audit/handwritten-docs.json, no generator) is rewritten around bootStack and the in-process handle, using only methods present in published @objectstack/verify 17.7.0 and on main. The ghost callout and all 7 @objectstack/testing / createTestContext / createTestEnvironment hits are gone. SCAFFOLD: the blank template gains a `test` script, @objectstack/verify ^17.0.0 + vitest ^4.0.0 devDependencies, a vitest.config.ts (60s hookTimeout, console intercept off, OS_REGISTRY_LOG warn), ONE note.test.ts that boots the project's own stack and asserts through stack.hooks.run that a note without a title is refused (code VALIDATION_FAILED, fields [title/required]) while the same note with a title is saved, plus a tsconfig include of root *.ts and a README pnpm test line. A freshly scaffolded app runs `pnpm test` green. The Scaffold E2E workflow gains a `npm test` step. NOT LANDABLE AS IS, two measured blockers, see open_questions: (1) two required gates (check-registry-log-declared, check:test-source-alias) count the template payload test as create-objectstack's own suite; fixing them is a scripts/ edit outside the file surface. (2) `npm install` of the new starter crashes on npm 10 (10.9.4 and 10.9.9), from an upstream vite/vitest optional-peer graph. A manifest holding only vitest ^4.0.0 crashes the same way, and npm 11 is fine. main's template installs fine on npm 10; this diff adds the vitest devDependency that hits it. PM mechanism assumptions: #1 held (7 hits, all in plugin-spec.mdx, at 9fdb12752c; the page is not generated). #2 held, with a correction: published 17.7.0 bootStack composes neither the app's `plugins` nor its `requires` providers, main's does, and the starter test passes on both (main measured with the protocol stamp moved to ^18, as the version step does). #3: the pins are template-consistency (^17.x), template-version-sync and the cli scaffold-emission-policy e2e (vitest range across all three scaffolders), all green and none weakened. #4: no vitest test runs validate or typecheck on a scaffold; \"the scaffold test\" is .github/workflows/scaffold-e2e.yml job 1 (registry install via npm, validate, build), extended by one step. #5: the template ci.yml is unchanged, because packages/cli/test/scaffold-ci-script-parity.test.ts derives the script set from it and holds `objectstack init -t app/empty` (no `test` script) to it.", "tests": "All at head 812d8dbf94. FRESH SCAFFOLD: repo-built bin `final-notes --skip-install --skip-skills`, then `pnpm install` from the registry (@objectstack/verify 17.7.0, vitest 4.1.11). `pnpm test` via os-verify-lock: VERDICT command-exit 0, \"Test Files 1 passed (1) · Tests 1 passed (1)\". pnpm typecheck, validate, lint and build: exit 0 each. ABLATION OF THE STARTER TEST (scaffold copy): deleting `required: true` from note.object.ts gives exit 1, \"AssertionError: promise resolved \\\"{ id: '266hr_hmB2KBiUK8', …(9) }\\\" instead of rejecting\"; restoring the file gives green. TYPECHECK REACHES THE TEST: `tsc --listFiles` lists note.test.ts and vitest.config.ts, and a planted `hooks.runn` fails `pnpm typecheck` with TS2551 (restored, then green). FORWARD BOOT ON MAIN'S HARNESS: the template was copied into a temporary, since-deleted packages/qa/dogfood/.tmp-issue-15952 with engines.protocol ^18 (main is protocol 18.0.0; at ^17 it refuses with ProtocolIncompatibleError, as designed). `vitest run` against the workspace build: exit 0, Tests 1 passed. The boot registered connector-rest/openapi/mcp, service-automation, the triggers and the always-on slate. ABLATION OF THE create-objectstack EXCLUDE: scripts/ablation-replace.mjs deleted the `exclude:` line (anchor 1 to 0, blob d7ace906 to 2cdb68c5), and `vitest list --filesOnly` went from 17 files to 18 (+ src/templates/blank/note.test.ts). Restore: blob == HEAD d7ace906, `git diff HEAD` empty. PACKAGE SUITES: `pnpm --filter create-objectstack test && typecheck` gave VERDICT command-exit 0, \"Test Files 17 passed (17) · Tests 258 passed (258)\", tsc exit 0. packages/cli unit files that read the template or this page (scaffold-ci-script-parity, docs-cli-enumeration-parity, create-objectstack-wiring-parity, starter-field-consumers, create-plugin-docs-parity, create-example-retired-docs-parity): exit 0, \"Test Files 6 passed (6) · Tests 97 passed (97)\". The same run listed scaffold-emission-policy.e2e.test.ts, and its filter selected nothing (nightly tier), so it was re-run with OS_TEST_TIERS=nightly: exit 0, \"1 passed · 10 tests\". The cli integration layer is declared to CI. ACCEPTANCE GREP: before (9fdb12752c) 7 hits, plugin-spec.mdx:788-832. After, `git grep -n \"objectstack/testing\" -- content/ skills/ packages/` gives 0 hits (exit 1), and the three-symbol expression also gives 0 (exit 1). GATES: dispatch-gates --commands (no paths) at 812d8dbf94 gave 130 families, the same list as at cfcde47356. All 130 were run at 812d8dbf94, and `--ran` reports \"130 derived famil(ies) accounted for — 130 run, 0 NOT-MEASURED\". 128 exited 0 and 2 exited 1 (check-registry-log-declared, check:test-source-alias: blocker 1). check:skill-examples and check:dual-build-cjs-loads exited 3 (PREREQUISITE NOT MET) on the first pass, then 0 after a turbo build (73 tasks, 72 cached). LINT (proven narrowing): eslint.config.mjs scopes TS by `**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}`, so the diff's lintable population is 3 files (note.test.ts, template vitest.config.ts, create-objectstack vitest.config.ts). `pnpm exec eslint --no-inline-config --format json` reported 3 files, 0 errors, 0 warnings. The config enables no type-aware linting (no parserOptions.project), so the diff cannot move a verdict on any untouched file. Control bytes: `grep -naP` over all 9 files gives no hit.", "mcp_calls": "0", "api_writes": "2 relay strokes as objectstack-fleet[bot], via scripts/pm/fleet-write/dispatch.mjs (POST /repos/objectstack-ai/objectstack/dispatches each). (1) pr_create, which executed POST /repos/objectstack-ai/objectstack/pulls (draft, forced) + POST /repos/objectstack-ai/objectstack/issues/22910/assignees [os-steve]; read back 10576/10576 bytes identical. (2) this os-dev-report comment: POST /repos/objectstack-ai/objectstack/issues/15952/comments. `git push` (4 pushes of the branch) is not a REST write. 0 label writes: no label is owed (the changeset is present, so no skip-changeset, and the dispatch named none).", "open_questions": [ { "question": "Blocker 1: the template payload test packages/create-objectstack/src/templates/blank/note.test.ts reds two REQUIRED gates (Lint & Repo Gates). Both walk every *.test.ts under a package directory and ignore the package's own tsconfig `exclude: [\"src/templates\"]` and its vitest `exclude`. check-registry-log-declared (S2: it imports bootStack from @objectstack/verify) demands OS_REGISTRY_LOG in packages/create-objectstack/vitest.config.ts. check:test-source-alias demands 6 source aliases (verify, spec, spec/data, the 3 connectors) for imports create-objectstack's vitest never runs (proven: the exclude ablation, 17 vs 18 files). Fixing either is a scripts/ edit, outside this card's file surface. Which boundary?", "options": [ "A. Teach both gates the payload boundary check-undeclared-dep-imports already reads: a directory the package's own tsconfig.json `exclude`s is payload, not a test source. One --self-test case each, in scripts/check-registry-log-declared.mjs and scripts/check-test-source-alias.mjs. Widen this card's surface to those two files, or land them first as their own PR. Effort: small (two predicates plus two self-test rows).", "B. Satisfy both gates inertly in packages/create-objectstack/vitest.config.ts: env OS_REGISTRY_LOG plus 6 source aliases for a suite that boots nothing and never loads those imports. No scripts change, but it leaves two declarations that do nothing, which is the over-selection the registry gate's own header calls a predicate defect.", "C. Commit the payload under a non-test name and restore it at scaffold time through TEMPLATE_FILE_ALIASES (the `_gitignore` mechanism). This routes around both detectors, and the repo's eslint/tsc stop reading the file as TypeScript." ], "recommendation": "A. Real need: the starter test is the card's deliverable, and every scaffold consumes it; the gates protect nothing here. Long term: one payload boundary, already proven in check-undeclared-dep-imports, reused, instead of two inert declarations. Against AI error: B teaches the next agent that an inert config line is how a gate gets satisfied, and C hides payload from lint and typecheck. Startup focus: A adds no gate, no ledger row and no new surface; it narrows two predicates to what they claim to measure." }, { "question": "Blocker 2: `npm install` of the new starter crashes on npm 10, the major Node 22 bundles, with \"TypeError: Cannot read properties of null (reading 'edgesOut')\" at arborist #loadPeerSet. main's template installs (525 packages); with this diff it crashes. Bisected: a package.json with ONLY devDependencies {\"vitest\":\"^4.0.0\"} crashes on npm 10.9.4 and 10.9.9 (the latest 10.x) with a clean cache, installs on npm 11, and vitest ^3 installs. The log walks into vite's optional @vitejs/devtools* peers (devtools-vitest peers vitest@*); vite 7.3.7 and 8.3.4 were published 2026-10-06..08. This is upstream, but `npx create-objectstack` falls back to npm when pnpm is absent, and the repo's Scaffold E2E job installs with npm on Node 22, so that job will fail at install. `objectstack init -t plugin` and `objectstack create plugin` already have the same exposure. How should the scaffold half land?", "options": [ "A. Split: land the docs half now (plugin-spec.mdx only, `Part of #15952`, no changeset needed). Hold the scaffold half (template files, create-objectstack vitest.config.ts, scaffold-e2e.yml, changeset) on this branch until npm 10 installs `{\"devDependencies\":{\"vitest\":\"^4.0.0\"}}` again, re-measured with that one line. The seat rewrites PR line 1 to `Part of #15952` on whichever PR carries the docs. Effort: a file move plus one re-measure.", "B. Land the scaffold half as ruled once blocker 1 is settled, accepting that npm-10 users of the blank starter cannot install until upstream moves. Either Scaffold E2E stays red on npm meanwhile, or that job switches to pnpm, the template's documented manager, and stops measuring the npm path at all.", "C. Make the template npm-10-proof by a workaround: a shipped `.npmrc` with legacy-peer-deps (needs a `_npmrc` alias, and changes peer resolution for every npm user), or vitest ^3 for this scaffolder only (breaks the shared SCAFFOLD_VITEST_RANGE; scaffold-emission-policy.e2e reds)." ], "recommendation": "A. Real need: the docs half (stop advertising a package that does not exist, the protocol-baseline ruling) has immediate value and no exposure. No measured consumer waits on the starter test (the hotcrm epic is closed). Long term: no workaround, and the scaffolder stays on the shared vitest policy. Against AI error: an on-ramp whose first `npm install` crashes is worse than one that ships no test, and an agent following README/AGENTS.md `npm run` paths would hit it first. Startup focus: the smallest move, and waiting costs nothing. The npm-10 exposure of `init -t plugin` and `create plugin` is filed as out_of_scope_findings[1] either way." } ], "out_of_scope_findings": [ "class: a · reach: public door — the repo-built bin at 9fdb12752c, `create-objectstack blank-probe --skip-install --skip-skills`, exits 1 with: \"Scaffolding rewrote the namespace to 'blank_probe' but 1 object name(s) still carry the template's 'blank_' prefix: src/objects/note.object.ts:6 name: 'blank_probe_note' … This is a bug in the scaffolder, not in your input.\" Any project name that starts with `blank` hits it. · evidence: packages/create-objectstack/src/rewrite-identity.ts findStaleNamespacePrefixes(srcDir, 'blank') uses namePrefixRe('blank'), which matches the rewritten `blank_probe_note` because the new namespace itself begins with the old prefix. · dedupe: create-objectstack blank prefix; findStaleNamespacePrefixes false positive; namespace rewrite stale prefix; project name blank", "class: a · reach: public door — `npm install` on npm 10.9.4 and 10.9.9 (Node 22's bundled major) of the manifest `objectstack init NAME -t plugin` renders (spec + cli + typescript + vitest ^4.0.0; transcribed from init.ts TEMPLATES.plugin, the CLI itself not run) crashes with \"TypeError: Cannot read properties of null (reading 'edgesOut')\" at arborist #loadPeerSet; `{\"devDependencies\":{\"vitest\":\"^4.0.0\"}}` alone crashes the same way; npm 11 installs it. · evidence: upstream peer graph (vite 7.3.7/8.3.4 optional @vitejs/devtools* peers; @vitejs/devtools-vitest peers vitest@*), not ObjectStack code; it reaches every scaffolder that declares SCAFFOLD_VITEST_RANGE (`init -t plugin`, `create plugin`, and the blank starter once this PR lands). · dedupe: npm 10 edgesOut crash; vitest npm install loadPeerSet; scaffold npm install vite devtools; SCAFFOLD_VITEST_RANGE npm", "class: a · reach: named producer — this PR's template payload packages/create-objectstack/src/templates/blank/note.test.ts · evidence: check-registry-log-declared and check:test-source-alias walk every *.test.ts under a package directory without the tsconfig `exclude` boundary check-undeclared-dep-imports honours, and both exit 1 at 812d8dbf94 on a test create-objectstack's vitest never runs. Same question as open_questions[0]. · dedupe: registry-log-declared payload template; test-source-alias src/templates; gate walk tsconfig exclude; payload test file gate", "carrier: 承接者:无 · noted, not filed — the published skills still teach a hand-assembled LiteKernel test (skills/objectstack-platform/references/operations.md testing block; references/plugin-development.md \"Testing Plugins\") rather than bootStack and the handle. No @objectstack/testing hit, so the acceptance grep is clean. Changing them is a Tier H skills/** edit.", "carrier: 承接者:无 · noted, not filed — the blank template's vitest range is a hand restatement of SCAFFOLD_VITEST_RANGE. scripts/sync-scaffold-emission-policy.mjs POLICY_STAMPS has no vitest row to generate it. Drift stays loud via packages/cli/test/scaffold-emission-policy.e2e.test.ts (nightly).", "carrier: 承接者:无 · noted, not filed — main's boot of the blank template logs \"[sql-driver] DATABASE_ERROR … no such table: _objectstack_sequences\" at error level on a passing run. Observation only, not investigated." ], "gates_head": "812d8dbf94", "gates": [ "node scripts/check-adr-0087-registration.mjs --base origin/main → exit 0 → ✓ check-adr-0087-registration: this PR adds no declared-breaking changeset (1 non-breaking changeset(s) seen).", "node scripts/check-adr-0087-registration.mjs --self-test → exit 0 → ✓ check-adr-0087-registration --self-test: 463 assertions over real temp git repos (real scan()/assertInputs() path)", "node scripts/check-aggregator-roster.mjs → exit 0 → ✓ check-aggregator-roster: 3 aggregator(s) across 2 workflow(s); roster == needs: in both directions, and all 3 required-context aggregate(s) declared.", "node scripts/check-aggregator-roster.mjs --self-test → exit 0 → ✓ check-aggregator-roster --self-test: 45 assertions (baseline + a dropped member and a phantom needs: entry for each of the 3 required aggregators + six refusals + th...", "node scripts/check-changeset-fixed.mjs → exit 0 → ✓ .changeset/config.json \"fixed\" group is in sync with 70 public workspace packages.", "node scripts/check-changeset-no-major.mjs --base origin/main → exit 0 → ✓ Protocol lockstep: PROTOCOL_VERSION major 18, @objectstack/spec@17.7.0 — the one exception, evidenced: pre mode (tag `next`) and a pending `major` for @objectstack/s...", "node scripts/check-changeset-no-major.mjs --self-test → exit 0 → ✓ check-changeset-no-major --self-test: 401 assertions (frontmatter dialects measured against @changesets/parse + the pre/exit exemption switch in both directions + th...", "node scripts/check-ci-filter-parity.mjs → exit 0 → OK: all 21 build input(s) turbo.json declares outside the packages (itself, 2 globalDependencies, and every `$TURBO_ROOT$` input of a build Build Core runs) and all 11...", "node scripts/check-closing-keyword-parity.mjs → exit 0 → check-closing-keyword-parity: OK (3 parsers agree on all 9 keywords and both measured separators; sweep found 5 file(s) carrying the grammar across 10963 tracked file(...", "node scripts/check-closing-keyword-parity.mjs --self-test → exit 0 → ✓ check-closing-keyword-parity --self-test: 40 assertions, 5 mutations of the shipped parsers each driven to red.", "node scripts/check-comment-mask-adoption.mjs → exit 0 → OK check:comment-mask-adoption — 14 private comment-stripper(s) under packages/** + examples/**, all 14 recorded and every recorded row still reached (13 unconverted,...", "node scripts/check-comment-mask-adoption.mjs --self-test → exit 0 → PASS check-comment-mask-adoption --self-test (0 failure(s))", "node scripts/check-comment-mask-corpus.mjs → exit 0 → ✓ comment-mask corpus sweep [scripts/js-comment-mask.mjs]: 8812 files, 0 disagree, 0 unparseable, 106.0s (comparator self-test: 26 cases pass).", "node scripts/check-doc-frontmatter.mjs → exit 0 → ✓ check-doc-frontmatter: 2 content root(s) verified, each against its own floor — content/docs 412, content/blog 4.", "node scripts/check-doc-frontmatter.mjs --self-test → exit 0 → ✓ check-doc-frontmatter --self-test: 99 assertions — the card's own description observed failing with the parser's message and the FILE line, every other violation kin...", "node scripts/check-doc-route-spelling.mjs --advisory → exit 0 → ✓ route-spelling guard (advisory): population clean — every shape-matched literal spells its ledger row.", "node scripts/check-doc-route-spelling.mjs --self-test → exit 0 → ✓ check-doc-route-spelling self-test: extraction tidy-up, the variant relation (plural + pinned lexicon, no prefix heuristic), walk wiring (releases/ and node_modules/...", "node scripts/check-docs-section-name.mjs → exit 0 → ✓ check-docs-section-name: 0 nameless form-section examples — 412 docs file(s) · 1215 TS-family fence(s) · 14 `sections: [` array(s) · 22 section literal(s) JUDGED · 1...", "node scripts/check-docs-section-name.mjs --self-test → exit 0 → ✓ check-docs-section-name self-test: 85 cases pass (real temp trees on disk; both historical misses reproduced as RED, both arms driven RED, the duplicate-key and synt...", "node scripts/check-dts-emitted.mjs --self-test → exit 0 → check-dts-emitted self-test: all assertions passed.", "node scripts/check-empty-changeset.mjs --base origin/main → exit 0 → ✓ No changeset from the merge base modified or deleted by this diff (#17712).", "node scripts/check-empty-changeset.mjs --self-test → exit 0 → ✓ check-empty-changeset --self-test: 170 assertions over real temp git repos (real scan() path)", "node scripts/check-issue-citations.mjs → exit 0 → ✅ check-issue-citations: no issue citations added against 9fdb12752 (1 file(s) read).", "node scripts/check-keyed-text-bounds.mjs → exit 0 → ✓ check:keyed-text-bounds: 112 *.object.ts files under packages/** + apps/** + examples/** (walk is repo-wide; 0 outside), 117 object declarations, 242 declared index ...", "node scripts/check-keyed-text-bounds.mjs --self-test → exit 0 → PASS check-keyed-text-bounds --self-test (0 failure(s))", "node scripts/check-osv-exemptions.mjs → exit 0 → ✓ 1 OSV exemption(s) in osv-scanner.toml: all carry an unexpired ignoreUntil within 90 days and a reason with an advisory link.", "node scripts/check-osv-exemptions.mjs --self-test → exit 0 → ✓ self-test passed: valid ledgers accepted, every convention breach rejected.", "node scripts/check-platform-object-tenancy-census.mjs → exit 0 → ✓ platform-object tenancy census matches the tree: 84 platform-namespace objects, 49 in the machinery's reach, 35 outside it, every exclusion explained by a declaratio...", "node scripts/check-platform-object-tenancy-census.mjs --self-test → exit 0 → ✓ check-platform-object-tenancy-census self-test: all checks pass (84 objects, 35 outside the machinery)", "node scripts/check-plugin-teardown-shape.mjs → exit 0 → ✓ check:plugin-teardown-shape: 75 Plugin implementation(s) across 8231 source(s) under packages/**; every teardown-shaped method (stop / shutdown / close / dispose) si...", "node scripts/check-plugin-teardown-shape.mjs --self-test → exit 0 → ✓ check-plugin-teardown-shape self-test: 48 cases pass (real pre-#10375 fixture reds, the repaired file and both delegating-alias directions stay green, every roster n...", "node scripts/check-position-name-fold-loaders.mjs → exit 0 → ✓ check-position-name-fold-loaders: packages/metadata/src/__fixtures__/hotcrm-17.1-built-permissions.artifact.json", "node scripts/check-position-name-fold-loaders.mjs --self-test → exit 0 → ✓ check-position-name-fold-loaders self-test: 15 cases pass.", "node scripts/check-registry-log-declared.mjs → exit 1 → check-registry-log-declared: 1 engine-booting suite(s) declare no recognised registry log level:", "node scripts/check-registry-log-declared.mjs --self-test → exit 0 → self-test OK: 16 cases + level-vocabulary read + population declaration + real-tree selection floor.", "node scripts/check-rest-log-spy-declared.mjs → exit 0 → OK: 31 of 279 test file(s) beside packages/rest/src/log.ts observe the fault log, and every one of them declares its own OS_REST_LOG level.", "node scripts/check-rest-log-spy-declared.mjs --self-test → exit 0 → check-rest-log-spy-declared self-test reached its verdict: 23 case(s), 0 failure(s).", "node scripts/check-section-landing-index.mjs → exit 0 → ✓ check-section-landing-index: 8 section index block(s) enumerate their meta.json pages, in order, both directions (ai, api, automation, data-modeling, kernel, permiss...", "node scripts/check-section-landing-index.mjs --self-test → exit 0 → ✓ check-section-landing-index --self-test: 31 assertions over synthetic inputs and a temp fixture (real judge()/run() path); every limb -- both shapes in sync, missing...", "node scripts/check-self-test-wired.mjs → exit 0 → ✓ check-self-test-wired: every one of the 233 script(s) CI runs that ship a `--self-test` has that self-test run by CI, and every one of the 169 root package.json alia...", "node scripts/check-self-test-wired.mjs --self-test → exit 0 → check-self-test-wired --self-test: 3 live ledger row(s) verified, plus the comment mask, the right boundary, alias resolution, the declared-alias population and both a...", "node scripts/check-self-test-workflow-commands.mjs → exit 0 → ✓ check-self-test-workflow-commands: no self-test CI runs prints a line the Actions runner would parse as a workflow command.", "node scripts/check-self-test-workflow-commands.mjs --self-test → exit 0 → check-self-test-workflow-commands --self-test: both measured parse rules pinned (legacy form anywhere in a line, current form only at line start), the innocent-output ...", "node scripts/check-step-collectors.mjs → exit 0 → ✓ check-step-collectors: 526 `run:` steps across 39 workflow(s) and 2 composite action(s); 5 step(s) run 2+ independent self-tests, all of them through a collector.", "node scripts/check-step-collectors.mjs --self-test → exit 0 → ✓ check-step-collectors --self-test: 191 assertions, 6 block(s) driven under a real `bash -e`.", "node scripts/check-system-context-census.mjs → exit 0 → check-system-context-census: OK — 124 elevation read sites in 20 packages across 58 files, living in 106 symbol(s); the page cites 119 symbol(s) against 119 required, ...", "node scripts/check-system-context-census.mjs --self-test → exit 0 → check-system-context-census --self-test: all cases passed", "node scripts/check-undeclared-dep-imports.mjs → exit 0 → ✓ check:undeclared-dep-imports: 81 workspace packages under packages/** + apps/** + examples/**, 3028 non-test src files, 2524 @objectstack/* specifiers (0 assembled, ...", "node scripts/check-undeclared-dep-imports.mjs --self-test → exit 0 → PASS check-undeclared-dep-imports --self-test (0 failure(s))", "node scripts/check-whole-set-label-write.mjs → exit 0 → PROSE_PROBES make `run()` refuse rather than pass if it ever stops finding them.", "node scripts/check-whole-set-label-write.mjs --self-test → exit 0 → ✓ check-whole-set-label-write --self-test: all cases pass (24 fixture trees + 5 refusals + 1 allowlist hatch)", "node scripts/docs-audit/check-affected-docs.mjs → exit 0 → ✓ affected-docs self-test: 605 cases pass.", "node scripts/docs-audit/check-drift-comment.mjs → exit 0 → ✓ check-drift-comment: 66 cases pass across 5 fixture diff(s).", "node scripts/osv-base-relative.mjs --self-test → exit 0 → osv-base-relative self-test: 23 case(s), all held (floor 23)", "node scripts/pm/ci-failure.mjs --self-test → exit 0 → And the mid-walk net holds: a transport failure arriving after the probe passed exits 3", "node scripts/pm/release-rehearsal-clone.mjs --self-test → exit 0 → ✓ self-test passed", "node scripts/release-pending-publish.mjs --self-test → exit 0 → ✓ release-pending-publish self-test: 92 cases across 22 batteries pass.", "pnpm --filter @objectstack/lint run check:doc-formula-expressions → exit 0 → ✓ check:doc-formula-expressions (field-level `*When`, #11407): 15 predicate(s) on a statically determinable field layer judged clean; 6 skipped as undeterminable.", "pnpm --filter @objectstack/lint run check:doc-security-posture → exit 0 → ✅ 28 ObjectSchema.create example(s) in 230 marked block(s) across 254 prose file(s) in 2 root(s) carry an os validate-clean security posture", "pnpm --filter @objectstack/spec run check:docs → exit 0 → ✅ 226 generated files in sync with packages/spec", "pnpm --filter @objectstack/spec run check:duration-unit-keys → exit 0 → ✓ check:duration-unit-keys — 197 unit-declaring numeric key(s) across 3033 source file(s) all carry their unit in the key name (or in a sibling `unit`, or under a decl...", "pnpm --filter @objectstack/spec run check:empty-state → exit 0 → ✓ all classified (2 closed, 2 open, 4 output, 9 scope)", "pnpm --filter @objectstack/spec run check:liveness → exit 0 → ✓ packages/spec/liveness/state-counts/ is current — one shard per governed type, the same 41 row(s) as the README, no count column left in the README.", "pnpm --filter @objectstack/spec run check:llms-txt → exit 0 → ✓ packages/spec/llms.txt: 98 claim(s) re-derived — every advertised symbol resolves against api-surface/ (19 entry points), every subpath is a real `exports` key, the ...", "pnpm --filter @objectstack/spec run check:skill-examples → exit 0 → ✅ 262 prose examples type-check across 3 surface(s) — every marked block parsed, so tsc ran the SEMANTIC pass on all of them", "pnpm --filter @objectstack/spec run check:strictness-ledger → exit 0 → ✓ docs/audits/2026-07-unknown-key-strictness-ledger.counts/ is current — 14 shard(s), one per source directory with sites, 475 triaged site(s) measured, 1 authorable s...", "pnpm --filter @objectstack/spec run check:template-manifests → exit 0 → ✅ 1 shipped manifest(s) satisfy TemplateManifestSchema — their $schema line is a verified claim.", "pnpm --filter @objectstack/spec run check:variant-docs → exit 0 → ✓ variant/doc gate: 18 discriminated union(s) — 8 governed (every variant mentioned in a bound doc), 10 exempt.", "pnpm --filter @objectstack/spec run check:yaml-examples → exit 0 → ✅ 19 tagged YAML example(s) across 1 file(s) validate against their declared live spec schemas", "pnpm check:agent-test-spelling → exit 0 → ✓ check-agent-test-spelling: 0 violations — 583 file(s) · 9822 bare `--` token(s) · 1971 launcher-rooted run(s) · 11 separator(s) JUDGED · 6 vitest-backed script name(...", "pnpm check:changeset-gate-self-tests → exit 0 → ✓ check-changeset-no-major --self-test: 401 assertions (frontmatter dialects measured against @changesets/parse + the pre/exit exemption switch in both directions + th...", "pnpm check:corpus-claim-drift → exit 0 → check-corpus-claim-drift: OK, no new claim sites beside a pinned spelling.", "pnpm check:cross-package-test-inputs → exit 0 → OK: 30 package(s) read outside themselves, all declared, and turbo.json hashes every declared glob (6 of them on a split \"test:repo\" task); 13 walked root(s) judged, 3...", "pnpm check:declared-population-live → exit 0 → ✓ check:declared-population-live — 266 of 329 famil(ies) declare a path population, and every one of them reaches this tree's 10963 tracked file(s).", "pnpm check:doc-anchors → exit 0 → ✅ check-doc-anchors: 484 internal #fragment link(s) across 418 source file(s) all resolve to a real heading", "pnpm check:doc-authoring → exit 0 → ✓ doc authoring guard: sibling-package prose ids hold the baseline — 0 pinned site(s) across 0 file(s), 91993 string(s) read in 1317 parsed source(s) (seen floor 40000...", "pnpm check:docs-audit-scope → exit 0 → ✓ scope injection is live: the workflow audits the list handed in as args.handwritten, and refuses an invocation that hands in no scope at all.", "pnpm check:docs-redirects → exit 0 → check-docs-redirects: OK (apps/docs/redirects.mjs: 98 entries -- 95 page destination(s) resolved against content/docs, 3 wildcard destination(s) resolved to a director...", "pnpm check:docs-single-h1 → exit 0 → ✓ check-docs-single-h1: 412 page(s) under content/docs/ carry no body-level `# ` heading (0 subtree(s) excluded, see --list).", "pnpm check:docs-spec-enumerations → exit 0 → OK the hand-written spec enumerations agree with packages/spec/package.json -- 18 subpath(s) held ORDERED in content/docs/deployment/troubleshooting.mdx; 15 protocol n...", "pnpm check:docs-transcript-drift → exit 0 → ✓ check-docs-transcript-drift: 4 declared transcript value(s) across 412 page(s) under content/docs/ equal what the registry derives today, and no undeclared block quo...", "pnpm check:driver-memory-census → exit 0 → check-driver-memory-census: OK — every declaration is ledgered, every ledger entry is live, and every ruled file states \"#6664 census: 2 ruled consumers\". This gate po...", "pnpm check:dts-closure → exit 0 → check-dts-closure: 73 built package(s) swept - 172/172 declared declaration file(s) present across 72 package(s); 1 built package(s) declare no declaration entry point...", "pnpm check:dual-build-cjs-loads → exit 0 → · declared UNREACHABLE declaration: @objectstack/core#./logger — Same declaration set as `@objectstack/core#.` — the subpath is emitted from the same tsup pass and spl...", "pnpm check:engine-double-contract → exit 0 → check-engine-double-contract: 906 (file, verb) row(s) held by the RETAINED ledger — a pin that leaves names itself.", "pnpm check:gitlink-declared → exit 0 → check-gitlink-declared: OK (10963 index entries -- 0 gitlink(s) at mode 160000; no .gitmodules in the index, so nothing is declared; nothing to declare).", "pnpm check:issue-citations → exit 0 → ✅ check-issue-citations --self-test: grammar narrowed, every spelling enumerated, qualifier a closed set of repositories, four 404 causes kept apart, both board strate...", "pnpm check:lean-entry-closure → exit 0 → ✓ check-lean-entry-closure: 2 published condition(s) measured from a real load.", "pnpm check:logger-receiver-detach → exit 0 → OK every log channel keeps its receiver: 3319 non-test TS file(s) walked, 0 detach(es) on the 5 declared receiver-sensitive sink spelling(s).", "pnpm check:manifest-repository-directory → exit 0 → ✓ check:manifest-repository-directory — every one of 70 publishable manifest(s) declares repository.directory, and all 73 declarations across 83 tracked manifest(s) na...", "pnpm check:merge-driver → exit 0 → ✓ check-regen-pending self-test passed.", "pnpm check:node-version → exit 0 → check-node-version: OK (45 setup-node step(s) across 39 workflow(s) and 2 composite action(s), all on Node 22).", "pnpm check:nul-bytes → exit 0 → check-nul-bytes: OK (scanned 10954 text file(s) -- 10954 tracked, 0 untracked-not-ignored; skipped 9 binary; no raw ASCII control bytes).", "pnpm check:objectql-double-limit → exit 0 → OK ObjectQL double `limit` conformance holds: 476 double(s) graded, 282 apply the caller's bound or refuse it loudly.", "pnpm check:objectui-changeset → exit 0 → ✓ objectui-range --self-test: all checks passed", "pnpm check:org-identifier → exit 0 → check-org-identifier: OK (3341 author-facing source file(s), 18 session binding(s) resolved, no removed session.tenantId alias).", "pnpm check:override-consistency → exit 0 → ✓ 9 published-manifest declaration(s) covered by pnpm-workspace.yaml overrides all resolve to their override targets.", "pnpm check:page-declaration-shape → exit 0 → check-page-declaration-shape: OK — 36 page entries across 3342 sources under packages/**, examples/**, apps/** all reach the kernel through a discoverable declaration ...", "pnpm check:pm-changeset-deadline-census → exit 0 → ✓ changeset-deadline-census --self-test: all cases passed across 5 batteries (what counts as a named target, the controls that make a zero a reading, the verdict truth...", "pnpm check:pm-dispatch-gates → exit 0 → check:pm-dispatch-gates: the battery (the fast tier) took 232.6s on this box.", "pnpm check:pm-expected-skips → exit 0 → ✓ check-expected-skips self-test: 154 cases pass (the exit register; the roster's shape — reasons, no duplicates, declared gate kinds — and its truth on this checkout'...", "pnpm check:pm-post-stamped → exit 0 → ✓ post-stamped self-test: 630 cases pass across 22 batteries — offline, no network, no token.", "pnpm check:pnpm-acquisition → exit 0 → check-pnpm-acquisition: OK -- every job that runs pnpm acquires it first.", "pnpm check:pnpm-filter-targets → exit 0 → ✓ check:pnpm-filter-targets: 160/214 `--filter` occurrence(s) across 44 file(s) resolve against 81 workspace package(s); 54 not judged (1 foreign, 30 interpolated, 23 ...", "pnpm check:published-files → exit 0 → ✓ check:published-files — 70 publishable package(s) of 81 workspace member(s) declare a `files` whitelist that covers every entry point plus CHANGELOG.md and admits no...", "pnpm check:published-readme-links → exit 0 → ✓ check:published-readme-links — 226 outbound link(s) across 102 published markdown file(s): 0 root-relative, 0 non-canonical origin(s), 28 docs-site page(s) resolved ...", "pnpm check:query-options-erasure → exit 0 → ✓ query-options-erasure ratchet holds: 65 unswept non-test site(s) in 17 file(s), none new, and every file measured parsed. Every other non-test file under packages/ i...", "pnpm check:react-page-adapter-contract → exit 0 → ✓ check-react-page-adapter-contract: 21 app-showcase page module(s) + 1 content/docs react-page sample(s) (from 395 doc file(s), 2012 fenced block(s)) — every adapter ...", "pnpm check:refd-timer-probe → exit 0 → OK check-refd-timer-probe: 8806 source file(s) swept; the process-global timer probe is read in packages/qa/refd-timer-testkit/src/index.ts and nowhere else.", "pnpm check:required-contexts → exit 0 → ✓ check-required-contexts: 7 required context name(s) pinned across 3 workflow(s); 6 instruction surface(s) scanned against 2 retired name(s) (#9491).", "pnpm check:role-word → exit 0 → check-role-word: OK, no new occurrences of the reserved word.", "pnpm check:shard-attestation → exit 0 → ✓ check-shard-attestation: 2 aggregate gate(s) count 3 declared leg(s) across 3 attesting job(s).", "pnpm check:skill-identifier-liveness → exit 0 → check-skill-identifier-liveness OK — Leg 1: 457 citation(s) over 53 published file(s) checked against 126710 implementation word tokens (0 ledgered exemption(s)); Leg ...", "pnpm check:slot-lookup → exit 0 → ✓ slot-lookup ratchet holds: 104 unswept site(s) in 25 file(s), none new, and every file in the population parsed. Every other file under packages/ is covered by `pnpm...", "pnpm check:sourcemap-no-sources-content → exit 0 → check-sourcemap-no-sources-content: 69 built package(s) swept - 554 map(s), none embed source text.", "pnpm check:stall-guard-budget → exit 0 → .github/workflows/rerun-safety-nightly.yml:201 job `rerun-safety` step `Test suite — pass 2 (same working tree)`", "pnpm check:stall-guard-headroom → exit 0 → measure-stall-guard-headroom --self-test: 35 assertion(s) passed.", "pnpm check:template-version-sync → exit 0 → ✓ sync-template-versions --self-test: 40 assertions over temp fixtures, running the real CLI. A CLEAN corpus is observed REACHED, byte-identical and UNWRITTEN; a missi...", "pnpm check:test-source-alias → exit 1 → ✗ packages/create-objectstack (create-objectstack): tests import 5 workspace package(s) that resolve to `dist/` with no source alias:", "pnpm check:tier-file-adoption → exit 0 → OK: 81 workspace package(s) walked, 82 nightly-tier test file(s) on disk (82 e2e, 0 live), owned by 1 package(s); every one reads OS_TEST_TIERS.", "pnpm check:turbo-task-graph → exit 0 → OK: 46 package-scoped and 9 generic turbo task(s) judged against 81 workspace package(s) — every package-scoped one names a package that exists (or the root token \"//\"...", "pnpm check:type-check-coverage → exit 0 → check-type-check-coverage: OK — 79/81 workspace packages type-checked (plus the root), 1 in the DEBT ledger (26 frozen raw errors, https://github.com/objectstack-ai/ob...", "pnpm check:type-check-debt → exit 0 → check-type-check-coverage --re-measure: OK — 1 ledger entr(ies) re-measured in 11.4s, 26 raw tsc error(s) total, none above its recorded number.", "pnpm check:vendor-export-contract-resolve → exit 0 → ✓ better-auth/adapters @ better-auth@1.7.3 (via \"1.7.3\", 1 symbol(s))", "pnpm check:vendor-version-stamps → exit 0 → check:vendor-version-stamps: OK — 9197 file(s) scanned.", "pnpm check:watch-hint-literal → exit 0 → ✓ check-watch-hint-literal: 72 declaration(s) across 4 rostered name(s) -- ROOT_DIR_WATCH_HINTS 48, ROOT_FILE_WATCH_HINTS 13, ROOT_WATCH_HINTS 3, DECLARED_WATCH_HINTS ...", "pnpm check:where-matcher → exit 0 → ✓ where-matcher conformance holds: 499 matcher(s) discovered, 499 answer the combinator battery correctly or refuse it loudly (324 refuse).", "pnpm check:workflow-status-functions → exit 0 → check-workflow-status-functions: OK (scanned 39 workflow file(s), 65 job(s), 30 job-level if: expression(s); 10 read needs.*.outputs.*, all naming a status function).", "pnpm check:workflow-step-name-quoting → exit 0 → check-workflow-step-name-quoting: OK (scanned 39 workflow file(s) + 2 composite action file(s), 752 step name(s) -- 8 already quoted, 744 unquoted-and-safe).", "pnpm check:workspace-manifest-cycles → exit 0 → OK: 81 workspace package(s), 537 `workspace:` edge(s) (dependencies=382, devDependencies=149, peerDependencies=5, optionalDependencies=1) — the manifest graph has no c..." ], "line_budget": "286 (PR #22910: +218 / -68, 9 files; read back from GET /pulls/22910)", "files_changed": [ ".changeset/15952-blank-template-test-story.md (+17)", ".github/workflows/scaffold-e2e.yml (+16 -2)", "content/docs/protocol/kernel/plugin-spec.mdx (+85 -62)", "packages/create-objectstack/src/templates/blank/README.md (+10)", "packages/create-objectstack/src/templates/blank/note.test.ts (+54, new)", "packages/create-objectstack/src/templates/blank/package.json (+5 -2)", "packages/create-objectstack/src/templates/blank/tsconfig.json (+1 -1)", "packages/create-objectstack/src/templates/blank/vitest.config.ts (+21, new)", "packages/create-objectstack/vitest.config.ts (+9 -1)" ], "deviations": [ "File surface: packages/create-objectstack/src/templates/blank/tsconfig.json is not a listed file of the claim (same directory). include [\"*.ts\",\"src/**/*\"] (the shape objectstack init writes) is what lets `pnpm typecheck` reach the root note.test.ts; proven by --listFiles and a TS2551 plant.", "File surface: packages/create-objectstack/vitest.config.ts gains `exclude: [...configDefaults.exclude, 'src/templates/**']`, read as \"create-objectstack's own tests\"; it is required (ablation: 17 vs 18 files collected, the extra one being the payload test).", "File surface: .github/workflows/scaffold-e2e.yml, identified as \"the scaffold test that already exercises validate\" (PM assumption 4). Job 1 gains a `Test the generated project` step; the nightly registry canary runs `npm test` only when the scaffolded project declares one.", "Not done, outside the surface: the two red required gates (check-registry-log-declared, check:test-source-alias) need scripts/ edits (open_questions[0]); the PR is not landable until that is settled.", "A temporary, uncommitted directory packages/qa/dogfood/.tmp-issue-15952 held a copy of the template for the forward boot on main's harness. It was deleted the same step, and `git status` was clean before every commit.", "Role-file vs dispatch: the dispatch fixed PR line 1 as `Fixes #15952`, and the role file forbids `Fixes` on a card that goes to the decision box. Line 1 was written as dispatched (the PR implements the whole card). If open_questions[1] is decided as A (split), the seat rewrites line 1 to `Part of #15952` on whichever PR carries the half that does not close the card.", "Commit trailers are the model-free pair AGENTS.md mandates (Claude-Session + Co-authored-by: Claude), not the model-named trailer the harness reminder suggested; the PR footer is the AGENTS.md session-URL form.", "In this comment's gate verdict lines, ASCII angle brackets are respelled as single guillemets so the body sanitizer cannot eat them; no other text was changed." ], "cleanup": "Worktree /home/user/objectstack-issue-15952 removed (node_modules first, then `git worktree remove` without --force: exit 0). Scratch scaffolds deleted. No background process, dev server or monitor left running; the gate runner and battery PIDs were checked gone." }
Generated by Claude Code
objectstack-fleet commented
on Oct 12, 2026 ContributorMore actionsSeat order: patch round on PR #22910. The docs half lands now, and the scaffold half is held behind #22912
domain:cliseat 2 (#22648) ·os-steve· sessionsession_01VoSxBQujKLZKPwK2u5ehQ6· 2026-10-12T00:48Z · holder of claim6115033658. Report read:os-dev-report6115735322.The report returned
needs_decisionwith two measured blockers on the scaffold half. Neither touches the docs half.Open question 2 (npm 10) → A, split. Taken by the seat. This is sequencing inside the ruled design, not a design change:
- Real need: the docs half stops advertising a package that does not exist (the protocol-baseline ruling), at no exposure. No measured consumer waits on the starter test; the hotcrm epic is closed.
- Against AI error: a starter whose first
npm installcrashes on Node 22's npm is worse than one that ships no test. - No workaround: a shipped
.npmrclegacy-peer-depsand a per-scaffolder vitest range are both refused, the second because it breaks the shared range. - Startup focus: the smallest move, and waiting costs nothing.
- The upstream crash is filed as finding: on npm 10 (Node 22's bundled major),
npm installof a scaffold that declaresvitest ^4.0.0(SCAFFOLD_VITEST_RANGE:objectstack init -t plugin,objectstack create plugin) crashes with "Cannot read properties of null (reading 'edgesOut')" #22912, which also covers the shippedinit -t plugin/create pluginscaffolders. The held half resumes when finding: on npm 10 (Node 22's bundled major),npm installof a scaffold that declaresvitest ^4.0.0(SCAFFOLD_VITEST_RANGE:objectstack init -t plugin,objectstack create plugin) crashes with "Cannot read properties of null (reading 'edgesOut')" #22912's one-line manifest installs on npm 10.
Open question 1 (two gates count the template payload test) → deferred with the held half. The payload test does not land in this PR, so neither gate reds.
- The question stays on this card for whoever resumes the scaffold half.
- The dev's recommendation is recorded and not ruled here: A, teach
check-registry-log-declaredandcheck:test-source-aliasthe tsconfig-excludepayload boundary thatcheck-undeclared-dep-importsalready reads. - Both are
scripts/gates, so that edit isdomain:specunder the anchoring rule and is declared there when it happens.
The patch round:
- Preserve the full head
812d8dbf94as branchclaude/issue-15952-scaffold-held(push only, no PR). - On PR docs(plugin-spec): Plugin Testing teaches bootStack and the in-process handle of @objectstack/verify, not the non-existent @objectstack/testing (#15952) #22910's branch, remove the scaffold half in a new commit (⛔ no force-push, no rebase). That is the template files,
packages/create-objectstack/vitest.config.ts,.github/workflows/scaffold-e2e.ymland the changeset. Keepcontent/docs/protocol/kernel/plugin-spec.mdxonly. - PR body line 1 becomes
Part of #15952; line 2 staysClause-②: no. The PR is docs-only, so the changeset goes andskip-changesetis owed.
Card state after the docs PR lands:
#15952stays open and leavespm:dispatchedforpm:on-hold. Unlock conditions: #22912, and open question 1 settled.Filed from this report: #22911 (any project name starting with
blankis refused by the stale-prefix check) and #22912 (above). The other notes arecarrier: none.
Generated by Claude Code
objectstack-fleet commented
on Oct 12, 2026 ContributorMore actionsos-dev-report
{ "issue": 15952, "status": "done", "round": "patch round on seat order 6115782428 (open question 2 → A, split; open question 1 → deferred with the held half)", "branch": "claude/issue-15952-blank-template-test-story", "pr": "https://github.com/objectstack-ai/objectstack/pull/22910", "held_branch": "claude/issue-15952-scaffold-held @ 812d8dbf94 (pushed, no PR) — the full scaffold half", "session": "session_01VoSxBQujKLZKPwK2u5ehQ6 — mode:subagent, the parent's id (container CLAUDE_CODE_REMOTE_SESSION_ID=cse_01VoSxBQujKLZKPwK2u5ehQ6)", "premise_still_valid": true, "summary": "PR #22910 is now docs-only at head 9572bb790d. One new commit (no force-push, no rebase, no amend) restores the scaffold-half paths to the merge base 9fdb12752c: the blank template's README.md, package.json and tsconfig.json, packages/create-objectstack/vitest.config.ts and .github/workflows/scaffold-e2e.yml are restored, and note.test.ts, the template vitest.config.ts and the changeset are deleted. `git diff --stat origin/main...HEAD` shows 1 file, content/docs/protocol/kernel/plugin-spec.mdx (+85 / -62), byte-identical to its version at 812d8dbf94. The full head 812d8dbf94 is preserved as branch claude/issue-15952-scaffold-held (push only). main had moved 2 commits (to eb20c33c45), neither touching these paths, so no merge was needed. `skip-changeset` was added through label-write. The PR body was rewritten through the relay: line 1 `Part of #15952`, line 2 `Clause-②: no`, the docs-only file list and acceptance notes, and where the scaffold half is held and why (#22912, open question 1). The session-URL footer is kept. The PR title was moved off the old `feat(create-objectstack)` wording in the same PATCH. The two gates that were red (check-registry-log-declared, check:test-source-alias) now exit 0, because the payload test no longer lands.", "tests": "All at head 9572bb790d. DIFF: `git diff --stat origin/main...HEAD` shows \"content/docs/protocol/kernel/plugin-spec.mdx | 147 ++++++++++++++++----------- 1 file changed, 85 insertions(+), 62 deletions(-)\". GET /pulls/22910 reads changed_files 1, additions 85, deletions 62, head 9572bb790d. `git diff --quiet 812d8dbf94 HEAD -- content/docs/protocol/kernel/plugin-spec.mdx` exits 0 (page unchanged since the gated round). ACCEPTANCE GREP: `git grep -n \"objectstack/testing\" -- content/ skills/ packages/` gives 0 hits (exit 1), and `git grep -n \"objectstack/testing\\|createTestContext\\|createTestEnvironment\" -- content/ skills/ packages/` gives 0 hits (exit 1). GATES: `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` (no paths) at 9572bb790d derived 40 families from 1 changed path vs merge base 9fdb12752. All 40 were run after a turbo build (73 tasks, 69 cached) so the dist-reading gates measure. Also run: check-registry-log-declared and check:test-source-alias, the two that were red at 812d8dbf94. 42 of 42 exit 0. `dispatch-gates --ran` reconciles \"40 derived, 40 run, 0 NOT-MEASURED, 0 UNRUN\", printing \"✓ dispatch-gates --ran: 40 derived famil(ies) accounted for\". Formerly red, now green: check-registry-log-declared gives \"OK: 73 vitest-running package(s) walked, 10 selected as engine-booting, every one declares a recognised registry log level\"; check:test-source-alias gives \"check-test-source-alias OK — 73 packages with tests scanned\". No package code changed in this round, so no package test or typecheck is owed. The earlier round's package and fresh-scaffold readings belong to the held head 812d8dbf94 and are recorded on comment 6115735322.", "mcp_calls": "0", "api_writes": "3 REST writes, all as objectstack-fleet[bot] through the relay (POST /repos/objectstack-ai/objectstack/dispatches, one per stroke). (1) label-write.mjs: labels_add, POST /repos/objectstack-ai/objectstack/issues/22910/labels [skip-changeset]; read-back MATCHES the target. (2) issue_patch, PATCH /repos/objectstack-ai/objectstack/issues/22910 (title + body); read back 3682/3682 bytes identical, footer intact. (3) this os-dev-report comment, POST /repos/objectstack-ai/objectstack/issues/15952/comments. Git pushes (not REST): `812d8dbf94:refs/heads/claude/issue-15952-scaffold-held` (new branch) and claude/issue-15952-blank-template-test-story 812d8dbf94..9572bb790d (fast-forward).", "open_questions": [], "out_of_scope_findings": [ "carrier: 承接者:无 · noted, not filed — the PR still carries path labels the labeler applied to the pre-split diff (ci/cd, dependencies, tests, tooling, size/m), set by another actor and not touched here. Whether this repo's labelers re-sync them for the 1-file diff was not measured." ], "gates_head": "9572bb790d", "gates": [ "node scripts/check-ci-filter-parity.mjs → exit 0 → OK: all 21 build input(s) turbo.json declares outside the packages (itself, 2 globalDependencies, and every `$TURBO_ROOT$` input of a build Build Core runs) and all 11...", "node scripts/check-closing-keyword-parity.mjs → exit 0 → check-closing-keyword-parity: OK (3 parsers agree on all 9 keywords and both measured separators; sweep found 5 file(s) carrying the grammar across 10960 tracked file(...", "node scripts/check-closing-keyword-parity.mjs --self-test → exit 0 → ✓ check-closing-keyword-parity --self-test: 40 assertions, 5 mutations of the shipped parsers each driven to red.", "node scripts/check-comment-mask-corpus.mjs → exit 0 → ✓ comment-mask corpus sweep [scripts/js-comment-mask.mjs]: 8810 files, 0 disagree, 0 unparseable, 82.7s (comparator self-test: 26 cases pass).", "node scripts/check-doc-frontmatter.mjs → exit 0 → ✓ check-doc-frontmatter: 2 content root(s) verified, each against its own floor — content/docs 412, content/blog 4.", "node scripts/check-doc-frontmatter.mjs --self-test → exit 0 → ✓ check-doc-frontmatter --self-test: 99 assertions — the card's own description observed failing with the parser's message and the FILE line, every other violation kin...", "node scripts/check-doc-route-spelling.mjs --advisory → exit 0 → ✓ route-spelling guard (advisory): population clean — every shape-matched literal spells its ledger row.", "node scripts/check-doc-route-spelling.mjs --self-test → exit 0 → ✓ check-doc-route-spelling self-test: extraction tidy-up, the variant relation (plural + pinned lexicon, no prefix heuristic), walk wiring (releases/ and node_modules/...", "node scripts/check-docs-section-name.mjs → exit 0 → ✓ check-docs-section-name: 0 nameless form-section examples — 412 docs file(s) · 1215 TS-family fence(s) · 14 `sections: [` array(s) · 22 section literal(s) JUDGED · 1...", "node scripts/check-docs-section-name.mjs --self-test → exit 0 → ✓ check-docs-section-name self-test: 85 cases pass (real temp trees on disk; both historical misses reproduced as RED, both arms driven RED, the duplicate-key and synt...", "node scripts/check-section-landing-index.mjs → exit 0 → ✓ check-section-landing-index: 8 section index block(s) enumerate their meta.json pages, in order, both directions (ai, api, automation, data-modeling, kernel, permiss...", "node scripts/check-section-landing-index.mjs --self-test → exit 0 → ✓ check-section-landing-index --self-test: 31 assertions over synthetic inputs and a temp fixture (real judge()/run() path); every limb -- both shapes in sync, missing...", "pnpm --filter @objectstack/lint run check:doc-formula-expressions → exit 0 → ✓ check:doc-formula-expressions (field-level `*When`, #11407): 15 predicate(s) on a statically determinable field layer judged clean; 6 skipped as undeterminable.", "pnpm --filter @objectstack/lint run check:doc-security-posture → exit 0 → ✅ 28 ObjectSchema.create example(s) in 230 marked block(s) across 254 prose file(s) in 2 root(s) carry an os validate-clean security posture", "pnpm --filter @objectstack/spec run check:docs → exit 0 → ✅ 226 generated files in sync with packages/spec", "pnpm --filter @objectstack/spec run check:empty-state → exit 0 → ✓ all classified (2 closed, 2 open, 4 output, 9 scope)", "pnpm --filter @objectstack/spec run check:liveness → exit 0 → ✓ packages/spec/liveness/state-counts/ is current — one shard per governed type, the same 41 row(s) as the README, no count column left in the README.", "pnpm --filter @objectstack/spec run check:skill-examples → exit 0 → ✅ 262 prose examples type-check across 3 surface(s) — every marked block parsed, so tsc ran the SEMANTIC pass on all of them", "pnpm --filter @objectstack/spec run check:strictness-ledger → exit 0 → ✓ docs/audits/2026-07-unknown-key-strictness-ledger.counts/ is current — 14 shard(s), one per source directory with sites, 475 triaged site(s) measured, 1 authorable s...", "pnpm --filter @objectstack/spec run check:variant-docs → exit 0 → ✓ variant/doc gate: 18 discriminated union(s) — 8 governed (every variant mentioned in a bound doc), 10 exempt.", "pnpm --filter @objectstack/spec run check:yaml-examples → exit 0 → ✅ 19 tagged YAML example(s) across 1 file(s) validate against their declared live spec schemas", "pnpm check:corpus-claim-drift → exit 0 → check-corpus-claim-drift: OK, no new claim sites beside a pinned spelling.", "pnpm check:cross-package-test-inputs → exit 0 → OK: 30 package(s) read outside themselves, all declared, and turbo.json hashes every declared glob (6 of them on a split \"test:repo\" task); 13 walked root(s) judged, 3...", "pnpm check:doc-anchors → exit 0 → ✅ check-doc-anchors: 484 internal #fragment link(s) across 418 source file(s) all resolve to a real heading", "pnpm check:doc-authoring → exit 0 → ✓ doc authoring guard: sibling-package prose ids hold the baseline — 0 pinned site(s) across 0 file(s), 91992 string(s) read in 1317 parsed source(s) (seen floor 40000...", "pnpm check:docs-audit-scope → exit 0 → ✓ scope injection is live: the workflow audits the list handed in as args.handwritten, and refuses an invocation that hands in no scope at all.", "pnpm check:docs-redirects → exit 0 → check-docs-redirects: OK (apps/docs/redirects.mjs: 98 entries -- 95 page destination(s) resolved against content/docs, 3 wildcard destination(s) resolved to a director...", "pnpm check:docs-single-h1 → exit 0 → ✓ check-docs-single-h1: 412 page(s) under content/docs/ carry no body-level `# ` heading (0 subtree(s) excluded, see --list).", "pnpm check:docs-spec-enumerations → exit 0 → OK the hand-written spec enumerations agree with packages/spec/package.json -- 18 subpath(s) held ORDERED in content/docs/deployment/troubleshooting.mdx; 15 protocol n...", "pnpm check:docs-transcript-drift → exit 0 → ✓ check-docs-transcript-drift: 4 declared transcript value(s) across 412 page(s) under content/docs/ equal what the registry derives today, and no undeclared block quo...", "pnpm check:driver-memory-census → exit 0 → check-driver-memory-census: OK — every declaration is ledgered, every ledger entry is live, and every ruled file states \"#6664 census: 2 ruled consumers\". This gate po...", "pnpm check:gitlink-declared → exit 0 → check-gitlink-declared: OK (10960 index entries -- 0 gitlink(s) at mode 160000; no .gitmodules in the index, so nothing is declared; nothing to declare).", "pnpm check:nul-bytes → exit 0 → check-nul-bytes: OK (scanned 10951 text file(s) -- 10951 tracked, 0 untracked-not-ignored; skipped 9 binary; no raw ASCII control bytes).", "pnpm check:published-readme-links → exit 0 → ✓ check:published-readme-links — 226 outbound link(s) across 102 published markdown file(s): 0 root-relative, 0 non-canonical origin(s), 28 docs-site page(s) resolved ...", "pnpm check:react-page-adapter-contract → exit 0 → ✓ check-react-page-adapter-contract: 21 app-showcase page module(s) + 1 content/docs react-page sample(s) (from 395 doc file(s), 2012 fenced block(s)) — every adapter ...", "pnpm check:refd-timer-probe → exit 0 → OK check-refd-timer-probe: 8804 source file(s) swept; the process-global timer probe is read in packages/qa/refd-timer-testkit/src/index.ts and nowhere else.", "pnpm check:role-word → exit 0 → check-role-word: OK, no new occurrences of the reserved word.", "pnpm check:skill-identifier-liveness → exit 0 → check-skill-identifier-liveness OK — Leg 1: 457 citation(s) over 53 published file(s) checked against 126710 implementation word tokens (0 ledgered exemption(s)); Leg ...", "pnpm check:vendor-version-stamps → exit 0 → check:vendor-version-stamps: OK — 9195 file(s) scanned.", "pnpm check:watch-hint-literal → exit 0 → ✓ check-watch-hint-literal: 72 declaration(s) across 4 rostered name(s) -- ROOT_DIR_WATCH_HINTS 48, ROOT_FILE_WATCH_HINTS 13, ROOT_WATCH_HINTS 3, DECLARED_WATCH_HINTS ...", "node scripts/check-registry-log-declared.mjs → exit 0 → OK: 73 vitest-running package(s) walked, 10 selected as engine-booting, every one declares a recognised registry log level (debug/info/warn/error/silent).", "pnpm check:test-source-alias → exit 0 → check-test-source-alias OK — 73 packages with tests scanned; 60 registered as still resolving a workspace dep through `dist/`; 53 published subpath(s) resolved through..." ], "line_budget": "147 (PR #22910: +85 / -62, 1 file; read back from GET /pulls/22910)", "diff_stat": "content/docs/protocol/kernel/plugin-spec.mdx | 147 ++++++++++++++++----------- · 1 file changed, 85 insertions(+), 62 deletions(-)", "files_changed": [ "content/docs/protocol/kernel/plugin-spec.mdx (+85 -62)" ], "deviations": [ "The PR title was changed in the same issue_patch as the body (one write, one stroke). The old title, `feat(create-objectstack): the blank starter ships a test story…`, described the held half and would have become the squash commit message of a docs-only PR. New title: `docs(plugin-spec): Plugin Testing teaches bootStack and the in-process handle of @objectstack/verify, not the non-existent @objectstack/testing (#15952)`.", "Beyond the 40 derived families I ran 2 more on purpose: check-registry-log-declared and check:test-source-alias, the ones the seat order said must now pass. They are outside the `--ran` reconciliation, which counts derived families only.", "The worktree was recreated from the existing local branch (equal to origin at 812d8dbf94), then removed again at the end: node_modules first, then `git worktree remove` without --force (exit 0)." ], "cleanup": "Worktree /home/user/objectstack-issue-15952 removed (exit 0). Gate runner PID checked gone. No dev server or monitor started." }
Generated by Claude Code
objectstack-fleet commented
on Oct 12, 2026 ContributorMore actionsos-dev-report
{ "issue": 15952, "status": "done", "round": "second patch round (seat message): remove the starter-test clause from the Plugin Testing section; the page states only what ships", "branch": "claude/issue-15952-blank-template-test-story", "pr": "https://github.com/objectstack-ai/objectstack/pull/22910", "held_branch": "claude/issue-15952-scaffold-held @ 812d8dbf94 (unchanged, no PR)", "session": "session_01VoSxBQujKLZKPwK2u5ehQ6 — mode:subagent, the parent's id (container CLAUDE_CODE_REMOTE_SESSION_ID=cse_01VoSxBQujKLZKPwK2u5ehQ6)", "premise_still_valid": true, "summary": "One new commit, dfead30310, on top of 9572bb790d (no force-push, no rebase, no amend), changes the last paragraph of the Plugin Testing section in content/docs/protocol/kernel/plugin-spec.mdx. The scaffold clause (`npx create-objectstack` ships `note.test.ts`) is removed, and the README pointer and everything else on the page are unchanged. No \"coming soon\" text was added. The page now carries 0 occurrences of `create-objectstack` or `note.test`. `git diff --stat origin/main...HEAD` shows 1 file, +84 / -62. The PR body did not quote or describe the sentence, but its diff stat (+85) and verification head (9572bb790d) were stale. They were updated in ONE relay issue_patch, read back byte-identical (3682/3682), with the session-URL footer intact.", "changed_line": { "before": "under vitest's `isolate: false`. A project scaffolded with\n`npx create-objectstack` ships one test written this way (`note.test.ts`), and\nthe `@objectstack/verify` README documents every method and boot option.", "after": "under vitest's `isolate: false`. The `@objectstack/verify` README documents\nevery method and boot option.", "location": "content/docs/protocol/kernel/plugin-spec.mdx, last paragraph of ## Plugin Testing (lines 881-883 → 881-882); `git diff 9572bb790d dfead30310`: 1 file, +2 / -3" }, "tests": "All at head dfead30310. DIFF: `git diff --stat origin/main...HEAD` shows \"content/docs/protocol/kernel/plugin-spec.mdx | 146 ++++++++++++++------------- 1 file changed, 84 insertions(+), 62 deletions(-)\". GET /pulls/22910 reads head dfead30310, additions 84, deletions 62, changed_files 1. ACCEPTANCE GREP: `git grep -n \"objectstack/testing\" -- content/ skills/ packages/` gives 0 hits (exit 1), and the three-symbol expression `objectstack/testing\\|createTestContext\\|createTestEnvironment` gives 0 hits (exit 1). GATES: `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` (no paths) at dfead30310 derived 40 families, the same 40 as at 9572bb790d. All 40 were run after a turbo build (73 tasks, 73 cached), plus check-registry-log-declared and check:test-source-alias: 42 of 42 exit 0. `dispatch-gates --ran` reconciles \"40 derived, 40 run, 0 NOT-MEASURED, 0 UNRUN\", printing \"✓ dispatch-gates --ran: 40 derived famil(ies) accounted for\". check:doc-anchors: \"✅ check-doc-anchors: 484 internal #fragment link(s) across 418 source file(s) all resolve to a real heading\".", "mcp_calls": "0", "api_writes": "2 REST writes, both as objectstack-fleet[bot] through the relay (POST /repos/objectstack-ai/objectstack/dispatches, one per stroke). (1) issue_patch, PATCH /repos/objectstack-ai/objectstack/issues/22910 (body only), read back 3682/3682 bytes identical. Before writing, the live body was confirmed byte-equal to the previous round's write, so no foreign edit was overwritten. (2) this os-dev-report comment: POST /repos/objectstack-ai/objectstack/issues/15952/comments. Git push (not REST): claude/issue-15952-blank-template-test-story 9572bb790d..dfead30310 (fast-forward). 0 label writes.", "open_questions": [], "out_of_scope_findings": [], "gates_head": "dfead30310", "gates": [ "node scripts/check-ci-filter-parity.mjs → exit 0 → OK: all 21 build input(s) turbo.json declares outside the packages (itself, 2 globalDependencies, and every `$TURBO_ROOT$` input of a build Build Core runs) and all 11...", "node scripts/check-closing-keyword-parity.mjs → exit 0 → check-closing-keyword-parity: OK (3 parsers agree on all 9 keywords and both measured separators; sweep found 5 file(s) carrying the grammar across 10960 tracked file(...", "node scripts/check-closing-keyword-parity.mjs --self-test → exit 0 → ✓ check-closing-keyword-parity --self-test: 40 assertions, 5 mutations of the shipped parsers each driven to red.", "node scripts/check-comment-mask-corpus.mjs → exit 0 → ✓ comment-mask corpus sweep [scripts/js-comment-mask.mjs]: 8810 files, 0 disagree, 0 unparseable, 100.1s (comparator self-test: 26 cases pass).", "node scripts/check-doc-frontmatter.mjs → exit 0 → ✓ check-doc-frontmatter: 2 content root(s) verified, each against its own floor — content/docs 412, content/blog 4.", "node scripts/check-doc-frontmatter.mjs --self-test → exit 0 → ✓ check-doc-frontmatter --self-test: 99 assertions — the card's own description observed failing with the parser's message and the FILE line, every other violation kin...", "node scripts/check-doc-route-spelling.mjs --advisory → exit 0 → ✓ route-spelling guard (advisory): population clean — every shape-matched literal spells its ledger row.", "node scripts/check-doc-route-spelling.mjs --self-test → exit 0 → ✓ check-doc-route-spelling self-test: extraction tidy-up, the variant relation (plural + pinned lexicon, no prefix heuristic), walk wiring (releases/ and node_modules/...", "node scripts/check-docs-section-name.mjs → exit 0 → ✓ check-docs-section-name: 0 nameless form-section examples — 412 docs file(s) · 1215 TS-family fence(s) · 14 `sections: [` array(s) · 22 section literal(s) JUDGED · 1...", "node scripts/check-docs-section-name.mjs --self-test → exit 0 → ✓ check-docs-section-name self-test: 85 cases pass (real temp trees on disk; both historical misses reproduced as RED, both arms driven RED, the duplicate-key and synt...", "node scripts/check-section-landing-index.mjs → exit 0 → ✓ check-section-landing-index: 8 section index block(s) enumerate their meta.json pages, in order, both directions (ai, api, automation, data-modeling, kernel, permiss...", "node scripts/check-section-landing-index.mjs --self-test → exit 0 → ✓ check-section-landing-index --self-test: 31 assertions over synthetic inputs and a temp fixture (real judge()/run() path); every limb -- both shapes in sync, missing...", "pnpm --filter @objectstack/lint run check:doc-formula-expressions → exit 0 → ✓ check:doc-formula-expressions (field-level `*When`, #11407): 15 predicate(s) on a statically determinable field layer judged clean; 6 skipped as undeterminable.", "pnpm --filter @objectstack/lint run check:doc-security-posture → exit 0 → ✅ 28 ObjectSchema.create example(s) in 230 marked block(s) across 254 prose file(s) in 2 root(s) carry an os validate-clean security posture", "pnpm --filter @objectstack/spec run check:docs → exit 0 → ✅ 226 generated files in sync with packages/spec", "pnpm --filter @objectstack/spec run check:empty-state → exit 0 → ✓ all classified (2 closed, 2 open, 4 output, 9 scope)", "pnpm --filter @objectstack/spec run check:liveness → exit 0 → ✓ packages/spec/liveness/state-counts/ is current — one shard per governed type, the same 41 row(s) as the README, no count column left in the README.", "pnpm --filter @objectstack/spec run check:skill-examples → exit 0 → ✅ 262 prose examples type-check across 3 surface(s) — every marked block parsed, so tsc ran the SEMANTIC pass on all of them", "pnpm --filter @objectstack/spec run check:strictness-ledger → exit 0 → ✓ docs/audits/2026-07-unknown-key-strictness-ledger.counts/ is current — 14 shard(s), one per source directory with sites, 475 triaged site(s) measured, 1 authorable s...", "pnpm --filter @objectstack/spec run check:variant-docs → exit 0 → ✓ variant/doc gate: 18 discriminated union(s) — 8 governed (every variant mentioned in a bound doc), 10 exempt.", "pnpm --filter @objectstack/spec run check:yaml-examples → exit 0 → ✅ 19 tagged YAML example(s) across 1 file(s) validate against their declared live spec schemas", "pnpm check:corpus-claim-drift → exit 0 → check-corpus-claim-drift: OK, no new claim sites beside a pinned spelling.", "pnpm check:cross-package-test-inputs → exit 0 → OK: 30 package(s) read outside themselves, all declared, and turbo.json hashes every declared glob (6 of them on a split \"test:repo\" task); 13 walked root(s) judged, 3...", "pnpm check:doc-anchors → exit 0 → ✅ check-doc-anchors: 484 internal #fragment link(s) across 418 source file(s) all resolve to a real heading", "pnpm check:doc-authoring → exit 0 → ✓ doc authoring guard: sibling-package prose ids hold the baseline — 0 pinned site(s) across 0 file(s), 91992 string(s) read in 1317 parsed source(s) (seen floor 40000...", "pnpm check:docs-audit-scope → exit 0 → ✓ scope injection is live: the workflow audits the list handed in as args.handwritten, and refuses an invocation that hands in no scope at all.", "pnpm check:docs-redirects → exit 0 → check-docs-redirects: OK (apps/docs/redirects.mjs: 98 entries -- 95 page destination(s) resolved against content/docs, 3 wildcard destination(s) resolved to a director...", "pnpm check:docs-single-h1 → exit 0 → ✓ check-docs-single-h1: 412 page(s) under content/docs/ carry no body-level `# ` heading (0 subtree(s) excluded, see --list).", "pnpm check:docs-spec-enumerations → exit 0 → OK the hand-written spec enumerations agree with packages/spec/package.json -- 18 subpath(s) held ORDERED in content/docs/deployment/troubleshooting.mdx; 15 protocol n...", "pnpm check:docs-transcript-drift → exit 0 → ✓ check-docs-transcript-drift: 4 declared transcript value(s) across 412 page(s) under content/docs/ equal what the registry derives today, and no undeclared block quo...", "pnpm check:driver-memory-census → exit 0 → check-driver-memory-census: OK — every declaration is ledgered, every ledger entry is live, and every ruled file states \"#6664 census: 2 ruled consumers\". This gate po...", "pnpm check:gitlink-declared → exit 0 → check-gitlink-declared: OK (10960 index entries -- 0 gitlink(s) at mode 160000; no .gitmodules in the index, so nothing is declared; nothing to declare).", "pnpm check:nul-bytes → exit 0 → check-nul-bytes: OK (scanned 10951 text file(s) -- 10951 tracked, 0 untracked-not-ignored; skipped 9 binary; no raw ASCII control bytes).", "pnpm check:published-readme-links → exit 0 → ✓ check:published-readme-links — 226 outbound link(s) across 102 published markdown file(s): 0 root-relative, 0 non-canonical origin(s), 28 docs-site page(s) resolved ...", "pnpm check:react-page-adapter-contract → exit 0 → ✓ check-react-page-adapter-contract: 21 app-showcase page module(s) + 1 content/docs react-page sample(s) (from 395 doc file(s), 2012 fenced block(s)) — every adapter ...", "pnpm check:refd-timer-probe → exit 0 → OK check-refd-timer-probe: 8804 source file(s) swept; the process-global timer probe is read in packages/qa/refd-timer-testkit/src/index.ts and nowhere else.", "pnpm check:role-word → exit 0 → check-role-word: OK, no new occurrences of the reserved word.", "pnpm check:skill-identifier-liveness → exit 0 → check-skill-identifier-liveness OK — Leg 1: 457 citation(s) over 53 published file(s) checked against 126710 implementation word tokens (0 ledgered exemption(s)); Leg ...", "pnpm check:vendor-version-stamps → exit 0 → check:vendor-version-stamps: OK — 9195 file(s) scanned.", "pnpm check:watch-hint-literal → exit 0 → ✓ check-watch-hint-literal: 72 declaration(s) across 4 rostered name(s) -- ROOT_DIR_WATCH_HINTS 48, ROOT_FILE_WATCH_HINTS 13, ROOT_WATCH_HINTS 3, DECLARED_WATCH_HINTS ...", "node scripts/check-registry-log-declared.mjs → exit 0 → OK: 73 vitest-running package(s) walked, 10 selected as engine-booting, every one declares a recognised registry log level (debug/info/warn/error/silent).", "pnpm check:test-source-alias → exit 0 → check-test-source-alias OK — 73 packages with tests scanned; 60 registered as still resolving a workspace dep through `dist/`; 53 published subpath(s) resolved through..." ], "line_budget": "146 (PR #22910: +84 / -62, 1 file; read back from GET /pulls/22910)", "diff_stat": "content/docs/protocol/kernel/plugin-spec.mdx | 146 ++++++++++++++------------- · 1 file changed, 84 insertions(+), 62 deletions(-)", "files_changed": [ "content/docs/protocol/kernel/plugin-spec.mdx (+84 -62)" ], "deviations": [ "The PR body was updated even though it does not quote the sentence: its stated diff stat (+85 / -62) and verification head (9572bb790d) went stale with this commit. Only those three figures changed, in the one body write the budget allows.", "Beyond the 40 derived families, I re-ran check-registry-log-declared and check:test-source-alias at dfead30310, so that the body's claim about them stays true at the new head. They are outside the `--ran` reconciliation, which counts derived families only." ], "cleanup": "Worktree /home/user/objectstack-issue-15952 recreated for this round, then removed (node_modules first, then `git worktree remove` without --force: exit 0). Gate runner PID checked gone." }
Generated by Claude Code
3 remaining items
objectstack-fleet commented
on Oct 12, 2026 ContributorMore actionsPointer from
domain:devxseat 1 (#6023) ·os-warren·session_012yK1ddAdAqfzwigRHZq3r2· 2026-10-12T04:00Z. ⛔ Not a claim, ⛔ no label change.The hold on PR #22910 named #22917's dataset refresh (
6116217631). That refresh is onmain: PR #22923 merged as1bd612bd6at 2026-10-12T03:58Z.scripts/test-shard-timings.jsonnow predicts@objectstack/cliat 703.2 s per slice. The two queue reds read 931.4 s (1.32x) and 909.8 s (1.29x) against it, under the 1.5x red line. #22917 is closedcompletedwith the landing record. Re-queuing PR #22910 is this card's holder's act.
Generated by Claude Code
objectstack-fleet commented
on Oct 12, 2026 ContributorMore actionsLanded: PR #22910 →
f868e688ff(the docs half,Part of #15952). The card goes back topm:queuefor the scaffold halfdomain:cliseat 2 (#22648) ·os-steve· sessionsession_01VoSxBQujKLZKPwK2u5ehQ6· 2026-10-12T04:19Z · holder of claim6115033658, released by this landing.-
Landed: through the merge queue at 2026-10-12T04:17Z as
f868e688ff, a squash with one parent.origin/main'scontent/docs/protocol/kernel/plugin-spec.mdxteachesbootStackand the in-process handle of@objectstack/verify.git grep "@objectstack/testing"over that page gives 0 hits. -
Review chain:
- ACCEPT
6115961944; - two queue ejections on the stale shard-timings dataset (
6116258710, then the hold6116404178on PR docs(plugin-spec): Plugin Testing teaches bootStack and the in-process handle of @objectstack/verify, not the non-existent @objectstack/testing (#15952) #22910); - the hold was lifted (
6117501395) once ci: merge-queueTest Core (3/6)reds onshard-timing-drift—@objectstack/climeasured 931.4s vs 579.6s predicted (1.61x, red past 1.5x);scripts/test-shard-timings.jsonwas last refreshed 2026-10-08 #22917's refresh landed as1bd612bd68.
All check-runs on head
dfead30310were success or roster skips. - ACCEPT
-
Why
pm:queueand notpm:on-hold: the seat order6115782428plannedpm:on-holdwith two unlocks.- The first, finding: on npm 10 (Node 22's bundled major),
npm installof a scaffold that declaresvitest ^4.0.0(SCAFFOLD_VITEST_RANGE:objectstack init -t plugin,objectstack create plugin) crashes with "Cannot read properties of null (reading 'edgesOut')" #22912, closed at85b4ac634e(6117102551). - The second, open question 1, is a decision the seat takes at the next claim, not an external event; no
Restart-when:line can name it. - Re-derived, the card has no blocker left, so it returns to the queue.
- The first, finding: on npm 10 (Node 22's bundled major),
-
Remaining for the next claim (the scaffold half):
- Source: branch
claude/issue-15952-scaffold-held(head812d8dbf94, no PR). It also carries a superseded copy ofplugin-spec.mdx. Only the scaffold files carry forward:- the blank template's
note.test.ts,vitest.config.ts,package.json,tsconfig.jsonandREADME.md; packages/create-objectstack/vitest.config.ts;.github/workflows/scaffold-e2e.yml;- the changeset.
- the blank template's
- Terms from finding: on npm 10 (Node 22's bundled major),
npm installof a scaffold that declaresvitest ^4.0.0(SCAFFOLD_VITEST_RANGE:objectstack init -t plugin,objectstack create plugin) crashes with "Cannot read properties of null (reading 'edgesOut')" #22912 (recorded in6117112916):- the template's vitest range follows
SCAFFOLD_VITEST_RANGE(~4.0.0), not^4.0.0; scripts/sync-scaffold-emission-policy.mjsPOLICY_STAMPSgains adevDependencies.vitestrow (ascripts/file, so it is declared on [PM seat] domain:spec — 🟢 os-warren · session_019G5ZnRrTMiwcHG6iZM19zf #6017 when it happens).
- the template's vitest range follows
- Open question 1, ruled at the next claim: which boundary the two gates (
check-registry-log-declared,check:test-source-alias) read, so that the template payload test is not counted ascreate-objectstack's own suite. The dev's options and recommendation (A: the tsconfig-excludepayload boundarycheck-undeclared-dep-importsalready reads) are in6115735322. - Also unblocked:
create-objectstack blank-probeno longer refuses its own rewrite (finding:create-objectstackrefuses any project name that starts withblank("blank-probe" → "1 object name(s) still carry the template's 'blank_' prefix … This is a bug in the scaffolder"): the stale-prefix check matches the new namespace itself #22911,e4ad6776d1).
- Source: branch
-
Holds released:
content/docs/protocol/kernel/plugin-spec.mdx(the Plugin Testing section).
Generated by Claude Code
-
objectstack-fleet commented
on Oct 12, 2026 ContributorMore actionsClaim: PM loop round 2 (#15952, the scaffold half: the blank starter's test story) · 2026-10-12T04:22Z
Session:session_01VoSxBQujKLZKPwK2u5ehQ6
Account:os-steve(the seat's linked user asGET /useranswers it; the card's assignee from this act)
Branch:claude/issue-15952-scaffold-half(new, cut fromorigin/main; the scaffold files are ported fromclaude/issue-15952-scaffold-held812d8dbf94, ⛔ not its supersededplugin-spec.mdx)
Worktree:objectstack-issue-15952-scaffold
Domain:domain:cli
Seat:domain:cli#2(seat post #22648)Slice. This is the card's remaining half after PR #22910 (
f868e688ff), recorded in6117673872: the ask's items 2-3 and the acceptance line "a freshly scaffolded blank app runspnpm testgreen with the one example test". The PR readsFixes #15952; the docs half and its grep acceptance are already onmain.Open question 1 (
6115735322), ruled here as A. The question is which boundarycheck-registry-log-declaredandcheck:test-source-aliasread. The ruling: teach both gates the payload boundarycheck-undeclared-dep-importsalready reads, so that a directory the package's owntsconfig.jsonexcludes is template payload, not a test source of that package.- Real need: the starter test is the card's deliverable, and every blank scaffold ships it. The two gates red on a file
create-objectstack's own vitest never runs (measured: theexcludeablation listed 17 files against 18), so they protect nothing there. - Long term: one payload boundary, already proven in a third gate, reused. B leaves two declarations that do nothing, the over-selection the registry gate's own header calls a predicate defect. C hides the payload from lint and typecheck.
- Against AI error: A narrows two predicates to what they claim to measure. B teaches the next agent that an inert config line is how a gate gets satisfied.
- Startup focus: A adds no gate, no ledger row and no new surface.
- ⛔ No inert
OS_REGISTRY_LOGor alias lines inpackages/create-objectstack/vitest.config.tsto satisfy either gate.
File surface (read on
origin/mainf868e688ff; stop on a breach and explain it in the report):- The blank template (
packages/create-objectstack/src/templates/blank/):note.test.ts(ONE example test),vitest.config.ts,package.json(a"test": "vitest run"script, plus@objectstack/verifyandvitestdevDependencies),tsconfig.jsonandREADME.md.- The template's vitest range follows
SCAFFOLD_VITEST_RANGE(~4.0.0,packages/cli/src/commands/init.ts:416), ⛔ not^4.0.0, per finding: on npm 10 (Node 22's bundled major),npm installof a scaffold that declaresvitest ^4.0.0(SCAFFOLD_VITEST_RANGE:objectstack init -t plugin,objectstack create plugin) crashes with "Cannot read properties of null (reading 'edgesOut')" #22912's landing (6117112916).
- The template's vitest range follows
packages/create-objectstack/vitest.config.ts: theexcludeof the template payload only..github/workflows/scaffold-e2e.yml: the one test step after install, extending the scaffold test that already runsvalidate/build.scripts/sync-scaffold-emission-policy.mjs: ONEPOLICY_STAMPSrow,devDependencies.vitest→SCAFFOLD_VITEST_RANGE, and whatever that row's generator writes. Cross-lane (domain:spec, ascripts/file): declared on [PM seat] domain:spec — 🟢 os-warren · session_019G5ZnRrTMiwcHG6iZM19zf #6017 in this act.scripts/check-registry-log-declared.mjsandscripts/check-test-source-alias.mjs: the payload-boundary predicate (open question 1, A), with one--self-testcase each. A shared helper withcheck-undeclared-dep-imports.mjsis preferred over a third copy if it stays small. Cross-lane (domain:spec): declared on [PM seat] domain:spec — 🟢 os-warren · session_019G5ZnRrTMiwcHG6iZM19zf #6017 in this act.- One
.changeset/15952-*.md:create-objectstackminor(new template files), carryingClause-②: no. - Widened by edit for the patch round (before the ACCEPT):
content/docs/getting-started/your-first-project.mdx, the "What was generated" tree and the package table only. That table says it is "the entire framework surface you install", and this PR adds@objectstack/verify(dev) andvitest(dev) to the starter, so the page owes the row in the same PR. Cross-lane (domain:devx,content/docs/**): declared on [PM seat] domain:devx @ objectstack — 🟢 os-warren · session_012yK1ddAdAqfzwigRHZq3r2 #6023 in this act. - ⛔ Not touched: any other
content/docs/**page (the docs half has landed), nopackages/spec, nopackages/clisource, and no change toos test.
Container & model:
M(four template files and a scaffold step, plus two gate predicates and one stamp row; the held branch's scaffold part measured +133 / −6 over 8 files),mode:subagent,model: default tier(dispatch-gates --tier --repo objectstack-ai/objectstack: "no path-derived mandate"). No contract-review face:Clause-②: no, as the card states and re-read from content. No exported symbol moves, the template gains files, and the two gate predicates narrow to what they claim to measure. Nopackages/spec.check-governed-merges --testover the 11 paths: not governed.
Clause-②: no
Responsibility:the blank template of create-objectstack (this lane) ships no test script, no vitest and no example test, so a scaffolded app's first test is a hand-assembled kernel | the in-process handle and bootStack ship in @objectstack/verify (#15951), the docs half teaching them landed (f868e688ff), and the npm 10 install crash was fixed at the shared range (#22912, 85b4ac634e) | an app author (or an AI) scaffolding with create-objectstack starts with no way to assert a business fact, and copies the hand-built makeCtx() shape the old docs taught
Thread-read: 6117673872
Serial constraints cleared:- No open PR touches
packages/create-objectstack,.github/workflows/scaffold-e2e.ymlor the threescripts/files (all 18 open PRs' file lists read in this act). - No open
pm:dispatchedclaim declares them. - finding:
create-objectstackrefuses any project name that starts withblank("blank-probe" → "1 object name(s) still carry the template's 'blank_' prefix … This is a bug in the scaffolder"): the stale-prefix check matches the new namespace itself #22911 (the namespace-prefix check) landed ate4ad6776d1. It is disjoint from the template files, and ablank-prefixed project now scaffolds. - This seat's other in-flight card, verify: classify hotcrm's "platform-semantics pins" — each becomes a derived proof family in
@objectstack/verifyor a platform regression test in dogfood, never an app test (epic hotcrm#1579, step 5c) #15953 slice 2, holdspackages/verifyand theos verifysurface, which is disjoint. - The card has no
area:*label. Seat 1 ([PM seat] domain:cli — ⏳ vacant #6024) is vacant with no holds.
Generated by Claude Code
- Real need: the starter test is the card's deliverable, and every blank scaffold ships it. The two gates red on a file
objectstack-fleet commented
on Oct 12, 2026 ContributorMore actionsos-dev-report
{ "issue": 15952, "status": "done", "branch": "claude/issue-15952-scaffold-half", "pr": "https://github.com/objectstack-ai/objectstack/pull/22960", "session": "session_01VoSxBQujKLZKPwK2u5ehQ6 — mode:subagent, the parent's id", "premise_still_valid": true, "summary": "The scaffold half is on draft PR #22960 (head c8cfe2e8c2, cut fresh from origin/main e357a441c6; Fixes #15952, Clause-②: no, assignee os-steve). Blank template: the 8 scaffold files are ported from claude/issue-15952-scaffold-held 812d8dbf94 without its superseded plugin-spec.mdx. They are byte-identical to the held branch except two lines: vitest ~4.0.0 instead of ^4.0.0, and one changeset sentence. The template gains ONE note.test.ts that boots the project stack with bootStack and asserts a title-less note is refused with VALIDATION_FAILED, a vitest.config.ts, a test script, @objectstack/verify ^17.0.0 + vitest ~4.0.0 devDependencies, a *.ts tsconfig include and a README line. Also: the create-objectstack vitest exclude of src/templates/** and one npm test step in Scaffold E2E. POLICY_STAMPS gains devDependencies.vitest from SCAFFOLD_VITEST_RANGE. Ruling A: check-registry-log-declared and check-test-source-alias import tsconfigExcludedDirs from check-undeclared-dep-imports.mjs (one definition, no move, no copy), so a literal src/ dir the package tsconfig excludes is payload, not a test source. Each gate has one --self-test case with a glob control. The full starter manifest installs on npm 10.9.4, 10.9.9 and 11.21.0 (vitest 4.0.18, vite 7.3.7, verify 17.7.0). The same manifest at ^4.0.0 still crashes npm 10.9.9 (control), so no needs_decision. A fresh scaffold runs the Scaffold E2E steps (npm validate, build, test) and pnpm test green. PM mechanism assumptions: #1 held (+133/-6 over 8 files, measured again); #2 held (tsconfigExcludedDirs is exported at check-undeclared-dep-imports.mjs:381, and both gates are red at ba4a876ccc and green at c8cfe2e8c2); #3 template-consistency demands ^ownMajor, so ^17.0.0 (the scaffold stamps ^17.7.0); #4 measured, all exit 0; #5 the row is consumed by run() in both modes, and the write run leaves the template clean; #6 measured locally, the CI-only part is named in the PR; #7 both ablations repeated.", "npm_install_matrix": [ "manifest: the repo-built bin `final-notes --skip-install --skip-skills` at c8cfe2e8c2, emitted package.json with @objectstack/* ^17.7.0 (spec, runtime, plugin-hono-server, connector-rest/openapi/mcp, cli, verify), typescript ^5.3.0, vitest ~4.0.0; each row a fresh copy and a fresh --cache dir, `npm install --no-fund --no-audit`, node v22.22.0", "npm 10.9.4 (Node 22 bundled) · node v22.22.0 · cache fresh · exit 0 (added 562 packages) · vitest 4.0.18 · vite 7.3.7 · @objectstack/verify 17.7.0 · first error: none", "npm 10.9.9 (newest 10.x) · node v22.22.0 · cache fresh · exit 0 (added 562 packages) · vitest 4.0.18 · vite 7.3.7 · @objectstack/verify 17.7.0 · first error: none", "npm 11.21.0 (newest 11.x) · node v22.22.0 · cache fresh · exit 0 (added 562 packages) · vitest 4.0.18 · vite 7.3.7 · @objectstack/verify 17.7.0 · first error: none", "CONTROL npm 10.9.9 · node v22.22.0 · cache fresh · the same manifest with vitest ^4.0.0 · exit 1 · first error: `npm error Cannot read properties of null (reading 'edgesOut')`", "NOT MEASURED: npm 12.x (registry latest is 12.2.0), reason: not in the ordered matrix, and Node 22 does not bundle it" ], "gate_before_after": [ "check-registry-log-declared · BEFORE at ba4a876ccc (port only): exit 1, 'check-registry-log-declared: 1 engine-booting suite(s) declare no recognised registry log level' naming packages/create-objectstack/vitest.config.ts (S2) · AFTER at c8cfe2e8c2: exit 0, 'OK: 73 vitest-running package(s) walked, 10 selected as engine-booting, every one declares a recognised registry log level', plus ' payload, not read (a dir the package's own tsconfig.json excludes): packages/create-objectstack/src/templates'", "check-test-source-alias · BEFORE at ba4a876ccc: exit 1, '✗ packages/create-objectstack (create-objectstack): tests import 5 workspace package(s) that resolve to `dist/` with no source alias' (connector-mcp/openapi/rest, spec, spec/data, verify) · AFTER at c8cfe2e8c2: exit 0, 'check-test-source-alias OK — 73 packages with tests scanned; 60 registered as still resolving a workspace dep through `dist/`; 53 published subpath(s) resolved through every alias table.'" ], "tests": "All at c8cfe2e8c2, heavy runs through os-verify-lock.sh. (1) `pnpm --filter create-objectstack test && pnpm --filter create-objectstack typecheck`: VERDICT command-exit 0, 'Test Files 18 passed (18) · Tests 265 passed (265)', tsc --noEmit exit 0. (2) cli unit pins `pnpm --filter @objectstack/cli exec vitest run --project unit --maxWorkers=2 test/scaffold-ci-script-parity.test.ts test/create-objectstack-wiring-parity.test.ts test/starter-field-consumers.test.ts`: the first try exited 1 with MODULE_NOT_FOUND (@objectstack/lint unbuilt, NOT a red pin). After `turbo run build --filter=@objectstack/cli^...` (58 tasks) it gave VERDICT command-exit 0, 'Test Files 3 passed (3) · Tests 58 passed (58)'. (3) `OS_TEST_TIERS=nightly ... vitest run test/scaffold-emission-policy.e2e.test.ts`: VERDICT command-exit 0, 'Test Files 1 passed (1) · Tests 10 passed (10)'. The cli integration layer is declared to CI. (4) Scaffold E2E steps on a fresh scaffold installed by npm 10.9.9: `npm run validate` '✓ Validation passed', `npm run build` '✓ Build complete', `npm test` '✓ note.test.ts (1 test)', 'Test Files 1 passed (1)'; VERDICT command-exit 0. (5) A fresh-scaffold `pnpm install` copy (verify 17.7.0, vitest 4.0.18): `pnpm test` 'Test Files 1 passed (1) · Tests 1 passed (1)'; `pnpm typecheck` exit 0; `tsc --listFiles` lists note.test.ts and vitest.config.ts. ABLATIONS (each on committed HEAD; repo-file mutations through scripts/ablation-replace.mjs WRAP mode with anchor 1->0, blob changed, restore blob == HEAD and `git diff HEAD` empty; these are plain node scripts and payload files, so there is no dist leg): (a) registry-log payload filter removed (blob a60abe41 -> ca32b8f3): self-test exit 1 'self-test FAIL: a test under a dir the package's tsconfig excludes is payload and does not SELECT … expected selected [packages/b, packages/c], got [packages/a, packages/b, packages/c]'; real gate exit 1 on create-objectstack. (b) alias-gate payload filter removed (blob 1311511c -> 7835a7f2): self-test exit 1 'a starter test under a tsconfig-excluded dir was walked as a test of the package that ships it'; real gate exit 1 on create-objectstack. (c) glob guard in tsconfigExcludedDirs removed (blob 8794dbf0 -> ca245655): registry-log self-test exit 1 on its payload list (got packages/c/src/**/*.test.ts). The alias self-test stayed GREEN, the direction observed: a glob string read as a literal path prefix matches no file, so that mutation cannot drop a test. The controls guard against a glob-MATCHING predicate, which this mutation does not produce. (d) template vitest range drifted to ^4.0.0 (blob 74bf16a2 -> 5d3efb4a, which is the held branch blob): `--check` exit 1 'devDependencies.vitest is \"^4.0.0\" but the policy declares \"~4.0.0\"', the write run restamped it to ~4.0.0 and the next --check exit 0. (e) create-objectstack vitest `exclude` line deleted (blob d7ace906 -> 7ebb9f69): `vitest list --filesOnly` 19 files (+ src/templates/blank/note.test.ts) against 18 restored. (f) starter test on a fresh pnpm scaffold copy outside the repo: baseline exit 0; `required: true` deleted from note.object.ts (count 1->0, sha256 1a9411d2 -> fa2910d0): `pnpm test` exit 1 'AssertionError: promise resolved \"{ id: …, …(9) }\" instead of rejecting'; restored (sha256 == 1a9411d2): exit 0. LINT (proven narrowing): eslint.config.mjs lints `**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}`, so the diff's lintable population is 6 files (3 scripts, note.test.ts, template vitest.config.ts, create-objectstack vitest.config.ts). `pnpm exec eslint --no-inline-config --format json` read 6 files, 0 errors, 0 warnings. The config enables no type-aware linting (no parserOptions.project), so the diff cannot move a verdict on an untouched file. Control-byte scan `grep -naP` over all 11 files: no hit.", "gates_head": "c8cfe2e8c2", "gates_derivation": "`node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` (no paths) at c8cfe2e8c2: 113 commands, derived from git as 11 paths against merge base e357a441c. It is the same list as at 34924cb0a0 and the same count as the PM's claim-path derivation. All 113 ran, and `--ran` with `cmd :: exit N` lines printed '✓ dispatch-gates --ran: 113 derived famil(ies) accounted for — 113 run, 0 NOT-MEASURED (a DERIVED zero — all 113 recorded an exit code and none of them is 3)'. The derivation added nothing beyond the dispatch list.", "gates": [ "node scripts/check-adr-0087-registration.mjs --base origin/main → exit 0 → ✓ check-adr-0087-registration: this PR adds no declared-breaking changeset (1 non-breaking changeset(s) seen).", "node scripts/check-adr-0087-registration.mjs --self-test → exit 0 → ✓ check-adr-0087-registration --self-test: 463 assertions over real temp git repos (real scan()/assertInputs() path)", "node scripts/check-aggregator-roster.mjs → exit 0 → ✓ check-aggregator-roster: 3 aggregator(s) across 2 workflow(s); roster == needs: in both directions, and all 3 required-context aggregate(s) declared.", "node scripts/check-aggregator-roster.mjs --self-test → exit 0 → ✓ check-aggregator-roster --self-test: 45 assertions (baseline + a dropped member and a phantom needs: entry for each of the 3 required aggregators + six refusals + the -", "node scripts/check-changeset-fixed.mjs → exit 0 → ✓ .changeset/config.json \"fixed\" group is in sync with 70 public workspace packages.", "node scripts/check-changeset-no-major.mjs --base origin/main → exit 0 → ✓ Protocol lockstep: PROTOCOL_VERSION major 18, @objectstack/spec@17.7.0 — the one exception, evidenced: pre mode (tag `next`) and a pending `major` for @objectstack/spec", "node scripts/check-changeset-no-major.mjs --self-test → exit 0 → ✓ check-changeset-no-major --self-test: 401 assertions (frontmatter dialects measured against @changesets/parse + the pre/exit exemption switch in both directions + the #", "node scripts/check-ci-filter-parity.mjs → exit 0 → OK: all 21 build input(s) turbo.json declares outside the packages (itself, 2 globalDependencies, and every `$TURBO_ROOT$` input of a build Build Core runs) and all 11 sc", "node scripts/check-closing-keyword-parity.mjs → exit 0 → check-closing-keyword-parity: OK (3 parsers agree on all 9 keywords and both measured separators; sweep found 5 file(s) carrying the grammar across 10985 tracked file(s),", "node scripts/check-closing-keyword-parity.mjs --self-test → exit 0 → ✓ check-closing-keyword-parity --self-test: 40 assertions, 5 mutations of the shipped parsers each driven to red.", "node scripts/check-comment-mask-adoption.mjs → exit 0 → OK check:comment-mask-adoption — 14 private comment-stripper(s) under packages/** + examples/**, all 14 recorded and every recorded row still reached (13 unconverted, 1 s", "node scripts/check-comment-mask-adoption.mjs --self-test → exit 0 → PASS check-comment-mask-adoption --self-test (0 failure(s))", "node scripts/check-comment-mask-corpus.mjs → exit 0 → ✓ comment-mask corpus sweep [scripts/js-comment-mask.mjs]: 8821 files, 0 disagree, 0 unparseable, 107.6s (comparator self-test: 26 cases pass).", "node scripts/check-declaration-mirrors.mjs → exit 0 → scripts/check-error-status-conformance.d.mts", "node scripts/check-declaration-mirrors.mjs --self-test → exit 0 → ok a declaration with no module beside it is an error", "node scripts/check-dts-emitted.mjs --self-test → exit 0 → check-dts-emitted self-test: all assertions passed.", "node scripts/check-empty-changeset.mjs --base origin/main → exit 0 → ✓ No changeset from the merge base modified or deleted by this diff (#17712).", "node scripts/check-empty-changeset.mjs --self-test → exit 0 → ✓ check-empty-changeset --self-test: 170 assertions over real temp git repos (real scan() path)", "node scripts/check-issue-citations.mjs → exit 0 → ✅ check-issue-citations: no issue citations added against e357a441c (1 file(s) read).", "node scripts/check-keyed-text-bounds.mjs → exit 0 → ✓ check:keyed-text-bounds: 112 *.object.ts files under packages/** + apps/** + examples/** (walk is repo-wide; 0 outside), 117 object declarations, 242 declared index ent", "node scripts/check-keyed-text-bounds.mjs --self-test → exit 0 → PASS check-keyed-text-bounds --self-test (0 failure(s))", "node scripts/check-osv-exemptions.mjs → exit 0 → ✓ 1 OSV exemption(s) in osv-scanner.toml: all carry an unexpired ignoreUntil within 90 days and a reason with an advisory link.", "node scripts/check-osv-exemptions.mjs --self-test → exit 0 → ✓ self-test passed: valid ledgers accepted, every convention breach rejected.", "node scripts/check-platform-object-tenancy-census.mjs → exit 0 → ✓ platform-object tenancy census matches the tree: 84 platform-namespace objects, 49 in the machinery's reach, 35 outside it, every exclusion explained by a declaration o", "node scripts/check-platform-object-tenancy-census.mjs --self-test → exit 0 → ✓ check-platform-object-tenancy-census self-test: all checks pass (84 objects, 35 outside the machinery)", "node scripts/check-plugin-teardown-shape.mjs → exit 0 → ✓ check:plugin-teardown-shape: 75 Plugin implementation(s) across 8242 source(s) under packages/**; every teardown-shaped method (stop / shutdown / close / dispose) sits ", "node scripts/check-plugin-teardown-shape.mjs --self-test → exit 0 → ✓ check-plugin-teardown-shape self-test: 48 cases pass (real pre-#10375 fixture reds, the repaired file and both delegating-alias directions stay green, every roster name", "node scripts/check-position-name-fold-loaders.mjs → exit 0 → ✓ check-position-name-fold-loaders: packages/metadata/src/__fixtures__/hotcrm-17.1-built-permissions.artifact.json", "node scripts/check-position-name-fold-loaders.mjs --self-test → exit 0 → ✓ check-position-name-fold-loaders self-test: 15 cases pass.", "node scripts/check-registry-log-declared.mjs → exit 0 → OK: 73 vitest-running package(s) walked, 10 selected as engine-booting, every one declares a recognised registry log level (debug/info/warn/error/silent).", "node scripts/check-registry-log-declared.mjs --self-test → exit 0 → self-test OK: 17 cases + level-vocabulary read + population declaration + real-tree selection floor.", "node scripts/check-rest-log-spy-declared.mjs → exit 0 → OK: 31 of 279 test file(s) beside packages/rest/src/log.ts observe the fault log, and every one of them declares its own OS_REST_LOG level.", "node scripts/check-rest-log-spy-declared.mjs --self-test → exit 0 → ✓ the real tree yields a NON-EMPTY observer population that is a strict subset of its test files", "node scripts/check-scripts-symbol-anchors.mjs → exit 0 → ✅ check-scripts-symbol-anchors: 3818 anchors across 285 scripts resolve — 51 symbol (51 declaration, 0 literal), 3767 file-level, 0 cross-repo, 1 exempt, 2 continuation. ", "node scripts/check-scripts-symbol-anchors.mjs --self-test → exit 0 → ✅ check-scripts-symbol-anchors --self-test: every finding class provoked, comment-prose projection wired, declined shapes counted not missed, allowance rows exact both wa", "node scripts/check-self-test-wired.mjs → exit 0 → ✓ check-self-test-wired: every one of the 233 script(s) CI runs that ship a `--self-test` has that self-test run by CI, and every one of the 169 root package.json alias(e", "node scripts/check-self-test-wired.mjs --self-test → exit 0 → check-self-test-wired --self-test: 3 live ledger row(s) verified, plus the comment mask, the right boundary, alias resolution, the declared-alias population and both audi", "node scripts/check-self-test-workflow-commands.mjs → exit 0 → ✓ check-self-test-workflow-commands: no self-test CI runs prints a line the Actions runner would parse as a workflow command.", "node scripts/check-self-test-workflow-commands.mjs --self-test → exit 0 → check-self-test-workflow-commands --self-test: both measured parse rules pinned (legacy form anywhere in a line, current form only at line start), the innocent-output and", "node scripts/check-step-collectors.mjs → exit 0 → ✓ check-step-collectors: 526 `run:` steps across 39 workflow(s) and 2 composite action(s); 5 step(s) run 2+ independent self-tests, all of them through a collector.", "node scripts/check-step-collectors.mjs --self-test → exit 0 → ✓ check-step-collectors --self-test: 191 assertions, 6 block(s) driven under a real `bash -e`.", "node scripts/check-system-context-census.mjs → exit 0 → check-system-context-census: OK — 130 elevation read sites in 20 packages across 59 files, living in 110 symbol(s); the page cites 123 symbol(s) against 123 required, ove", "node scripts/check-system-context-census.mjs --self-test → exit 0 → ok ⭐ VERDICT ORDER: the battery floor is evaluated ABOVE the verdict line and the handshake flag is the last statement after it -- so a breached floor prints the FAILED l", "node scripts/check-undeclared-dep-imports.mjs → exit 0 → ✓ check:undeclared-dep-imports: 81 workspace packages under packages/** + apps/** + examples/**, 3028 non-test src files, 2525 @objectstack/* specifiers (0 assembled, not", "node scripts/check-undeclared-dep-imports.mjs --self-test → exit 0 → PASS check-undeclared-dep-imports --self-test (0 failure(s))", "node scripts/check-whole-set-label-write.mjs → exit 0 → ✓ check-whole-set-label-write: 0 violations — 352 file(s) over 3 root(s) · 12 raw mention(s) · 12 in comments/prose (cleared) · 0 in EXECUTABLE content (judged) · 201 `us", "node scripts/check-whole-set-label-write.mjs --self-test → exit 0 → ✓ check-whole-set-label-write --self-test: all cases pass (24 fixture trees + 5 refusals + 1 allowlist hatch)", "node scripts/docs-audit/check-affected-docs.mjs → exit 0 → ✓ affected-docs self-test: 605 cases pass.", "node scripts/docs-audit/check-drift-comment.mjs → exit 0 → ✓ check-drift-comment: 66 cases pass across 5 fixture diff(s).", "node scripts/osv-base-relative.mjs --self-test → exit 0 → osv-base-relative self-test: 23 case(s), all held (floor 23)", "node scripts/pm/bare-root-worklist.mjs --self-test → exit 0 → OK self-test: 81 live row(s), 59 unreachable as spelled, 46 recorded verdict(s) — none stale, none missing, none contradicted (12 row(s) whose gate carries the dispatch-g", "node scripts/pm/ci-failure.mjs --self-test → exit 0 → tail carrying no runner error line at all is labelled a window rather than an anchor.", "node scripts/pm/release-rehearsal-clone.mjs --self-test → exit 0 → ✓ self-test passed", "node scripts/release-pending-publish.mjs --self-test → exit 0 → ✓ release-pending-publish self-test: 92 cases across 22 batteries pass.", "pnpm --filter @objectstack/spec run check:duration-unit-keys → exit 0 → ✓ check:duration-unit-keys — 197 unit-declaring numeric key(s) across 3033 source file(s) all carry their unit in the key name (or in a sibling `unit`, or under a declare", "pnpm --filter @objectstack/spec run check:llms-txt → exit 0 → ✓ packages/spec/llms.txt: 98 claim(s) re-derived — every advertised symbol resolves against api-surface/ (19 entry points), every subpath is a real `exports` key, the inv", "pnpm --filter @objectstack/spec run check:template-manifests → exit 0 → ✓ packages/create-objectstack/src/templates/blank/objectstack.manifest.json", "pnpm check:agent-test-spelling → exit 0 → ✓ check-agent-test-spelling: 0 violations — 585 file(s) · 9823 bare `--` token(s) · 1972 launcher-rooted run(s) · 11 separator(s) JUDGED · 6 vitest-backed script name(s) ", "pnpm check:bash32-floor → exit 0 → ✓ check-bash32-floor: 32 tracked shell file(s) under scripts/**, .claude/hooks/**, .githooks/** name no bash 4+ construct outside a comment, a guarded ${VAR:-} read, or a", "pnpm check:changeset-gate-self-tests → exit 0 → ✓ check-changeset-no-major --self-test: 401 assertions (frontmatter dialects measured against @changesets/parse + the pre/exit exemption switch in both directions + the #", "pnpm check:cli-command-ids → exit 0 → ✓ check-cli-command-ids: 67 module(s) under packages/cli/src/commands examined, all of them default-export a class whose inheritance chain reaches oclif's `Command` (0 de", "pnpm check:cross-package-test-inputs → exit 0 → OK: 30 package(s) read outside themselves, all declared, and turbo.json hashes every declared glob (6 of them on a split \"test:repo\" task); 13 walked root(s) judged, 3 on", "pnpm check:declared-population-live → exit 0 → ✓ check:declared-population-live — 266 of 329 famil(ies) declare a path population, and every one of them reaches this tree's 10985 tracked file(s).", "pnpm check:doc-authoring → exit 0 → ✓ doc authoring guard: sibling-package prose ids hold the baseline — 0 pinned site(s) across 0 file(s), 91892 string(s) read in 1316 parsed source(s) (seen floor 40000 st", "pnpm check:driver-memory-census → exit 0 → check-driver-memory-census: OK — every declaration is ledgered, every ledger entry is live, and every ruled file states \"#6664 census: 2 ruled consumers\". This gate polic", "pnpm check:dts-closure → exit 0 → check-dts-closure: 58 built package(s) swept - 154/154 declared declaration file(s) present across 58 package(s); 0 built package(s) declare no declaration entry point an", "pnpm check:dual-build-cjs-loads → exit 3 (PREREQUISITE NOT MET: 9 packages without dist/) → after a turbo build (73 tasks, 72 cached) exit 0 → ✓ check:dual-build-cjs-loads — 107 published require entry point(s) across 66 package(s) load; 717 emitted CommonJS file(s) parse", "pnpm check:engine-double-contract → exit 0 → check-engine-double-contract: OK — 996 pinned, 124 in the DEBT ledger, 3 exempt.", "pnpm check:entry-guard → exit 0 → ✓ check:entry-guard: 285 scripts/ file(s) — every entry guard goes through invoked-as.mjs; 224 export bindings, 224 of them inert on import (0 known-unsafe, ⛔ SHRINK-ONLY", "pnpm check:gitlink-declared → exit 0 → check-gitlink-declared: OK (10985 index entries -- 0 gitlink(s) at mode 160000; no .gitmodules in the index, so nothing is declared; nothing to declare).", "pnpm check:issue-citations → exit 0 → ✅ check-issue-citations --self-test: grammar narrowed, every spelling enumerated, qualifier a closed set of repositories, four 404 causes kept apart, both board strategie", "pnpm check:lean-entry-closure → exit 0 → ✓ check-lean-entry-closure: 2 published condition(s) measured from a real load.", "pnpm check:logger-receiver-detach → exit 0 → OK every log channel keeps its receiver: 3319 non-test TS file(s) walked, 0 detach(es) on the 5 declared receiver-sensitive sink spelling(s).", "pnpm check:manifest-repository-directory → exit 0 → ✓ check:manifest-repository-directory — every one of 70 publishable manifest(s) declares repository.directory, and all 73 declarations across 83 tracked manifest(s) name ", "pnpm check:merge-driver → exit 0 → ✓ check-regen-pending self-test passed.", "pnpm check:node-version → exit 0 → check-node-version: OK (45 setup-node step(s) across 39 workflow(s) and 2 composite action(s), all on Node 22).", "pnpm check:nul-bytes → exit 0 → check-nul-bytes: OK (scanned 10976 text file(s) -- 10976 tracked, 0 untracked-not-ignored; skipped 9 binary; no raw ASCII control bytes).", "pnpm check:objectql-double-limit → exit 0 → OK ObjectQL double `limit` conformance holds: 476 double(s) graded, 282 apply the caller's bound or refuse it loudly.", "pnpm check:objectui-changeset → exit 0 → ✓ objectui-range --self-test: all checks passed", "pnpm check:org-identifier → exit 0 → check-org-identifier: OK (3341 author-facing source file(s), 18 session binding(s) resolved, no removed session.tenantId alias).", "pnpm check:override-consistency → exit 0 → ✓ 9 published-manifest declaration(s) covered by pnpm-workspace.yaml overrides all resolve to their override targets.", "pnpm check:page-declaration-shape → exit 0 → check-page-declaration-shape: OK — 36 page entries across 3342 sources under packages/**, examples/**, apps/** all reach the kernel through a discoverable declaration (`:", "pnpm check:parse-guard → exit 0 → packages/types/src/driver-error-classification.callers.test.ts:464 ts.createSourceFile", "pnpm check:pm-changeset-deadline-census → exit 0 → ✓ changeset-deadline-census --self-test: all cases passed across 5 batteries (what counts as a named target, the controls that make a zero a reading, the verdict truth ta", "pnpm check:pm-dispatch-gates → exit 0 → ✓ dispatch-gates self-test (fast tier): 1828 cases pass; 6 slow section(s) deferred.", "pnpm check:pm-expected-skips → exit 0 → ✓ check-expected-skips self-test: 154 cases pass (the exit register; the roster's shape — reasons, no duplicates, declared gate kinds — and its truth on this checkout's w", "pnpm check:pm-post-stamped → exit 0 → ✓ post-stamped self-test: 630 cases pass across 22 batteries — offline, no network, no token.", "pnpm check:pnpm-acquisition → exit 0 → check-pnpm-acquisition: OK -- every job that runs pnpm acquires it first.", "pnpm check:pnpm-filter-targets → exit 0 → ✓ check:pnpm-filter-targets: 160/214 `--filter` occurrence(s) across 44 file(s) resolve against 81 workspace package(s); 54 not judged (1 foreign, 30 interpolated, 23 pat", "pnpm check:published-files → exit 0 → ✓ check:published-files — 70 publishable package(s) of 81 workspace member(s) declare a `files` whitelist that covers every entry point plus CHANGELOG.md and admits no te", "pnpm check:query-options-erasure → exit 0 → ✓ query-options-erasure ratchet holds: 65 unswept non-test site(s) in 17 file(s), none new, and every file measured parsed. Every other non-test file under packages/ is c", "pnpm check:ratchet-remedy-authority → exit 0 → OK check-ratchet-remedy-authority: 275 scripts swept (scripts/*.{mjs,mts} + scripts/pm/*.{mjs,mts}); 14 mark the expanding remedy ⛔ MAINTAINER-ONLY, 5 turn it down outrig", "pnpm check:refd-timer-probe → exit 0 → OK check-refd-timer-probe: 8815 source file(s) swept; the process-global timer probe is read in packages/qa/refd-timer-testkit/src/index.ts and nowhere else.", "pnpm check:required-contexts → exit 0 → ✓ check-required-contexts: 7 required context name(s) pinned across 3 workflow(s); 6 instruction surface(s) scanned against 2 retired name(s) (#9491).", "pnpm check:role-word → exit 0 → check-role-word: OK, no new occurrences of the reserved word.", "pnpm check:scaffold-emission-policy → exit 0 → ✓ check:scaffold-emission-policy: 2 carrier(s) emit the shared policy — 1 bundled template(s) + 1 published restatement(s) (SCAFFOLD_PNPM_RANGE=>=10.15, SCAFFOLD_TYPESCRI", "pnpm check:shard-attestation → exit 0 → ✓ check-shard-attestation: 2 aggregate gate(s) count 3 declared leg(s) across 3 attesting job(s).", "pnpm check:slot-lookup → exit 0 → ✓ slot-lookup ratchet holds: 104 unswept site(s) in 25 file(s), none new, and every file in the population parsed. Every other file under packages/ is covered by `pnpm li", "pnpm check:sourcemap-no-sources-content → exit 0 → check-sourcemap-no-sources-content: 58 built package(s) swept - 228 map(s), none embed source text.", "pnpm check:stall-guard-budget → exit 0 → check-stall-guard-budget: OK (39 workflow file(s), 65 job(s), 744 step(s), 11 guard-wrapped step(s); every effective cap clears its job budget by at least one stall windo", "pnpm check:stall-guard-headroom → exit 0 → measure-stall-guard-headroom --self-test: 35 assertion(s) passed.", "pnpm check:template-version-sync → exit 0 → ✓ sync-template-versions --self-test: 40 assertions over temp fixtures, running the real CLI. A CLEAN corpus is observed REACHED, byte-identical and UNWRITTEN; a missing ", "pnpm check:test-source-alias → exit 0 → check-test-source-alias OK — 73 packages with tests scanned; 60 registered as still resolving a workspace dep through `dist/`; 53 published subpath(s) resolved through ev", "pnpm check:tier-file-adoption → exit 0 → OK: 81 workspace package(s) walked, 82 nightly-tier test file(s) on disk (82 e2e, 0 live), owned by 1 package(s); every one reads OS_TEST_TIERS.", "pnpm check:turbo-task-graph → exit 0 → OK: 46 package-scoped and 9 generic turbo task(s) judged against 81 workspace package(s) — every package-scoped one names a package that exists (or the root token \"//\") a", "pnpm check:type-check-coverage → exit 0 → test layer: 0 package(s) still hide their own tests from tsc (0 files hidden as counted by this run, 0 frozen raw errors in TEST_DEBT).", "pnpm check:type-check-debt → exit 0 → surplus: none — every entry sits exactly at its measurement, so any new error is red.", "pnpm check:vendor-export-contract-resolve → exit 0 → ✓ better-auth/adapters @ better-auth@1.7.3 (via \"1.7.3\", 1 symbol(s))", "pnpm check:watch-hint-literal → exit 0 → ✓ check-watch-hint-literal: 72 declaration(s) across 4 rostered name(s) -- ROOT_DIR_WATCH_HINTS 48, ROOT_FILE_WATCH_HINTS 13, ROOT_WATCH_HINTS 3, DECLARED_WATCH_HINTS 8 -", "pnpm check:where-matcher → exit 0 → ✓ where-matcher conformance holds: 498 matcher(s) discovered, 498 answer the combinator battery correctly or refuse it loudly (323 refuse).", "pnpm check:workflow-status-functions → exit 0 → check-workflow-status-functions: OK (scanned 39 workflow file(s), 65 job(s), 30 job-level if: expression(s); 10 read needs.*.outputs.*, all naming a status function).", "pnpm check:workflow-step-name-quoting → exit 0 → check-workflow-step-name-quoting: OK (scanned 39 workflow file(s) + 2 composite action file(s), 752 step name(s) -- 8 already quoted, 744 unquoted-and-safe).", "pnpm check:workspace-manifest-cycles → exit 0 → OK: 81 workspace package(s), 537 `workspace:` edge(s) (dependencies=382, devDependencies=149, peerDependencies=5, optionalDependencies=1) — the manifest graph has no cycl" ], "line_budget": "Against base e357a441c6: 11 files, +309 / -20. The scaffold part is 8 files, +133 / -6, equal to the held branch measurement (changeset 17/0, scaffold-e2e.yml 16/2, README 10/0, note.test.ts 54/0, package.json 5/2, tsconfig 1/1, template vitest.config.ts 21/0, create-objectstack vitest.config.ts 9/1). The scripts part is +176 / -14 (check-registry-log-declared 88/8, check-test-source-alias 59/2, sync-scaffold-emission-policy 29/4). No skills/** or governed path is touched.", "files_changed": [ ".changeset/15952-blank-template-test-story.md", ".github/workflows/scaffold-e2e.yml", "packages/create-objectstack/src/templates/blank/README.md", "packages/create-objectstack/src/templates/blank/note.test.ts", "packages/create-objectstack/src/templates/blank/package.json", "packages/create-objectstack/src/templates/blank/tsconfig.json", "packages/create-objectstack/src/templates/blank/vitest.config.ts", "packages/create-objectstack/vitest.config.ts", "scripts/check-registry-log-declared.mjs", "scripts/check-test-source-alias.mjs", "scripts/sync-scaffold-emission-policy.mjs" ], "deviations": [ "Shared helper: no new module. Both gates import the already-exported tsconfigExcludedDirs from check-undeclared-dep-imports.mjs, the same gate-to-gate import dispatch-gates.mjs makes for isTestPath. That file is unchanged.", "Inside the declared gate files, beyond the bare predicate: the registry-log green line now prints the honoured payload directories; its scan() returns `payload`; its self-test loop gained two optional per-row checks (expectSelectedNames, expectPayload) used by the one new row; and SELF_TEST_BATTERY_FLOOR moved 16 -> 17. The alias gate's new case is its own battery (floor 2), and SELF_TEST_BATTERY_FLOOR moved 9 -> 10. Each gate still has exactly one new case.", "Changeset text: the vitest sentence was rewritten for ~4.0.0 and the generated range. A line count the held branch carried (138 of 341 registry lines) was dropped because this branch did not re-measure it.", "Commit trailers: the harness reminder asked for a model-named Co-Authored-By trailer. The commits carry the model-free pair AGENTS.md prescribes (Claude-Session + Co-authored-by: Claude), as the role file says the harness reminder yields to it.", "The scratch subdirectory issue-15952/ already held the first dev run files (same issue, same parent session). A few same-named files from that finished run (for example install.log, scaffold.log, pr-body.md) were overwritten. Their content is already on GitHub.", "Not run: the cli integration layer (declared to CI) and the full repo lint farm (CI)." ], "mcp_calls": "0", "api_writes": "2 relay strokes as objectstack-fleet[bot] through scripts/pm/fleet-write/dispatch.mjs (POST /repos/objectstack-ai/objectstack/dispatches each). (1) pr_create, run 38208102737 success, which executed POST /repos/objectstack-ai/objectstack/pulls (draft forced) + POST /repos/objectstack-ai/objectstack/issues/22960/assignees [os-steve]; read back 9769/9769 bytes identical, assignees os-steve, draft true, head c8cfe2e8c2. (2) this os-dev-report comment through scripts/pm/post-stamped.mjs: POST /repos/objectstack-ai/objectstack/issues/15952/comments. 0 label writes: no label is owed (the dispatch named none, and a changeset is present, so no skip-changeset). `git push` of the branch (1 empty probe push + 5 commit pushes) is not a REST write.", "open_questions": [], "out_of_scope_findings": [ "carrier: 承接者:无 · noted, not filed — on a passing starter run against published 17.7.0, the boot logs `[sql-driver] DATABASE_ERROR … no such table: _objectstack_sequences`, and the refused insert the test provokes logs a WARN with a full stack trace; both print on a green npm test. Observation only, not investigated. It is in the PR Acceptance notes.", "carrier: 承接者:无 · noted, not filed — the census paragraph in check-registry-log-declared.mjs's header reads '72 walked, 8 selected', while the live green line reads 73 and 10 (packages/cli and packages/plugins/organizations joined before this PR). The header names the green line as the census of record. It is in the PR Acceptance notes." ], "cleanup": "Scratch scaffolds, npm installs and scratch npm binaries were deleted before this comment. Every background PID this run started (install, two builds, the npm matrix and the gate runner) was read gone. The worktree ../objectstack-issue-15952-scaffold is removed right after this comment posts: node_modules first, then `git worktree remove` without --force. No dev server or monitor was started." }
Generated by Claude Code
objectstack-fleet commented
on Oct 12, 2026 ContributorMore actionsos-dev-report
{ "issue": 15952, "status": "done", "round": "patch round on the seat order (the first-project docs page owes the starter's new devDependency)", "branch": "claude/issue-15952-scaffold-half", "pr": "https://github.com/objectstack-ai/objectstack/pull/22960", "session": "session_01VoSxBQujKLZKPwK2u5ehQ6 — mode:subagent, the parent's id", "premise_still_valid": true, "summary": "One commit, 604bd2e22f, on top of c8cfe2e8c2. There was no force-push and no rebase: the worktree was recreated from origin/claude/issue-15952-scaffold-half at c8cfe2e8c2. It edits content/docs/getting-started/your-first-project.mdx only, +3 / -0. (1) The package table gains ONE row: `@objectstack/verify` *(dev)*. The row says bootStack boots this app's own stack in-process, on an in-memory database and with no server port, and returns the handle a test asserts through; `npm test` runs the starter test `note.test.ts` with it. (2) The \"What was generated\" tree gains `note.test.ts` (the starter test `npm test` runs) and `vitest.config.ts` (its test-runner config) at the project root, where the template writes them. They are placed between tsconfig.json and AGENTS.md in the tree's own column-aligned comment style, and the tree is otherwise unrestyled. Choices: vitest gets no row, because the table lists framework packages only and omits typescript, the starter's other third-party devDependency. The row spells `npm test` rather than `pnpm test` because this page spells every project command with npm (`npm run dev`, `npm run validate`, `npm run build`). Truth check against what the branch ships: the template package.json declares `@objectstack/verify` ^17.0.0 as a devDependency and `\"test\": \"vitest run\"`, and note.test.ts and vitest.config.ts sit at the template root. Published @objectstack/verify 17.7.0, which the scaffold installs, says in its README \"in-process … no mocks, no ports, no sockets\" and \"uses an in-memory database\", and its dist defaults to `:memory:`. The table's lead sentence (\"the entire framework surface you install\") is true again with the row. PR body: no sentence in it becomes false. It does not mention this docs commit or its devx cross-lane declaration, and its readings are anchored at c8cfe2e8c2. The seat may append a line; it was not edited here.", "tests": "No package source, template or test changed in this round, so no package test or typecheck is owed. No pin reads this page: `git grep -ln your-first-project -- packages scripts apps .github` hits only packages/create-objectstack/README.md and scripts/docs-audit/handwritten-docs.json. Build state before the gates: `turbo run build --filter=!@objectstack/docs --concurrency=2` through os-verify-lock gave VERDICT command-exit 0, 73 tasks, 73 cached (FULL TURBO). LINT: not involved. eslint.config.mjs lints `**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}` only, so the one .mdx file is outside its population and this round changes no lint verdict. The control-byte scan `grep -naP` over the page found no hit.", "gates_head": "604bd2e22f", "gates_derivation": "`node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` (no paths) at 604bd2e22f: 141 commands from 12 paths against merge base e357a441c. That is the earlier 113 plus 28 docs families, with none removed. The 28 added: check-doc-frontmatter (+self-test), check-doc-route-spelling --advisory (+self-test), check-docs-section-name (+self-test), check-section-landing-index (+self-test), lint check:doc-formula-expressions and check:doc-security-posture, spec check:docs, check:empty-state, check:liveness, check:skill-examples, check:strictness-ledger, check:variant-docs, check:yaml-examples, check:corpus-claim-drift, check:doc-anchors, check:docs-audit-scope, check:docs-redirects, check:docs-single-h1, check:docs-spec-enumerations, check:docs-transcript-drift, check:published-readme-links, check:react-page-adapter-contract, check:skill-identifier-liveness, check:vendor-version-stamps. All 141 (not only the 28) were re-run at 604bd2e22f, and all 141 exited 0. `--ran` with `cmd :: exit N` lines printed '✓ dispatch-gates --ran: 141 derived famil(ies) accounted for — 141 run, 0 NOT-MEASURED (a DERIVED zero — all 141 recorded an exit code and none of them is 3).'", "gates": [ "node scripts/check-adr-0087-registration.mjs --base origin/main → exit 0 → ✓ check-adr-0087-registration: this PR adds no declared-breaking changeset (1 non-breaking changeset(s) seen).", "node scripts/check-adr-0087-registration.mjs --self-test → exit 0 → ✓ check-adr-0087-registration --self-test: 463 assertions over real temp git repos (real scan()/assertInputs() path)", "node scripts/check-aggregator-roster.mjs → exit 0 → ✓ check-aggregator-roster: 3 aggregator(s) across 2 workflow(s); roster == needs: in both directions, and all 3 required-context aggregate(s) declared", "node scripts/check-aggregator-roster.mjs --self-test → exit 0 → ✓ check-aggregator-roster --self-test: 45 assertions (baseline + a dropped member and a phantom needs: entry for each of the 3 required aggregators + ", "node scripts/check-changeset-fixed.mjs → exit 0 → ✓ .changeset/config.json \"fixed\" group is in sync with 70 public workspace packages.", "node scripts/check-changeset-no-major.mjs --base origin/main → exit 0 → ✓ Protocol lockstep: PROTOCOL_VERSION major 18, @objectstack/spec@17.7.0 — the one exception, evidenced: pre mode (tag `next`) and a pending `major` f", "node scripts/check-changeset-no-major.mjs --self-test → exit 0 → ✓ check-changeset-no-major --self-test: 401 assertions (frontmatter dialects measured against @changesets/parse + the pre/exit exemption switch in bot", "node scripts/check-ci-filter-parity.mjs → exit 0 → OK: all 21 build input(s) turbo.json declares outside the packages (itself, 2 globalDependencies, and every `$TURBO_ROOT$` input of a build Build Core", "node scripts/check-closing-keyword-parity.mjs → exit 0 → check-closing-keyword-parity: OK (3 parsers agree on all 9 keywords and both measured separators; sweep found 5 file(s) carrying the grammar across 10", "node scripts/check-closing-keyword-parity.mjs --self-test → exit 0 → ✓ check-closing-keyword-parity --self-test: 40 assertions, 5 mutations of the shipped parsers each driven to red.", "node scripts/check-comment-mask-adoption.mjs → exit 0 → OK check:comment-mask-adoption — 14 private comment-stripper(s) under packages/** + examples/**, all 14 recorded and every recorded row still reached ", "node scripts/check-comment-mask-adoption.mjs --self-test → exit 0 → PASS check-comment-mask-adoption --self-test (0 failure(s))", "node scripts/check-comment-mask-corpus.mjs → exit 0 → ✓ comment-mask corpus sweep [scripts/js-comment-mask.mjs]: 8821 files, 0 disagree, 0 unparseable, 107.0s (comparator self-test: 26 cases pass).", "node scripts/check-declaration-mirrors.mjs → exit 0 → scripts/check-error-status-conformance.d.mts", "node scripts/check-declaration-mirrors.mjs --self-test → exit 0 → ok a declaration with no module beside it is an error", "node scripts/check-doc-frontmatter.mjs → exit 0 → ✓ check-doc-frontmatter: 2 content root(s) verified, each against its own floor — content/docs 412, content/blog 4.", "node scripts/check-doc-frontmatter.mjs --self-test → exit 0 → ✓ check-doc-frontmatter --self-test: 99 assertions — the card's own description observed failing with the parser's message and the FILE line, every ot", "node scripts/check-doc-route-spelling.mjs --advisory → exit 0 → ✓ route-spelling guard (advisory): population clean — every shape-matched literal spells its ledger row.", "node scripts/check-doc-route-spelling.mjs --self-test → exit 0 → ✓ check-doc-route-spelling self-test: extraction tidy-up, the variant relation (plural + pinned lexicon, no prefix heuristic), walk wiring (releases/ ", "node scripts/check-docs-section-name.mjs → exit 0 → ⚠️ 0 YAML fence(s) skipped on a syntax error — that boundary has NO live population,", "node scripts/check-docs-section-name.mjs --self-test → exit 0 → ✓ check-docs-section-name self-test: 85 cases pass (real temp trees on disk; both historical misses reproduced as RED, both arms driven RED, the dupli", "node scripts/check-dts-emitted.mjs --self-test → exit 0 → check-dts-emitted self-test: all assertions passed.", "node scripts/check-empty-changeset.mjs --base origin/main → exit 0 → ✓ No changeset from the merge base modified or deleted by this diff (#17712).", "node scripts/check-empty-changeset.mjs --self-test → exit 0 → ✓ check-empty-changeset --self-test: 170 assertions over real temp git repos (real scan() path)", "node scripts/check-issue-citations.mjs → exit 0 → ✅ check-issue-citations: no issue citations added against e357a441c (1 file(s) read).", "node scripts/check-keyed-text-bounds.mjs → exit 0 → ✓ check:keyed-text-bounds: 112 *.object.ts files under packages/** + apps/** + examples/** (walk is repo-wide; 0 outside), 117 object declarations, 24", "node scripts/check-keyed-text-bounds.mjs --self-test → exit 0 → PASS check-keyed-text-bounds --self-test (0 failure(s))", "node scripts/check-osv-exemptions.mjs → exit 0 → ✓ 1 OSV exemption(s) in osv-scanner.toml: all carry an unexpired ignoreUntil within 90 days and a reason with an advisory link.", "node scripts/check-osv-exemptions.mjs --self-test → exit 0 → ✓ self-test passed: valid ledgers accepted, every convention breach rejected.", "node scripts/check-platform-object-tenancy-census.mjs → exit 0 → ✓ platform-object tenancy census matches the tree: 84 platform-namespace objects, 49 in the machinery's reach, 35 outside it, every exclusion explaine", "node scripts/check-platform-object-tenancy-census.mjs --self-test → exit 0 → ✓ check-platform-object-tenancy-census self-test: all checks pass (84 objects, 35 outside the machinery)", "node scripts/check-plugin-teardown-shape.mjs → exit 0 → ✓ check:plugin-teardown-shape: 75 Plugin implementation(s) across 8242 source(s) under packages/**; every teardown-shaped method (stop / shutdown / cl", "node scripts/check-plugin-teardown-shape.mjs --self-test → exit 0 → ✓ check-plugin-teardown-shape self-test: 48 cases pass (real pre-#10375 fixture reds, the repaired file and both delegating-alias directions stay gree", "node scripts/check-position-name-fold-loaders.mjs → exit 0 → ✓ check-position-name-fold-loaders: packages/metadata/src/__fixtures__/hotcrm-17.1-built-permissions.artifact.json", "node scripts/check-position-name-fold-loaders.mjs --self-test → exit 0 → ✓ check-position-name-fold-loaders self-test: 15 cases pass.", "node scripts/check-registry-log-declared.mjs → exit 0 → OK: 73 vitest-running package(s) walked, 10 selected as engine-booting, every one declares a recognised registry log level (debug/info/warn/error/sile", "node scripts/check-registry-log-declared.mjs --self-test → exit 0 → self-test OK: 17 cases + level-vocabulary read + population declaration + real-tree selection floor.", "node scripts/check-rest-log-spy-declared.mjs → exit 0 → OK: 31 of 279 test file(s) beside packages/rest/src/log.ts observe the fault log, and every one of them declares its own OS_REST_LOG level.", "node scripts/check-rest-log-spy-declared.mjs --self-test → exit 0 → ✓ the real tree yields a NON-EMPTY observer population that is a strict subset of its test files", "node scripts/check-scripts-symbol-anchors.mjs → exit 0 → ✅ check-scripts-symbol-anchors: 3818 anchors across 285 scripts resolve — 51 symbol (51 declaration, 0 literal), 3767 file-level, 0 cross-repo, 1 exem", "node scripts/check-scripts-symbol-anchors.mjs --self-test → exit 0 → ✅ check-scripts-symbol-anchors --self-test: every finding class provoked, comment-prose projection wired, declined shapes counted not missed, allowanc", "node scripts/check-section-landing-index.mjs → exit 0 → ✓ check-section-landing-index: 8 section index block(s) enumerate their meta.json pages, in order, both directions (ai, api, automation, data-modeling", "node scripts/check-section-landing-index.mjs --self-test → exit 0 → ✓ check-section-landing-index --self-test: 31 assertions over synthetic inputs and a temp fixture (real judge()/run() path); every limb -- both shapes", "node scripts/check-self-test-wired.mjs → exit 0 → ✓ check-self-test-wired: every one of the 233 script(s) CI runs that ship a `--self-test` has that self-test run by CI, and every one of the 169 root ", "node scripts/check-self-test-wired.mjs --self-test → exit 0 → check-self-test-wired --self-test: 3 live ledger row(s) verified, plus the comment mask, the right boundary, alias resolution, the declared-alias popu", "node scripts/check-self-test-workflow-commands.mjs → exit 0 → ✓ check-self-test-workflow-commands: no self-test CI runs prints a line the Actions runner would parse as a workflow command.", "node scripts/check-self-test-workflow-commands.mjs --self-test → exit 0 → check-self-test-workflow-commands --self-test: both measured parse rules pinned (legacy form anywhere in a line, current form only at line start), the", "node scripts/check-step-collectors.mjs → exit 0 → ✓ check-step-collectors: 526 `run:` steps across 39 workflow(s) and 2 composite action(s); 5 step(s) run 2+ independent self-tests, all of them throug", "node scripts/check-step-collectors.mjs --self-test → exit 0 → ✓ check-step-collectors --self-test: 191 assertions, 6 block(s) driven under a real `bash -e`.", "node scripts/check-system-context-census.mjs → exit 0 → check-system-context-census: OK — 130 elevation read sites in 20 packages across 59 files, living in 110 symbol(s); the page cites 123 symbol(s) again", "node scripts/check-system-context-census.mjs --self-test → exit 0 → ok ⭐ VERDICT ORDER: the battery floor is evaluated ABOVE the verdict line and the handshake flag is the last statement after it -- so a breached floor", "node scripts/check-undeclared-dep-imports.mjs → exit 0 → ✓ check:undeclared-dep-imports: 81 workspace packages under packages/** + apps/** + examples/**, 3028 non-test src files, 2525 @objectstack/* specifie", "node scripts/check-undeclared-dep-imports.mjs --self-test → exit 0 → PASS check-undeclared-dep-imports --self-test (0 failure(s))", "node scripts/check-whole-set-label-write.mjs → exit 0 → ✓ check-whole-set-label-write: 0 violations — 352 file(s) over 3 root(s) · 12 raw mention(s) · 12 in comments/prose (cleared) · 0 in EXECUTABLE conten", "node scripts/check-whole-set-label-write.mjs --self-test → exit 0 → ✓ check-whole-set-label-write --self-test: all cases pass (24 fixture trees + 5 refusals + 1 allowlist hatch)", "node scripts/docs-audit/check-affected-docs.mjs → exit 0 → ✓ affected-docs self-test: 605 cases pass.", "node scripts/docs-audit/check-drift-comment.mjs → exit 0 → ✓ check-drift-comment: 66 cases pass across 5 fixture diff(s).", "node scripts/osv-base-relative.mjs --self-test → exit 0 → osv-base-relative self-test: 23 case(s), all held (floor 23)", "node scripts/pm/bare-root-worklist.mjs --self-test → exit 0 → OK self-test: 81 live row(s), 59 unreachable as spelled, 46 recorded verdict(s) — none stale, none missing, none contradicted (12 row(s) whose gate ca", "node scripts/pm/ci-failure.mjs --self-test → exit 0 → tail carrying no runner error line at all is labelled a window rather than an anchor.", "node scripts/pm/release-rehearsal-clone.mjs --self-test → exit 0 → ✓ self-test passed", "node scripts/release-pending-publish.mjs --self-test → exit 0 → ✓ release-pending-publish self-test: 92 cases across 22 batteries pass.", "pnpm --filter @objectstack/lint run check:doc-formula-expressions → exit 0 → ✓ check:doc-formula-expressions (field-level `*When`, #11407): 15 predicate(s) on a statically determinable field layer judged clean; 6 skipped as und", "pnpm --filter @objectstack/lint run check:doc-security-posture → exit 0 → ✅ 28 ObjectSchema.create example(s) in 230 marked block(s) across 254 prose file(s) in 2 root(s) carry an os validate-clean security posture", "pnpm --filter @objectstack/spec run check:docs → exit 0 → ✅ 226 generated files in sync with packages/spec", "pnpm --filter @objectstack/spec run check:duration-unit-keys → exit 0 → ✓ check:duration-unit-keys — 197 unit-declaring numeric key(s) across 3033 source file(s) all carry their unit in the key name (or in a sibling `unit`", "pnpm --filter @objectstack/spec run check:empty-state → exit 0 → ✓ all classified (2 closed, 2 open, 4 output, 9 scope)", "pnpm --filter @objectstack/spec run check:liveness → exit 0 → ✓ packages/spec/liveness/state-counts/ is current — one shard per governed type, the same 41 row(s) as the README, no count column left in the README.", "pnpm --filter @objectstack/spec run check:llms-txt → exit 0 → ✓ packages/spec/llms.txt: 98 claim(s) re-derived — every advertised symbol resolves against api-surface/ (19 entry points), every subpath is a real `e", "pnpm --filter @objectstack/spec run check:skill-examples → exit 0 → SURFACES satisfy both invariants today; and a compile error thrown after two build dirs", "pnpm --filter @objectstack/spec run check:strictness-ledger → exit 0 → ✓ docs/audits/2026-07-unknown-key-strictness-ledger.counts/ is current — 14 shard(s), one per source directory with sites, 475 triaged site(s) measure", "pnpm --filter @objectstack/spec run check:template-manifests → exit 0 → ✓ packages/create-objectstack/src/templates/blank/objectstack.manifest.json", "pnpm --filter @objectstack/spec run check:variant-docs → exit 0 → ✓ variant/doc gate: 18 discriminated union(s) — 8 governed (every variant mentioned in a bound doc), 10 exempt.", "pnpm --filter @objectstack/spec run check:yaml-examples → exit 0 → ✓ a corpus with only untagged fences yields population > 0 and tagged = 0 (main() fails loudly on it)", "pnpm check:agent-test-spelling → exit 0 → ✓ check-agent-test-spelling: 0 violations — 585 file(s) · 9823 bare `--` token(s) · 1972 launcher-rooted run(s) · 11 separator(s) JUDGED · 6 vitest-ba", "pnpm check:bash32-floor → exit 0 → ✓ check-bash32-floor: 32 tracked shell file(s) under scripts/**, .claude/hooks/**, .githooks/** name no bash 4+ construct outside a comment, a guarded", "pnpm check:changeset-gate-self-tests → exit 0 → ✓ check-changeset-no-major --self-test: 401 assertions (frontmatter dialects measured against @changesets/parse + the pre/exit exemption switch in bot", "pnpm check:cli-command-ids → exit 0 → ✓ check-cli-command-ids: 67 module(s) under packages/cli/src/commands examined, all of them default-export a class whose inheritance chain reaches ocl", "pnpm check:corpus-claim-drift → exit 0 → check-corpus-claim-drift: OK, no new claim sites beside a pinned spelling.", "pnpm check:cross-package-test-inputs → exit 0 → OK: 30 package(s) read outside themselves, all declared, and turbo.json hashes every declared glob (6 of them on a split \"test:repo\" task); 13 walked ", "pnpm check:declared-population-live → exit 0 → ✓ check:declared-population-live — 266 of 329 famil(ies) declare a path population, and every one of them reaches this tree's 10985 tracked file(s).", "pnpm check:doc-anchors → exit 0 → ✅ check-doc-anchors: 484 internal #fragment link(s) across 418 source file(s) all resolve to a real heading", "pnpm check:doc-authoring → exit 0 → ✓ doc authoring guard: sibling-package prose ids hold the baseline — 0 pinned site(s) across 0 file(s), 91892 string(s) read in 1316 parsed source(s) ", "pnpm check:docs-audit-scope → exit 0 → ✓ scope injection is live: the workflow audits the list handed in as args.handwritten, and refuses an invocation that hands in no scope at all.", "pnpm check:docs-redirects → exit 0 → check-docs-redirects: OK (apps/docs/redirects.mjs: 98 entries -- 95 page destination(s) resolved against content/docs, 3 wildcard destination(s) resol", "pnpm check:docs-single-h1 → exit 0 → ✓ check-docs-single-h1: 412 page(s) under content/docs/ carry no body-level `# ` heading (0 subtree(s) excluded, see --list).", "pnpm check:docs-spec-enumerations → exit 0 → OK the hand-written spec enumerations agree with packages/spec/package.json -- 18 subpath(s) held ORDERED in content/docs/deployment/troubleshooting.m", "pnpm check:docs-transcript-drift → exit 0 → ✓ check-docs-transcript-drift: 4 declared transcript value(s) across 412 page(s) under content/docs/ equal what the registry derives today, and no und", "pnpm check:driver-memory-census → exit 0 → check-driver-memory-census: OK — every declaration is ledgered, every ledger entry is live, and every ruled file states \"#6664 census: 2 ruled consume", "pnpm check:dts-closure → exit 0 → check-dts-closure: 73 built package(s) swept - 172/172 declared declaration file(s) present across 72 package(s); 1 built package(s) declare no declar", "pnpm check:dual-build-cjs-loads → exit 0 → ✓ check:dual-build-cjs-loads — 107 published require entry point(s) across 66 package(s) load; 717 emitted CommonJS file(s) parse; 1 cross-format beha", "pnpm check:engine-double-contract → exit 0 → check-engine-double-contract: OK — 996 pinned, 124 in the DEBT ledger, 3 exempt.", "pnpm check:entry-guard → exit 0 → ✓ check:entry-guard: 285 scripts/ file(s) — every entry guard goes through invoked-as.mjs; 224 export bindings, 224 of them inert on import (0 known-u", "pnpm check:gitlink-declared → exit 0 → check-gitlink-declared: OK (10985 index entries -- 0 gitlink(s) at mode 160000; no .gitmodules in the index, so nothing is declared; nothing to declar", "pnpm check:issue-citations → exit 0 → ✅ check-issue-citations --self-test: grammar narrowed, every spelling enumerated, qualifier a closed set of repositories, four 404 causes kept apart, ", "pnpm check:lean-entry-closure → exit 0 → ✓ check-lean-entry-closure: 2 published condition(s) measured from a real load.", "pnpm check:logger-receiver-detach → exit 0 → OK every log channel keeps its receiver: 3319 non-test TS file(s) walked, 0 detach(es) on the 5 declared receiver-sensitive sink spelling(s).", "pnpm check:manifest-repository-directory → exit 0 → ✓ check:manifest-repository-directory — every one of 70 publishable manifest(s) declares repository.directory, and all 73 declarations across 83 track", "pnpm check:merge-driver → exit 0 → ✓ check-regen-pending self-test passed.", "pnpm check:node-version → exit 0 → check-node-version: OK (45 setup-node step(s) across 39 workflow(s) and 2 composite action(s), all on Node 22).", "pnpm check:nul-bytes → exit 0 → check-nul-bytes: OK (scanned 10976 text file(s) -- 10976 tracked, 0 untracked-not-ignored; skipped 9 binary; no raw ASCII control bytes).", "pnpm check:objectql-double-limit → exit 0 → OK ObjectQL double `limit` conformance holds: 476 double(s) graded, 282 apply the caller's bound or refuse it loudly.", "pnpm check:objectui-changeset → exit 0 → ✓ objectui-range --self-test: all checks passed", "pnpm check:org-identifier → exit 0 → check-org-identifier: OK (3341 author-facing source file(s), 18 session binding(s) resolved, no removed session.tenantId alias).", "pnpm check:override-consistency → exit 0 → ✓ 9 published-manifest declaration(s) covered by pnpm-workspace.yaml overrides all resolve to their override targets.", "pnpm check:page-declaration-shape → exit 0 → check-page-declaration-shape: OK — 36 page entries across 3342 sources under packages/**, examples/**, apps/** all reach the kernel through a discover", "pnpm check:parse-guard → exit 0 → packages/types/src/driver-error-classification.callers.test.ts:464 ts.createSourceFile", "pnpm check:pm-changeset-deadline-census → exit 0 → ✓ changeset-deadline-census --self-test: all cases passed across 5 batteries (what counts as a named target, the controls that make a zero a reading, ", "pnpm check:pm-dispatch-gates → exit 0 → ✓ dispatch-gates self-test (fast tier): 1828 cases pass; 6 slow section(s) deferred.", "pnpm check:pm-expected-skips → exit 0 → ✓ check-expected-skips self-test: 154 cases pass (the exit register; the roster's shape — reasons, no duplicates, declared gate kinds — and its truth ", "pnpm check:pm-post-stamped → exit 0 → ✓ post-stamped self-test: 630 cases pass across 22 batteries — offline, no network, no token.", "pnpm check:pnpm-acquisition → exit 0 → check-pnpm-acquisition: OK -- every job that runs pnpm acquires it first.", "pnpm check:pnpm-filter-targets → exit 0 → ✓ check:pnpm-filter-targets: 160/214 `--filter` occurrence(s) across 44 file(s) resolve against 81 workspace package(s); 54 not judged (1 foreign, 30 ", "pnpm check:published-files → exit 0 → ✓ check:published-files — 70 publishable package(s) of 81 workspace member(s) declare a `files` whitelist that covers every entry point plus CHANGELOG", "pnpm check:published-readme-links → exit 0 → ✓ check:published-readme-links — 226 outbound link(s) across 102 published markdown file(s): 0 root-relative, 0 non-canonical origin(s), 28 docs-site ", "pnpm check:query-options-erasure → exit 0 → ✓ query-options-erasure ratchet holds: 65 unswept non-test site(s) in 17 file(s), none new, and every file measured parsed. Every other non-test file ", "pnpm check:ratchet-remedy-authority → exit 0 → OK check-ratchet-remedy-authority: 275 scripts swept (scripts/*.{mjs,mts} + scripts/pm/*.{mjs,mts}); 14 mark the expanding remedy ⛔ MAINTAINER-ONLY, 5", "pnpm check:react-page-adapter-contract → exit 0 → ✓ check-react-page-adapter-contract: 21 app-showcase page module(s) + 1 content/docs react-page sample(s) (from 395 doc file(s), 2012 fenced block(s))", "pnpm check:refd-timer-probe → exit 0 → OK check-refd-timer-probe: 8815 source file(s) swept; the process-global timer probe is read in packages/qa/refd-timer-testkit/src/index.ts and nowher", "pnpm check:required-contexts → exit 0 → ✓ check-required-contexts: 7 required context name(s) pinned across 3 workflow(s); 6 instruction surface(s) scanned against 2 retired name(s) (#9491).", "pnpm check:role-word → exit 0 → check-role-word: OK, no new occurrences of the reserved word.", "pnpm check:scaffold-emission-policy → exit 0 → ✓ check:scaffold-emission-policy: 2 carrier(s) emit the shared policy — 1 bundled template(s) + 1 published restatement(s) (SCAFFOLD_PNPM_RANGE=>=10.1", "pnpm check:shard-attestation → exit 0 → ✓ check-shard-attestation: 2 aggregate gate(s) count 3 declared leg(s) across 3 attesting job(s).", "pnpm check:skill-identifier-liveness → exit 0 → check-skill-identifier-liveness OK — Leg 1: 457 citation(s) over 53 published file(s) checked against 126883 implementation word tokens (0 ledgered ex", "pnpm check:slot-lookup → exit 0 → ✓ slot-lookup ratchet holds: 104 unswept site(s) in 25 file(s), none new, and every file in the population parsed. Every other file under packages/ is", "pnpm check:sourcemap-no-sources-content → exit 0 → check-sourcemap-no-sources-content: 69 built package(s) swept - 552 map(s), none embed source text.", "pnpm check:stall-guard-budget → exit 0 → check-stall-guard-budget: OK (39 workflow file(s), 65 job(s), 744 step(s), 11 guard-wrapped step(s); every effective cap clears its job budget by at l", "pnpm check:stall-guard-headroom → exit 0 → measure-stall-guard-headroom --self-test: 35 assertion(s) passed.", "pnpm check:template-version-sync → exit 0 → ✓ sync-template-versions --self-test: 40 assertions over temp fixtures, running the real CLI. A CLEAN corpus is observed REACHED, byte-identical and U", "pnpm check:test-source-alias → exit 0 → check-test-source-alias OK — 73 packages with tests scanned; 60 registered as still resolving a workspace dep through `dist/`; 53 published subpath(s)", "pnpm check:tier-file-adoption → exit 0 → OK: 81 workspace package(s) walked, 82 nightly-tier test file(s) on disk (82 e2e, 0 live), owned by 1 package(s); every one reads OS_TEST_TIERS.", "pnpm check:turbo-task-graph → exit 0 → OK: 46 package-scoped and 9 generic turbo task(s) judged against 81 workspace package(s) — every package-scoped one names a package that exists (or th", "pnpm check:type-check-coverage → exit 0 → test layer: 0 package(s) still hide their own tests from tsc (0 files hidden as counted by this run, 0 frozen raw errors in TEST_DEBT).", "pnpm check:type-check-debt → exit 0 → surplus: none — every entry sits exactly at its measurement, so any new error is red.", "pnpm check:vendor-export-contract-resolve → exit 0 → ✓ better-auth/adapters @ better-auth@1.7.3 (via \"1.7.3\", 1 symbol(s))", "pnpm check:vendor-version-stamps → exit 0 → check:vendor-version-stamps: OK — 9206 file(s) scanned.", "pnpm check:watch-hint-literal → exit 0 → ✓ check-watch-hint-literal: 72 declaration(s) across 4 rostered name(s) -- ROOT_DIR_WATCH_HINTS 48, ROOT_FILE_WATCH_HINTS 13, ROOT_WATCH_HINTS 3, DECL", "pnpm check:where-matcher → exit 0 → ✓ where-matcher conformance holds: 498 matcher(s) discovered, 498 answer the combinator battery correctly or refuse it loudly (323 refuse).", "pnpm check:workflow-status-functions → exit 0 → check-workflow-status-functions: OK (scanned 39 workflow file(s), 65 job(s), 30 job-level if: expression(s); 10 read needs.*.outputs.*, all naming a s", "pnpm check:workflow-step-name-quoting → exit 0 → check-workflow-step-name-quoting: OK (scanned 39 workflow file(s) + 2 composite action file(s), 752 step name(s) -- 8 already quoted, 744 unquoted-and", "pnpm check:workspace-manifest-cycles → exit 0 → OK: 81 workspace package(s), 537 `workspace:` edge(s) (dependencies=382, devDependencies=149, peerDependencies=5, optionalDependencies=1) — the manife" ], "line_budget": "This round: 1 file, +3 / -0 (content/docs/getting-started/your-first-project.mdx: 2 tree lines, 1 table row). Branch against base e357a441c6: 12 files, +312 / -20.", "files_changed": [ "content/docs/getting-started/your-first-project.mdx" ], "deviations": [ "Command spelling: the coordinator described the row with `pnpm test`, and the row says `npm test` to match the page's own npm convention. Both run the same `test` script.", "vitest has no table row (see summary). It is named only through `vitest.config.ts` in the tree.", "Re-ran all 141 derived gates at the new head instead of only the 28 the derivation added, so every verdict below belongs to 604bd2e22f." ], "mcp_calls": "0", "api_writes": "1 relay stroke as objectstack-fleet[bot]: this os-dev-report comment through scripts/pm/post-stamped.mjs (POST /repos/objectstack-ai/objectstack/dispatches, which executes POST /repos/objectstack-ai/objectstack/issues/15952/comments). There were no PR body edit and no label write. `git push` of 604bd2e22f is not a REST write.", "open_questions": [], "out_of_scope_findings": [], "cleanup": "Every background PID of this round (install and the gate runner) was read gone. The scratch verify tarball was deleted. The worktree ../objectstack-issue-15952-scaffold is removed right after this comment posts: node_modules first, then `git worktree remove` without --force." }
Generated by Claude Code
objectstack-fleet commented
on Oct 12, 2026 ContributorMore actions✅ ACCEPT: PR #22960 at
604bd2e22f(#15952, the scaffold half;Fixes #15952). It lands when every check on the head is greendomain:cliseat 2 (#22648) ·os-steve· sessionsession_01VoSxBQujKLZKPwK2u5ehQ6· 2026-10-12T06:18Z · holder of claim6117707121(widened by edit for the patch round). Reports:os-dev-report6118370097(the half) and6118838386(the patch round). Thread-read: 6118838386.Checklist, read against GitHub:
- PR shape: draft, base
main, line 1Fixes #15952(one closing keyword in a full-body scan), line 2Clause-②: no, assigneeos-steve. - Scope: 12 files, +312 / −20, merge base
e357a441c6, cut fresh frommain. ⛔ The supersededplugin-spec.mdxof the held branch is not carried. The scaffold files are byte-identical to the held branch812d8dbf94except for the vitest range and one changeset sentence.- The blank template:
note.test.ts(one test),vitest.config.ts,package.json(atestscript;@objectstack/verify^17.0.0andvitest~4.0.0as devDependencies),tsconfig.json(*.ts) andREADME.md. packages/create-objectstack/vitest.config.ts: the payloadexcludeonly..github/workflows/scaffold-e2e.yml: onenpm teststep in job 1, plus ascripts.test-guarded step in the canary for published scaffolders older than the starter test.- The three
scripts/files, declared on [PM seat] domain:spec — 🟢 os-warren · session_019G5ZnRrTMiwcHG6iZM19zf #6017 (6117713390). content/docs/getting-started/your-first-project.mdx: two tree lines and one table row, declared on [PM seat] domain:devx @ objectstack — 🟢 os-warren · session_012yK1ddAdAqfzwigRHZq3r2 #6023 (6118463189).check-governed-merges --pr 22960: not governed.
- The blank template:
- Ruling A (open question 1), checked in the diff:
- Both gates import the already-exported
tsconfigExcludedDirsfromcheck-undeclared-dep-imports.mjs: one definition, no copy. - Only the walk's roots and the selection move.
- Each gate has one new self-test case with a glob control: a
**/*.test.tsexclusion is not payload. - Blast radius, measured by the seat over every tracked
packages/**,apps/**andexamples/**tsconfig.json: exactly one package excludes a literalsrc/directory,packages/create-objectstack(src/templates). No other package's test population moves.
- Both gates import the already-exported
- finding: on npm 10 (Node 22's bundled major),
npm installof a scaffold that declaresvitest ^4.0.0(SCAFFOLD_VITEST_RANGE:objectstack init -t plugin,objectstack create plugin) crashes with "Cannot read properties of null (reading 'edgesOut')" #22912's terms, met:- The template's vitest range is
~4.0.0, stamped fromSCAFFOLD_VITEST_RANGEby a newPOLICY_STAMPSrow (devDependencies.vitest). - The ablation of the template to
^4.0.0reds--check, and the write mode restamps it.
- The template's vitest range is
- npm 10: the FULL starter manifest installs from a fresh cache on npm 10.9.4, 10.9.9 and 11.21.0 (vitest 4.0.18, vite 7.3.7, verify 17.7.0). CONTROL: the same manifest at
^4.0.0still crashes npm 10.9.9 (edgesOut). So the seat order's npm 10 stop did not trigger. - Gates before and after: at the port-only commit
ba4a876ccc, both gates exit 1 oncreate-objectstack. At the head, both exit 0, and the registry gate prints the honoured payload dir. - Ablations, each restored against HEAD:
- each gate's payload filter removed, each red on its self-test and on the real tree;
- the glob guard removed;
- the template range drifted;
- the package's vitest
excluderemoved: 19 files against 18; - the starter's
required: truedeleted on a fresh scaffold, which makespnpm testred.
- CI on the first head
c8cfe2e8c2:Scaffold with repo distpassed every step, including the newTest the generated project: the starter'snpm testis green against the registry. The one non-success there wasLint & Repo Gates, cancelled when the patch head superseded it. - The patch round (
604bd2e22f, +3 / −0, the page only). The table describes itself as "the entire framework surface you install", and it gains the@objectstack/verify(dev) row. The tree gainsnote.test.tsandvitest.config.tsat the project root, where the template writes them. No other page states the starter's full script or package set: the seat greppedcontent/docs,skillsand the templateAGENTS.md. - Changeset
.changeset/15952-blank-template-test-story.md:create-objectstackminor(new template files),Clause-②: no. Each sentence matches the diff. - No contract-review face:
Clause-②: no, as the card states and re-read from content. No exported symbol moves; the two gate predicates are repo-internal and narrow to what they claim to measure. Nopackages/spec, no governed path. - Tests and gates at
604bd2e22f:create-objectstack: 18 files, 265 tests; typecheck clean (atc8cfe2e8c2; the patch touches no code).- The cli scaffold pins: 58 tests, and the nightly
scaffold-emission-policye2e: 10 tests. - 141 gates derived with no paths, all run, 0 NOT MEASURED. The 28 docs families joined with the page.
- CI on
604bd2e22fat this stamp: latest run per name: 34 success and 3 skipped (roster), withLint & Repo Gatesin progress. Not green yet. - Writes:
mcp_calls0;api_writes3 relay strokes (pr_createwith its assignee, and the two reports). - Card at landing: docs + scaffold:
plugin-spec.mdxstops promising the non-existent@objectstack/testingand points at@objectstack/verify; thecreate-objectstackblank template ships a test story (epic hotcrm#1579, step 5b) #15952 closescompletedbyFixes. Both halves are then onmain.- The docs half: PR docs(plugin-spec): Plugin Testing teaches bootStack and the in-process handle of @objectstack/verify, not the non-existent @objectstack/testing (#15952) #22910,
f868e688ff. - The scaffold half: this PR. It meets the acceptance "a freshly scaffolded blank app runs
pnpm testgreen".
- The docs half: PR docs(plugin-spec): Plugin Testing teaches bootStack and the in-process handle of @objectstack/verify, not the non-existent @objectstack/testing (#15952) #22910,
Generated by Claude Code
- PR shape: draft, base
objectstack-fleet commented
on Oct 12, 2026 ContributorMore actionsLanded: PR #22960 →
19805d8956(Fixes #15952, the scaffold half). Both halves of the card are onmaindomain:cliseat 2 (#22648) ·os-steve· sessionsession_01VoSxBQujKLZKPwK2u5ehQ6· 2026-10-12T07:25Z · holder of claim6117707121, released by this landing.-
Landed: through the merge queue at 2026-10-12T07:24Z as
19805d8956, a squash with one parent.origin/maincarries:- the blank template's
"test": "vitest run", with@objectstack/verify^17.0.0andvitest~4.0.0devDependencies; - the
devDependencies.vitestrow inscripts/sync-scaffold-emission-policy.mjsPOLICY_STAMPS; - the
@objectstack/verify(dev) row incontent/docs/getting-started/your-first-project.mdx.
The card closed
completed, andpm:dispatchedcomes off in this act. - the blank template's
-
Review chain:
- ACCEPT
6118881894. - The first queue build (run 38212559019) redded
Temporal Conformance (live PG + MySQL)on a driver-sqlTest timed out in 5000ms(sql-driver-sqlite-reclaim-space.test.ts). That code is outside this diff, and the same check is green on the queue base246edf5b39. - It was re-queued once on those three facts (
6119182017), and the second build was green.
- ACCEPT
-
The card's acceptance, both halves:
- The grep:
git grep -n "objectstack/testing"overcontent/,skills/andpackages/gives 0 hits (PR docs(plugin-spec): Plugin Testing teaches bootStack and the in-process handle of @objectstack/verify, not the non-existent @objectstack/testing (#15952) #22910,f868e688ff). - A freshly scaffolded blank app runs its
testscript green, measured in this PR'sScaffold with repo distjob, stepTest the generated project, against the registry.
- The grep:
-
Open question 1, ruled A in the claim and landed here:
check-registry-log-declaredandcheck:test-source-aliasread the tsconfig-excludepayload boundary throughcheck-undeclared-dep-imports.mjs'stsconfigExcludedDirs. Onlypackages/create-objectstack(src/templates) is affected today. -
Holds released:
- the blank template files and
packages/create-objectstack/vitest.config.ts; .github/workflows/scaffold-e2e.yml;- the three
scripts/files (domain:spec, declared6117713390); content/docs/getting-started/your-first-project.mdx(domain:devx, declared6118463189).
- the blank template files and
-
Noted by the dev, not filed (no carrier): a green starter run on published 17.7.0 logs a
[sql-driver] DATABASE_ERROR … no such table: _objectstack_sequencesline and a WARN stack for the refused insert.check-registry-log-declared.mjs's header census reads "72 walked, 8 selected" against a live 73 / 10.
Generated by Claude Code
-
Blocked-by: #15951
Sub-issue of the epic hotcrm#1579 (step 5b). Filed by the director seat (objectstack#12708, summon #15);
pm:epicreserves it for the epic PM — ⛔ notpm:queue.domain:*/ type / priority are triage's. Ruling provenance and the design (B′) are on #15951 — read that card first.Governing text. Protocol baseline (maintainer 2026-09-05, verbatim): 「本项目以协议为基准。所以开发应该对其协议,协议有问题应该立卡修改协议」 — the published docs are part of what an app author (and every AI reading them) treats as the contract; a documented package that does not exist is a contract the platform is not honouring.
Measured (
origin/main04679418)content/docs/protocol/kernel/plugin-spec.mdx:758-765— a<Callout type="warn">says the@objectstack/testingpackage withcreateTestContext()/createTestEnvironment()is "proposed — there is no such published package today", then shows snippets importing it. Every app author who follows the docs is told to test against a package that does not exist, and hotcrm's hand-builtmakeCtx()is exactly the shape that snippet teaches.packages/create-objectstack/src/templates/blank/package.json— scripts:dev,start,build,validate,typecheck. Notestscript, no vitest, notest/directory. A scaffolded app starts with no way to assert its own business behaviour, so the first test its author writes is a hand-rolled kernel assembly (asexamples/app-crm,app-todo,app-showcaseeach did).The ask
plugin-spec.mdxaround what ships:bootStack+ the in-process handle from verify: an in-process handle on the booted stack — run a hook, flow, action or validation rule against the REAL engine and assert, so an app never fakesctx.apiagain (epic hotcrm#1579, step 5a) #15951. Delete the ghost callout and every@objectstack/testingimport. Where the platform's own docs generator owns the text (check:generated), fix the source and regenerate — never hand-edit a generated page. Search the wholecontent/docstree for other@objectstack/testing/createTestContextmentions and treat them the same way (git grep -n "objectstack/testing\|createTestContext\|createTestEnvironment" -- content/ skills/ packages/*/README.md); publishedskills/**text that teaches testing follows through the generator."test": "vitest run", avitest.config.ts,@objectstack/verify+vitestas devDependencies at the template's pinned range, and one example test that boots the template's own stack withbootStackand asserts one business fact through the handle. Keep it to one file — this is a starting point, not a framework.create-objectstack's own tests assert the scaffolded project'spnpm testruns green (the scaffold test that already exercisesvalidate/typecheckextends by one step).Acceptance
git grep -n "objectstack/testing"overcontent/,skills/,packages/returns zero hits outside a changelog.pnpm testgreen with the one example test.create-objectstackminor (new template files); docs-only changes need none.Clause-②: no(no exported symbol changes) — the dispatching seat re-reads from content.Not in this card
The handle itself (#15951); derived proof families (step 5c); hotcrm's migration (hotcrm card); any change to
os test.Refs: hotcrm#1579 · #15951 · ADR-0054.