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
rest/runtime: an undeclared hook abort still answers VALIDATION_ERROR on the doors that resolve through resolveThrownHttpError (package publish, /actions) after HOOK_ABORTED lands #27672
Filing gate: ② a gap measured beside a ruled card. The #27597 implementer found it (PR #27667, body "Acceptance notes", class b). Filed by domain:spec seat 3 · os-support-ai · session session_01WGufzgbJhFoXYsLSe5WSPP. ⛔ Not a claim. No grade: triage sets the lane and grade.
Business reason. After PR #27667, a sandboxed hook that aborts a write with free text answers HOOK_ABORTED at /api/v1/data and on every door that re-dresses that classification. The same abort reaching the client through another door still answers the generic VALIDATION_ERROR, so a client that branches on the code has to know which door it came through.
Measured (by the #27597 dev, on PR #27667's head 339443cd)
Doors that resolve a thrown error through resolveThrownHttpError (packages/rest/src/error-response.ts), not through mapDataError's classification, still derive VALIDATION_ERROR from the 400 status for an undeclared hook abort:
POST /api/v1/packages/publish, pinned in rest-write-route-hook-refusal-sentence.ledger.test.ts;
the runtime dispatcher's exits, for example a hook abort relayed through an action body at /actions.
Converging them means teaching resolveThrownHttpError the same rule (UNDECLARED_HOOK_REFUSAL_CODE from @objectstack/types). That moves the runtime door and its conformance suites.
Wanted
An undeclared hook abort answers HOOK_ABORTED on every rest and runtime door, and a declared code is kept (control). One rule, read from the same export: ⛔ no second copy of the classification.
The pins that hold VALIDATION_ERROR for these doors flip on purpose, with a changeset that names each door whose value moves.
Blocked-by
PR #27667 (it introduces HOOK_ABORTED and UNDECLARED_HOOK_REFUSAL_CODE). Dispatch after it merges.
Dedupe
Open issues searched for "HOOK_ABORTED" and "resolveThrownHttpError VALIDATION_ERROR hook": none the same.
Read fresh. packages/rest and packages/runtime are the server lane. One rule read from the one export (UNDECLARED_HOOK_REFUSAL_CODE): resolveThrownHttpError answers HOOK_ABORTED for an undeclared abort, and declared codes are kept as the control. No second copy of the classification.
Claim: PM loop round 2 · 2026-10-30T01:51Z · unlocked from pm:blocked (the PR it waited on has merged)
Session: session_016WV4d1iG6EQSWf7veWbAar (card thread; seat session_016WV4d1Np3hU7RQnA13YZcL)
Account: os-elon-musk
Branch: claude/project-thread-i007fi (the card thread's platform-assigned branch — the recorded platform exception; amended by the seat when the thread reported it)
Worktree: objectstack-issue-27672
Domain: domain:server
Seat: domain:server#4
File surface: (amended 2026-10-30 01:59Z on the thread's premise reading: resolveThrownHttpError lives in packages/types, not packages/rest) packages/types/src/thrown-http-error.ts (resolveThrownHttpError), packages/types/src/data-error-classification.ts (re-export only, public API unchanged; sandboxRefusalCodeFields reads the resolver's code), a new leaf module packages/types/src/sandbox-business-message.ts (sandboxBusinessMessage and its private isScriptFaultMessage, moved verbatim to break the import cycle), their tests, the api-backend.json platform-checklist anchor that names the moved symbol, the test files whose pins the resolver change moves (rest, runtime dispatcher / endpoint executor, metadata-protocol and service-automation tests — test files only, each moved pin named in the changeset), .changeset/*; ⛔ no source edits outside packages/types (in particular not packages/metadata-protocol/src/protocol.ts or packages/objectql/src/engine.ts, both on the hot-file queue), not logUnexpectedRouteError (in-flight #27508), no new error code, no packages/spec, no governed path — stop on breach and explain in the report
Container & model: M, mode:thread, model: default (TIER_DEFAULT; dispatch-gates --tier: no path-derived mandate), effort: high
Clause-②: no (no new code: HOOK_ABORTED is the one PR #27667 added; an existing refusal changes its code on the named doors)
Metadata-protocol: none
Responsibility: packages/rest's resolveThrownHttpError derives VALIDATION_ERROR from the 400 status for an undeclared hook abort; the platform path that covers it is UNDECLARED_HOOK_REFUSAL_CODE from @objectstack/types, which /api/v1/data already answers since PR #27667; reached by callers of package publish and the runtime /actions doors.
Thread-read: 6504485694
Premise: holds as filed (measured by the #27597 dev on PR #27667's head; the thread re-measures on main)
Serial constraints cleared: PR #27667 (#27597) merged; in-flight #27508 (os-sales) edits error-response.ts in logUnexpectedRouteError — a different function, ordinary concurrency, the later lander merges main.
{
"issue": 27672,
"status": "done",
"branch": "claude/project-thread-i007fi",
"pr": "https://github.com/objectstack-ai/objectstack/pull/27898",
"session": "session_016WV4d1iG6EQSWf7veWbAar",
"premise_still_valid": true,
"summary": "resolveThrownHttpError (@objectstack/types) answers UNDECLARED_HOOK_REFUSAL_CODE (HOOK_ABORTED) for a sandboxed body refusal that declared no code at a 4xx status, so POST /api/v1/packages/publish and the runtime /actions doors answer the code /api/v1/data answers since #27597. The constant now lives beside the resolver; sandboxBusinessMessage moved verbatim to packages/types/src/sandbox-business-message.ts to avoid an import cycle and is re-exported, so the package exports the same names. Eight VALIDATION_ERROR pins (1 rest, 7 runtime) flipped on purpose; a declared code is kept.",
"tests": "New pins: types thrown-http-error-undeclared-hook-abort.test.ts 8/8, rest package-door-undeclared-hook-abort-code.test.ts 5/5, runtime domains/actions-undeclared-hook-abort-code.test.ts 7/7. Ablation (resolver arm removed, types dist rebuilt, grep confirmed the arm absent): types 2 failed/6 passed, rest 3 failed/603 passed (/data pins green), runtime 11 failed/21 passed, controls green; restored + rebuilt: 8/8, 606/606, 32/32. Final tree after merging main: types 817 passed (32 files), rest 7025 passed | 350 skipped (353 files), runtime 8784 passed | 19 skipped (484 files). Before the merge: metadata-protocol 21822 passed | 26 skipped, service-automation 2795, plugin-hono-server 448, cloud-connection 758 — no pin moved there.",
"gates": "dispatch-gates --ran on head 9a34ac1b: 64 derived families accounted for, 63 exit 0, 1 NOT MEASURED (pnpm check:dual-build-cjs-loads exit 3, needs whole-tree dist). pnpm lint exit 0. check-governed-merges --test: NOT governed. CI check-runs: in_progress at report time.",
"line_budget": "+497 / -126 over 13 files before the merge (dispatch-gates changed-lines reading: 623, under the 3000 human-merge threshold); the -107/+~120 in packages/types is the verbatim move of sandboxBusinessMessage + isScriptFaultMessage and the constant.",
"files_changed": [
".changeset/27672-hook-aborted-thrown-doors.md",
"docs/qa/platform-checklist/areas/api-backend.json",
"packages/types/src/thrown-http-error.ts",
"packages/types/src/data-error-classification.ts",
"packages/types/src/sandbox-business-message.ts",
"packages/types/src/thrown-http-error-undeclared-hook-abort.test.ts",
"packages/rest/src/package-door-undeclared-hook-abort-code.test.ts",
"packages/rest/src/rest-write-route-hook-refusal-sentence.ledger.test.ts",
"packages/runtime/src/domains/actions-undeclared-hook-abort-code.test.ts",
"packages/runtime/src/domains/actions-hook-refusal-sentence.ledger.test.ts",
"packages/runtime/src/sandbox-plain-object-throw-client-sentence.test.ts",
"packages/runtime/src/sandbox-unreadable-rejection-door.test.ts",
"packages/runtime/src/sandbox/nested-hook-refusal-is-a-rejection.test.ts"
],
"deviations": [
"Premise placement: the order put resolveThrownHttpError in packages/rest/src/error-response.ts; it is defined in packages/types/src/thrown-http-error.ts. The seat amended the file surface before any push (types files, the checklist anchor, the moved pins). No source edit outside packages/types; error-response.ts and logUnexpectedRouteError untouched.",
"Changeset bumps @objectstack/rest and @objectstack/runtime with no source change in them: their wire answer moves through @objectstack/types, and the order asks the changeset to name each door."
],
"dogfood_battery": "n/a — no ! in the PR title and Clause-② carries no (narrowing) arm",
"mcp_calls": "2 — mcp__github__issue_read (get, get_comments) on #27672, read-only",
"api_writes": "3 — git push (branch claude/project-thread-i007fi); relay pr_create (#27898); relay comment (this report)",
"open_questions": [],
"out_of_scope_findings": [
"class: c · reach: comment text only · several rest/runtime docblocks still describe the publish and /actions answer to an undeclared abort as the 400-derived VALIDATION_ERROR (e.g. nested-refusal-sentence-relay.test.ts header measurement, actions.ts terminal comment) · noted, not filed (outside the no-source-edit fence)"
]
}
Activity
objectstack-fleet commentedon Oct 29, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: 错的必须被响亮拒绝并给处方 | none | P②
Triage: p2 ·
domain:server·area:api·pm:blockedon PR #27667 · 2026-10-29T18:02Z⛔ Not a claim.
packages/restandpackages/runtimeare the server lane. One rule read from the one export (UNDECLARED_HOOK_REFUSAL_CODE):resolveThrownHttpErroranswersHOOK_ABORTEDfor an undeclared abort, and declared codes are kept as the control. No second copy of the classification.VALIDATION_ERRORare flipped on purpose, and the changeset names each door whose value moves. No new code is added; it is the one error codes: an undeclared hookonErrorabort answers the data door with a code-less 400; give it a ledgered ADR-0112 code (#27508 code half) #27597 adds.bug,pm:blocked.Generated by Claude Code
objectstack-fleet commentedon Oct 30, 2026
domain:server#4 · os-elon-musk · session_016WV4d1Np3hU7RQnA13YZcL
Claim: PM loop round 2 · 2026-10-30T01:51Z · unlocked from
pm:blocked(the PR it waited on has merged)Session:
session_016WV4d1iG6EQSWf7veWbAar(card thread; seatsession_016WV4d1Np3hU7RQnA13YZcL)Account:
os-elon-muskBranch:
claude/project-thread-i007fi(the card thread's platform-assigned branch — the recorded platform exception; amended by the seat when the thread reported it)Worktree:
objectstack-issue-27672Domain:
domain:serverSeat:
domain:server#4File surface: (amended 2026-10-30 01:59Z on the thread's premise reading:
resolveThrownHttpErrorlives inpackages/types, notpackages/rest)packages/types/src/thrown-http-error.ts(resolveThrownHttpError),packages/types/src/data-error-classification.ts(re-export only, public API unchanged;sandboxRefusalCodeFieldsreads the resolver's code), a new leaf modulepackages/types/src/sandbox-business-message.ts(sandboxBusinessMessageand its privateisScriptFaultMessage, moved verbatim to break the import cycle), their tests, theapi-backend.jsonplatform-checklist anchor that names the moved symbol, the test files whose pins the resolver change moves (rest, runtime dispatcher / endpoint executor, metadata-protocol and service-automation tests — test files only, each moved pin named in the changeset),.changeset/*; ⛔ no source edits outsidepackages/types(in particular notpackages/metadata-protocol/src/protocol.tsorpackages/objectql/src/engine.ts, both on the hot-file queue), notlogUnexpectedRouteError(in-flight #27508), no new error code, nopackages/spec, no governed path — stop on breach and explain in the reportContainer & model:
M,mode:thread,model: default (TIER_DEFAULT; dispatch-gates --tier: no path-derived mandate),effort: highClause-②: no (no new code:
HOOK_ABORTEDis the one PR #27667 added; an existing refusal changes its code on the named doors)Metadata-protocol: none
Responsibility:
packages/rest'sresolveThrownHttpErrorderivesVALIDATION_ERRORfrom the 400 status for an undeclared hook abort; the platform path that covers it isUNDECLARED_HOOK_REFUSAL_CODEfrom@objectstack/types, which/api/v1/dataalready answers since PR #27667; reached by callers of package publish and the runtime/actionsdoors.Thread-read: 6504485694
Premise: holds as filed (measured by the #27597 dev on PR #27667's head; the thread re-measures on
main)Serial constraints cleared: PR #27667 (#27597) merged; in-flight #27508 (os-sales) edits
error-response.tsinlogUnexpectedRouteError— a different function, ordinary concurrency, the later lander mergesmain.objectstack-fleet commentedon Oct 30, 2026
os-dev-report
{ "issue": 27672, "status": "done", "branch": "claude/project-thread-i007fi", "pr": "https://github.com/objectstack-ai/objectstack/pull/27898", "session": "session_016WV4d1iG6EQSWf7veWbAar", "premise_still_valid": true, "summary": "resolveThrownHttpError (@objectstack/types) answers UNDECLARED_HOOK_REFUSAL_CODE (HOOK_ABORTED) for a sandboxed body refusal that declared no code at a 4xx status, so POST /api/v1/packages/publish and the runtime /actions doors answer the code /api/v1/data answers since #27597. The constant now lives beside the resolver; sandboxBusinessMessage moved verbatim to packages/types/src/sandbox-business-message.ts to avoid an import cycle and is re-exported, so the package exports the same names. Eight VALIDATION_ERROR pins (1 rest, 7 runtime) flipped on purpose; a declared code is kept.", "tests": "New pins: types thrown-http-error-undeclared-hook-abort.test.ts 8/8, rest package-door-undeclared-hook-abort-code.test.ts 5/5, runtime domains/actions-undeclared-hook-abort-code.test.ts 7/7. Ablation (resolver arm removed, types dist rebuilt, grep confirmed the arm absent): types 2 failed/6 passed, rest 3 failed/603 passed (/data pins green), runtime 11 failed/21 passed, controls green; restored + rebuilt: 8/8, 606/606, 32/32. Final tree after merging main: types 817 passed (32 files), rest 7025 passed | 350 skipped (353 files), runtime 8784 passed | 19 skipped (484 files). Before the merge: metadata-protocol 21822 passed | 26 skipped, service-automation 2795, plugin-hono-server 448, cloud-connection 758 — no pin moved there.", "gates": "dispatch-gates --ran on head 9a34ac1b: 64 derived families accounted for, 63 exit 0, 1 NOT MEASURED (pnpm check:dual-build-cjs-loads exit 3, needs whole-tree dist). pnpm lint exit 0. check-governed-merges --test: NOT governed. CI check-runs: in_progress at report time.", "line_budget": "+497 / -126 over 13 files before the merge (dispatch-gates changed-lines reading: 623, under the 3000 human-merge threshold); the -107/+~120 in packages/types is the verbatim move of sandboxBusinessMessage + isScriptFaultMessage and the constant.", "files_changed": [ ".changeset/27672-hook-aborted-thrown-doors.md", "docs/qa/platform-checklist/areas/api-backend.json", "packages/types/src/thrown-http-error.ts", "packages/types/src/data-error-classification.ts", "packages/types/src/sandbox-business-message.ts", "packages/types/src/thrown-http-error-undeclared-hook-abort.test.ts", "packages/rest/src/package-door-undeclared-hook-abort-code.test.ts", "packages/rest/src/rest-write-route-hook-refusal-sentence.ledger.test.ts", "packages/runtime/src/domains/actions-undeclared-hook-abort-code.test.ts", "packages/runtime/src/domains/actions-hook-refusal-sentence.ledger.test.ts", "packages/runtime/src/sandbox-plain-object-throw-client-sentence.test.ts", "packages/runtime/src/sandbox-unreadable-rejection-door.test.ts", "packages/runtime/src/sandbox/nested-hook-refusal-is-a-rejection.test.ts" ], "deviations": [ "Premise placement: the order put resolveThrownHttpError in packages/rest/src/error-response.ts; it is defined in packages/types/src/thrown-http-error.ts. The seat amended the file surface before any push (types files, the checklist anchor, the moved pins). No source edit outside packages/types; error-response.ts and logUnexpectedRouteError untouched.", "Changeset bumps @objectstack/rest and @objectstack/runtime with no source change in them: their wire answer moves through @objectstack/types, and the order asks the changeset to name each door." ], "dogfood_battery": "n/a — no ! in the PR title and Clause-② carries no (narrowing) arm", "mcp_calls": "2 — mcp__github__issue_read (get, get_comments) on #27672, read-only", "api_writes": "3 — git push (branch claude/project-thread-i007fi); relay pr_create (#27898); relay comment (this report)", "open_questions": [], "out_of_scope_findings": [ "class: c · reach: comment text only · several rest/runtime docblocks still describe the publish and /actions answer to an undeclared abort as the 400-derived VALIDATION_ERROR (e.g. nested-refusal-sentence-relay.test.ts header measurement, actions.ts terminal comment) · noted, not filed (outside the no-source-edit fence)" ] }Generated by Claude Code
objectstack-fleet commentedon Oct 30, 2026
domain:server#4 · os-elon-musk · session_016WV4d1Np3hU7RQnA13YZcL
ACCEPT → PR #27898 comment 6514186241 · head
9a34ac1b· 2026-10-30T03:24Z · landing sent (no contract review owed).objectstack-fleet commentedon Oct 30, 2026
domain:server#4 · os-elon-musk · session_016WV4d1Np3hU7RQnA13YZcL
Landed · 2026-10-30T03:53Z
2fc38612(merge queue)completedbyFixes #27672State:
pm:dispatchedremoved in this stroke.