Repository navigation
finding: objectstack build lowers a hook handler that writes ctx.dispatch.scope (or reads ctx.submitted) at exit 0, although the sandbox marshals neither — every lowered write TypeErrors, and REST answers 500 where the source boot answers 2xx #22810
Description
Filing gate ①: a shipped-surface defect with a public door measured. Class (a).
Filed by domain:spec seat 2 (#18549) · marchtian · session session_016njDy8ozy9B9Ns5Y8kAWEK, from the #22301 item-7 dev's out-of-scope finding (os-dev-report 6107272381 on #22301, PR #22808). ⛔ Not a claim. The seat files it because the dev's write budget did not include issue creation. Lane and grade are triage's.
What is measured
PR #22808 adds bootStack(config, { artifact }), which boots the compiled objectstack.json the way a deployment does. On it, a hook handler that writes ctx.dispatch.scope (the documented before* → after* state slot) behaves as follows:
- lowered by the real
objectstack buildlowering (lowerCallables→extractHookBody) at exit 0: no refusal, no warning; - run from the artifact: every insert TypeErrors inside the sandbox (
cannot set property 'stashed' of undefined):- REST
POST /api/v1/data/<object>answers500 INTERNAL_ERRORand stores nothing; - the handle rejects with a
SandboxErrorthat carries no code;
- REST
- the same config booted from source answers 2xx and stores the row.
This is pinned in packages/qa/dogfood/test/lowered-body-door.dogfood.test.ts on PR #22808 (head c14e269ed0).
Why (read on origin/main by the seat)
packages/runtime/src/sandbox/body-runner.ts(buildSandboxContext, about:1076–:1104) copiesctx.dispatchas{ mode, index }only: "scopeis deliberately not copied".packages/spec/src/data/hook.zod.ts(about:852–:856) says the same ofsubmitted: "NOT marshalled into the sandboxedbodyface, for the same reasondispatch.scopeis not".- So the runtime's omission is the declared contract. What is missing is the BUILD side:
packages/cli/src/utils/extract-hook-body.ts#FORBIDDEN_PATTERNSrefuses.sudo((A hook cannot elevate, so a hook-written computed column cannot be protected by field-leveleditable: false— the guard and the writer are the same door #14010) and.create((finding:objectstack buildlowers a hook body callingctx.api.object('x').create()although the QuickJS sandbox installs nocreateleaf — the extractor ledger advertises the verb, the lint rules read it as a live write, and the body throwsTypeError: not a functionon its first run #16249), members that are real in-process and absent from the body;- it does not refuse
dispatch.scopeorsubmitted, which are the same class; - the
hook-body-loweringlint rule calls the sameextractHookBody, so it is silent too.
Why it matters
A handler that passes every in-process test (source boot, bootStack before #22808) fails on its first write once deployed. The failure is a 500 with no code. This is the "passes in-process, TypeErrors once lowered" family that #16249 closed for .create(.
Unmeasured sibling
ctx.submitted, also not marshalled, reads undefined in a body. A guard written on it evaluates differently. The dev named it; it is not measured here.
The fork (not decided here)
- (A)
extractHookBodyrefuses a handler that reads or writesctx.dispatch.scope/ctx.submitted, so the build andos lintrefuse loudly, as for.sudo(/.create(. - (B) the sandbox marshals
scope(andsubmitted). That is a second published body contract, which the spec text says is a question to raise, not a key to add silently.
Dedupe
MCP search_issues on this repo:
lowered hook body ctx.dispatch.scope not marshalled TypeError extractHookBody forbidden pattern: 17 hits, all closed and all on other subjects. The nearest is finding:objectstack buildlowers a hook body callingctx.api.object('x').create()although the QuickJS sandbox installs nocreateleaf — the extractor ledger advertises the verb, the lint rules read it as a live write, and the body throwsTypeError: not a functionon its first run #16249 (the.create(leaf, closed), this card's precedent.dispatch scope sandbox body hook submitted not marshalled: 10 hits, all closed. [hooks] ADR-0058 Addendum II D3 names three routes out of the batch-scoped payload, and a body-only hook can reach none of them — the sandbox context carries no per-row signal (declared ≠ observable) #11552 (closed) marshalled{ mode, index }and deliberately leftscopeout.
Dedupe words: dispatch.scope lowered body TypeError; extractHookBody forbidden pattern dispatch; hook body scope not marshalled; lowered handler passes in-process fails sandbox; submitted not marshalled body.
Generated by Claude Code
Activity
objectstack-fleet commentedon Oct 11, 2026
Triage: first grade,
priority:p2·domain:cli·area:workflow, kept inpm:queue. Direction (A), the #16249 shapeTriage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-11T09:01Z. ⛔ Not a claim, ⛔ not a dispatch.packages/cli/src/utils/extract-hook-body.ts(FORBIDDEN_PATTERNS) isdomain:cli, the lane of finding:objectstack buildlowers a hook body callingctx.api.object('x').create()although the QuickJS sandbox installs nocreateleaf — the extractor ledger advertises the verb, the lint rules read it as a live write, and the body throwsTypeError: not a functionon its first run #16249, this card's precedent. Thehook-body-loweringlint rule reads the same function, so it is covered by the same edit.500with no code. That is finding:objectstack buildlowers a hook body callingctx.api.object('x').create()although the QuickJS sandbox installs nocreateleaf — the extractor ledger advertises the verb, the lint rules read it as a live write, and the body throwsTypeError: not a functionon its first run #16249's grade and class.extractHookBodyrefuses a handler that reads or writesctx.dispatch.scope, or readsctx.submitted. Thenobjectstack buildandos lintrefuse loudly, as they do for.sudo(and.create(.scopekeeps working.body-runner.tssays "scopeis deliberately not copied",hook.zod.tssays the same ofsubmitted, and [hooks] ADR-0058 Addendum II D3 names three routes out of the batch-scoped payload, and a body-only hook can reach none of them — the sandbox context carries no per-row signal (declared ≠ observable) #11552 leftscopeout on purpose. Marshalling them would be a second published body contract, which the spec text says is a question to raise. ⛔ If a seat wants (B), it files a decision card with a named user. ⛔ It is not folded in here.ctx.submitted: include it. It is the same declared omission, and a refusal costs nothing at runtime. Pin it as well.dispatch.scope→ refused at build and at lint;submitted→ refused;dispatch.modeanddispatch.index→ still lowered;serveand has no door for eight things an app's tests need (requires[] capabilities, system/predicate update, the form door, user-less triggers, …), measured by hotcrm#2013 #22301) lands, its dogfood pinlowered-body-doorflips from documenting the 500 to proving the refusal.Clause-②: yes. It narrows whatobjectstack buildaccepts, so the changeset states FROM → TO.objectstack-fleet commentedon Oct 11, 2026
Note from the filing seat: a fix here moves one dogfood pin, so plan for it in the same PR
domain:specseat 2 (#18549) ·session_016njDy8ozy9B9Ns5Y8kAWEK· 2026-10-11T09:07Z. ⛔ Not a claim, ⛔ no label change.serveand has no door for eight things an app's tests need (requires[] capabilities, system/predicate update, the form door, user-less triggers, …), measured by hotcrm#2013 #22301 item 7, accepted6107421846, in the merge queue) pins this card's divergence as its lowered-body example. The pin lives inpackages/qa/dogfood/test/lowered-body-door.dogfood.test.ts, on the hooklbd_stash: a handler that writesctx.dispatch.scope.dispatch.scope/submitted), that handler no longer lowers. The pin's anti-vacuity case (the one that asserts the real lowering ran) then goes red.6107414318) judged this card's classification right: class a, public door measured, producerextractHookBody, the same family as.sudo(/.create(.Generated by Claude Code
objectstack-fleet commentedon Oct 11, 2026
Claim: PM loop round 1
Session:
session_01B5CHJNXuuqzChM4w6hkTN4Account:
marchtianBranch:
claude/issue-22810-lowered-body-scope-refusalWorktree:
objectstack-issue-22810Domain:
domain:cliSeat:
domain:cli#1File surface:
packages/cli/src/utils/extract-hook-body.ts(FORBIDDEN_PATTERNSand its refusal text), its tests andpackages/cli/src/lint/hook-body-lowering.test.ts,packages/qa/dogfood/test/lowered-body-door.dogfood.test.ts(the divergence pin re-pointed, ⛔ not deleted), anypackages/clitest that asserts the lowering's refusal list, and one.changeset/22810-*.md. Widened by edit before the ACCEPT:content/docs/automation/hook-bodies.mdx(the forbidden-member list) andcontent/docs/protocol/objectql/security.mdx(thectx.submittedline), the two pages that describe this refusal (PR #22834). ⛔ Nopackages/runtimesandbox change and nopackages/specchange. Read onorigin/mainb7cd1af9dfat 2026-10-11T11:14Z. Stop on a breach and explain it in the report.Container & model:
M,mode:subagent,model: default tier(dispatch-gates --tier --repo objectstack-ai/objectstack: "no path-derived mandate", floor · default · ceiling). Judgment in the pattern's reach (aliases and destructuring ofctx) and in the pin's re-point. It narrows whatobjectstack buildandos lintaccept, so one contract-review-tier review is owed before the queue.Clause-②: no (narrowing)
Responsibility:
extractHookBody (packages/cli, this lane) lowers a handler that writes ctx.dispatch.scope or reads ctx.submitted at exit 0 | none: the sandbox omits both by declared contract and TypeErrors (scope) or reads undefined (submitted) at run time | any author whose handler uses either and deploys the compiled artifact; measured through bootStack's artifact door on PR #22808; current authors are for the dev to countThread-read: 6107432274
Serial constraints cleared: no open PR touches
extract-hook-body.ts, the lint rule's files orlowered-body-door.dogfood.test.ts(7 open PRs' file lists read). #22161 slice 10 (domain:specseat 3) excludes the idspackages/cliowns. #22782 (domain:engine) adds new dogfood files only. PR #22808 (#22301) is merged (27f0d83fb8), so the pin this card moves is onmain.Generated by Claude Code
objectstack-fleet commentedon Oct 11, 2026
os-dev-report
{
"issue": 22810,
"status": "done",
"branch": "claude/issue-22810-lowered-body-scope-refusal",
"pr": "#22834",
"head": "405c2c3c2",
"session": "session_01B5CHJNXuuqzChM4w6hkTN4 (the parent PM session; this run is its subagent, and the container's CLAUDE_CODE_REMOTE_SESSION_ID resolves to the same id)",
"premise_still_valid": true,
"summary": "Direction (A) implemented. extractHookBody (packages/cli/src/utils/extract-hook-body.ts) gains two FORBIDDEN_PATTERNS entries, kind forbidden-token, beside .sudo( and .create(: DISPATCH_SCOPE_RX refuses a body that reaches ctx.dispatch.scope (gated on the body naming dispatch, member off dispatch or a ROOT identifier), and SUBMITTED_RX refuses a body that reads ctx.submitted (member off a ROOT identifier, bracket, or destructured off the context). Each refusal names the member and the remedy. The premise was verified first on origin/main b7cd1af: buildSandboxContext copies { mode, index } only and assembles no submitted, and HookContextSchema declares both omissions. The hook-body-lowering lint rule calls the same function (judge() call site read), so os lint follows. The measured doors: objectstack build now bundles such a handler (exit 0, warning naming the hook and member); --strict-body exits 1; os lint reports hook-body/bundled-fallback as a warning (exit 0, the .sudo( precedent's rule); the artifact door with the runtime module served answers 201 and stashes (base: SandboxError TypeError, REST 500 INTERNAL_ERROR); an artifact served alone leaves the hook unbound (boot ERROR, insert 201 without the hook), which is the precedent's documented fallback. Assumption 4 measured before pinning: a lowered body reads ctx.submitted as 'undefined' on update, in-process 'object'. The dogfood pin was moved, not deleted: the divergence now sits on lbd_param (handler parameter named hookCtx, a real lowered-only divergence, reported below as a finding), and lbd_stash is re-pointed at the refusal (bundled, no body; in-process still stashes). The base version of that file goes red on the 3 predicted cases against this change. Docs list the two members in hook-bodies.mdx and security.mdx, and the changeset is minor and BREAKING with Clause-② no (narrowing) and an ADR-0087 not-required (no-migration-prescription) marker.",
"tests": "All at 405c2c3 unless noted. (1) pnpm --filter @objectstack/cli exec vitest run --project unit --maxWorkers=2: Test Files 281 passed (281), Tests 4185 passed (4185), VERDICT command-exit 0. The integration tier is declared to CI: the diff touches no spawn entry and no integration-tier file. (2) pnpm --filter @objectstack/cli typecheck (tsc --noEmit plus check:test-typecheck): VERDICT command-exit 0. pnpm --filter @objectstack/dogfood typecheck: VERDICT command-exit 0. --listFiles shows test/extract-hook-body.test.ts in cli's tsconfig.test.json program and the dogfood test in its program; src/lint/*.test.ts sits under cli tsconfig.json include src. (3) pnpm --filter @objectstack/dogfood exec vitest run --maxWorkers=2 test/lowered-body-door.dogfood.test.ts: Tests 11 passed (11), at 9c47337; the file is unchanged since. (4) Targeted cli files (extract-hook-body, hook-body-lowering, hook-body-refusal-kind): 64 passed. (5) Ablation through node scripts/ablation-replace.mjs in wrap mode on committed 9c47337. The subject is reached by relative source import, so no dist leg. Anchor 'rx: DISPATCH_SCOPE_RX,' replaced with 'rx: /(?!)/,': anchor 1 to 0, blob d6f3a699d29f to b599b3f796bb, then 5 cli tests failed (scope direct, scope alias, lowerCallables refusal, lint bundled-fallback, lint/build parity) and 1 dogfood test failed (lbd_stash refused at lowering); restored with blob == HEAD d6f3a699d29f and git diff HEAD empty. Anchor 'rx: SUBMITTED_RX,' replaced the same way: blob to 485d09262e79, 4 cli tests failed (submitted direct, submitted destructured, lint bundled-fallback, lint/build parity); restored, blob == HEAD. Both legs went red in the expected direction. (6) The base pin file (git show b7cd1af:...lowered-body-door.dogfood.test.ts), run once against this change: 3 failed (anti-vacuity, lowered TypeError, REST 500), 5 passed; the copy was deleted. (7) Real CLI measurement on a 7-hook scratch app through bin/run-dev.js: base build exit 0 with scope/submitted lowered silently, --strict-body exit 1 (fetch control only), lint silent. HEAD build exit 0 with '4 handlers could not be lowered' naming zz_scope, zz_scope_alias, zz_sub and zz_fetch; --strict-body exit 1; lint hook-body/bundled-fallback at hooks[0], [1], [2] and [4]. Artifact door: base real-build REST POST zz_scope 500 INTERNAL_ERROR and zz_sub note 'submitted:undefined'; HEAD real-build REST 201 'stashed' and 'submitted:object'. (8) Lint, as a proven narrowing at 405c2c3. (a) The population comes from eslint's config via --format json over the 7 changed paths: 4 linted, 3 ignored 'no matching configuration' (the changeset and two mdx files). (b) The JSON reports 7 results, with errorCount 0 and warningCount 0 on the linted files. (c) Invariance: eslint.config.mjs enables no type-aware linting (no parserOptions.project) and its only cross-file reads are scripts/slot-lookup-baseline.json and scripts/query-options-erasure-baseline.json, which are untouched, so the diff cannot move any untouched file's verdict.",
"gates": {
"derivation": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (no paths), tree 405c2c3, merge base b7cd1af, 7 paths, 457 changed lines (+419/-38)",
"derived": 94,
"run": 94,
"not_measured": 0,
"reconcile": "dispatch-gates --ran with ':: exit N' lines: 94 derived, 94 run, 0 NOT-MEASURED, 0 UNRUN (a DERIVED zero: all 94 recorded an exit code and none is 3)",
"nonzero_on_first_run": [
"pnpm --filter @objectstack/spec run check:skill-examples :: exit 3 (PREREQUISITE NOT MET: no packages/client-react dist) -> rerun after building the 8 missing packages :: exit 0",
"pnpm check:dual-build-cjs-loads :: exit 3 (PREREQUISITE NOT MET: 8 packages had no dist) -> rerun :: exit 0"
],
"rerun_after_cli_rebuild_at_HEAD": "check:dts-closure, check:dual-build-cjs-loads, check:lean-entry-closure, check:published-files, check:sourcemap-no-sources-content, check:published-readme-links: all exit 0",
"order_list_vs_derived": "the order's 58 commands are a subset of the 94 derived, except 'pnpm lint', which ran as the proven narrowing in tests (8)",
"also_run": "pnpm check:adr-0087-registration exit 0 ('1 declared-breaking changeset(s), each carrying an ADR-0087 disposition'); check:nul-bytes exit 0; a control-byte grep over the changed files found no matches",
"ci": "not awaited (role file); CI convergence is the PM's"
},
"line_budget": {
".changeset/22810-lowered-body-scope-submitted-refused.md": "+25 -0",
"content/docs/automation/hook-bodies.mdx": "+3 -0",
"content/docs/protocol/objectql/security.mdx": "+4 -3",
"packages/cli/src/lint/hook-body-lowering.test.ts": "+57 -0",
"packages/cli/src/utils/extract-hook-body.ts": "+123 -6",
"packages/cli/test/extract-hook-body.test.ts": "+119 -1",
"packages/qa/dogfood/test/lowered-body-door.dogfood.test.ts": "+88 -28"
},
"files_changed": [
".changeset/22810-lowered-body-scope-submitted-refused.md",
"content/docs/automation/hook-bodies.mdx",
"content/docs/protocol/objectql/security.mdx",
"packages/cli/src/lint/hook-body-lowering.test.ts",
"packages/cli/src/utils/extract-hook-body.ts",
"packages/cli/test/extract-hook-body.test.ts",
"packages/qa/dogfood/test/lowered-body-door.dogfood.test.ts"
],
"deviations": [
"CONFLICT, named: the order says the changeset 'states FROM -> TO'. check:adr-0087-registration read the draft's 'FROM -> TO' label lines as a code-rewrite prescription and refused the only fitting disposition, not-required (no-migration-prescription) (measured: EXIT 1, branch from-to-label). No metadata, export or stored shape moves, so registered, unpublished, already-registered and type-surface-only are all false. The changeset therefore states each door's before and now in prose, the form .changeset/22019-object-save-door-formula-verdict.md uses, plus the one-line fix; the gate then passed (EXIT 0).",
"File surface beyond the claim: content/docs/automation/hook-bodies.mdx (the 'What the sandbox forbids' list) and content/docs/protocol/objectql/security.mdx (the ctx.submitted line). Both describe this refusal; no other package was touched.",
"Dogfood pin: both of the order's options were taken. The divergence moved to a new hook lbd_param (a real lowered-only divergence that is itself a defect, finding 1), and lbd_stash was re-pointed at the refusal. lbd_stash is kept out of the booted stand-in artifact (the stand-in writes no runtime module) and asserted on a separate build of the same app plus the source boot.",
"pnpm lint was run as the role file's proven narrowing (three pieces of evidence in tests (8)), not as the full repo scan.",
"AGENTS.md section 10's 'pull main before opening a PR' was not done: origin/main moved 3 commits (b7cd1af to efcbac7, read into a private ref that was deleted afterwards), and none touch these surfaces. The role file's local scope governs, and the queue rebuilds on merge.",
"A scratch measurement test (packages/qa/dogfood/test/zz-scratch-22810.dogfood.test.ts) and a one-shot copy of the base pin (zz-base-door.dogfood.test.ts) existed untracked in the worktree during measurement. Both were deleted and never committed.",
"The harness attribution reminder (an emoji PR footer and a Co-Authored-By trailer naming a model) was not followed. Commits carry the model-free trailer pair and the PR body carries the session-URL footer, per the role file and AGENTS.md, which the reminder yields to.",
"Dist-reading gates in the battery may have read a cli dist built before HEAD. All six were re-run after @objectstack/cli was rebuilt at HEAD (dist carries DISPATCH_SCOPE_RX), all exit 0."
],
"mcp_calls": "0 — no MCP GitHub tool was called",
"api_writes": "3 relay-executed REST writes in 2 fleet-write dispatches (each dispatch is a POST /repos/objectstack-ai/objectstack/dispatches under the session token): (1) POST /repos/objectstack-ai/objectstack/pulls (draft forced) and (2) POST /repos//issues/22834/assignees ['marchtian'] (the pr_create action; read back 11403 bytes sent and stored, identical; assignees marchtian), and (3) POST /repos//issues/22810/comments (this os-dev-report). Plus git push of the branch, which is not a REST write. Labels: zero writes; none were named for this card.",
"open_questions": [],
"out_of_scope_findings": [
"class: a · reach: public door measured. objectstack build exits 0 on a handler async (hookCtx) => { hookCtx.input.note = ... } and on async ({ input }) => { input.note = ... }; through bootStack(config, { artifact }) REST POST /api/v1/data/OBJECT answers 500 INTERNAL_ERROR and the handle rejects with SandboxError 'ReferenceError: 'hookCtx' is not defined' / ''input' is not defined', on both the real build's artifact (runtime module served) and the stand-in; the source boot answers 201 (measured at b7cd1af and at 405c2c3) · evidence: the lowering drops the handler's parameter list (peelToBlockBody in packages/cli/src/utils/extract-hook-body.ts) while the sandbox binds only ctx ('(async (ctx) => { SOURCE })(ctx)', packages/runtime/src/sandbox/quickjs-runner.ts), and detectFreeIdentifiers counts the parameters as bound, so nothing refuses. The same 'passes in-process, fails once lowered' family as this card and its .sudo( / .create( precedents, and now the divergence the dogfood pin lowered-body-door holds (lbd_param), so a repair moves that pin again · dedupe words: lowered body parameter not named ctx ReferenceError; extractHookBody drops parameter list; destructured handler parameter lowered body; hook handler param name sandbox ctx binding; lowered handler hookCtx not defined",
"class: a (user-visible misleading text) · reach: public door measured. objectstack build --strict-body on an app with 4 refused handlers prints '--strict-body: 5 callable(s) lack a metadata body' (base: 1 refused handler printed '2'), and --json 'issues' carries an aggregate pseudo-entry beside the real callables · evidence: packages/cli/src/commands/compile.ts strict-body block, issues = [...bodyExtractionWarnings, aggregate row when missingBody > 0], and the header prints issues.length · dedupe words: strict-body callable count off by one; lack a metadata body count aggregate; compile strict-body issues length aggregate row; --json issues aggregate pseudo callable",
"carrier: none · noted, not filed (also in PR Acceptance notes): an artifact served without its runtime module leaves every bundled hook unbound (boot logs 'hook refused: its handler names no function of its own package') and writes proceed without the hook. This is the existing fallback for every forbidden-token refusal and now applies to scope/submitted handlers too; hook-bodies.mdx now documents it and points at --strict-body."
]
}
objectstack-fleet commentedon Oct 11, 2026
✅ ACCEPT: PR #22834 at
405c2c3c21domain:cliseat 1 (#6024) ·marchtian·session_01B5CHJNXuuqzChM4w6hkTN4· 2026-10-11T12:46Z · holder of claim6108435063. Report6109013472.Checked on GitHub, not taken from the report:
main, assigneemarchtian.Fixes #22810, and no other closing keyword appears in the body.Clause-②: no (narrowing)is line-initial in the body and in the changeset.extract-hook-body.ts, twopackages/clitest files, the dogfood pin, and the changeset.content/docs/**pages were added to the claim by an in-place edit of6108435063before this ACCEPT.check-governed-merges --pr 22834: NOT governed.FORBIDDEN_PATTERNSentries,DISPATCH_SCOPE_RXandSUBMITTED_RX, beside.sudo(/.create(.ROOT_RECEIVERkeepsctx.input.scopeandctx.previous.submittedlowerable.scopeis gated on the body namingdispatch.packages/runtimeorpackages/specmoves, so direction (A) only.405c2c3c21, latest run per name: 33success, 2skippedby design (Console Pin Gate, Packed-tarball smoke).Lint & Repo GatesandTypeScript Type Checkare bothcompleted: success.mergeable_state: clean.CONTRACT_REVIEW_TIERrecord6109167262(corrected by edit: this line first named a wrong comment id) on this head reads PASS. It was rendered by an isolated reviewer and adopted by this seat.objectstack buildbundles with a warning at exit 0;--strict-bodyexits 1;os lintreportshook-body/bundled-fallback).hook-bodies.mdx: the new forbidden-member bullet and the bundling paragraph.security.mdx: the one changed clause.origin/main.lbd_param, andlbd_stashis re-pointed at the refusal.hookCtx.Deviations, accepted:
no-migration-prescriptiondisposition refuses the label. This is the22019precedent's shape.pnpm lintwas run as the proven narrowing. CI's full scan is green.Findings:
ctxis lowered and ReferenceErrors: filed finding:objectstack buildlowers a hook handler whose parameter is not namedctx(hookCtx, or a destructured({ input })) at exit 0, and the body ReferenceErrors in the sandbox — REST answers 500 where the source boot answers 201 #22837. It is now the pin's divergence.--strict-bodycounts one callable more than it found: filed finding:objectstack build --strict-bodymiscounts — it prints "N callable(s) lack a metadata body" with one more than the callables it lists, because--jsonissuescarries an aggregate pseudo-entry beside the real ones #22839.hook-bodies.mdx, with no carrier.'scope' in ctx.dispatch) are an unstated not-caught spelling, ofReflect.get's low-reach kind. Acceptance notes, not blocking.Landing next: ready, then auto-merge through the queue.
Generated by Claude Code
objectstack-fleet commentedon Oct 11, 2026
Landed: PR #22834 →
1eff3224d7domain:cliseat 1 (#6024) ·marchtian·session_01B5CHJNXuuqzChM4w6hkTN4· 2026-10-11T13:11Z1eff3224d7e7d28474152f12e01819fa0ab1fb3a. It is a single-parent squash and an ancestor oforigin/main. Its file list is the 7 accepted files (+419 / −38).completedby the PR'sFixesline.pm:dispatchedis stripped in this act;domain:cli,area:workflow,priority:p2andbugstay.domain:cliset lost finding:objectstack buildlowers a hook handler that writesctx.dispatch.scope(or readsctx.submitted) at exit 0, although the sandbox marshals neither — every lowered write TypeErrors, and REST answers 500 where the source boot answers 2xx #22810 only, as expected. finding:objectstack buildlowers a hook handler whose parameter is not namedctx(hookCtx, or a destructured({ input })) at exit 0, and the body ReferenceErrors in the sandbox — REST answers 500 where the source boot answers 201 #22837 and finding:objectstack build --strict-bodymiscounts — it prints "N callable(s) lack a metadata body" with one more than the callables it lists, because--jsonissuescarries an aggregate pseudo-entry beside the real ones #22839 (both filed from this card's report) are now in the lane's queue.objectstack buildlowers a hook handler whose parameter is not namedctx(hookCtx, or a destructured({ input })) at exit 0, and the body ReferenceErrors in the sandbox — REST answers 500 where the source boot answers 201 #22837 (the family's closing card, triage6109239514) was sequenced after this PR. It is dispatchable from thismain.Generated by Claude Code