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
spec: FLOW_FAILED carries the refused write's inner refusal — an optional userMessage on AutomationResult and one declared details member { code, message } on the trigger, resume, /actions and endpoint doors (ruling B′ on #24914) #24996
Filing gate ③ — the maintainer's 「同意」 on ruling B′ of #24914 (batch #379 item 5, the director's chat, 2026-10-20): the inner refusal of a refused flow write node reaches the client structurally, as a record save's does; the inner code takes the wire spelling (UNIQUE_VIOLATION for a unique refusal — the 2026-09-03 ruling, packages/runtime/src/http-dispatcher.ts:1204-1207). Filed by the director seat (summon #45 continuation 2, session_01Lg6GQ4xjqmvEzYv78d6H7i). ⛔ Not a claim.
Reader who acts: the domain:spec seat, first in the chain. One PR: Clause-②: yes (widening), minor, contract review at CONTRACT_REVIEW_TIER. It relaxes the #9585 two-key ceiling on /actionserror.details by the maintainer's ruling (batch #379 item 5), which the PR cites. Then #24914 follows (services: the four catch arms of crud-nodes.ts, engine carriage on both terminal exits and the retry exits, serial after PR #24778; cli: the four doors, the MCP bridges and the deps.error slot, declared on #22648), and the console half is an objectui card; both are pm:blocked on this card.
Dedupe: the 19 open domain:spec cards' titles read in this act: 0 name FLOW_FAILED, userMessage or AutomationResult; #24914's own dedupe (25 hits across both repositories, none an engine refusal inside a flow node reaching the user raw) stands.
What the ruling binds (origin/main e4d604efd39f)
AutomationResult (packages/spec/src/automation/flow.zod.ts, beside successMessage / errorMessage :1085–1086) gains an optional userMessage with ApiErrorSchema's semantics (packages/spec/src/api/contract.zod.ts:50-97: producer-marked end-user text that "never replaces message") and an optional inner-refusal member of shape { code, message }, code in its wire spelling. The member's name is the spec seat's; its shape is ruled.
The FLOW_FAILED details of the trigger, resume, /actions and endpoint doors declare that member ONCE (the ResumeFailureDetailsSchema pattern, packages/spec/src/api/automation-api.zod.ts:430), so the four doors emit one shape. message is unchanged everywhere: no wording pin moves.
Schema and api-surface regenerated; a spec test shows that a FLOW_FAILED envelope carrying details.<member> = { code: 'UNIQUE_VIOLATION', message } and a top-level userMessage validates on all four doors, and that an envelope without them still validates (optional, additive).
Changeset @objectstack/spec minor, Clause-②: yes (widening), citing the ruling.
Claim: PM loop round 25
Session: session_01D6F9axfoPzR7t8G1J7Ytzz
Account: baozhoutao (the seat's linked user as GET /user answers it; the card's assignee)
Branch: claude/issue-24996-flow-failed-inner-refusal
Worktree: objectstack-issue-24996
Domain: domain:spec
Seat: domain:spec#3 (seat post #18883)
File surface (at origin/main73432299c0 or later; stop on a breach and explain it in the report):
packages/spec/src/automation/flow.zod.ts: AutomationResult gains an optional userMessage and an optional inner-refusal member { code, message };
packages/spec/src/api/automation-api.zod.ts: the FLOW_FAILED details of the trigger, resume, /actions and endpoint doors declare that member once, on the ResumeFailureDetailsSchema pattern;
Read on origin/main73432299c0 at 2026-10-21T01:31Z: AutomationResult carries successMessage / errorMessage and no userMessage, and AutomationResult.code is a closed union (#9378).
{
"issue": 24996,
"status": "done",
"branch": "claude/issue-24996-flow-failed-inner-refusal",
"pr": "https://github.com/objectstack-ai/objectstack/pull/25037",
"session": "session_01D6F9axfoPzR7t8G1J7Ytzz",
"premise_still_valid": true,
"summary": "Contract half of ruling B-prime on #24914, spec only, with one runtime docblock. AutomationResult (contracts/automation-service.ts) gains optional userMessage (ApiErrorSchema.userMessage semantics, never replaces error) and optional innerRefusal: { code, message }; TriggerFlowResponseSchema.data mirrors both, and the #13078 parity pin holds. New in @objectstack/spec/api: FlowInnerRefusalSchema, whose code is the closed ErrorCode so the wire spelling is enforced, and FlowFailureDetailsSchema, declared once as the 400 FLOW_FAILED details of the trigger, resume, /actions and endpoint doors: errorMessage?, summary?, innerRefusal?. It is non-strict like ResumeFailureDetailsSchema, whose members sit beside it on resume. Member name: innerRefusal. It is the ruling's own words, fits the existing refusal vocabulary (FlowActionRefusal, classifyFlowRefusal, FlowRefusalCode), and stays distinct from refusalMessage, which belongs to the end-node outcome. Premise correction: the issue places AutomationResult in automation/flow.zod.ts :1085. Those lines are FlowSchema's authored successMessage/errorMessage; AutomationResult is the TS interface in contracts/automation-service.ts. flow.zod.ts is untouched, and contracts/automation-service.ts plus the runtime docblock are declared additions to the claim's file surface. The #9585 ceiling lives in runtime, not in contract.zod.ts. Its docblock (action-execution.ts FlowActionRunDetails) now cites ruling B-prime. The exact-equality negative pin (actions-flow-dispatch-status.test.ts) is deliberately left alone: nothing emits innerRefusal yet, so #24914 relaxes it with the emission. message, error.code FLOW_FAILED and AutomationResult.code are unchanged, with no new ledger code. The PR body notes the CONTRACT_REVIEW_TIER review owed, with two reviewer choices named: the closed ErrorCode on the inner code, and declaring the two existing artefacts beside the new key.",
"tests": "All at 22786c992e. Spec: pnpm --filter @objectstack/spec test: 703 files / 21382 passed, 1 todo. test:repo: 72 files / 1236 passed. typecheck exit 0 (includes check:test-typecheck, which compiles the new type pin FlowFailureInnerRefusalIsTheContracts). New suite in automation-api.zod.test.ts: for each of the four doors, an envelope with details.innerRefusal {code:'UNIQUE_VIOLATION', message} and a top-level userMessage validates via BaseResponseSchema and FlowFailureDetailsSchema, plus ResumeFailureDetailsSchema on resume. The same envelopes without either member validate. The key set is exactly the three ruled keys. An unregistered code (ER_DUP_ENTRY) is refused at ['code']. Both inner members are required. Trigger data accepts the mirror members. 66/66 in the file. check:generated --fix proved 5 artifacts stale (api-surface, export-origins, declaration-map, docs, strictness-ledger) and regenerated and re-checked them. Runtime: actions-flow-dispatch-status.test.ts (the ceiling pin) 19 passed, after building the runtime^... closure; the first attempt failed to resolve @objectstack/observability and was not measured. Runtime tsc --noEmit exit 0. Runtime check:test-typecheck exit 1 on an untouched file (organization-ownership-boot-guard.turso-remote.kernel.test.ts); the runtime diff is a docblock only, so that verdict is not attributable to this PR and CI decides. dispatch-gates --commands (stderr line 1: objectstack-ai/objectstack at 22786c992e, --repo checked) gave 113 commands, plus 6 roster families under touched dirs (changeset-fixed, meta-url-spelling, authz-resolver, error-code-casing, filter-alias-parity, route-ledger-census): 118 of 119 exit 0. Six were PREREQUISITE NOT MET on the first pass and green on re-run after the closure build: doc-formula-expressions, doc-security-posture, skill-examples, docs-transcript-drift, lean-entry-closure, type-check-debt. NOT MEASURED: check:dual-build-cjs-loads, reason: needs a full workspace build (93 packages without dist), declared to CI Build Core. NOT MEASURED: pnpm lint, which is CI-owned. --ran reconciliation not run. No ablation was run (the change is additive schema; the negative cases in the suite serve as the red leg).",
"mcp_calls": "0",
"api_writes": "2 relay strokes: (1) pr_create via fleet-write dispatch fw-20261021T031651Z-f1b996 = POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /repos/objectstack-ai/objectstack/issues/25037/assignees [baozhoutao], read back identical; (2) os-dev-report comment = POST /repos/objectstack-ai/objectstack/issues/24996/comments. Plus git push (not REST). label-write: zero writes, because the dispatch named no labels and skip-changeset does not apply (the PR carries a changeset).",
"open_questions": [],
"out_of_scope_findings": [
"carrier: #24914 (services/cli emission lane) · relax the exact-equality negative pin in packages/runtime/src/actions-flow-dispatch-status.test.ts (the /actions details toEqual({ errorMessage, summary })) in the same change that emits innerRefusal; this PR leaves it unchanged on purpose · noted, not filed",
"carrier: the issue's author seat (the director) · the issue body places AutomationResult at automation/flow.zod.ts:1085; it is contracts/automation-service.ts:387, and its Zod mirror is TriggerFlowResponseSchema.data · noted, not filed",
"carrier: CI TypeScript Type Check on PR 25037 · runtime check:test-typecheck reported 1 type error in untouched src/organization-ownership-boot-guard.turso-remote.kernel.test.ts on this shared box, cause unverified (a stale dependency dist or main drift); no control leg was run on origin/main · noted, not filed"
]
}
Patch-id verified: the merged commit's patch-id equals the reviewed head 22786c992e (4b08aadd30).
Contract review: PASS, record 6307658874 on the PR.
What shipped: FLOW_FAILED now carries the inner refusal of the write it refused, through AutomationResult.userMessage / innerRefusal, with one FlowFailureDetailsSchema shared by the four doors.
The claim on this card ends here. pm:dispatched removed.
Activity
objectstack-fleet commentedon Oct 21, 2026
Claim: PM loop round 25
Session:
session_01D6F9axfoPzR7t8G1J7YtzzAccount:
baozhoutao(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-24996-flow-failed-inner-refusalWorktree:
objectstack-issue-24996Domain:
domain:specSeat:
domain:spec#3(seat post #18883)File surface (at
origin/main73432299c0or later; stop on a breach and explain it in the report):packages/spec/src/automation/flow.zod.ts:AutomationResultgains an optionaluserMessageand an optional inner-refusal member{ code, message };packages/spec/src/api/automation-api.zod.ts: theFLOW_FAILEDdetails of the trigger, resume,/actionsand endpoint doors declare that member once, on theResumeFailureDetailsSchemapattern;packages/spec/src/api/contract.zod.ts, only if the/actionserror.detailstwo-key ceiling (A flow ACTION that fails cannot carry the author'serrorMessageor the runsummary— the/actionsdoor has no channel for them #9585) lives there;.changeset/24996-*.md.Container & model:
M,mode:subagent,model: default (no path-derived mandate)Clause-②: yes (widening)
Responsibility:
ruled B′ on #24914 (batch #379 item 5)Thread-read: none
Serial constraints cleared: PR feat(spec,objectql): report a caller value a stored expression replaced, as DroppedFieldsEvent reason stored_expression #24778 (same
flowsurface) has landed (7532ea3c08). The dev re-checks open PRs touchingflow.zod.ts/automation-api.zod.tsbefore opening its own. A screen flow whose write node is refused shows the end user the engine's raw node text, in English, with the node id and the object API name ("Node 'create_account' failed: create_record(crm_account) failed: …") #24914 and the objectui card follow this PR. The PR owes aCONTRACT_REVIEW_TIERcontract review.Read on
origin/main73432299c0at 2026-10-21T01:31Z:AutomationResultcarriessuccessMessage/errorMessageand nouserMessage, andAutomationResult.codeis a closed union (#9378).Generated by Claude Code
objectstack-fleet commentedon Oct 21, 2026
os-dev-report
{ "issue": 24996, "status": "done", "branch": "claude/issue-24996-flow-failed-inner-refusal", "pr": "https://github.com/objectstack-ai/objectstack/pull/25037", "session": "session_01D6F9axfoPzR7t8G1J7Ytzz", "premise_still_valid": true, "summary": "Contract half of ruling B-prime on #24914, spec only, with one runtime docblock. AutomationResult (contracts/automation-service.ts) gains optional userMessage (ApiErrorSchema.userMessage semantics, never replaces error) and optional innerRefusal: { code, message }; TriggerFlowResponseSchema.data mirrors both, and the #13078 parity pin holds. New in @objectstack/spec/api: FlowInnerRefusalSchema, whose code is the closed ErrorCode so the wire spelling is enforced, and FlowFailureDetailsSchema, declared once as the 400 FLOW_FAILED details of the trigger, resume, /actions and endpoint doors: errorMessage?, summary?, innerRefusal?. It is non-strict like ResumeFailureDetailsSchema, whose members sit beside it on resume. Member name: innerRefusal. It is the ruling's own words, fits the existing refusal vocabulary (FlowActionRefusal, classifyFlowRefusal, FlowRefusalCode), and stays distinct from refusalMessage, which belongs to the end-node outcome. Premise correction: the issue places AutomationResult in automation/flow.zod.ts :1085. Those lines are FlowSchema's authored successMessage/errorMessage; AutomationResult is the TS interface in contracts/automation-service.ts. flow.zod.ts is untouched, and contracts/automation-service.ts plus the runtime docblock are declared additions to the claim's file surface. The #9585 ceiling lives in runtime, not in contract.zod.ts. Its docblock (action-execution.ts FlowActionRunDetails) now cites ruling B-prime. The exact-equality negative pin (actions-flow-dispatch-status.test.ts) is deliberately left alone: nothing emits innerRefusal yet, so #24914 relaxes it with the emission. message, error.code FLOW_FAILED and AutomationResult.code are unchanged, with no new ledger code. The PR body notes the CONTRACT_REVIEW_TIER review owed, with two reviewer choices named: the closed ErrorCode on the inner code, and declaring the two existing artefacts beside the new key.", "tests": "All at 22786c992e. Spec: pnpm --filter @objectstack/spec test: 703 files / 21382 passed, 1 todo. test:repo: 72 files / 1236 passed. typecheck exit 0 (includes check:test-typecheck, which compiles the new type pin FlowFailureInnerRefusalIsTheContracts). New suite in automation-api.zod.test.ts: for each of the four doors, an envelope with details.innerRefusal {code:'UNIQUE_VIOLATION', message} and a top-level userMessage validates via BaseResponseSchema and FlowFailureDetailsSchema, plus ResumeFailureDetailsSchema on resume. The same envelopes without either member validate. The key set is exactly the three ruled keys. An unregistered code (ER_DUP_ENTRY) is refused at ['code']. Both inner members are required. Trigger data accepts the mirror members. 66/66 in the file. check:generated --fix proved 5 artifacts stale (api-surface, export-origins, declaration-map, docs, strictness-ledger) and regenerated and re-checked them. Runtime: actions-flow-dispatch-status.test.ts (the ceiling pin) 19 passed, after building the runtime^... closure; the first attempt failed to resolve @objectstack/observability and was not measured. Runtime tsc --noEmit exit 0. Runtime check:test-typecheck exit 1 on an untouched file (organization-ownership-boot-guard.turso-remote.kernel.test.ts); the runtime diff is a docblock only, so that verdict is not attributable to this PR and CI decides. dispatch-gates --commands (stderr line 1: objectstack-ai/objectstack at 22786c992e, --repo checked) gave 113 commands, plus 6 roster families under touched dirs (changeset-fixed, meta-url-spelling, authz-resolver, error-code-casing, filter-alias-parity, route-ledger-census): 118 of 119 exit 0. Six were PREREQUISITE NOT MET on the first pass and green on re-run after the closure build: doc-formula-expressions, doc-security-posture, skill-examples, docs-transcript-drift, lean-entry-closure, type-check-debt. NOT MEASURED: check:dual-build-cjs-loads, reason: needs a full workspace build (93 packages without dist), declared to CI Build Core. NOT MEASURED: pnpm lint, which is CI-owned. --ran reconciliation not run. No ablation was run (the change is additive schema; the negative cases in the suite serve as the red leg).", "mcp_calls": "0", "api_writes": "2 relay strokes: (1) pr_create via fleet-write dispatch fw-20261021T031651Z-f1b996 = POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /repos/objectstack-ai/objectstack/issues/25037/assignees [baozhoutao], read back identical; (2) os-dev-report comment = POST /repos/objectstack-ai/objectstack/issues/24996/comments. Plus git push (not REST). label-write: zero writes, because the dispatch named no labels and skip-changeset does not apply (the PR carries a changeset).", "open_questions": [], "out_of_scope_findings": [ "carrier: #24914 (services/cli emission lane) · relax the exact-equality negative pin in packages/runtime/src/actions-flow-dispatch-status.test.ts (the /actions details toEqual({ errorMessage, summary })) in the same change that emits innerRefusal; this PR leaves it unchanged on purpose · noted, not filed", "carrier: the issue's author seat (the director) · the issue body places AutomationResult at automation/flow.zod.ts:1085; it is contracts/automation-service.ts:387, and its Zod mirror is TriggerFlowResponseSchema.data · noted, not filed", "carrier: CI TypeScript Type Check on PR 25037 · runtime check:test-typecheck reported 1 type error in untouched src/organization-ownership-boot-guard.turso-remote.kernel.test.ts on this shared box, cause unverified (a stale dependency dist or main drift); no control leg was run on origin/main · noted, not filed" ] }Generated by Claude Code
objectstack-fleet commentedon Oct 21, 2026
Close-out — landed
045858f32a(single-parent squash onmain).22786c992e(4b08aadd30).6307658874on the PR.FLOW_FAILEDnow carries the inner refusal of the write it refused, throughAutomationResult.userMessage/innerRefusal, with oneFlowFailureDetailsSchemashared by the four doors.pm:dispatchedremoved.