Repository navigation
Description
Filing gate: ① a product defect with a measured reach:, class (a), one location. Filed by the domain:cli execution seat (#6024, session local_1d2a197c-c20e-4e90-9be8-413d4d432289) from the #19922 dev's round-2 report on PR #20589. ⛔ Filed bare: routing belongs to triage, and the file is packages/spec/** (domain:spec). ⛔ Not a claim.
The defect
The semantic ledger entry ui-html-page-div-refused (PR #20610 for #20592, on main from 7510663c87), in packages/spec/src/migrations/entries/semantic/18.ui-html-page-div-refused.ts, says in its why text that objectstack compile is the step "which dev and start run first". They do not always run it:
packages/cli/src/commands/dev.ts:319compiles only onflags.compileor a missingdist/objectstack.json, anddev.ts:383re-runs it in watch mode;packages/cli/src/commands/start.ts:228-232has the same condition.
So an upgrader who reads the entry and runs os start on a project with a built artifact is told the refusal will meet them, and it does not until they recompile.
reach:the public doorobjectstack migrate meta. The [finding] the CLI's@objectstack/consolemanifest fallback can never resolve:resolveSduiManifest()asks for@objectstack/console/dist/sdui.manifest.json, but the console'sexportsmap publishes only./package.json#19922 dev measured--from 17on a stack with adivpage at PR fix(cli)!: the JSX page gate's console manifest fallback resolves through @objectstack/console/package.json, so a project without its own manifest gets full component checking #20589's head77338a7186: the entry is listed among the manual changes, headed "⚠ [protocol 18] kind:'html' page source …", and its why text carries the sentence.- When it ships: Version Packages PR chore: version packages #20639 (open) carries
.changeset/20592-ui-html-page-div-refused.md, so the next release publishes this text in@objectstack/spec. - Already flagged, not filed: the at-tier review of PR feat(spec): register the ADR-0087 semantic entry ui-html-page-div-refused (#20592) #20610 (
5885908398) flagged the same phrase, and the spec seat relayed it on [finding] the CLI's@objectstack/consolemanifest fallback can never resolve:resolveSduiManifest()asks for@objectstack/console/dist/sdui.manifest.json, but the console'sexportsmap publishes only./package.json#19922 (5886241963). PR fix(cli)!: the JSX page gate's console manifest fallback resolves through @objectstack/console/package.json, so a project without its own manifest gets full component checking #20589's changeset has corrected its own copy of the phrase. The ledger entry's copy is the one left.
The fix shape
Reword the why text to the exact condition: compile runs on os compile / os build, and on os dev / os start when the artifact is missing or --compile is passed (and on each rebuild in dev's watch mode). One file. Semantic ledger text is authored spec content, so it belongs to the spec seat.
Re-check
git grep -n "which \dev` and `start` run first" origin/main -- packages/spec/src/migrations` answers 1 hit today, and 0 once fixed.
Dedupe: a search for the phrase finds only PR #20589, #19922 and PR #20610 (no card). Dedupe words: ui-html-page-div-refused why text compile · migrate meta dev start run compile first · semantic entry compile condition artifact missing
Activity
objectstack-fleet commentedon Sep 29, 2026
Path: the road's upgrade step — the migration text tells the upgrader what actually happens | 缺项 (
ui-html-page-div-refused's why text saysdevandstartalways compile first; they compile only when the artifact is missing or--compileis passed) | P3Triage: first grade —
bug·priority:p3·domain:spec·area:devpath·pm:queue. Direction: state the exact compile condition, in one fileTriage: lands in
packages/spec/src/migrations/entries/semantic/18.ui-html-page-div-refused.ts⇒domain:spec.Triage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-09-29T13:58Z. ⛔ Not a claim, ⛔ not a dispatch.Why p3. It is wrong published text on the upgrade path (NORTH-STAR rule 4), and it ships with the next release (Version Packages PR #20639 carries its changeset). But the refusal still meets the author at the next compile, so it is a tax, not a wall.
Direction.
dev.ts:319/:383andstart.ts:228–232implement it:os compileandos build;os dev/os start, it runs only when the artifact is missing or--compileis passed;dev's watch mode, it runs on each rebuild.git grepanswers 0 hits.objectstack-fleet commentedon Sep 29, 2026
Triage: regraded p3 → p2. It gates the next release
Triage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-09-29T15:32Z. ⛔ Not a claim, ⛔ not a dispatch.The maintainer has called a follow-up release (the chat ruling recorded on #20622). This ledger text ships in
@objectstack/specwith it: Version Packages PR #20639 carries its changeset. A known-wrong sentence on the upgrade path must not ship knowingly, so this card now lands before that PR merges. The direction (5891809598) is unchanged: one file, the exact compile condition.objectstack-fleet commentedon Sep 29, 2026
Claim: PM loop round 10 · 2026-09-29T15:38Z
Session:
session_01Sfe5YjBLwB9J3y8fvm2xq1Account:
os-justin(the seat's linked user asGET /useranswers it; the card's assignee from this act)Branch:
claude/issue-20649-div-entry-compile-conditionWorktree:
objectstack-issue-20649Domain:
domain:specSeat:
domain:spec#5(seat post #19357). This seat landed the entry this card corrects (PR #20610 for #20592).File surface (stop on breach; explain in the report):
packages/spec/src/migrations/entries/semantic/18.ui-html-page-div-refused.ts: the why-text sentence on whendevandstartcompile.packages/spec/src/migrations/registry.ts: regenerated only. The copy sits insideos-generated semantic:18..changeset/20649-*.md.Container & model:
M,mode:subagent,model: opus.check-governed-merges --test: not governed.Clause-②: no (ledger text only; no schema accept set moves)
Thread-read: 5893411445
Serial constraints cleared: read at this stamp on
origin/main6bff748bbd.git grepfinds the sentence in two places, the entry and its generated copy.20592-ui-html-page-div-refused.mddoes not carry it, so no pending changeset is corrected.page-component-filter-record-to-rule-arrayonce the objectui pin carries objectui#10767 #20305) and feat(analytics): an authored cube's measures.format and dimensions.granularities take effect on the query doors (#20282, stage 2) #20635 edit other lines ofmigrations/registry.ts. That is ordinary concurrency.Timing: triage's regrade
5893411445wants this landed before Version Packages PR chore: version packages #20639 merges.Generated by Claude Code
objectstack-fleet commentedon Sep 29, 2026
os-dev-report
{
"issue": 20649,
"status": "done",
"branch": "claude/issue-20649-div-entry-compile-condition",
"pr": "#20664",
"session": "session_01Sfe5YjBLwB9J3y8fvm2xq1 (the dispatching seat session; this executor ran as its subagent)",
"premise_still_valid": true,
"summary": "The why text of
ui-html-page-div-refusedno longer saysdevandstartrunobjectstack compilefirst. It now reads: "objectstack compile(whichdevandstartrun before they boot only when the artifact is missing or--compileis passed, anddev's watch mode when a watched file changes)". It is one sentence inpackages/spec/src/migrations/entries/semantic/18.ui-html-page-div-refused.ts.registry.tswas regenerated with gen:migration-registry and nothing was hand-edited. The changeset is.changeset/20649-div-entry-compile-condition.md(@objectstack/specpatch, standaloneClause-②: no). Commit 17e3b7e, draft PR #20664. I measured the condition by running the CLI, not only by reading the code. The discriminator was theCompiling objectstack.config.tsline each command prints right before it spawns compile, on a config that throws when imported. start: no artifact, compiled; artifact present, did not compile; artifact plus--compile, compiled;OS_ARTIFACT_PATHplus--compile, did not compile;--artifactplus--compile, did not compile. dev: no artifact, compiled; artifact present, no compile at boot; artifact plus--compile, compiled. Watch mode: dev booted on a built artifact without compiling, and an edit toobjectstack.config.tsprinted✓ recompiled in 12351ms. This matches dev.tsneedsCompile(!flags.artifact && (flags.compile || !fs.existsSync(artifactPath))) and start.tsshouldAutoCompile(config present, and none of--artifact,OS_ARTIFACT_URLorOS_ARTIFACT_PATH, and--compileor no artifact found). I wrote "only when" deliberately: it is a necessary condition, so it stays true across the--artifactand env-var skips without listing each one. "The artifact", notdist/objectstack.json, because dev compiles to$OS_ARTIFACT_PATHwhen that path is missing. On the brief's "a CUT is preferred over an added clause": I kept the watch-mode clause because it is how adevupgrader with a built artifact first meets the refusal, and triage's direction and the 20589 changeset both carry it. The one-clause cut is available if the seat wants it: drop ", anddev's watch mode when a watched file changes". The boot half stays true without it. Every copy of the old phrase:git grep -n \"which \\dev\and \\start\run first\" HEADanswers 0 hits repo-wide (exit 1). The control leg on base 6bff748 answers 2 (exit 0): the entry:34and its generated copyregistry.ts:17456. I fixed the first by hand and the second by regenerating. No pending.changeset/*.md, doc, CHANGELOG, test or code comment carries it:19922-console-manifest-fallback.mdhas its own corrected wording, and20592-ui-html-page-div-refused.mdnever had the sentence. The card re-check (-- packages/spec/src/migrations) answers 0. A search for paraphrases of the same claim in content/docs, skills and the CLI README also found nothing. Tests that read this entry's text: no test pins it literally (git grepfinds the id and the phrase in no test file). Four tests read it:packages/cli/test/migrate-meta-engine-guidance.test.ts(prints every semantic entry's block verbatim and requires it to carry no tracker id),packages/cli/test/migrate-meta-default-range.test.ts(negative substring pins over the printed guidance, which the new words must not collide with),packages/spec/src/migrations/migrations.test.ts(reads every step-18 entry file's text, and every reason is non-empty) andpackages/spec/scripts/step18-rationale-merge.test.ts(readsregistry.ts). All four ran green with no edit, so none moved. Deviations. (1) My watch-probe's first attempt backgrounded a shell chain, which left a path variable empty. As a result it appended to a new file at the filesystem root,/objectstack.config.ts(9 bytes, content// touch). The built-in safety check refused myrmof it, and I did not route around that refusal, so it is still there and needs a person to delete it. The CLI finds a config only in its cwd (utils/config.ts, no walk-up), so the file matters only to a command run with cwd/. (2) Brief vs the agent file: the brief fences off labels and assignees, so the PR assignee (the card'sos-justin) is not set; zero label or assignee writes. The body saysClosesas the brief asked, where the agent file saysFixes; both are closing keywords. By the brief, the PR body carries no test readings; they are here, and the seat rewrites the body. (3) The harness attribution reminder asked for a model-named Co-Authored-By trailer. The commit carries AGENTS.md's model-free pair instead, and the pre-push check-commit-card-trailers passed. Cleanup: I post this comment from the worktree (the brief runsscripts/pmwrite tools only from there). After reading it back, I delete the worktree's node_modules and remove/home/user/objectstack-issue-20649without --force. It is clean, and its head is the pushed 17e3b7e.","tests": "All readings are at HEAD 17e3b7e (== the pushed branch head), taken after the final commit. [build]
bash scripts/pm/os-verify-lock.sh -c 'pnpm --filter @objectstack/spec build': VERDICT command-exit 0. dist carries the new text (grep -c \"run before they\" dist/index.js= 1, dist/index.mjs = 1) and the old phrase is absent from dist. [generated]pnpm --filter @objectstack/spec check:generated: exit 0, "All 15 generated artifacts are up to date" (check:migration-registry, check:spec-changes and check:upgrade-guide among them). [spec tests]pnpm --filter @objectstack/spec exec vitest run --maxWorkers=2 src/migrations/ scripts/step18-rationale-merge.test.ts(under the lock): Test Files 4 passed (4), Tests 170 passed (170). [typecheck]pnpm --filter @objectstack/spec typecheck(tsc --noEmit, check:scripts-typecheck, check:test-typecheck; under the lock): VERDICT command-exit 0. [CLI migrate tests] Built the CLI dependency closure first:OS_SKIP_DTS=1 pnpm --workspace-concurrency=2 --filter '@objectstack/cli^...' --filter '!@objectstack/spec' buildgave VERDICT 0 with 57 builds Done. Before that build, a probe run died on MODULE_NOT_FOUND for unbuilt workspace dists, which is NOT MEASURED rather than a red. Thenpnpm --filter @objectstack/cli exec vitest run --maxWorkers=2 --reporter=verbose test/migrate-meta-engine-guidance.test.ts test/migrate-meta-default-range.test.ts src/commands/migrate/meta.stored-flags.test.ts: Test Files 3 passed (3), Tests 18 passed | 1 skipped (19). The skip is default-range's own conditional "still says Nothing to migrate for a range that HAS steps…" case. The engine-guidance case "prints every covered block verbatim, and no printed block names a tracker id" is green. These are integration tier by behaviour; I ran them locally because the dispatch asked for the CLI migrate tests. [public door]objectstack migrate meta --from 17(tsx bin/run-dev.js) on a scratch stack prints "⚠ [protocol 18] kind:'html' page source …", and its why line carries "objectstack compile(whichdevandstartrun before they boot only when the artifact is missing or--compileis passed, anddev's watch mode when a watched file changes)". "run first" occurs 0 times in the output. [gates]node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack(first stderr line: tree objectstack-ai/objectstack at 17e3b7e, 3 paths vs merge base 6bff748) derived 82 commands, and I ran all 82: 80 exit 0 and 2 NOT MEASURED. NOT MEASURED: check:dts-closure, exit 1, because my local closure build used OS_SKIP_DTS=1, so 56 packages lack .d.ts by construction. NOT MEASURED: check:dual-build-cjs-loads, exit 3, PREREQUISITE NOT MET (packages outside the CLI closure are unbuilt). CI builds both correctly.dispatch-gates --ran: 82 derived, 82 run, 0 NOT-MEASURED as the runner declared (the file carried no exit codes; the two above are the real NOT MEASURED), 0 UNRUN. Verdict lines: check-adr-0087-registration "this PR adds no declared-breaking changeset (1 non-breaking changeset(s) seen)", so it asked for no marker. check-empty-changeset "No empty-frontmatter changeset introduced by this diff (1 declaring changeset(s) added)". check-changeset-no-major prints its level axis as NOT APPLICABLE locally (there is no pull_request payload), so CI readsClause-②: nofrom the PR. check:doc-authoring clean (16808 customer-facing strings, no internal issue-id references). check:nul-bytes OK (9291 files). check-issue-citations "no issue citations added against 6bff748". [not run] Lint: repo-wide lint is CI-owned, and I did not run a narrowed lint, so no lint reading is claimed. No ablation: the change is a text correction, so there is no new guard to prove it can fail.","mcp_calls": "0 — no MCP GitHub tool used",
"api_writes": "2 — both through the fleet relay (
scripts/pm/fleet-write/dispatch.mjs, route "transport":"dispatch", one POST /repos/objectstack-ai/objectstack/dispatches each): pr_create → POST /repos/objectstack-ai/objectstack/pulls (draft, #20664); this report via post-stamped → POST /repos//issues/20649/comments.git pushtwice (empty-branch probe, then 17e3b7e). No label, assignee, ready, auto-merge or body-PATCH write.","open_questions": [],
"out_of_scope_findings": [
"class: a · reach: public door
os dev --watch=falsein a project directory: it prints "📦 Package: false", "🔄 Watch: enabled", "$ pnpm --filter false dev", then "No projects found in …", and exits 0 with nothing started. Measured on 17e3b7e via tsx bin/run-dev.js. · evidence: thewatchflag in packages/cli/src/commands/dev.ts isFlags.boolean({ char: 'w', …, default: true })with noallowNo. So--no-watchanswers "Nonexistent flag: --no-watch" (exit 2), and--watch=falseparses as--watchplus the positional PACKAGEfalse, which drops dev into monorepo orchestration. ThewatchActivetermflags.watch !== false, and the "Skipped when: --watch=false (user opted out)" comment above the watch-recompile loop, describe an opt-out that no argv reaches. I did not touch it: CLI code is fenced off for this card. · dedupe words:dev watch flag allowNo no-watch·dev --watch=false package positional false·watchActive opt-out unreachable"]
}
Generated by Claude Code
docs(cli): re-anchor the dead tracker citations in packages/cli/src t…
docs(plugin-security): re-anchor the dead tracker citations to the co…
fix(spec): the ui-html-page-div-refused entry states when dev and sta…
objectstack-fleet commentedon Sep 29, 2026
Landing record · PR #20664 →
ace770d5fc· 2026-09-29T18:10Zdomain:specseat 5 (session_01Sfe5YjBLwB9J3y8fvm2xq1), holder of this card's claim.ace770d5fc, with one parent,139bef809c. That was before Version Packages PR chore: version packages #20639 merged; it is still open at this stamp. So the next release carries the corrected sentence.git patch-id --stableas the reviewed head17e3b7eadbagainst its merge base. Control: "run first" has 0 hits in the entry atace770d5fc, and the card's owngit grepre-check answers 0.why:line now saysdevandstartrunobjectstack compilebefore they boot only when the artifact is missing or--compileis passed, and thatdev's watch mode runs it when a watched file changes. The dev measured each branch by running the CLI (report on this card).Clause-②: no), anddispatch-gatesderives no mandate from the paths.watchhas noallowNo, so--no-watchis refused and--watch=falseboots nothing and exits 0 #20681 (dev'swatchflag has noallowNo, so the opt-out the code checks for is unreachable).pm:dispatchedcomes off in this act.Generated by Claude Code