You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Full cli area run of the checklist-test skill — all 6 items driven against real CLI invocations + a live showcase (opus subagent, isolated boot + file DB). Text-only per RUNNER.md.
dev-boot-contract (7/7 + both negatives) — health + ready + console all serve; --seed-admin does not overwrite an existing admin account on a second boot (old password still works, the new one 401s); all 5 DB-choice variants print the right resolved URL and the nothing-chosen default is a persistent project-anchored sqlite file (never memory://), verified on disk; --fresh creates and deletes its tempdir after exit (verified twice, plus a global sweep for leftovers); an occupied port auto-shifts and every printed URL uses the actual port (grepping the log for the requested port came back empty); a stale artifact warns with the newest-source filename and the fix line but still boots; a missing config exits 1 in ~2 s with a located remedy. Item text drift (not a defect): clause 2 names .objectstack/data/dev.db and resolveDefaultDevDbUrl, both superseded by the unified objectstack.db default. The load-bearing property holds; the item text needs a refresh.
migrate-plan-apply-json (7/7 + both negatives) — bare migrate plans without writing, proven physically (a sqlite_master dump before/after compared byte-equal, twice) rather than from the payload; the --json payload carries the declared keys; all five--json subcommands exit exactly 0 (no os migrate 成功时退出码是随机非零值(208/171/176/163/62…),--version / --help 却干净退出 0 #4873 duration-in-exit-slot leak — the format.exit-code pin was run, 4/4); destructive drops are skipped without --allow-destructive and applied with it (PRAGMA table_info proving both sides); apply is idempotent (in_sync on re-run); a busy DB refuses apply with exit 1 naming the holding pid while plan still succeeds with a warning; confirmation_required does not mutate (again proven by a physical dump). Cosmetic oddity, not filed: the summary prints "1 table(s) to create, 1 column(s) to add" immediately followed by "0 change(s): 0 safe, 0 needs-confirm, 0 destructive".
verify-verdict-exit-mapping (5/5 + both negatives) — every status is a member of the declared six-name union and the summary reconciles with a recomputed sum on both a clean and a staged-failing run; the exit-1 side was staged (a QA-only beforeInsert hook rewriting a field so written ≠ read-back) rather than skipped, closing the item's knownGap, and the human format agreed with the recomputed sum; a 400 VALIDATION_FAILED is classified needs-fixture and excluded from hardFailures while a 5xx would be a real failure; --rls adds the rls block and boots a separate stack, proven empirically by counting plugin-load lines (2 vs 1) rather than from a comment; OS_TENANCY_POSTURE=isolatedhard-fails with a located enterprise-package error instead of the 普查:plugin-auth 之外还有 6 处把被降级的 OS_MULTI_ORG_ENABLED 当「是不是多组织」在读 —— 只设 OS_TENANCY_POSTURE 的部署会静默走错分支 #5262 quiet single-org pass.
flag-command-error-ux (4/4 + both negatives) — unknown flag, invalid enum value (with the full allowed set enumerated), unknown top-level command and unknown topic subcommand all exit 2 with a located stderr message; the command body provably never ran (stdout empty, and the body markers captured from genuine runs of the same commands were absent); --help swept across the root plus all 30 declared variants — 31/31 exit 0 with exactly one USAGE block each, none inferred from a sibling.
🔴 FAIL — 1 item
scaffold-first-run — 4 of 6 published remote templates fail their very first npm run build
The blank template's full published first-run is clean end to end (scaffold → install → validate → build → boot → health 200 in 7 s → ready). The skills boundary is proven: --all --copy installs exactly the curated 11 (set-equality, zero diff) and repo-root discovery surfaces 11 with no internal skill leaking.
Reproduction rule
npx -y create-objectstack@latest canary-app -t todo --skip-skills --skip-install
cd canary-app && npm install && npm run build
Expected exit 0. Actual exit 2:
defineStack namespace-prefix validation failed (2 issues):
Object todo_label is missing the package namespace prefix.
Rename it to canary_app_todo_label (namespace = canary_app)
Reproduced on 4 independent templates — todo / compliance / content / contracts (2 / 4 / 5 / 3 issues respectively). procurement is blocked(environment) (codeload 503/403 in this sandbox).
Root cause (located). Published create-objectstack@16.1.0 rewrites namespace: in objectstack.config.ts to the sanitized project name but not the object-name literals, because it reads the template's original namespace from objectstack.manifest.json only — and a remote template's manifest is the template-registry document, which has no namespace key at all. The guard falls through and the rewrite is silently skipped. Verified on the generated tree: the config says namespace tpl_todo while the object literal still says name: 'todo_task'. This triggers for any project name whose sanitized namespace differs from the template's own — i.e. every real user, and CI's own canary-app.
⚠️ Already fixed at repo HEAD — do not re-file as a code bug. The residual action is a release, not a repair.
packages/create-objectstack/src/rewrite-identity.ts makes objectstack.config.ts the authority and self-verifies via findStaleNamespacePrefixes; its comment names this exact incident (#4902: "All five published remote templates … failed this way, and the nightly registry canary had been red on every one of them for weeks with nobody watching"). Pin run: rewrite-identity.test.ts10/10 pass.
But npm latest is still 16.1.0, so every new user who picks a non-blank template today gets a project that fails on its first build. Asks: (1) confirm the fix ships in 17.0.0, and (2) confirm the nightly registry canary goes green once it does.
🟡 PARTIAL — 1 item
build-own-contract — clause 4 is a clause scope gap, not a product defect
Passing: build/compile alias parity · the --json key contract · located per-path schema errors (not a bare "validation failed") · all failing author-time rules reported at once with where/message/hint/rule/path · build-vs-validate --json parity proven by computed set-equality on both the success and the failure envelope · advisory-vs-error separation.
Clause 4 is partial. Exit codes are clean for every --json invocation (0/1/1/1), but a config-load-time throw exits 2 on the human path (reproduced twice), because compile.ts's catch ends in this.error() and oclif's ExitError is 2 — the CliExitCode 0|1 type only narrows the emitJson/emitText slot. That is oclif's standard error exit, the same code cli.flag-command-error-ux asserts as correct, and not the #4873 duration-leak this clause exists to pin.
Checklist reconciliation needed (not a product bug): two items in this area disagree about exit code 2 — build-own-contract clause 4 treats it as outside the 0|1 union, flag-command-error-ux asserts it as the correct oclif error exit. The clause should be narrowed to the duration-leak it was written for.
Unverified side-observation, explicitly not filed: the runtime bundle filename hash differed across runs whose inputs were restored byte-for-byte, suggesting the bundle name may not be content-deterministic. Needs a dedicated reproduction before it means anything.
Full
cliarea run of thechecklist-testskill — all 6 items driven against real CLI invocations + a live showcase (opus subagent, isolated boot + file DB). Text-only per RUNNER.md.Result: 4 PASS · 1 PARTIAL · 1 FAIL.
Environment — framework
92f26f75(branchclaude/platform-test-checklist-ocwugl) · vendored console6314e87f· showcase app · isolated port + file DB.✅ PASS — 4 items
dev-boot-contract(7/7 + both negatives) — health + ready + console all serve;--seed-admindoes not overwrite an existing admin account on a second boot (old password still works, the new one 401s); all 5 DB-choice variants print the right resolved URL and the nothing-chosen default is a persistent project-anchored sqlite file (nevermemory://), verified on disk;--freshcreates and deletes its tempdir after exit (verified twice, plus a global sweep for leftovers); an occupied port auto-shifts and every printed URL uses the actual port (grepping the log for the requested port came back empty); a stale artifact warns with the newest-source filename and the fix line but still boots; a missing config exits 1 in ~2 s with a located remedy.Item text drift (not a defect): clause 2 names
.objectstack/data/dev.dbandresolveDefaultDevDbUrl, both superseded by the unifiedobjectstack.dbdefault. The load-bearing property holds; the item text needs a refresh.migrate-plan-apply-json(7/7 + both negatives) — baremigrateplans without writing, proven physically (asqlite_masterdump before/after compared byte-equal, twice) rather than from the payload; the--jsonpayload carries the declared keys; all five--jsonsubcommands exit exactly 0 (noos migrate成功时退出码是随机非零值(208/171/176/163/62…),--version/--help却干净退出 0 #4873 duration-in-exit-slot leak — theformat.exit-codepin was run, 4/4); destructive drops are skipped without--allow-destructiveand applied with it (PRAGMA table_infoproving both sides); apply is idempotent (in_syncon re-run); a busy DB refuses apply with exit 1 naming the holding pid while plan still succeeds with a warning;confirmation_requireddoes not mutate (again proven by a physical dump).Cosmetic oddity, not filed: the summary prints "1 table(s) to create, 1 column(s) to add" immediately followed by "0 change(s): 0 safe, 0 needs-confirm, 0 destructive".
verify-verdict-exit-mapping(5/5 + both negatives) — every status is a member of the declared six-name union and the summary reconciles with a recomputed sum on both a clean and a staged-failing run; the exit-1 side was staged (a QA-onlybeforeInserthook rewriting a field so written ≠ read-back) rather than skipped, closing the item'sknownGap, and the human format agreed with the recomputed sum; a 400VALIDATION_FAILEDis classifiedneeds-fixtureand excluded fromhardFailureswhile a 5xx would be a real failure;--rlsadds the rls block and boots a separate stack, proven empirically by counting plugin-load lines (2 vs 1) rather than from a comment;OS_TENANCY_POSTURE=isolatedhard-fails with a located enterprise-package error instead of the 普查:plugin-auth 之外还有 6 处把被降级的 OS_MULTI_ORG_ENABLED 当「是不是多组织」在读 —— 只设 OS_TENANCY_POSTURE 的部署会静默走错分支 #5262 quiet single-org pass.flag-command-error-ux(4/4 + both negatives) — unknown flag, invalid enum value (with the full allowed set enumerated), unknown top-level command and unknown topic subcommand all exit 2 with a located stderr message; the command body provably never ran (stdout empty, and the body markers captured from genuine runs of the same commands were absent);--helpswept across the root plus all 30 declared variants — 31/31 exit 0 with exactly one USAGE block each, none inferred from a sibling.🔴 FAIL — 1 item
scaffold-first-run— 4 of 6 published remote templates fail their very firstnpm run buildThe blank template's full published first-run is clean end to end (scaffold → install → validate → build → boot → health 200 in 7 s → ready). The skills boundary is proven:
--all --copyinstalls exactly the curated 11 (set-equality, zero diff) and repo-root discovery surfaces 11 with no internal skill leaking.Reproduction rule
Expected exit 0. Actual exit 2:
Reproduced on 4 independent templates —
todo/compliance/content/contracts(2 / 4 / 5 / 3 issues respectively).procurementisblocked(environment)(codeload 503/403 in this sandbox).Root cause (located). Published
create-objectstack@16.1.0rewritesnamespace:inobjectstack.config.tsto the sanitized project name but not the object-name literals, because it reads the template's original namespace fromobjectstack.manifest.jsononly — and a remote template's manifest is the template-registry document, which has nonamespacekey at all. The guard falls through and the rewrite is silently skipped. Verified on the generated tree: the config says namespacetpl_todowhile the object literal still saysname: 'todo_task'. This triggers for any project name whose sanitized namespace differs from the template's own — i.e. every real user, and CI's owncanary-app.🟡 PARTIAL — 1 item
build-own-contract— clause 4 is a clause scope gap, not a product defectPassing: build/compile alias parity · the
--jsonkey contract · located per-path schema errors (not a bare "validation failed") · all failing author-time rules reported at once withwhere/message/hint/rule/path· build-vs-validate--jsonparity proven by computed set-equality on both the success and the failure envelope · advisory-vs-error separation.Clause 4 is
partial. Exit codes are clean for every--jsoninvocation (0/1/1/1), but a config-load-time throw exits 2 on the human path (reproduced twice), becausecompile.ts's catch ends inthis.error()and oclif'sExitErroris 2 — theCliExitCode 0|1type only narrows theemitJson/emitTextslot. That is oclif's standard error exit, the same codecli.flag-command-error-uxasserts as correct, and not the #4873 duration-leak this clause exists to pin.Checklist reconciliation needed (not a product bug): two items in this area disagree about exit code 2 —
build-own-contractclause 4 treats it as outside the0|1union,flag-command-error-uxasserts it as the correct oclif error exit. The clause should be narrowed to the duration-leak it was written for.Unverified side-observation, explicitly not filed: the runtime bundle filename hash differed across runs whose inputs were restored byte-for-byte, suggesting the bundle name may not be content-deterministic. Needs a dedicated reproduction before it means anything.