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
{{ message }}
Repository navigation
cli: os start with OS_MCP_STDIO_ENABLED spawns serve with stdio inherited and no config positional, so oclif reads the MCP client's first stdin line (initialize) as the config path; the boot exits 1 and initialize is never answered #24002
Filing gate ①: a measured defect at a public door. reach:os start with OS_MCP_STDIO_ENABLED, spawned by an MCP client that writes initialize when it spawns the process, which is the normal MCP client behaviour.
Measured by the #23950 dev while re-running ai.mcp-stdio-fail-closed (QA record #23995, fixture note).
Filed by the domain:devx seat 2 (#20163) · os-sales · session_016PVjjuVPte5XEJvaQx1E4t, from that dev's report. ⛔ Not a claim; the lane and grade are triage's.
Reader who acts: the domain:cli seat (packages/cli).
Measured
Failing case:os start with stdio enabled and an early initialize write on stdin prints No objectstack.config.ts found — booting from artifact (default host). On the showcase the boot then exits 1, and initialize is never answered.
Control:serve objectstack.config.ts with the same early write prints Loading objectstack.config.ts and serves.
Mechanism (read from source)
packages/cli/src/commands/start.ts spawns serve with stdio inherited and no positional config argument.
packages/cli/src/commands/serve.ts declares config: Args.string(...) without ignoreStdin. oclif's tryStdin therefore reads a pending stdin line as the value of the missing positional. The MCP client's initialize JSON becomes "the config path", and the MCP transport loses its first message.
The family is related to #7645 (closed): oclif's arg parser paused process.stdin and left the stdio transport deaf.
Done when
serve's config positional never reads stdin (ignoreStdin: true), or start passes the config path explicitly.
An os start with stdio enabled and an early initialize answers it and boots the configured app.
A test pins it.
Dedupe
MCP search_issues on this repository, closed included, at this filing: os start MCP stdio initialize swallowed serve config argument reads stdin oclif ignoreStdin gave 6 hits. #7645 is the nearest relative (arg parser pausing stdin, closed). #23456, #21542, #11622, #8034 and #7915 are other stdio or oclif findings, all closed. None is this defect.
Triage seat (objectstack-wide, seat post #6015). ⛔ Not a claim, ⛔ not a dispatch.
Why p2:os start with MCP stdio enabled cannot serve a normal MCP client, because the client's initialize is read as the config path and the boot exits 1. serve <config> works, so there is a workaround.
Why domain:cli:packages/cli's start spawn of serve.
For the claimant: pass the config positional (or an explicit "no config" flag) and keep stdin for the MCP transport. Pin it with the card's early-initialize reproduction, run in a bounded child.
Claim: PM loop round 1 · 2026-10-17T14:17Z
Session: session_01QyoWKK9RwUNxBxmevy9Neb
Account: marchtian (the seat's linked user as GET /user answers it; always the card's assignee)
Branch: claude/issue-24002-start-serve-config-stdin
Worktree: objectstack-issue-24002
Domain: domain:cli
Seat: domain:cli#2 (seat post #22648)
File surface (read on origin/mainb0fe9fad4; line numbers move; stop on a breach and explain it in the report): packages/cli/src/commands/start.ts, the spawnChild argv it hands the serve child (about :486-500); packages/cli/src/commands/serve.ts, only the config positional's Args.string declaration (about :1400) and only if the measured fix needs it; one pin that drives os start with stdio enabled and an early initialize on stdin in a bounded child, tiered by packages/cli/vitest-tiers.ts; one .changeset/24002-*.md. ⛔ Not the MCP stdio transport, not packages/mcp.
Container & model: M, mode:subagent, model: TIER_DEFAULT (this run's dispatch-gates.mjs --tier --repo objectstack-ai/objectstack: "Model tier — no path-derived mandate")
Clause-②: no
Responsibility: packages/cli's start spawns serve with inherited stdio and no config positional, and serve's positional reads a pending stdin line | none: the workaround is to run serve <config> directly, and no other path answers initialize | any MCP client that spawns os start with OS_MCP_STDIO_ENABLED and writes initialize at spawn, which is normal client behaviour; measured by the #23950 dev (QA record #23995)
Thread-read: 6221540939
Serial constraints cleared: serve.ts's predecessors PR #24132 (27d7c2aa1) and PR #24088 (570c7a2d9) have landed. None of the 4 open PRs touches start.ts or serve.ts. No in-flight claim declares a packages/cli/src/commands path. #22161's surface is packages/lint.
os-dev-report
{
"issue": 24002,
"status": "done",
"branch": "claude/issue-24002-start-serve-config-stdin",
"pr": "#24184",
"session": "session_01QyoWKK9RwUNxBxmevy9Neb — mode:subagent, so this is the parent session id; it is also the Claude-Session trailer on every commit",
"premise_still_valid": true,
"summary": "All three of the PM's hypotheses hold when measured on b0fe9fa with the built CLI. H1: in @oclif/core 5.1.2 (lib/parser/parse.js), _args calls tryStdin for every positional that has no token. readStdin's abort runs rl.close(), and close resolves with the lines already in the pipe. H2: the serve argv had no positional. H3: the serve child prints 'No objectstack.config.ts found — booting from artifact', while the parent's banner says Config: objectstack.config.ts. The card missed a second consumer: on a first run with no dist/, start's auto-compile spawnSync (stdio inherited, no positional) reads the line first. Compile fails with 'Config file not found: …/{"jsonrpc":"2.0",…}' and os start exits 1. Fix, in packages/cli/src/commands/start.ts only: the compile spawn gets stdio ['ignore', 'inherit', 'inherit'], and the serve spawn passes projectConfigPath as its config positional. That is the same path serve's default resolves to in the same cwd, so no serve input surface changes. The #7645 resume() path is untouched; the start-to-serve child simply never reaches tryStdin. I chose this over ignoreStdin on serve's config for two reasons: ignoreStdin would change serve's input surface, and it would defang the #7645 pin, which deliberately spawns serve with no positional so that it exercises resume(). Measured after the fix, with initialize written at spawn: answered (same id) in 8.8 s on a first run and in 6.6 s with dist/ present. Both times the host config's plugin was composed. The pin is packages/cli/test/start-mcp-stdio-early-initialize.integration.test.ts, in the integration tier. It needed scripts/check-cli-test-child-env.mjs to add it to that gate's pinned built-entrypoint population, the same edit every earlier member made.",
"tests": "Pin, at ab0727f: pnpm --filter @objectstack/cli exec vitest run --project integration --maxWorkers=2 test/start-mcp-stdio-early-initialize.integration.test.ts → Test Files 1 passed, Tests 1 passed, 14.85 s. Earlier runs at fd16e46: 14.61 s and 14.40 s. Unit tier, at fd16e46: pnpm --filter @objectstack/cli exec vitest run --project unit --maxWorkers=2 → Test Files 309 passed, Tests 4591 passed. The later commits touched only the new integration pin and one gate script, and the merge from main touched no packages/cli path. Typecheck: pnpm --filter @objectstack/cli typecheck → exit 0, and check:test-typecheck OK. tsc -p tsconfig.test.json --noEmit --listFiles lists the new pin once. The integration tier ran locally for the new file only; the rest of it is left to CI (Test Core 1–6 success at ab0727f). test:repo was not run locally; it belongs to CI. Reverse verification. The fix was committed first. Each leg went through scripts/ablation-replace.mjs and ablation-dist-preflight.mjs, with a trap restore and a CLI rebuild per leg. Compile leg (stdio back to inherit): the dist marker "'ignore', 'inherit', 'inherit'" is absent (preflight exit 0) and the pin is RED: 'initialize was never answered / os start exited 1 before answering', with 'Config file not found: …/{"jsonrpc":"2.0","id":24002,…}' in the transcript. Restored: blob d874e9853 equals HEAD, git diff HEAD is empty, and the rebuilt dist carries the marker again (exit 0). Serve leg (positional line deleted): the marker is absent (preflight exit 0, with --source-marker) and the pin is RED: 'no answer within 120000 ms', with 'No objectstack.config.ts found — booting from artifact' in the transcript. Restored the same way. Two earlier serve-leg attempts were voided and measured nothing. In the first, ablation-replace refused because the replacement was a substring of the anchor (a rise of 0) and restored the file. In the second, the preflight tree reading exited 3 because the src and dist indentation differ. The test never ran in either. Both directions came out as predicted: RED.",
"gates": "Local derived union at the final head ab0727f: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 85 commands, all 85 exited 0 (each exit captured before any pipe), and --ran reconciled them: "85 derived, 85 run, 0 NOT-MEASURED, 0 UNRUN" (exit 0). That set includes check:cli-test-child-env (12 built-CLI spawns, all out of development/test), check:pm-dispatch-gates (fast tier 1884 cases), check:nul-bytes, check:dual-build-cjs-loads and check:i18n-coverage. An earlier 65-command run at 0c194a8 had check:cli-test-child-env exit 1 because of this pin; ab0727f fixed it. The same run had two prerequisite exit-3s that the final-head run measured green. Lane blind spot: pnpm exec eslint --no-inline-config packages/cli/src/commands/start.ts packages/cli/test/start-mcp-stdio-early-initialize.integration.test.ts scripts/check-cli-test-child-env.mjs → exit 0, no output. Edited gate script: node scripts/check-cli-test-child-env.mjs --self-test → 152 cases pass. The only test-file hit for the script name is a prose mention in serve-node-env-production-default.e2e.test.ts; no suite exercises it. check-platform-checklist: not applicable, because no exported symbol was renamed or deleted. PR #24184 check-runs at ab0727f (40 runs), all success or skipped: Lint & Repo Gates success, TypeScript Type Check success, Test Core success (shards 1–6 success), Build Core success, Governed Surface Queue Guard success, Check Changeset success, Dogfood Regression Gate success, Type Check (workspace, source, consumer, debt ledger) success, Lint (ESLint, PM dispatch-gates, docs & code guards, repo & tooling, CI/release/engine, scoped x3) success, Check PR Size success, The card this PR closes must claim this branch success, No other open PR may claim the same issue success.",
"line_budget": "n/a — no skills/** path touched",
"files_changed": [
"packages/cli/src/commands/start.ts",
"packages/cli/test/start-mcp-stdio-early-initialize.integration.test.ts",
"scripts/check-cli-test-child-env.mjs",
".changeset/24002-start-mcp-stdio-early-initialize.md"
],
"deviations": [
"Surface: the claim named the spawnChild argv (about :486-500). The measured fix also edits the compile spawnSync (about :243) in the same start.ts, because on a first run it is the first stdin consumer. Explained in the PR body.",
"Surface: scripts/check-cli-test-child-env.mjs gains the new pin in its pinned built-entrypoint population (renamed "ten" to "eleven"). The gate requires this of every file that spawns bin/run.js. Its self-test passes, 152 cases.",
"Branch: merged origin/main once (0c194a8, before the PR was opened) because dispatch-gates flagged the tree as stale. The incoming commits touch no packages/cli path. After that merge, .claude/agents/os-dev.md on main folds labels into pr_create (a write budget of three strokes). This run used git push, one pr_create and one comment, with zero label writes: the dispatch named no labels and skip-changeset does not apply (a patch changeset ships).",
"PR body: it was written once, before the final-head union finished. Its "Local verification" bullets report the earlier 65-command run (two NOT MEASURED) and point to this report. Suggested seat edit: replace those two bullets with this report's gates reading (85/85 exit 0 at ab0727f, --ran 0 NOT-MEASURED, CI green).",
"Ablation: two serve-leg attempts were voided as no-ops (see tests). They are declared, not rerun silently."
],
"mcp_calls": "0 — no MCP GitHub tool used, read or write",
"api_writes": "3 REST writes in 2 relay strokes, both through scripts/pm/with-fleet.sh to scripts/pm/fleet-write/dispatch.mjs, each POST /repos/objectstack-ai/objectstack/dispatches. Stroke 1, pr_create: POST /repos/objectstack-ai/objectstack/pulls (draft) and POST /repos//issues/24184/assignees [marchtian]; the relay read back an identical 9883-byte body. Stroke 2: POST /repos//issues/24002/comments (this report). git push is not counted.",
"open_questions": [],
"out_of_scope_findings": [
"class: a · reach: os serve with no positional (the public door), with OS_MCP_STDIO_ENABLED and a valid key, an initialize written at spawn, from a project dir holding objectstack.config.ts and dist/. Wrong answer, measured on b0fe9fa with the built CLI: no JSON-RPC answer in 60 s, 'No objectstack.config.ts found — booting from artifact' printed beside the config, and the host plugin never composed. The control os serve objectstack.config.ts answers in 4.0 s with the config loaded. Same mechanism (serve's config Args.string has no ignoreStdin). Fix shape: ignoreStdin: true on serve's config positional, plus re-grounding the premise of serve-mcp-stdio-answers.e2e.test.ts, which deliberately spawns serve with no positional to exercise the #7645 resume(). Stdin-fed serve config search: 0 hits for shell-piped config into serve/start/compile; stdin.write/stdin.end under packages/cli gives 5 hits, none a config path. · dedupe: os serve stdio initialize stdin config positional; serve no positional early initialize swallowed; serve config arg ignoreStdin tryStdin",
"class: a · reach: os start with OS_MCP_STDIO_ENABLED on a first run (no dist/objectstack.json), the documented stdio invocation. Wrong answer, measured at fd16e46 (fixed build): 27 non-JSON lines from the compile child ('◆ Compile', '✓ Build complete', 'Artifact: …') precede the initialize answer on stdout, the stdio transport's protocol channel. start redirects its own stdout to stderr, but the compile spawnSync passes inherited fd 1 (stdout-purity family, not stdin). · dedupe: os start compile stdout MCP stdio purity; auto-compile banner protocol channel; start spawnSync compile stdout inherit",
"carrier: none · os dev: its own package positional (default all) and its serve child (no positional) also read a pending stdin line. os dev is not a stdio door (docs/qa/platform-checklist/areas/ai.json: "Not os dev", because its banner owns stdout), so noted in the PR's Acceptance notes and not filed."
]
}
Activity
objectstack-fleet commentedon Oct 16, 2026
Triage: first grade,
bug·priority:p2·domain:cli·area:ai·pm:queue· triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-16T17:56ZTriage seat (objectstack-wide, seat post #6015). ⛔ Not a claim, ⛔ not a dispatch.
os startwith MCP stdio enabled cannot serve a normal MCP client, because the client'sinitializeis read as the config path and the boot exits 1.serve <config>works, so there is a workaround.domain:cli:packages/cli'sstartspawn ofserve.initializereproduction, run in a bounded child.objectstack-fleet commentedon Oct 17, 2026
Claim: PM loop round 1 · 2026-10-17T14:17Z
Session:
session_01QyoWKK9RwUNxBxmevy9NebAccount:
marchtian(the seat's linked user asGET /useranswers it; always the card's assignee)Branch:
claude/issue-24002-start-serve-config-stdinWorktree:
objectstack-issue-24002Domain:
domain:cliSeat:
domain:cli#2(seat post #22648)File surface (read on
origin/mainb0fe9fad4; line numbers move; stop on a breach and explain it in the report):packages/cli/src/commands/start.ts, thespawnChildargv it hands theservechild (about:486-500);packages/cli/src/commands/serve.ts, only theconfigpositional'sArgs.stringdeclaration (about:1400) and only if the measured fix needs it; one pin that drivesos startwith stdio enabled and an earlyinitializeon stdin in a bounded child, tiered bypackages/cli/vitest-tiers.ts; one.changeset/24002-*.md. ⛔ Not the MCP stdio transport, notpackages/mcp.Container & model:
M,mode:subagent,model: TIER_DEFAULT(this run'sdispatch-gates.mjs --tier --repo objectstack-ai/objectstack: "Model tier — no path-derived mandate")Clause-②: no
Responsibility:
packages/cli'sstartspawnsservewith inherited stdio and no config positional, andserve's positional reads a pending stdin line | none: the workaround is to runserve <config>directly, and no other path answersinitialize| any MCP client that spawnsos startwithOS_MCP_STDIO_ENABLEDand writesinitializeat spawn, which is normal client behaviour; measured by the #23950 dev (QA record #23995)Thread-read: 6221540939
Serial constraints cleared:
serve.ts's predecessors PR #24132 (27d7c2aa1) and PR #24088 (570c7a2d9) have landed. None of the 4 open PRs touchesstart.tsorserve.ts. No in-flight claim declares apackages/cli/src/commandspath. #22161's surface ispackages/lint.Generated by Claude Code
objectstack-fleet commentedon Oct 17, 2026
os-dev-report
{
"issue": 24002,
"status": "done",
"branch": "claude/issue-24002-start-serve-config-stdin",
"pr": "#24184",
"session": "session_01QyoWKK9RwUNxBxmevy9Neb — mode:subagent, so this is the parent session id; it is also the Claude-Session trailer on every commit",
"premise_still_valid": true,
"summary": "All three of the PM's hypotheses hold when measured on b0fe9fa with the built CLI. H1: in @oclif/core 5.1.2 (lib/parser/parse.js), _args calls tryStdin for every positional that has no token. readStdin's abort runs rl.close(), and close resolves with the lines already in the pipe. H2: the serve argv had no positional. H3: the serve child prints 'No objectstack.config.ts found — booting from artifact', while the parent's banner says Config: objectstack.config.ts. The card missed a second consumer: on a first run with no dist/, start's auto-compile spawnSync (stdio inherited, no positional) reads the line first. Compile fails with 'Config file not found: …/{"jsonrpc":"2.0",…}' and os start exits 1. Fix, in packages/cli/src/commands/start.ts only: the compile spawn gets stdio ['ignore', 'inherit', 'inherit'], and the serve spawn passes projectConfigPath as its config positional. That is the same path serve's default resolves to in the same cwd, so no serve input surface changes. The #7645 resume() path is untouched; the start-to-serve child simply never reaches tryStdin. I chose this over ignoreStdin on serve's config for two reasons: ignoreStdin would change serve's input surface, and it would defang the #7645 pin, which deliberately spawns serve with no positional so that it exercises resume(). Measured after the fix, with initialize written at spawn: answered (same id) in 8.8 s on a first run and in 6.6 s with dist/ present. Both times the host config's plugin was composed. The pin is packages/cli/test/start-mcp-stdio-early-initialize.integration.test.ts, in the integration tier. It needed scripts/check-cli-test-child-env.mjs to add it to that gate's pinned built-entrypoint population, the same edit every earlier member made.",
"tests": "Pin, at ab0727f:
pnpm --filter @objectstack/cli exec vitest run --project integration --maxWorkers=2 test/start-mcp-stdio-early-initialize.integration.test.ts→ Test Files 1 passed, Tests 1 passed, 14.85 s. Earlier runs at fd16e46: 14.61 s and 14.40 s. Unit tier, at fd16e46:pnpm --filter @objectstack/cli exec vitest run --project unit --maxWorkers=2→ Test Files 309 passed, Tests 4591 passed. The later commits touched only the new integration pin and one gate script, and the merge from main touched no packages/cli path. Typecheck:pnpm --filter @objectstack/cli typecheck→ exit 0, and check:test-typecheck OK.tsc -p tsconfig.test.json --noEmit --listFileslists the new pin once. The integration tier ran locally for the new file only; the rest of it is left to CI (Test Core 1–6 success at ab0727f). test:repo was not run locally; it belongs to CI. Reverse verification. The fix was committed first. Each leg went through scripts/ablation-replace.mjs and ablation-dist-preflight.mjs, with a trap restore and a CLI rebuild per leg. Compile leg (stdio back to inherit): the dist marker "'ignore', 'inherit', 'inherit'" is absent (preflight exit 0) and the pin is RED: 'initialize was never answered / os start exited 1 before answering', with 'Config file not found: …/{"jsonrpc":"2.0","id":24002,…}' in the transcript. Restored: blob d874e9853 equals HEAD, git diff HEAD is empty, and the rebuilt dist carries the marker again (exit 0). Serve leg (positional line deleted): the marker is absent (preflight exit 0, with --source-marker) and the pin is RED: 'no answer within 120000 ms', with 'No objectstack.config.ts found — booting from artifact' in the transcript. Restored the same way. Two earlier serve-leg attempts were voided and measured nothing. In the first, ablation-replace refused because the replacement was a substring of the anchor (a rise of 0) and restored the file. In the second, the preflight tree reading exited 3 because the src and dist indentation differ. The test never ran in either. Both directions came out as predicted: RED.","gates": "Local derived union at the final head ab0727f:
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderived 85 commands, all 85 exited 0 (each exit captured before any pipe), and--ranreconciled them: "85 derived, 85 run, 0 NOT-MEASURED, 0 UNRUN" (exit 0). That set includes check:cli-test-child-env (12 built-CLI spawns, all out of development/test), check:pm-dispatch-gates (fast tier 1884 cases), check:nul-bytes, check:dual-build-cjs-loads and check:i18n-coverage. An earlier 65-command run at 0c194a8 had check:cli-test-child-env exit 1 because of this pin; ab0727f fixed it. The same run had two prerequisite exit-3s that the final-head run measured green. Lane blind spot:pnpm exec eslint --no-inline-config packages/cli/src/commands/start.ts packages/cli/test/start-mcp-stdio-early-initialize.integration.test.ts scripts/check-cli-test-child-env.mjs→ exit 0, no output. Edited gate script:node scripts/check-cli-test-child-env.mjs --self-test→ 152 cases pass. The only test-file hit for the script name is a prose mention in serve-node-env-production-default.e2e.test.ts; no suite exercises it. check-platform-checklist: not applicable, because no exported symbol was renamed or deleted. PR #24184 check-runs at ab0727f (40 runs), all success or skipped: Lint & Repo Gates success, TypeScript Type Check success, Test Core success (shards 1–6 success), Build Core success, Governed Surface Queue Guard success, Check Changeset success, Dogfood Regression Gate success, Type Check (workspace, source, consumer, debt ledger) success, Lint (ESLint, PM dispatch-gates, docs & code guards, repo & tooling, CI/release/engine, scoped x3) success, Check PR Size success, The card this PR closes must claim this branch success, No other open PR may claim the same issue success.","line_budget": "n/a — no skills/** path touched",
"files_changed": [
"packages/cli/src/commands/start.ts",
"packages/cli/test/start-mcp-stdio-early-initialize.integration.test.ts",
"scripts/check-cli-test-child-env.mjs",
".changeset/24002-start-mcp-stdio-early-initialize.md"
],
"deviations": [
"Surface: the claim named the spawnChild argv (about :486-500). The measured fix also edits the compile spawnSync (about :243) in the same start.ts, because on a first run it is the first stdin consumer. Explained in the PR body.",
"Surface: scripts/check-cli-test-child-env.mjs gains the new pin in its pinned built-entrypoint population (renamed "ten" to "eleven"). The gate requires this of every file that spawns bin/run.js. Its self-test passes, 152 cases.",
"Branch: merged origin/main once (0c194a8, before the PR was opened) because dispatch-gates flagged the tree as stale. The incoming commits touch no packages/cli path. After that merge, .claude/agents/os-dev.md on main folds labels into pr_create (a write budget of three strokes). This run used git push, one pr_create and one comment, with zero label writes: the dispatch named no labels and skip-changeset does not apply (a patch changeset ships).",
"PR body: it was written once, before the final-head union finished. Its "Local verification" bullets report the earlier 65-command run (two NOT MEASURED) and point to this report. Suggested seat edit: replace those two bullets with this report's gates reading (85/85 exit 0 at ab0727f, --ran 0 NOT-MEASURED, CI green).",
"Ablation: two serve-leg attempts were voided as no-ops (see tests). They are declared, not rerun silently."
],
"mcp_calls": "0 — no MCP GitHub tool used, read or write",
"api_writes": "3 REST writes in 2 relay strokes, both through scripts/pm/with-fleet.sh to scripts/pm/fleet-write/dispatch.mjs, each POST /repos/objectstack-ai/objectstack/dispatches. Stroke 1, pr_create: POST /repos/objectstack-ai/objectstack/pulls (draft) and POST /repos//issues/24184/assignees [marchtian]; the relay read back an identical 9883-byte body. Stroke 2: POST /repos//issues/24002/comments (this report). git push is not counted.",
"open_questions": [],
"out_of_scope_findings": [
"class: a · reach:
os servewith no positional (the public door), with OS_MCP_STDIO_ENABLED and a valid key, an initialize written at spawn, from a project dir holding objectstack.config.ts and dist/. Wrong answer, measured on b0fe9fa with the built CLI: no JSON-RPC answer in 60 s, 'No objectstack.config.ts found — booting from artifact' printed beside the config, and the host plugin never composed. The controlos serve objectstack.config.tsanswers in 4.0 s with the config loaded. Same mechanism (serve's config Args.string has no ignoreStdin). Fix shape: ignoreStdin: true on serve's config positional, plus re-grounding the premise of serve-mcp-stdio-answers.e2e.test.ts, which deliberately spawns serve with no positional to exercise the #7645 resume(). Stdin-fed serve config search: 0 hits for shell-piped config into serve/start/compile; stdin.write/stdin.end under packages/cli gives 5 hits, none a config path. · dedupe: os serve stdio initialize stdin config positional; serve no positional early initialize swallowed; serve config arg ignoreStdin tryStdin","class: a · reach:
os startwith OS_MCP_STDIO_ENABLED on a first run (no dist/objectstack.json), the documented stdio invocation. Wrong answer, measured at fd16e46 (fixed build): 27 non-JSON lines from the compile child ('◆ Compile', '✓ Build complete', 'Artifact: …') precede the initialize answer on stdout, the stdio transport's protocol channel. start redirects its own stdout to stderr, but the compile spawnSync passes inherited fd 1 (stdout-purity family, not stdin). · dedupe: os start compile stdout MCP stdio purity; auto-compile banner protocol channel; start spawnSync compile stdout inherit","carrier: none · os dev: its own
packagepositional (default all) and its serve child (no positional) also read a pending stdin line. os dev is not a stdio door (docs/qa/platform-checklist/areas/ai.json: "Notos dev", because its banner owns stdout), so noted in the PR's Acceptance notes and not filed."]
}
objectstack-fleet commentedon Oct 17, 2026
ACCEPT → PR #24184 comment
6236434386·domain:cliseat 2 · sessionsession_01QyoWKK9RwUNxBxmevy9Neb· 2026-10-17T16:14Z · headab0727fa5all green; landing armed in this window. Out-of-scope findings filed as #24191 and #24192.Generated by Claude Code
objectstack-fleet commentedon Oct 17, 2026
Landed: PR #24184 →
7d6ec91d2(#24002,Fixes #24002) ·domain:cliseat 2 ·marchtian· sessionsession_01QyoWKK9RwUNxBxmevy9Neb· 2026-10-17T16:38Zmerged: true, merge commit7d6ec91d2, merged 2026-10-17T16:38Z through the merge queue (enqueued 2026-10-17T16:17Z)origin/main7d6ec91d2is an ancestor oforigin/main, with a single parent (squash). The 4 files and +384 / −2 match what was reviewed atab0727fa5gh-readonly-queue/main/*pr-24184*head remains6234975954→ report6236314177→ ACCEPT6236434386on PR fix(cli): os start answers an MCP initialize written at spawn — its compile and serve children no longer read stdin as the config path #24184 → pointer6236445023. Cross-lane declaration on [PM seat] domain:spec — ⏳ vacant #6017:6236419477(no objection).completedbyFixes.pm:dispatchedis stripped in this act, anddomain:cli/priority:p2/area:aistay.os servewith the stdio MCP transport and no config positional reads the client's earlyinitializeas its config path; it boots without the config and never answers #24191 (os servewith no positional) and cli: on a first run,os startwith the stdio MCP transport lets its compile step write 27 non-JSON lines to stdout, the protocol channel, ahead of theinitializeanswer #24192 (first-run compile output on the protocol stdout).Generated by Claude Code
chore(cli): changeset, measured budget and child-env population for t…