Uh oh!
There was an error while loading. Please reload this page.
fix(cli): os validate prints UI: 0 Apps instead of dropping the row - #10955
Conversation
…10504) printMetadataStats (packages/cli/src/utils/format.ts, shared by os validate, os info and os compile) gains an opt-in zeroFallback per summary section -- the one item to force-print at 0 instead of dropping the whole row when every item in that section is zero. Set only on UI ('Apps'), matching the triage ruling on #10504 (comment 5366623624): the blank/crud/full templates all ship zero apps deliberately, so a warning would fire on every clean scaffold's first run. Measured at this branch's head: a zero-apps run and a one-app run of the real CLI printed an identical summary except for the UI: line being entirely absent (not 0) in the zero-apps case -- both exited 0. Reproduced unchanged from the card's original 17.1.0 measurement. Data:/Logic:/Security: keep their current drop-at-zero behavior -- filed as its own finding (#10952) rather than widened here. The --json path already reported "apps": 0 explicitly; an unrelated --json warnings gap is filed separately (#10953). New test: packages/cli/test/print-metadata-stats-zero-row.test.ts pins both ends of the 0->1 transition directly against printMetadataStats.
📓 Docs Drift Check1 anchor(s) derived from 1 changed package(s); no hand-written page names any of them. ✅ What this run could not see
Coarse fallback — 23 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin e6936599ffe06a1c1d7886fbe7a8de4e58ae09c5 && git checkout e6936599ffe06a1c1d7886fbe7a8de4e58ae09c5
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 9cc6777d3e228952bc554c5f1c4f34b063fcf105 916a7e0b1e43f54a5fd07297899af132001cecf9 && git checkout -B drift-repro 9cc6777d3e228952bc554c5f1c4f34b063fcf105 && git merge --no-ff 916a7e0b1e43f54a5fd07297899af132001cecf9
node scripts/docs-audit/affected-docs.mjs --json 9cc6777d3e228952bc554c5f1c4f34b063fcf105 |
⛔ merge queue 构建失败 — 先分诊,再决定要不要重排队列构建 32537747879 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集), 失败的 job(日志抽取,best effort):
跨 PR 相同签名(24h,按失败测试文件聚合):
历史信号:
分诊清单:
Generated by Claude Code · merge-queue-triage workflow (#4859) |
Uh oh!
There was an error while loading. Please reload this page.
Fixes#10504
Premise re-derived at head
Reproduced the card's two-run measurement at this branch's head (commit
916a7e0b1e), spawning the real CLI (bin/run-dev.js validate, tsx oversrc/, no dependency onpackages/cli/dist) against a minimalblank-shapedconfig (one object, two fields) with and without one
apps: [...]entry:Zero apps (before fix):
One app (before fix):
Identical to the card's report: the
UI:row is absent (not0) at zeroapps, both exit
0. Premise still holds atmainhead — nothing onmainfixed this since the card was filed.What I measured about the printer's shape (brief fence #1)
packages/cli/src/utils/format.ts→printMetadataStatsrenders foursections (
Data,UI,Logic,Security) from one shared loop that dropsthe whole row when every item in a section is
0. This is a generalpattern, not UI-specific —
Logic:(flows/workflows/agents/apis all zero)and
Security:(positions/permissions both zero) vanish exactly the sameway. Triage's ruling in #10504 named only
UI:, so I did not widen the fixto the other three sections — filed as its own finding:
#10952 (
[finding] os validate's summary printer drops ANY zero-count section row, not just UI:).What I measured about
--json(brief fence #2)No divergence on the card's specific symptom:
--jsonalready reports"apps": 0explicitly at zero apps (statsis a plain object with everykey always present, never filtered). Confirmed both ends:
I did find an unrelated text/
--jsondivergence while checking this:the four inline advisories (
No objects defined,No apps or plugins defined,Missing manifest.id,Missing manifest.namespace) are computedafter the
--jsonbranch's earlyreturn, so--json'swarningsarray never carries any of them, regardless of the zero-apps question —
filed as #10953 (
[finding] os validate --json never carries the four inline non-blocking warnings the text summary prints). Not touched by thisPR.
Existing test pinning the old output (brief fence #3)
None found. Searched
packages/cli/test/**forprintMetadataStats,collectMetadataStats,UI:, and the exact strings from the card(
My App v0.1.0,Data: 1 Objects,No apps or plugins) — no test assertsthe current absent-row shape. No test to update.
The fix
printMetadataStatsgains an opt-inzeroFallbackper section — the oneitem to force-print at
0instead of dropping the row when every item inthat section is zero. Set only on
UI('Apps'), per triage's ruling(comment 5366623624): the
blank/crud/fulltemplates all ship zero appsdeliberately, so a warning would fire on every clean scaffold's first run —
this changes nothing about what
validateaccepts, rejects, or exits with.Data:/Logic:/Security:keep their current behavior untouched.Sanity check that the shared function's nonzero path is unaffected: the
full-workspace build (below) ran
os buildonexample-showcase(24objects, 1 app, 29 flows, …) and its printed summary is unchanged in shape:
New test — pins both ends of the 0→1 transition (brief fence #4)
packages/cli/test/print-metadata-stats-zero-row.test.ts— unit-testsprintMetadataStatsdirectly (theformatZodErrorspattern already used informat-zod-union.test.ts: captureconsole.log, strip ANSI, assert on theplain text), rather than spawning the full CLI, since the fix is entirely
inside this one function:
UI: 0 Appsis present (the regression)UI: 1 Apps(the transition triage said should becomelegible), and that
UI: 0 Appsis NOT also presentData:still renders unaffectedLogic:/Security:still drop their whole row at all-zero today —named as the one to update when/if [finding]
os validate's summary printer drops ANY zero-count section row, not justUI:—Logic:/Security:vanish the same way #10952 lands the wider fixReverse verification (run twice — once before, once after a real catch, see below)
Predicted direction: reverting only the production change
(
packages/cli/src/utils/format.ts) should turn the new test's zero-appsassertion (
UI: 0 Appspresent) RED with exactly the card's symptom (the rowabsent instead of zero), while the CLI's own exit code stays
0throughout(this was never a correctness gate). Committed the fix first, then, at the
final commit
916a7e0b1e:Both legs matched the prediction exactly: RED on revert with the card's
literal symptom (
Receivedshows the row is simply absent, not avalue-mismatch), GREEN on restore.
A real ratchet catch, fixed before push (not weakened)
check:type-check-debt's--re-measure(after building the full workspaceclosure — 70/70 tasks) caught a genuine +1 drift:
Root cause: my new test file's relative import
(
from '../src/utils/format') was missing the.jsextension requiredunder
moduleResolution: NodeNext—TS2835. (The siblingformat-zod-union.test.tshas the identical unextended import, alreadyabsorbed into the frozen 146 baseline; mine was simply a new occurrence of
the same pattern.) Fixed by adding the extension
(
from '../src/utils/format.js') — no ledger edit, no gate touched.Re-measured clean at the final commit:
(The same run surfaces an unrelated, pre-existing
@objectstack/plugin-authTEST_DEBT surplus — 109 recorded vs. 97 measured, a lowering opportunity
already tracked generically under #6376 — not caused by this diff and not
touched here.)
Gates — derived at the final commit, run there
node scripts/pm/dispatch-gates.mjsat916a7e0b1e(3 paths vs. merge base376b3dc0b0:.changeset/validate-zero-apps-row.md,packages/cli/src/utils/format.ts,packages/cli/test/print-metadata-stats-zero-row.test.ts) named:check:changeset-gate-self-testscheck:objectui-changesetcheck:slot-lookupcheck:test-source-aliascheck:type-source-resolutioncheck-adr-0087-registration.mjscheck-changeset-no-major.mjsmajorbumpcheck-ci-filter-parity.mjscheck-empty-changeset.mjscheck-plugin-teardown-shape.mjsdocs-audit/check-affected-docs.mjscheck:query-options-erasurecheck:engine-double-contractcheck:where-matchercheck:type-check-coveragecheck:type-check-debt(--re-measure, full closure built).js-extension fix above)Plus, directly (not just via the derivation):
pnpm --filter '@objectstack/cli^...' build— dependency closure — green.pnpm --filter @objectstack/cli test— 149 files / 1647 tests — green(whole package suite, re-run at the final commit, not just the new file).
pnpm --filter @objectstack/cli typecheck— green.node scripts/check-nul-bytes.mjs— clean, whole repo.No gate weakened, no threshold moved, no baseline raised. No change to
content/docs/releases/**. Changeset:.changeset/validate-zero-apps-row.md(patch,
@objectstack/cli).Generated by Claude Code