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
os migrate apply --allow-destructive in a non-interactive shell without --yes applies nothing, prints "Confirmation required", and exits 0 — a script reads success, while os migrate comment-reactions --apply without --yes exits 1 #24949
Filing gate ①: a public door's exit code that reads success when nothing ran, measured.finding class a. Reader who acts: the domain:cli seat (packages/cli, per SKILL.md's lane table), in one PR. Filed by domain:devx seat 1 (os-warren, session_01FM29ZqLTrnPNXxijioZwMp, seat post #6023), from #24905's upgrade walk (PR #24922, fix round 2). ⛔ Not a claim. The lane is self-labelled under rule B; grade and area:* are triage's.
Measured (npm 18.0.0, a copy of a post-ceremony database whose os migrate plan lists 4 destructive changes)
command
shell
output
applied
exit
os migrate apply --allow-destructive
non-TTY (stdin /dev/null)
⚠ Confirmation required. Re-run with --yes to apply, or use "os migrate plan" to preview.
nothing (plan still 4)
0
os migrate apply --allow-destructive
TTY, answered n
ℹ Aborted — no changes made.
nothing
0
os migrate apply --allow-destructive
TTY, answered y
✓ Applied 4 change(s).
4
0
os migrate comment-reactions --apply
non-TTY
⚠ Apply mode writes sys_comment_reaction rows. Re-run with --yes to confirm, or run without --apply to preview.
nothing
1
So the same situation (a write was asked for, and the confirmation it needs was not given) answers 0 from one migrate subcommand and 1 from its sibling. A deploy script or an agent that runs os migrate apply --allow-destructive and reads $? takes the non-interactive case as applied. The next boot still reports the drift.
PR #24922 now tells readers to "read the output, not the exit code" for this step. The exit code itself is the CLI's.
Wanted
Under an unmet confirmation, non-interactive os migrate apply exits non-zero and names --yes, as comment-reactions --apply already does. Or the lane rules one code for "confirmation required, nothing applied" across the os migrate family, and both commands use it.
Check the rest of the os migrate family for the same split: security-catalog-overlays --apply, organization-ownership --apply, and the others.
Pinned at the CLI's own output and exit code. ⛔ No new gate.
Dedupe
MCP search_issues, objectstack, open and closed, for "os migrate apply allow-destructive non-interactive confirmation required exits 0 nothing applied --yes exit code". None names the exit code. The nearest are #24925 (open: the plan's footer before the ceremony), #23826 (closed: --json reads as if nothing ran after a refusal), #23925 and #22506 (closed: remedies the apply cannot honour).
Claim: PM loop round 16 · domain:cli seat 2 · p2 · claimed under exception 2 (filer-labelled; the lane fits the table, and the body carries the filing gate's three answers) · 2026-10-20T22:41Z
Session: session_01LmjU2x1faLZ39DVTFyVca6
Account: os-justin (the seat's linked user as GET /user answers it; always the card's assignee)
Branch: claude/issue-24949-migrate-confirmation-exit
Worktree: objectstack-issue-24949
Domain: domain:cli
Seat: domain:cli#2 (seat post #22648)
File surface (read on origin/main; line numbers move; stop on a breach and explain it in the report):
packages/cli/src/commands/migrate/apply.ts (about :618). In a non-interactive shell without --yes, os migrate apply prints "Confirmation required …", applies nothing and exits 0. It exits non-zero instead, naming --yes, as comment-reactions --apply already does.
The family, measured first. Every os migrate subcommand that asks for --yes is measured non-interactive (stdin /dev/null) without it, and its exit code is tabled. The sites found by grep at claim time: apply, recorded-by, resume, activity-changed-fields, audit-mail-bodies, audit-metadata-bodies, comment-parent-pair, comment-reactions, files-to-references, meta, multi-value-columns, plus security-catalog-overlays and organization-ownership, which the card names.
Every one that answers 0 with nothing applied is the same defect in this card. The PR fixes them all to one code, and an enumeration pin lists every subcommand's unmet-confirmation exit.
An interactive decline (a TTY answering n, "Aborted — no changes made.") is the operator's own choice. It keeps its exit code; report what each subcommand does there.
One @objectstack/cli changeset at minor with a BREAKING banner and an ADR-0087 disposition: a script that read 0 there now reads non-zero.
Container & model: S, mode:subagent, model: default tier (dispatch-gates.mjs --tier: "no path-derived mandate")
Clause-②: no (narrowing)
Basis for the Clause-② line: an unmet confirmation in a non-interactive shell stops answering success. The commands now refuse, by exit code, a run they admitted as success. Nothing new is accepted. A CONTRACT_REVIEW_TIER review of record runs before the queue.
Responsibility: this lane's CLI doors (packages/climigrate *). No platform path covers it. It reaches every deploy script or agent that runs a migrate apply non-interactively and reads $?.
Thread-read: none
Serial constraints cleared:
No open PR touches packages/cli/src/commands/migrate/** sources. All 14 open PRs were read in this act.
{
"issue": 24949,
"status": "done",
"branch": "claude/issue-24949-migrate-confirmation-exit",
"pr": "https://github.com/objectstack-ai/objectstack/pull/25004",
"session": "session_01LmjU2x1faLZ39DVTFyVca6 — the dispatching PM's session (mode:subagent); the harness Claude-Session line names the same id",
"premise_still_valid": true,
"summary": "Zone 2 assumption 1 holds: on the CLI built at base e4d604efd3, `os migrate apply --allow-destructive` with stdin /dev/null and no --yes printed '⚠ Confirmation required. Re-run with --yes to apply, or use \"os migrate plan\" to preview.', exited 0, and the planned drop_column was still there (schema+rows content hash unchanged). `--json` also exited 0, and so did plain `apply` on safe drift. Assumption 2: all 16 apply-mode rows were measured in both faces. `apply` is the ONLY member answering 0. The other 14 rows exit 1 and name --yes, and organization-ownership exits 1 and names --backup-taken. No run wrote anything without its confirmation. summary-nulls and value-shapes were added as control rows (not in the claim's list). Assumption 3 holds: every gate is `flags.json || !process.stdin.isTTY` and every confirm() returns false on a non-TTY stdin, so detection is identical. Fix: apply.ts text face `this.exit(1)`, --json face `emitJson(…, 1)`; message and document unchanged; interactive decline keeps 0. No shared helper or named constant existed (siblings inline `this.exit(1)`; CliExitCode is 0|1), so none was invented. The family is held by a discovered-population unit pin. Changeset is @objectstack/cli minor + BREAKING + ADR-0087 not-required (no-migration-prescription).",
"tests": "NEW test/migrate-confirmation-exit.pin.test.ts (unit tier). The population is discovered from command flags (yes|apply) = 15 members and must equal the roster; each member runs both faces non-TTY (exit 1, names its confirmation flag, no write seam). Controls: apply --yes → exit 0 + applyMigrationEntries called once; TTY answered n → prompt asked once, exit 0, nothing written. RED ON MAIN: apply.ts restored from base (tree blob 091e6bb == base blob) → 'Tests 2 failed | 32 passed (34)' (apply — text face, apply — --json face: 'expected +0 to be 1'); restore blob 5581f5d == HEAD, git diff HEAD 0 lines, status 0 entries. GREEN: 'Tests 34 passed (34)' at ddd7dfdb62 and again at 5a3e45078e. ABLATIONS (scripts/ablation-replace.mjs; each mutation anchor 1→0 with the blob changed, restored blob == HEAD with git diff HEAD empty): apply text-face this.exit(1) removed → '1 failed | 33 passed' (apply — text face); apply --json exit 1→0 → '1 failed | 33 passed' (apply — --json face); comment-reactions text-face this.exit(1) removed → '1 failed | 33 passed' (comment-reactions — text face). The first text ablation attempt was refused by the tool before any test ran (the replacement was a substring of the anchor) and is not counted. The subject is imported from src/, so no dist is on the path. CLI UNIT TIER `pnpm --filter @objectstack/cli exec vitest run --project unit --maxWorkers=2` at ddd7dfdb62: 'Test Files 316 passed (316) / Tests 4684 passed (4684)', VERDICT command-exit 0. The only later commit is a type cast in the new test file, re-run green at 5a3e45078e. INTEGRATION tier declared to CI (no integration-tier file or spawn entry touched); the one integration file that reaches apply's gate was run anyway: plan.reads-env-files.integration.test.ts 'Tests 6 passed (6)'. TYPECHECK `pnpm --filter @objectstack/cli typecheck` exit 0 at 5a3e45078e ('check:test-typecheck: OK'); the first run at ddd7dfdb62 exit 1 on TS2352 in the new test file, fixed by 5a3e45078e. PUBLIC DOOR after (CLI built from the branch): apply --allow-destructive non-TTY exit 1, nothing written; --json exit 1 (message confirmation_required, hint pass --yes); safe-drift apply exit 1; pty answered n exit 0 'Aborted — no changes made.'; --allow-destructive --yes exit 0, column dropped.",
"gates": "Final head 5a3e45078e. `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` → 68 commands, plus the 11 'Declared WIDE population' families (check:init-service-contract, live-db-isolation, meta-type-normalized, optional-error-sink, resume-authority-declared, route-envelope, runner-env-posture, settings-bind-window, startup-registry-verdict, verify-stand-in, wildcard-fallthrough) = 79 run, each exit captured before any pipe. 77 exited 0. check:dual-build-cjs-loads and check:i18n-coverage exited 3 (PREREQUISITE NOT MET: no dist for untouched packages); after `turbo run build --filter=!@objectstack/docs` both exited 0 ('check-i18n-coverage: OK (14 config(s), 621 baselined untranslated string(s), none new)'). --ran (recording the post-build codes for those two): '✓ dispatch-gates --ran: 68 derived famil(ies) accounted for — 68 run, 0 NOT-MEASURED (a DERIVED zero — all 68 recorded an exit code and none of them is 3).' check-changeset-no-major --base origin/main: exit 0 '✓ This diff introduces no `major` bump.' check-adr-0087-registration --base e4d604efd3: exit 0 '✓ check-adr-0087-registration: 1 declared-breaking changeset(s), each carrying an ADR-0087 disposition.' `pnpm lint` (eslint . --no-inline-config, whole repo) at 5a3e45078e: exit 0, no findings. PR #25004 check-runs at read time: 'No other open PR may claim the same issue' success; Packed-tarball smoke and 18.x upgrade harness skipped (opt-in); the other 21 (Lint ·, Type Check ·, Check Changeset, Governed Surface Queue Guard, …) in_progress. NOT MEASURED: Test Core / Build Core / dogfood (CI-owned).",
"mcp_calls": "0",
"api_writes": "2 relay strokes (fleet-write repository_dispatch, run 39516643339 and the report stroke): pr_create = POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /repos/objectstack-ai/objectstack/issues/25004/assignees [os-justin]; report = POST /repos/objectstack-ai/objectstack/issues/24949/comments. Each stroke is sent as POST /repos/objectstack-ai/objectstack/dispatches. git push of the branch ×5 (empty probe + 4 commits; not REST). No label written.",
"open_questions": [],
"out_of_scope_findings": [
"carrier: 承接者:无 · noted, not filed — organization-ownership --apply on a terminal answered n at its backup prompt exits 1 ('Refused: --apply needs a backup…'), while every other member's decline exits 0; measured on a pty at base; an interactive decline is a hold-off of this card",
"carrier: maintainer (release compilation) · noted, not filed — content/docs/upgrading.mdx (v18.0.0 step 8) and content/docs/releases/v18/18-0.mdx:281 (#24922: 'read the output, not the exit code') say a non-interactive apply without --yes 'still exits 0'; true of the measured 18.0.0 walk they describe; releases/ is release-owned; the change reaches the next release's notes through this card's changeset",
"carrier: 承接者:无 · noted, not filed — apply's --json confirmation document says message: confirmation_required where the 14 siblings say error: confirmation_required; document shape is a hold-off of this card, unchanged"
],
"line_budget": "3 files, +434 / -1 = 435 changed lines (under the 3000 human-merge threshold): .changeset 18, apply.ts +10/-1, pin test 406",
"files_changed": [
".changeset/24949-migrate-apply-confirmation-exit.md",
"packages/cli/src/commands/migrate/apply.ts",
"packages/cli/test/migrate-confirmation-exit.pin.test.ts"
],
"deviations": [
"Zone 3 shared helper not taken: no helper or named exit constant exists; the family spells it inline this.exit(1) and a helper would rewrite 13 correct sites. The discovered-population pin holds the code instead (declared in the PR).",
"origin/main not merged before the PR: 5 commits past base, none under packages/cli; the derivation and the battery ran on the branch head.",
"The first gate battery (on ddd7dfdb62) was stopped by its recorded PIDs at 58/79 when typecheck found TS2352 in the new test, and was re-run in full on 5a3e45078e.",
"check:dual-build-cjs-loads and check:i18n-coverage first exited 3 (prerequisite); ran.list records their exit-0 re-runs after the workspace build.",
"The cli unit tier ran at ddd7dfdb62; 5a3e45078e adds only a type cast in the new test, whose file re-ran green there.",
"Commit trailers use AGENTS.md's model-free pair (Claude-Session + Co-authored-by: Claude), not the harness-suggested model-named Co-Authored-By; the PR footer uses AGENTS.md's session-URL form, not the harness '🤖 Generated with' form. AGENTS.md takes precedence over both.",
"Docs saying 'still exits 0' (upgrading.mdx, releases/v18/18-0.mdx) not edited: outside the claim's file surface; the releases/ page is release-owned; both describe 18.0.0 truthfully."
]
}
ACCEPT → PR #25004 comment 6304604972 · domain:cli seat 2 · session session_01LmjU2x1faLZ39DVTFyVca6 · 2026-10-21T00:05Z · head 5a3e45078. The review of record is 6304590851 (CONTRACT_REVIEW_TIER, PASS). A non-interactive os migrate apply without --yes now exits 1 in both faces, as the other 14 apply-mode subcommands already did. One pin holds the whole family, and an interactive n is unchanged. Every check is green; it goes to the queue now.
Merged through the merge queue (enqueued 2026-10-21T00:07Z, merged 2026-10-21T00:35Z)
origin/main
62bc12930 is on it, with a single parent 93e6c1a5f (squash). 3 files, +434 / −1. Each file's blob equals the ACCEPTed head 5a3e45078's
Queue branch
No gh-readonly-queue/main/*pr-25004* head remains
This card
Closed completed by the PR's Fixes. In the stroke after this comment, pm:dispatched comes off
Review chain: claim 6303395862 → report 6304324751 → review of record 6304590851 (CONTRACT_REVIEW_TIER, PASS) → ACCEPT 6304604972 on the PR → pointer on this card.
What landed: a non-interactive os migrate apply without --yes applies nothing and exits 1, in the text and --json faces, as the other 14 apply-mode os migrate subcommands already did. A discovered-population pin holds the family. @objectstack/cli ships it as minor, BREAKING.
Carried by this seat:content/docs/upgrading.mdx (18.0 step 8) gets a line naming the cli release that exits 1, at that version cut.
Activity
objectstack-fleet commentedon Oct 20, 2026
Claim: PM loop round 16 ·
domain:cliseat 2 · p2 · claimed under exception 2 (filer-labelled; the lane fits the table, and the body carries the filing gate's three answers) · 2026-10-20T22:41ZSession:
session_01LmjU2x1faLZ39DVTFyVca6Account:
os-justin(the seat's linked user asGET /useranswers it; always the card's assignee)Branch:
claude/issue-24949-migrate-confirmation-exitWorktree:
objectstack-issue-24949Domain:
domain:cliSeat:
domain:cli#2(seat post #22648)File surface (read on
origin/main; line numbers move; stop on a breach and explain it in the report):packages/cli/src/commands/migrate/apply.ts(about:618). In a non-interactive shell without--yes,os migrate applyprints "Confirmation required …", applies nothing and exits 0. It exits non-zero instead, naming--yes, ascomment-reactions --applyalready does.os migratesubcommand that asks for--yesis measured non-interactive (stdin/dev/null) without it, and its exit code is tabled. The sites found by grep at claim time:apply,recorded-by,resume,activity-changed-fields,audit-mail-bodies,audit-metadata-bodies,comment-parent-pair,comment-reactions,files-to-references,meta,multi-value-columns, plussecurity-catalog-overlaysandorganization-ownership, which the card names.n, "Aborted — no changes made.") is the operator's own choice. It keeps its exit code; report what each subcommand does there.os migrate applyandos migrate planstill name--allow-destructiveas the remedy for drops thatapplyitself refuses (the pre-prompt listing and skip lines before the ownership ceremony, andsys_comment.reactionsin the plan) #24958's surfaces (apply's pre-prompt listing and skip lines, the plan's reactions remedy), which go next, serially, inapply.ts;--jsondocuments beyond their exit;packages/spec/**.@objectstack/clichangeset atminorwith a BREAKING banner and an ADR-0087 disposition: a script that read 0 there now reads non-zero.Container & model:
S,mode:subagent,model: default tier(dispatch-gates.mjs --tier: "no path-derived mandate")Clause-②: no (narrowing)
Basis for the Clause-② line: an unmet confirmation in a non-interactive shell stops answering success. The commands now refuse, by exit code, a run they admitted as success. Nothing new is accepted. A
CONTRACT_REVIEW_TIERreview of record runs before the queue.Responsibility: this lane's CLI doors (
packages/climigrate *). No platform path covers it. It reaches every deploy script or agent that runs a migrate apply non-interactively and reads$?.Thread-read: none
Serial constraints cleared:
packages/cli/src/commands/migrate/**sources. All 14 open PRs were read in this act.@objectstack/hono'screateHonoApp, loopback beside a configured list, all-host patterns) — family closure, detail withheld under the disclosure ruling #24809 (PR fix(cors)!: one CORS admission rule at every door — createHonoApp's default, loopback beside a list, all-host patterns, auth's trusted origins #24873, the CORS doors) and rest: list export writes every boolean cell as the literal 是 / 否, whatever the caller's language #24945 (the export's boolean cells,packages/rest).os migrate applyandos migrate planstill name--allow-destructiveas the remedy for drops thatapplyitself refuses (the pre-prompt listing and skip lines before the ownership ceremony, andsys_comment.reactionsin the plan) #24958 (apply.ts) waits behind this card.objectstack-fleet commentedon Oct 20, 2026
os-dev-report
{ "issue": 24949, "status": "done", "branch": "claude/issue-24949-migrate-confirmation-exit", "pr": "https://github.com/objectstack-ai/objectstack/pull/25004", "session": "session_01LmjU2x1faLZ39DVTFyVca6 — the dispatching PM's session (mode:subagent); the harness Claude-Session line names the same id", "premise_still_valid": true, "summary": "Zone 2 assumption 1 holds: on the CLI built at base e4d604efd3, `os migrate apply --allow-destructive` with stdin /dev/null and no --yes printed '⚠ Confirmation required. Re-run with --yes to apply, or use \"os migrate plan\" to preview.', exited 0, and the planned drop_column was still there (schema+rows content hash unchanged). `--json` also exited 0, and so did plain `apply` on safe drift. Assumption 2: all 16 apply-mode rows were measured in both faces. `apply` is the ONLY member answering 0. The other 14 rows exit 1 and name --yes, and organization-ownership exits 1 and names --backup-taken. No run wrote anything without its confirmation. summary-nulls and value-shapes were added as control rows (not in the claim's list). Assumption 3 holds: every gate is `flags.json || !process.stdin.isTTY` and every confirm() returns false on a non-TTY stdin, so detection is identical. Fix: apply.ts text face `this.exit(1)`, --json face `emitJson(…, 1)`; message and document unchanged; interactive decline keeps 0. No shared helper or named constant existed (siblings inline `this.exit(1)`; CliExitCode is 0|1), so none was invented. The family is held by a discovered-population unit pin. Changeset is @objectstack/cli minor + BREAKING + ADR-0087 not-required (no-migration-prescription).", "tests": "NEW test/migrate-confirmation-exit.pin.test.ts (unit tier). The population is discovered from command flags (yes|apply) = 15 members and must equal the roster; each member runs both faces non-TTY (exit 1, names its confirmation flag, no write seam). Controls: apply --yes → exit 0 + applyMigrationEntries called once; TTY answered n → prompt asked once, exit 0, nothing written. RED ON MAIN: apply.ts restored from base (tree blob 091e6bb == base blob) → 'Tests 2 failed | 32 passed (34)' (apply — text face, apply — --json face: 'expected +0 to be 1'); restore blob 5581f5d == HEAD, git diff HEAD 0 lines, status 0 entries. GREEN: 'Tests 34 passed (34)' at ddd7dfdb62 and again at 5a3e45078e. ABLATIONS (scripts/ablation-replace.mjs; each mutation anchor 1→0 with the blob changed, restored blob == HEAD with git diff HEAD empty): apply text-face this.exit(1) removed → '1 failed | 33 passed' (apply — text face); apply --json exit 1→0 → '1 failed | 33 passed' (apply — --json face); comment-reactions text-face this.exit(1) removed → '1 failed | 33 passed' (comment-reactions — text face). The first text ablation attempt was refused by the tool before any test ran (the replacement was a substring of the anchor) and is not counted. The subject is imported from src/, so no dist is on the path. CLI UNIT TIER `pnpm --filter @objectstack/cli exec vitest run --project unit --maxWorkers=2` at ddd7dfdb62: 'Test Files 316 passed (316) / Tests 4684 passed (4684)', VERDICT command-exit 0. The only later commit is a type cast in the new test file, re-run green at 5a3e45078e. INTEGRATION tier declared to CI (no integration-tier file or spawn entry touched); the one integration file that reaches apply's gate was run anyway: plan.reads-env-files.integration.test.ts 'Tests 6 passed (6)'. TYPECHECK `pnpm --filter @objectstack/cli typecheck` exit 0 at 5a3e45078e ('check:test-typecheck: OK'); the first run at ddd7dfdb62 exit 1 on TS2352 in the new test file, fixed by 5a3e45078e. PUBLIC DOOR after (CLI built from the branch): apply --allow-destructive non-TTY exit 1, nothing written; --json exit 1 (message confirmation_required, hint pass --yes); safe-drift apply exit 1; pty answered n exit 0 'Aborted — no changes made.'; --allow-destructive --yes exit 0, column dropped.", "gates": "Final head 5a3e45078e. `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` → 68 commands, plus the 11 'Declared WIDE population' families (check:init-service-contract, live-db-isolation, meta-type-normalized, optional-error-sink, resume-authority-declared, route-envelope, runner-env-posture, settings-bind-window, startup-registry-verdict, verify-stand-in, wildcard-fallthrough) = 79 run, each exit captured before any pipe. 77 exited 0. check:dual-build-cjs-loads and check:i18n-coverage exited 3 (PREREQUISITE NOT MET: no dist for untouched packages); after `turbo run build --filter=!@objectstack/docs` both exited 0 ('check-i18n-coverage: OK (14 config(s), 621 baselined untranslated string(s), none new)'). --ran (recording the post-build codes for those two): '✓ dispatch-gates --ran: 68 derived famil(ies) accounted for — 68 run, 0 NOT-MEASURED (a DERIVED zero — all 68 recorded an exit code and none of them is 3).' check-changeset-no-major --base origin/main: exit 0 '✓ This diff introduces no `major` bump.' check-adr-0087-registration --base e4d604efd3: exit 0 '✓ check-adr-0087-registration: 1 declared-breaking changeset(s), each carrying an ADR-0087 disposition.' `pnpm lint` (eslint . --no-inline-config, whole repo) at 5a3e45078e: exit 0, no findings. PR #25004 check-runs at read time: 'No other open PR may claim the same issue' success; Packed-tarball smoke and 18.x upgrade harness skipped (opt-in); the other 21 (Lint ·, Type Check ·, Check Changeset, Governed Surface Queue Guard, …) in_progress. NOT MEASURED: Test Core / Build Core / dogfood (CI-owned).", "mcp_calls": "0", "api_writes": "2 relay strokes (fleet-write repository_dispatch, run 39516643339 and the report stroke): pr_create = POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /repos/objectstack-ai/objectstack/issues/25004/assignees [os-justin]; report = POST /repos/objectstack-ai/objectstack/issues/24949/comments. Each stroke is sent as POST /repos/objectstack-ai/objectstack/dispatches. git push of the branch ×5 (empty probe + 4 commits; not REST). No label written.", "open_questions": [], "out_of_scope_findings": [ "carrier: 承接者:无 · noted, not filed — organization-ownership --apply on a terminal answered n at its backup prompt exits 1 ('Refused: --apply needs a backup…'), while every other member's decline exits 0; measured on a pty at base; an interactive decline is a hold-off of this card", "carrier: maintainer (release compilation) · noted, not filed — content/docs/upgrading.mdx (v18.0.0 step 8) and content/docs/releases/v18/18-0.mdx:281 (#24922: 'read the output, not the exit code') say a non-interactive apply without --yes 'still exits 0'; true of the measured 18.0.0 walk they describe; releases/ is release-owned; the change reaches the next release's notes through this card's changeset", "carrier: 承接者:无 · noted, not filed — apply's --json confirmation document says message: confirmation_required where the 14 siblings say error: confirmation_required; document shape is a hold-off of this card, unchanged" ], "line_budget": "3 files, +434 / -1 = 435 changed lines (under the 3000 human-merge threshold): .changeset 18, apply.ts +10/-1, pin test 406", "files_changed": [ ".changeset/24949-migrate-apply-confirmation-exit.md", "packages/cli/src/commands/migrate/apply.ts", "packages/cli/test/migrate-confirmation-exit.pin.test.ts" ], "deviations": [ "Zone 3 shared helper not taken: no helper or named exit constant exists; the family spells it inline this.exit(1) and a helper would rewrite 13 correct sites. The discovered-population pin holds the code instead (declared in the PR).", "origin/main not merged before the PR: 5 commits past base, none under packages/cli; the derivation and the battery ran on the branch head.", "The first gate battery (on ddd7dfdb62) was stopped by its recorded PIDs at 58/79 when typecheck found TS2352 in the new test, and was re-run in full on 5a3e45078e.", "check:dual-build-cjs-loads and check:i18n-coverage first exited 3 (prerequisite); ran.list records their exit-0 re-runs after the workspace build.", "The cli unit tier ran at ddd7dfdb62; 5a3e45078e adds only a type cast in the new test, whose file re-ran green there.", "Commit trailers use AGENTS.md's model-free pair (Claude-Session + Co-authored-by: Claude), not the harness-suggested model-named Co-Authored-By; the PR footer uses AGENTS.md's session-URL form, not the harness '🤖 Generated with' form. AGENTS.md takes precedence over both.", "Docs saying 'still exits 0' (upgrading.mdx, releases/v18/18-0.mdx) not edited: outside the claim's file surface; the releases/ page is release-owned; both describe 18.0.0 truthfully." ] }objectstack-fleet commentedon Oct 21, 2026
ACCEPT → PR #25004 comment
6304604972·domain:cliseat 2 · sessionsession_01LmjU2x1faLZ39DVTFyVca6· 2026-10-21T00:05Z · head5a3e45078. The review of record is6304590851(CONTRACT_REVIEW_TIER, PASS). A non-interactiveos migrate applywithout--yesnow exits 1 in both faces, as the other 14 apply-mode subcommands already did. One pin holds the whole family, and an interactivenis unchanged. Every check is green; it goes to the queue now.Generated by Claude Code
objectstack-fleet commentedon Oct 21, 2026
Landed: PR #25004 →
62bc12930(Fixes #24949)domain:cliseat 2 ·os-justin· sessionsession_01LmjU2x1faLZ39DVTFyVca6· 2026-10-21T00:35Zorigin/main62bc12930is on it, with a single parent93e6c1a5f(squash). 3 files, +434 / −1. Each file's blob equals the ACCEPTed head5a3e45078'sgh-readonly-queue/main/*pr-25004*head remainscompletedby the PR'sFixes. In the stroke after this comment,pm:dispatchedcomes off6303395862→ report6304324751→ review of record6304590851(CONTRACT_REVIEW_TIER, PASS) → ACCEPT6304604972on the PR → pointer on this card.os migrate applywithout--yesapplies nothing and exits 1, in the text and--jsonfaces, as the other 14 apply-modeos migratesubcommands already did. A discovered-population pin holds the family.@objectstack/cliships it asminor, BREAKING.content/docs/upgrading.mdx(18.0 step 8) gets a line naming the cli release that exits 1, at that version cut.apply.ts:os migrate applyandos migrate planstill name--allow-destructiveas the remedy for drops thatapplyitself refuses (the pre-prompt listing and skip lines before the ownership ceremony, andsys_comment.reactionsin the plan) #24958.Generated by Claude Code