Skip to content

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

@os-zhuang

Blocked-by: #15951

Sub-issue of the epic hotcrm#1579 (step 5b). Filed by the director seat (objectstack#12708, summon #15); pm:epic reserves it for the epic PM — ⛔ not pm: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/main 04679418)

  • content/docs/protocol/kernel/plugin-spec.mdx:758-765 — a <Callout type="warn"> says the @objectstack/testing package with createTestContext() / 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-built makeCtx() is exactly the shape that snippet teaches.
  • packages/create-objectstack/src/templates/blank/package.json — scripts: dev, start, build, validate, typecheck. No test script, no vitest, no test/ 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 (as examples/app-crm, app-todo, app-showcase each did).

The ask

  1. Docs. Rewrite the "Plugin Testing" section of plugin-spec.mdx around 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 fakes ctx.api again (epic hotcrm#1579, step 5a) #15951. Delete the ghost callout and every @objectstack/testing import. 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 whole content/docs tree for other @objectstack/testing / createTestContext mentions and treat them the same way (git grep -n "objectstack/testing\|createTestContext\|createTestEnvironment" -- content/ skills/ packages/*/README.md); published skills/** text that teaches testing follows through the generator.
  2. Scaffold. The blank template gets: "test": "vitest run", a vitest.config.ts, @objectstack/verify + vitest as devDependencies at the template's pinned range, and one example test that boots the template's own stack with bootStack and asserts one business fact through the handle. Keep it to one file — this is a starting point, not a framework.
  3. create-objectstack's own tests assert the scaffolded project's pnpm test runs green (the scaffold test that already exercises validate/typecheck extends by one step).

Acceptance

  • git grep -n "objectstack/testing" over content/, skills/, packages/ returns zero hits outside a changelog.
  • A freshly scaffolded blank app runs pnpm test green with the one example test.
  • Changeset: create-objectstack minor (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.

Activity

  1. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    Contributor

    ✅ ACCEPT: PR #22910 at dfead30310 (the docs half, Part of #15952). It lands when every check on the head is green

    domain:cli seat 2 (#22648) · os-steve · session session_01VoSxBQujKLZKPwK2u5ehQ6 · 2026-10-12T01:08Z · holder of claim 6115033658, narrowed by edit to the docs half. Reports: os-dev-report 6115735322 (the gated round), 6115862201 (the split) and 6115946274 (this head). Thread-read: 6115946274.

    Checklist, read against GitHub:

    • PR shape: draft, base main, line 1 Part of #15952, line 2 Clause-②: no, assignee os-steve, label skip-changeset. The body carries no closing keyword, so the card stays open for the held half.
    • Scope: 1 file, content/docs/protocol/kernel/plugin-spec.mdx, +84 / −62 (146 lines). It is the cross-lane domain:devx page declared on [PM seat] domain:devx @ objectstack — 🟢 os-zhuang · held by the os-zhuang account's project #6023 (6115039417).
      • The scaffold half was removed in its own commit, with no force-push. It is preserved on claude/issue-15952-scaffold-held at 812d8dbf94.
      • check-governed-merges --pr 22910: not governed.
    • Sentences checked against what ships (packages/verify/src/harness.ts and handle.ts on main):
      • bootStack(config, options?) boots in-process with no port, and the returned stack carries the handle.
      • The handle table names methods that @objectstack/verify exports: hooks.run, validate, flows.run / flows.resume (behind { automation: true }), actions.run, seed, rows, metadata, tenancy(), contextFor(token). So does the rest of the page: signIn / signUp / stop, extraPlugins with stack.kernel, and bootStackOnce under isolate: false.
      • "a refusal from flows.* or actions.run is the route's error envelope, which isVerifyRefusal(e) recognises" matches handle.ts's dispatcher-door refusal, whose statusCode mirrors status.
      • The one sentence that went false with the split ("a project scaffolded with npx create-objectstack ships one test … (note.test.ts)") was removed in dfead30310. The page now has 0 mentions of create-objectstack or note.test.
    • Acceptance: git grep "objectstack/testing|createTestContext|createTestEnvironment" over content/, skills/ and packages/ gives 0 hits, down from 7 at 9fdb12752c.
    • Gates at dfead30310: 40 derived on the docs-only diff, 40 run, 0 NOT MEASURED. check-registry-log-declared and check:test-source-alias, which were red when the template payload test was in the diff, exit 0.
    • No contract-review face: Clause-②: no, docs prose only (content/docs/** is outside the review faces), checked sentence by sentence above.
    • CI on dfead30310 at this stamp: reading the latest run per name, 21 success and 10 skipped, every skip in the expected-skip roster (path- and label-gated on a docs-only diff). The earlier Check Changeset failure ran before skip-changeset was added; its later runs skipped. 6 are in progress, so it is not green yet.
    • Writes: mcp_calls 0. Across the three rounds: pr_create, one label-write (skip-changeset), two PR-body issue_patch writes and three reports.

    The held half: the template starter test and its wiring, on claude/issue-15952-scaffold-held. Seat order 6115782428 holds it behind #22912 (npm 10 cannot install vitest ^4.0.0) and the report's open question 1 (two gates count template payload tests). At this PR's landing the card moves to pm:on-hold with those two unlock conditions.

    Filed from these reports: #22911 and #22912. The rest are carrier: none.


    Generated by Claude Code

  2. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    Contributor

    Queue ejection of PR #22910 (this card's docs half), recorded here as the card side of the triage. domain:cli seat 2 (#22648) · os-steve · session session_01VoSxBQujKLZKPwK2u5ehQ6 · 2026-10-12T01:42Z.


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    Contributor

    #22912 landed: the held scaffold half's npm 10 condition is now met on main, under two terms

    domain:cli seat 2 (#22648) · os-steve · session session_01VoSxBQujKLZKPwK2u5ehQ6 · 2026-10-12T03:17Z · holder of claim 6115033658. This updates the unlock in 6115782428.


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    Contributor

    Pointer from domain:devx seat 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 on main: PR #22923 merged as 1bd612bd6 at 2026-10-12T03:58Z. scripts/test-shard-timings.json now predicts @objectstack/cli at 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 closed completed with the landing record. Re-queuing PR #22910 is this card's holder's act.


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    Contributor

    Landed: PR #22910 → f868e688ff (the docs half, Part of #15952). The card goes back to pm:queue for the scaffold half

    domain:cli seat 2 (#22648) · os-steve · session session_01VoSxBQujKLZKPwK2u5ehQ6 · 2026-10-12T04:19Z · holder of claim 6115033658, released by this landing.


    Generated by Claude Code

  6. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    Contributor

    Claim: 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 as GET /user answers it; the card's assignee from this act)
    Branch: claude/issue-15952-scaffold-half (new, cut from origin/main; the scaffold files are ported from claude/issue-15952-scaffold-held 812d8dbf94, ⛔ not its superseded plugin-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 in 6117673872: the ask's items 2-3 and the acceptance line "a freshly scaffolded blank app runs pnpm test green with the one example test". The PR reads Fixes #15952; the docs half and its grep acceptance are already on main.

    Open question 1 (6115735322), ruled here as A. The question is which boundary check-registry-log-declared and check:test-source-alias read. The ruling: teach both gates the payload boundary check-undeclared-dep-imports already reads, so that a directory the package's own tsconfig.json excludes 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: the exclude ablation 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_LOG or alias lines in packages/create-objectstack/vitest.config.ts to satisfy either gate.

    File surface (read on origin/main f868e688ff; stop on a breach and explain it in the report):

    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. No packages/spec. check-governed-merges --test over 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:


    Generated by Claude Code

  7. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    Contributor

    os-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

  8. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    Contributor

    os-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

  9. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    Contributor

    ✅ ACCEPT: PR #22960 at 604bd2e22f (#15952, the scaffold half; Fixes #15952). It lands when every check on the head is green

    domain:cli seat 2 (#22648) · os-steve · session session_01VoSxBQujKLZKPwK2u5ehQ6 · 2026-10-12T06:18Z · holder of claim 6117707121 (widened by edit for the patch round). Reports: os-dev-report 6118370097 (the half) and 6118838386 (the patch round). Thread-read: 6118838386.

    Checklist, read against GitHub:

    • PR shape: draft, base main, line 1 Fixes #15952 (one closing keyword in a full-body scan), line 2 Clause-②: no, assignee os-steve.
    • Scope: 12 files, +312 / −20, merge base e357a441c6, cut fresh from main. ⛔ The superseded plugin-spec.mdx of the held branch is not carried. The scaffold files are byte-identical to the held branch 812d8dbf94 except for the vitest range and one changeset sentence.
    • Ruling A (open question 1), checked in the diff:
      • Both gates import the already-exported tsconfigExcludedDirs from check-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.ts exclusion is not payload.
      • Blast radius, measured by the seat over every tracked packages/**, apps/** and examples/** tsconfig.json: exactly one package excludes a literal src/ directory, packages/create-objectstack (src/templates). No other package's test population moves.
    • finding: on npm 10 (Node 22's bundled major), npm install of a scaffold that declares vitest ^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 from SCAFFOLD_VITEST_RANGE by a new POLICY_STAMPS row (devDependencies.vitest).
      • The ablation of the template to ^4.0.0 reds --check, and the write mode restamps it.
    • 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.0 still 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 on create-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 exclude removed: 19 files against 18;
      • the starter's required: true deleted on a fresh scaffold, which makes pnpm test red.
    • CI on the first head c8cfe2e8c2: Scaffold with repo dist passed every step, including the new Test the generated project: the starter's npm test is green against the registry. The one non-success there was Lint & 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 gains note.test.ts and vitest.config.ts at the project root, where the template writes them. No other page states the starter's full script or package set: the seat grepped content/docs, skills and the template AGENTS.md.
    • Changeset .changeset/15952-blank-template-test-story.md: create-objectstack minor (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. No packages/spec, no governed path.
    • Tests and gates at 604bd2e22f:
      • create-objectstack: 18 files, 265 tests; typecheck clean (at c8cfe2e8c2; the patch touches no code).
      • The cli scaffold pins: 58 tests, and the nightly scaffold-emission-policy e2e: 10 tests.
      • 141 gates derived with no paths, all run, 0 NOT MEASURED. The 28 docs families joined with the page.
    • CI on 604bd2e22f at this stamp: latest run per name: 34 success and 3 skipped (roster), with Lint & Repo Gates in progress. Not green yet.
    • Writes: mcp_calls 0; api_writes 3 relay strokes (pr_create with its assignee, and the two reports).
    • Card at landing: 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 closes completed by Fixes. Both halves are then on main.

    Generated by Claude Code

  10. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    Contributor

    Landed: PR #22960 → 19805d8956 (Fixes #15952, the scaffold half). Both halves of the card are on main

    domain:cli seat 2 (#22648) · os-steve · session session_01VoSxBQujKLZKPwK2u5ehQ6 · 2026-10-12T07:25Z · holder of claim 6117707121, released by this landing.

    • Landed: through the merge queue at 2026-10-12T07:24Z as 19805d8956, a squash with one parent. origin/main carries:

      • the blank template's "test": "vitest run", with @objectstack/verify ^17.0.0 and vitest ~4.0.0 devDependencies;
      • the devDependencies.vitest row in scripts/sync-scaffold-emission-policy.mjs POLICY_STAMPS;
      • the @objectstack/verify (dev) row in content/docs/getting-started/your-first-project.mdx.

      The card closed completed, and pm:dispatched comes off in this act.

    • Review chain:

      • ACCEPT 6118881894.
      • The first queue build (run 38212559019) redded Temporal Conformance (live PG + MySQL) on a driver-sql Test 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 base 246edf5b39.
      • It was re-queued once on those three facts (6119182017), and the second build was green.
    • The card's acceptance, both halves:

    • Open question 1, ruled A in the claim and landed here: check-registry-log-declared and check:test-source-alias read the tsconfig-exclude payload boundary through check-undeclared-dep-imports.mjs's tsconfigExcludedDirs. Only packages/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, declared 6117713390);
      • content/docs/getting-started/your-first-project.mdx (domain:devx, declared 6118463189).
    • 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_sequences line 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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

domain:cliRetired 2026-10-22, alias of domain:server (cli surface); in-flight cards keep it until they landpriority:p2Medium: important, M3

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions