Repository navigation
[maintainer] dev-mode noise budget: a blank project written verbatim from the tutorial boots with 4 WARN lines and only one needs the author's hand — expected degradations to info, stacks only at debug, the actionable line highlighted with a one-line fix #22160
Description
Filing gate: ③ task dispatched by the maintainer, quoted verbatim below; the measurements are class (a) and were taken in this session.
reach: npx os dev --ui on a fresh npm create objectstack@latest project carrying the Build-with-Claude-Code tutorial's four files (17.7.0 packages): ⚠ Boot diagnostics — 4 warnings logged during startup; pnpm dev -- --fresh on the showcase at main (post-#22097): 4 WARN lines plus 2 unarmed-trigger lines.
Reader: domain:cli seat for the policy and the boot-diagnostics printer (packages/cli/src/utils/format.ts, packages/cli/src/utils/console.ts); each WARN line's owner for its level (packages/services/service-analytics, packages/objectql/src/engine.ts + driver-sql, packages/objectql/src/action-governance.ts, service-settings, plugin-sharing).
Dedup: search_issues "dev mode boot diagnostics too noisy warnings expected degradation should be info stack trace only at debug noise budget" → 5 hits, all closed: #22073 (one line per warning class, loopback OAuth → info; PR #22097), #3420 (官方示例应零警告启动), #13256, #4012, #3430. None states a dev-mode budget; this card generalises #22073's per-class fix into a rule and lists the four lines that survive it.
Prior rulings read: #22073 / PR #22097 (per-class summary lines, each printed once, loopback OAuth at info); #3420 (the examples should boot with zero warnings).
Filed on the maintainer's instruction in this session (category ③, quoted verbatim): 「终端噪音是最大的体验问题。 一个按教程原样写的空白项目,os dev 启动就打出 4 条 WARN:OAuth 明文(localhost 下属预期)、analytics 误报、sys_migration 带完整 knex 堆栈、action 无 handler。其中只有最后一条真的需要用户动手,却被淹没在其它三条里。建议给 dev 模式定一个"噪音预算":预期中的降级记 info,堆栈只在 --log-level debug 出现,真正需要动手的那条单独高亮并给一行修法。」
What a first boot looks like today
A blank project with the tutorial's object, action, view and app, npx os dev --ui, @objectstack/* 17.7.0 — the whole Boot diagnostics block, abridged:
⚠ Boot diagnostics — 4 warnings logged during startup:
WARN [Analytics] No admitObjectRead configured and no "security" service registered at init — … any authenticated caller can post an inline dataset and read counts … (#22154: false alarm, Security registers on the same boot)
WARN [action-governance] declared script actions with NO handler — a button wired to nothing (ADR-0078); add a `body`, or register a handler under the declared `target` {"count":1,"actions":["my_app_ticket:resolve_ticket"]} ← the only line the author must act on
WARN OAuth is served UNENCRYPTED: … (http://localhost:38421/api/v1/auth) … The transport rule accepts this origin only because the host is loopback … (info since PR #22097 on main; still WARN in 17.7.0)
WARN Insert operation failed {"object":"sys_migration","error":{"message":"UNIQUE constraint failed: sys_migration.id …","stack":"SqliteError: … at Client_BetterSQLite3._query (…/knex/lib/dialects/better-sqlite3/index.js:52:40) … (9 more frames)"}} (#22099)
On main (showcase, pnpm dev -- --fresh) the OAuth line is gone and the block reads: [Analytics] No admitObjectRead …, [SettingsService] Pre-bind READ of namespace 'auth' …, Insert operation failed {"object":"sys_migration" … full stack}, [sharing-rule] active business-unit rule expands to NO recipients …, plus two flow … declares a 'schedule' trigger but is NOT bound — disabled by deployment policy … lines. Not one of those six asks the showcase author to change anything.
The one line that does — the dead button — is visually identical to the rest: same WARN, same timestamp prefix, same density, a JSON tail. A newcomer reads four alarms and cannot tell the real one from the three they are supposed to ignore; the previous card in this series (#22152) is exactly the reader who missed it.
The rule being asked for
A dev-mode noise budget, stated once and enforced by a pin:
- Expected degradations print at
info. A line that says of itself "this is accepted / not a failure / resolves per query / disabled by policy" is not a warning: loopback OAuth (done in fix(cli,plugin-auth): one boot line per warning class, each printed once, and the loopback OAuth notice at info #22097),[Analytics] … the bridge resolves per query([finding] service-analytics: every default boot logs a WARN that no "security" service was registered at init, although the Security plugin registers moments later — the siblinggetReadScopepath logs the same situation atinfo#22154),[SettingsService] Pre-bind READ …,schedule trigger … disabled by deployment policy,[sharing-rule] … expands to NO recipientswhen the seed simply has no members. - Stack traces only at
--log-level debug. Thesys_migrationline carries a 10-frame knex stack into the default banner; the banner keeps the one-sentence message and the object name, the stack waits for debug ([finding] every artifact boot on a fresh:memory:database logsInsert operation failed … UNIQUE constraint failed: sys_migration.idwith a full knex stack in Boot diagnostics #22099 removes the line altogether, this rule covers the next one). - The actionable line is the exception, and it looks like one. Anything with a fix the author can apply (
add a body, or register a handler …) prints once, highlighted, with the one-line fix on its own line, and is counted separately:1 needs your attention · 3 informational. - A pin holds it. The blank template and the Build-with-Claude-Code example (with a registered handler) boot with
0 warnings;examples/app-showcaseboots with zero lines aboveinfothat are not actionable.packages/cli/src/utils/format.boot-warning-classes.test.tsis where fix(cli,plugin-auth): one boot line per warning class, each printed once, and the loopback OAuth notice at info #22097's classes already live.
Why it matters
The boot banner is the one place the tutorial sends the reader to look ("run it and look"); AGENTS.md's own log-level rule says escalating functional degradations to warn "trains everyone to skim error". Today it trains a newcomer to skim everything.
Generated by Claude Code
Activity
objectstack-fleet commentedon Oct 8, 2026
Retriage answered: the remainder is routed;
pm:queue→pm:blockedon #22099, the one blocker the blank-template acceptance still waits on.pm:retriageremovedTriage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-08T09:55Z. ⛔ Not a claim, ⛔ not a dispatch.Thread-read: 6056996366
Blocked-by: #22099
Your owner table, routed:
[Analytics]: [finding] service-analytics: every default boot logs a WARN that no "security" service was registered at init, although the Security plugin registers moments later — the siblinggetReadScopepath logs the same situation atinfo#22154 is closed, so that line is done.sys_migrationinsert: [finding] every artifact boot on a fresh:memory:database logsInsert operation failed … UNIQUE constraint failed: sys_migration.idwith a full knex stack in Boot diagnostics #22099 (open, p3,domain:services). It is the last record between the blank template and its "0 warnings" acceptance, hence the block.[SettingsService]Pre-bind READ (namespaceauth): the reporter's own docblock says it "never fires" on a correct boot (ADR-0116;check:settings-bind-window). It is filed as service-settings: the showcase boot fires the SettingsService "Pre-bind READ" diagnostic (namespace auth) — a reporter that never fires on a correct boot; find the early reader, do not demote the line #22257 (p3,domain:services): find the early reader, ⛔ do not demote.[sharing-rule]expands to NO recipients: the warning names unstamped business-unit membership rows. That is plugin-sharing: after the #15030 revert, 17.x still cannot reach a NULL-org-seeded business unit from an org-stamped rule — and #14547, its only tracker, is closed #15086's root cause (unstamped seed rows; v18 / ADR-0131), so it is tracked there, ⛔ not demoted.What closes this card: #22099 lands and the blank template boots with no warning record. The showcase lines are tracked on #22257, #15086 and #22255, and do not hold this card.
objectstack-fleet commentedon Oct 8, 2026
Unlock: #22099 closed
completed(PR #22336 →6ff6ed6a).pm:blocked→pm:queue; p3 anddomain:clistandTriage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-08T20:18Z. ⛔ Not a claim, ⛔ not a dispatch.:memory:database logsInsert operation failed … UNIQUE constraint failed: sys_migration.idwith a full knex stack in Boot diagnostics #22099 was its one blocker, as my retriage answer6057326250recorded. That card closed at 2026-10-08T19:34Z. A first boot no longer logs the falsesys_migrationfailed insert.main, built from the workspace packages, because 17.7.0 on npm carries neither fix. Closecompletedwhen it holds.objectstack-fleet commentedon Oct 9, 2026
Claim: PM loop round 1
Session:
session_01BmsuLyUeuG5CNpZFMH1jzSAccount:
os-elon-musk(the seat's linked user asGET /useranswers it; always the card's assignee)Branch:
claude/issue-22160-blank-template-acceptanceWorktree:
objectstack-issue-22160Domain:
domain:cliSeat:
domain:cli#1File surface: none planned. This is the acceptance measurement triage
6068291990names: boot a blank project written verbatim from the tutorial, onmainbuilt from the workspace packages, and read its Boot diagnostics. A line that needs a fix is named with its producer for its own card, ⛔ never demoted here. Any edit stops the run; explain it in the report.Container & model:
S, measurement,mode:subagent,model: default (opus).dispatch-gates --tierhas no paths to read. Rebuilding the tutorial project and judging each boot line against the maintainer's budget is judgment work.Clause-②: no
Responsibility: n/a — not a defect card (a maintainer-dispatched task, category ③; its remaining deliverable is the acceptance measurement)
Thread-read: 6068291990
Serial constraints cleared: no file is written. Lane siblings in flight: #22310 (PR #22404, patch round) and #22255 (
format.ts); a boot reading onmainis not affected by either branch.Generated by Claude Code
objectstack-fleet commentedon Oct 9, 2026
os-dev-report
{
"issue": 22160,
"status": "done",
"branch": "claude/issue-22160-blank-template-acceptance",
"pr": null,
"session": "session_01BmsuLyUeuG5CNpZFMH1jzS",
"premise_still_valid": false,
"summary": "Acceptance measured on main fdfdd7e, built from the workspace packages (not npm 17.7.0), with os dev --ui on a project scaffolded by this checkout's create-objectstack plus the tutorial's four files. Triage's first clause holds: the tutorial project boots with NO warning record. There is no Boot diagnostics block on the first boot or on a restart, 0 WARN records, and 0 WARN even in the full --log-level debug stream. The bare blank template is the same. Its second clause holds on the card's own project: with the card-era handler-less Resolve, the block is exactly one record, the dead button, printed highlighted with its one-line fix. The header reads '1 needs your attention' with 0 informational records, and it is byte-identical on both boots. The verbatim tutorial no longer declares a dead button (PR 22204 made Resolve declarative), so it has no actionable line at all. That falsifies order H2 in its letter for the verbatim tutorial, and it is what the budget asks for. premise_still_valid is false because the card's premise (4 WARN lines on a tutorial project) no longer holds on main: it is resolved, not mis-filed. No other warning line appeared, so nothing needs its own card under the triage acceptance. Closing completed is the seat's call.",
"pm_readings": {
"H1": "Holds with one correction. The card body's project is the pre-22204 tutorial (script action with target), while the page at fdfdd7e has a declarative Resolve and a form in its view. Both were recreated from this checkout: A = the page verbatim, B = A with only the card-era action file. The page used is content/docs/getting-started/build-with-claude-code.mdx (fdfdd7e for A, 3b49318 for B's action file).",
"H2": "B: holds. One actionable record, first, highlighted, with its fix; 0 informational; no stack. A (the verbatim tutorial): false in its letter, because there is no record at all, actionable or not. Expected degradations sit at INFO: at debug, the A3 stream has 0 WARN, and the [Analytics] bridge, the loopback OAuth notice and the sys_migration owner-bind record are all INFO. No stack printed at any level, so the stack-only-at-debug leg is NOT MEASURED here (nothing carried one).",
"H3": "Holds. No [Analytics] admitObjectRead warning and no sys_migration failed insert at any level on a fresh first boot (A3 at debug). The owner bind is recorded once, at INFO.",
"second_boot": "A restart on the same project and DB (A2, B2) printed exactly what the first boot printed in the block. No line appeared on a second boot only."
},
"tests": "Measured at objectstack origin/main fdfdd7e (worktree objectstack-issue-22160, branch claude/issue-22160-blank-template-acceptance = that sha, no commits). BUILD: bash scripts/pm/os-verify-lock.sh -c 'NODE_OPTIONS=--max-old-space-size=4096 pnpm turbo run build --concurrency=2 --filter=@objectstack/cli... --filter=@objectstack/connector-rest... --filter=@objectstack/connector-openapi... --filter=@objectstack/connector-mcp... --filter=create-objectstack...' -> 'Tasks: 59 successful, 59 total; Cached: 9 cached' and 'VERDICT command-exit 0 · held the lock 334s · waited 83s'. PROJECT: node packages/create-objectstack/bin/create-objectstack.js support-desk --skip-install --skip-skills (workspace create-objectstack 17.7.0, blank template, namespace support_desk), then the tutorial's four files extracted VERBATIM by script from content/docs/getting-started/build-with-claude-code.mdx at fdfdd7e (src/objects/ticket.object.ts, src/actions/ticket.actions.ts, src/views/ticket.view.ts, src/apps/support.app.ts) plus the four barrel export lines the page describes. Its node_modules/@objectstack/{spec,runtime,plugin-hono-server,connector-rest,connector-openapi,connector-mcp,cli} are symlinks to the built workspace packages (not npm 17.7.0); node_modules/.bin/os is the workspace cli bin. os validate on it: 'Validation passed', 'Data: 2 Objects 6 Fields', 'UI: 1 Apps 1 Views 1 Actions', exactly the page's expected output. VARIANTS: A = the tutorial verbatim (its Resolve is the declarative operation:update + patch since PR 22204, so it declares no script action). B = A with ONLY src/actions/ticket.actions.ts replaced by the card-era file (the page at 3b49318, the parent of 7b926f7: type 'script', target 'resolveTicket', nothing registers it) = the dead-button project the card body measured. T = the bare blank template, no tutorial files. BOOT: each boot ran under a real pty: script -qfec './node_modules/.bin/os dev --ui -p 37613' (NODE_PATH unset, NODE_OPTIONS=--max-old-space-size=4096, default log level), waited for 'Press Ctrl+C to stop' plus 20 s, then SIGINT to the os dev process group I started (recorded PID), exit 0, port free afterwards. RESULTS (WARN = timestamped WARN records in the whole output; stack = V8 frames anywhere): A2 first boot (fresh project): NO Boot diagnostics block at all; WARN 0; ERROR/FATAL 0; lines carrying a warning glyph 0; stack frames 0. A2 second boot (restart, same project and DB): NO Boot diagnostics block; WARN 0; glyph lines 0; stack 0. A3 first boot of a second fresh copy at --log-level debug: whole live stream 1850 DEBUG / 426 INFO / 0 WARN / 0 ERROR; stack frames 0. T first boot (bare blank template): NO Boot diagnostics block; WARN 0; glyph lines 0. B2 first boot and B2 second boot: the block below, byte-identical across the two boots including ANSI (md5 7fbd54f1569c3fa4c1a342f25b3acb55 both); WARN records outside the block 0; stack 0. Styling read from the raw pty bytes: header yellow, the record bold yellow, the fix line cyan, the hint dim. B2 Boot diagnostics block, verbatim (first boot = second boot):\n
text\n ⚠ Boot diagnostics — 1 needs your attention:\n ⚠ [action-governance] declared script actions with NO handler — a button wired to nothing (ADR-0078): support_desk_ticket:resolve_ticket\n fix: add a `body`, or register a handler under the declared `target`\n run with --log-level debug to watch the boot stream live\n\nA2 first boot, banner region verbatim from 'Loading objectstack.config.ts' to 'Press Ctrl+C to stop' (only edits: the scratch path prefix written SCRATCH, the 41-name plugin list line elided), showing there is no Boot diagnostics block:\ntext\n Loading objectstack.config.ts...\n ↪ secret fields: LocalCryptoProvider wired (dev) — set OS_SECRET_KEY and swap for KMS/Vault in production\n\n ✓ Server is ready\n\n\n 🤖 MCP server — connect a coding agent:\n ➜ API: http://localhost:37613/\n Endpoint http://localhost:37613/api/v1/mcp\n ➜ Console: http://localhost:37613/_console/\n Skill http://localhost:37613/api/v1/mcp/skill\n Connect claude mcp add --transport http support-desk http://localhost:37613/api/v1/mcp\n ➜ MCP: http://localhost:37613/api/v1/mcp\n Disable OS_MCP_SERVER_ENABLED=false\n connect an AI client (Claude Code, Cursor, …) · skill: http://localhost:37613/api/v1/mcp/skill\n\n 🔑 Dev admin: admin@objectos.ai / admin123\n seeded on empty DB · dev only — do not use in production\n platform admin — Setup, Studio and every record, but NO app-declared capability, so\n an app that gates navigation on requiredPermissions may show it an empty menu; grant\n it a permission set under Setup → Users, or sign in as an account your app seeds\n\n Config: objectstack.config.ts\n Mode: development\n Driver: SqlDriver(better-sqlite3) → file:SCRATCH/A2/support-desk/.objectstack/data/objectstack.db\n Tenancy: single\n Plugins: 41 loaded\n (41-plugin list elided)\n\n Press Ctrl+C to stop\n\nH3 at debug (A3): '[Analytics] admitObjectRead bridged to the "security" service; ... resolved per query' is INFO (service-analytics src/plugin.ts:1538, ctx.logger.info); the sys_migration insert ran once with no failure: 'Insert operation failed' 0 hits, 'UNIQUE constraint' 0 hits, and '[auth] default organization owner bind recorded in sys_migration' 1 hit at INFO (plugin-auth src/default-org-bootstrap-once.ts); 'OAuth is served UNENCRYPTED' is INFO (plugin-auth src/auth-plugin.ts:3492); '[SettingsService] Pre-bind READ' 0 hits; '[sharing-rule] ... NO recipients' 0 hits (only INFO 'hooks bound' lines). PRODUCERS of every line of the B2 block: header and the 'run with --log-level debug ...' hint are the printer itself (packages/cli/src/utils/format.ts printBootDiagnostics :1472, hint :1519-1520); the highlighted record is objectql (packages/objectql/src/action-governance.ts:583-590, logger.warn, message 'STATEMENT; FIX'), and its fix line is the text after the producer's '; ' derived by format.ts actionableRecord; it is the one line the author can act on. There is no other line in either block. NOT MEASURED: the stack-withholding leg of the budget. No record in any of the 7 boots carried a stack, so there was nothing to withhold; PR 22236's unit pins cover that leg. SETUP CONTROL (boot A1, the first try, kept as evidence and not used as the reading): with the workspace packages/console having no dist (pnpm build never produces it), the same project printed one line outside the block: '⚠ Page source andrequiresnot validated at save: no SDUI component manifest at PROJECT/sdui.manifest.json or WORKTREE/packages/console/dist/sdui.manifest.json ...' (packages/cli/src/utils/sdui-manifest.ts:270, printed by serve). It is an artifact of the workspace layout: the CLI looks for the manifest beside its OWN @objectstack/console dependency, and the published @objectstack/console@17.7.0 tarball carries dist/sdui.manifest.json. With that published dist present (see deviations) the line is gone (A2, B2, A3, T). A1 otherwise matched A2: no Boot diagnostics block, WARN 0.","gates": "none — no file changed (git status empty, branch head = fdfdd7e = BASE; the one gitignored write is listed under deviations)",
"files_changed": [],
"deviations": [
"To boot --ui as an installed CLI would, the published @objectstack/console@17.7.0 tarball (static SPA, npm integrity sha512-4Z8Fy47V... verified) was extracted into each scratch project's node_modules and copied into the worktree's GITIGNORED packages/console/dist (the output path pnpm objectui:build writes; packages/console/.gitignore 'dist/'). No tracked file changed. The worktree goes with the cleanup. Building the console at the pinned objectui sha was not attempted: it is a full objectui build, and the Console SPA logs nothing at server boot.",
"The scratch projects resolve @objectstack/* through symlinks to the built workspace packages instead of an npm install, so every server-side byte is fdfdd7e's.",
"Boot A1 was a setup control, not the reading (see tests: the SDUI-manifest line it printed is a workspace-layout artifact). The canonical first boots are on fresh copies A2, B2, A3 and T.",
"Each boot ran under a pty (script -qfec) so the output is what a terminal user sees, colors included."
],
"cleanup": "All 7 os dev servers were mine and each was stopped by its recorded os dev PID (SIGINT to that process group, the Ctrl+C equivalent); no process left (ps clean, port 37613 free after each). After this report is posted: rm -rf the worktree's node_modules, then git worktree remove (no --force). The remote branch stays at fdfdd7e (the empty write-route probe). Deleting it would be a write this order did not grant.",
"mcp_calls": "0",
"api_writes": "1 — this os-dev-report comment, POST /repos//issues/22160/comments, sent by scripts/pm/post-stamped.mjs through the fleet-write relay (POST /repos/objectstack-ai/objectstack/dispatches, executed as objectstack-fleet[bot]). git push of the empty branch is not a REST write. Reads: single-card REST GET of the issue and its comments.",
"open_questions": [],
"out_of_scope_findings": [
"class: a · reach: public door, os dev --ui on the tutorial project at fdfdd7e under a pty. The os dev parent's MCP connect block ('🤖 MCP server — connect a coding agent:' with Endpoint/Skill/Connect/Disable) interleaves line by line with the serve child's ready banner in 5 of 7 boots. Foreign lines inside the block: A2 first boot 3 (the ➜ API / Console / MCP rows), A3 4, B2 first boot 3 ('Tenancy', 'Plugins: 41 loaded' and its list, split from 'Config / Mode / Driver'), B2 restart 1, T 1 (the '🔑 Dev admin: admin@objectos.ai / admin123' credential line lands inside the Connect block). A1 was clean; the A2 restart printed the block above '✓ Server is ready'. Producer pair: packages/cli/src/commands/dev.ts:707-741 prints the block to the parent's stdout when the child's 'objectstack:listening' IPC arrives; the child sends that IPC at serve.ts:783 (announceListening) BEFORE it prints its banner to stderr (printServerReady :5396, printBootDiagnostics :5556). Two processes write one terminal unordered. The PM thread kept the 1-of-3 observation from PR 22236 as a note with no carrier (6056996366); this is the measured repro. · dedupe words: os dev MCP connect block interleaves ready banner · objectstack:listening IPC race banner order · Dev admin line inside MCP block"
]
}
objectstack-fleet commentedon Oct 9, 2026
Closing
completed: the acceptance holds onmaindomain:cliseat (#6024) ·session_01BmsuLyUeuG5CNpZFMH1jzS· 2026-10-09T03:37Z. Reviewed against the dev's report6073744623, not its prose alone.Triage's acceptance (
6068291990) holds, measured onorigin/mainfdfdd7e76. The build is from the workspace packages, not npm 17.7.0. The project is scaffolded by this checkout'screate-objectstack, plus the four files ofcontent/docs/getting-started/build-with-claude-code.mdxtaken verbatim, and booted withos dev --uiunder a real terminal.--log-level debugthe whole live stream had 0 WARN and 0 ERROR. The bare blank template gives the same answer.Resolve, a script action whose handler nothing registers): the block is exactly one record, the dead button. It prints first and highlighted, with its one-line fix (fix: add a body, or register a handler under the declared target), under the header1 needs your attention. It is byte-identical on both boots, so no line appears on a restart only.[Analytics]bridge, the loopback OAuth notice and thesys_migrationowner-bind record are INFO;sys_migrationfailed insert does not occur ('Insert operation failed' gives 0 hits);Delivered across: PR #22236 (the printer half,
11e6fc5f2e), #22154, #22099 (PR #22336), and the tutorial's declarativeResolve(PR #22204).Released: the claim
6073488552, a measurement with no file written. The empty branchclaude/issue-22160-blank-template-acceptanceatfdfdd7e76carries no commit.Filed separately from this measurement: the
os devparent's MCP connect block interleaves with the serve child's ready banner (measured in 5 of 7 boots), which turns a PR #22236 note into a measured repro. It is a separate defect, filed on its own card.Generated by Claude Code
feat(cli): Boot diagnostics noise budget, printer half: the line that…
fix(cli): print the deployment-policy unbound-flow class under a dim …