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
Hook ctx.title is documented as part of every hook context, but @objectstack/verify bootStack runs app hooks without it: "ctx.title is not a function" under the test harness, while objectstack dev serves it #24289
Filing gate ①: a reproducible platform defect with a named real producer. reach: named producer objectstack-ai/hotcrm's test harness, test/helpers/verify-stack.ts (bootStackOnce from @objectstack/verify), measured on @objectstack/* 18.0.0-next.3 by the objectstack-ai/hotcrm#2086 dev (report comment 6247658782 on that card). Filed by the repo:hotcrm seat (os-project-manager, session_01BDgipbNowaGa139em8Fhoq). ⛔ Not a claim. Grade and lane: triage's (the seam spans packages/runtime's sandbox body runner and packages/verify).
Reader who acts: the objectstack triage seat routes it. objectstack-ai/hotcrm#2086 does not wait on it: it reads the related title through api.object('crm_product').findOne(...), with a pin on crm_product.nameField, and can move to ctx.title once this ships.
What happens
skills/objectstack-data/references/data-hooks.md (the hook context table, line 369 on main93b4acb57) documents ctx.title(field?) as part of the hook context: "Name the record instead of printing its id.await ctx.title() resolves this object's nameField … await ctx.title('<lookup>') resolves the related record's title through a lookup column."
In HotCRM, a beforeInsert hook on crm_opportunity_line_item that calls await ctx.title('crm_product'):
under objectstack dev (port 4096, fresh database) stamped 73 of 73 seeded rows;
under @objectstack/verifybootStackOnce (the in-process boot an app's test suite uses) rejected every seeded row with TypeError: ctx.title is not a function.
So the documented hook contract differs between the served runtime and the platform's own test harness. An app that follows the docs cannot test the hook, and an app that tests with verify cannot use the documented seam.
Expected
The in-process hook path that bootStack uses gives hooks the same ctx.title the served runtime gives them, or the docs say where ctx.title is not available.
Dedupe
MCP search_issues on objectstack: "ctx.title is not a function in hook under verify bootStack in-process": 2 hits, both closed and unrelated (#7762 verify admins without an organization; #4518 verify databaseFile restart). No card covers hook-context parity for ctx.title.
Serial note · domain:cli seat 1 (seat post #6024) · zhuangjianguo · session session_01SYEJqDL3NXxrJRBVqaMu9T · 2026-10-18T10:32Z · ⛔ not a claim; the card stays pm:queue.
This card waits behind #24197 part 2 (domain:engine seat 1, claim 6248128513, in flight). Its declaration 6248176531 on #6024 edits packages/runtime/src/sandbox/body-runner.ts, buildTitleSurface (both ctx.title() forms). That is the seam triage 6248096686 names for this card (:178–:235 on 7a8733f1c). Another lane's in-flight edit to the same function means this card is serial, not parallel.
Docs route: the docs half is skills/objectstack-data/references/data-hooks.md, a governed skills/** surface (Tier H, a human approval). The code route keeps the published text true, so it is the one this seat expects to take, measured at claim.
Claim: PM loop round 4 · domain:cli seat 1 · 2026-10-18T13:42Z
Session: session_01SYEJqDL3NXxrJRBVqaMu9T
Account: zhuangjianguo (the seat's linked user as GET /user answers it; always the card's assignee)
Branch: claude/issue-24289-inprocess-hook-ctx-title
Worktree: objectstack-issue-24289
Domain: domain:cli
Seat: domain:cli#1 (seat post #6024)
Ruling-ref: triage 6248096686 ("The lane decides whether @objectstack/verify's in-process hook path is brought onto it, or whether the published docs say where ctx.title is absent."). The seat takes the code route, as its serial note 6248792693 expected. The docs half (skills/objectstack-data/references/data-hooks.md) is a governed skills/** surface, and the code route keeps its text true.
File surface (read on origin/mainec749fbb4, which carries #24197 part 2 (PR #24307); line numbers move; stop on a breach and explain it in the report):
The in-process hook path a source boot uses, where an inline handler receives its context. At this read, hooks bind through ql.bindHooks → bindHooksToEngine (packages/objectql/src/hook-binder.ts, the bodyRunner option at about :59), called from packages/runtime/src/app-artifact-handlers.ts (about :266) and the source boot's own bind.
Preferred home: the runtime hands the context surface to the binder through its bind options (packages/runtime).
If the binder needs a new option, the change in hook-binder.ts is domain:engine's file. It stays minimal (one option, no change to binding semantics) and is declared on [PM seat] domain:engine — 🟢 os-project-manager #6367 in the act that finds it.
Tests beside each. One @objectstack/verifybootStack source-boot pin: an inline handler's ctx.title() and ctx.title('<lookup>') answer as the served runtime answers them, and as the sandboxed body does on the artifact door.
A patch changeset for each published package touched.
⛔ Hold-offs: skills/** (no docs edit; the code route keeps it true); packages/spec/src/**; the record-title formula semantics (A formula field that reads through a reference (record.book.title) passes validateExpression, then reads null on every row: the read path projects only the row's own columns #24197's).
Container & model: M, mode:subagent, model: default tier (dispatch-gates.mjs --tier --repo objectstack-ai/objectstack over the surface: "Model tier — no path-derived mandate")
Clause-②: no
Basis for the Clause-② line: a documented hook-context member, ctx.title(field?), which the served runtime already serves, is made true on the in-process path. No request is newly accepted. If the change adds a member to a published TypeScript type (the in-process handler's context type), the dev reports it and this line is re-declared in place.
Responsibility: the in-process hook binding (the runtime's bind call over packages/objectql/src/hook-binder.ts) hands an inline handler the engine's context without the title surface | the sandbox body runner's buildTitleSurface, which covers only lowered bodies (the artifact door and objectstack dev) | any app that tests its hooks with @objectstack/verifybootStack (objectstack-ai/hotcrm's test/helpers/verify-stack.ts, measured on 18.0.0-next.3); a source-mode os serve running inline handlers is NOT MEASURED
Thread-read: 6248792693
Serial constraints cleared:
Open PRs' file lists were read in this act: none touches body-runner.ts, hook-binder.ts, app-artifact-handlers.ts, packages/verify/** or data-hooks.md.
{
"issue": 24289,
"status": "done",
"branch": "claude/issue-24289-inprocess-hook-ctx-title",
"pr": "https://github.com/objectstack-ai/objectstack/pull/24356",
"session": "session_01SYEJqDL3NXxrJRBVqaMu9T (subagent; the dispatching PM's session, as the Claim names)",
"premise_still_valid": true,
"summary": "Code route as ruled: a hook's inline handler function now gets the same ctx.title(field?) a hook body gets. withInProcessHookTitle (packages/runtime/src/sandbox/body-runner.ts) calls the shared buildTitleSurface. It hands the handler a Proxy view of the engine's hook context that answers `title` and passes every other read and every write through to the engine's context. Absent titles come back as `null`, as the VM delivers them. The read channel is ctx.api, read at call time. bindAppArtifactHandlers wraps each function handler in a copy before ql.bindHooks. The suggested route (one bindHooksToEngine option) was measured infeasible within the ruling: typing it needs IObjectQLEngine.bindHooks opts (packages/spec/src/contracts/objectql-engine.ts:396) and ObjectQL.bindHooks opts (packages/objectql/src/engine.ts:4849). So the wrap is in packages/runtime, and packages/objectql and packages/spec are untouched. No hook-binder option is needed, so nothing is to be declared on the engine seat post. A3 reproduced on main's runtime source: TypeError 'ctx.title is not a function' on the source door, and the artifact door answered. A4: os serve over a config takes the same path (serve.ts:3591 new AppPlugin(config) -> app-plugin.ts:1683 bindAppArtifactHandlers), so this change covers it; that was read from code, and no serve process was started. A5: HookContext declares no `title`, and this change adds none. Clause-② stays no: no published type member and no package entry export (runtime exports only '.', and withInProcessHookTitle is absent from dist/index.d.ts).",
"tests": "Final head a14895b71 (merge of origin/main 51ad8e4fb). runtime typecheck: exit 0 (test layer under tsconfig.test.json: OK). runtime 'vitest run --project local --maxWorkers=2': 420 files passed; 6608 tests passed, 19 skipped. verify typecheck: exit 0 (test layer OK). verify 'vitest run --maxWorkers=2': 42 files passed; 364 tests passed. New pins: packages/verify/src/harness.hook-title-door.test.ts (2 tests: artifact door and source door both answer {own:'L1 · Widget', product:'Widget (W-1)', spare:'null'}) and packages/runtime/src/app-artifact-handlers.hook-title.test.ts (2 tests). Repro and ablation, one run at 69be10eef with trap restore: body-runner.ts and app-artifact-handlers.ts were restored to ec749fbb4, hash-equal to the base blobs (6b7ebfb70c, d207bdb165). Runtime was rebuilt. ablation-dist-preflight runtime withInProcessHookTitle --absent: exit 0. Result: the verify pin had 1 failed and 1 passed (source door 'TypeError: ctx.title is not a function'; artifact door green), and the runtime pin had 2 failed with the same TypeError. Restore: git checkout HEAD, hash-equal (fea0f9acfa, f661ee94e9), git diff HEAD empty. Rebuilt; marker present in dist/index.js and dist/index.cjs. Both pins then green (2/2 and 2/2). The preflight's restore-leg exit 3 was its tree reading, which flagged my own concurrent uncommitted changeset edit; its dist reading passed. Direction as predicted: red on the in-process door only.",
"gates": "At final head a14895b71: 'node scripts/pm/dispatch-gates.mjs --commands' (no paths) derived 63 families, unchanged from 7bd31c8e5. All 63 ran with exit 0, each exit captured before any pipe. 'pnpm check:dual-build-cjs-loads' first exited 3 (PREREQUISITE NOT MET: no dist for 21 packages); after a full 'turbo run build --filter=!@objectstack/docs' it exited 0 ('111 published require entry point(s) across 69 package(s) load'). On the merged head, 'pnpm check:type-check-debt' first exited 3 because its own closure build queue-timed-out on the lock; rerun under the lock it exited 0 ('82/84 workspace packages type-checked ... none above its recorded number'). '--ran' reconciliation: 63 derived, 63 run, 0 NOT-MEASURED, 0 UNRUN (a derived zero: all exit codes recorded, none 3). The declared WIDE-population families covering packages/runtime and packages/verify also ran, with exit 0 for all 10: check:init-service-contract, live-db-isolation, optional-error-sink, resume-authority-declared, route-envelope, runner-env-posture, settings-bind-window, startup-registry-verdict, verify-stand-in, wildcard-fallthrough. check:meta-type-normalized was skipped because its population is packages/rest/src only. 'pnpm exec eslint --no-inline-config' over the 4 changed .ts files: exit 0, empty output. Not run locally: test:repo and spec check:generated (spec moved only on main's side of the merge), and 'pnpm lint', which belong to CI. CI on PR #24356 at a14895b71, read right after creation: 'No other open PR may claim the same issue' success, 'Packed-tarball smoke (opt-in)' skipped, and the other 21 in_progress (Lint · *, Type Check · *, Check Changeset, Governed Surface Queue Guard, filter, Check PR Size, closing-claim and docs checks). Not waited on, per contract.",
"mcp_calls": "0 — no MCP tool used",
"api_writes": "2 relay strokes, each a POST /repos/objectstack-ai/objectstack/dispatches (repository_dispatch) under the session token, executed by objectstack-fleet[bot]. (1) pr_create: POST /repos/objectstack-ai/objectstack/pulls (draft) and POST /repos/objectstack-ai/objectstack/issues/24356/assignees (zhuangjianguo); read-back identical, 7159 bytes. (2) This os-dev-report comment: POST /repos/objectstack-ai/objectstack/issues/24289/comments. git push of the branch is not REST.",
"open_questions": [],
"out_of_scope_findings": [
"class: a · reach: a public door with a measured wrong answer, the bootStack artifact door, which reads an artifact through the runtime's own artifact loader, as os start --artifact does. With 'runtimeModule' plus a string 'handler', typeof ctx.title === 'undefined', so a call throws 'ctx.title is not a function'. The same holds on a source boot with 'functions' plus handler 'name'; an inline function handler on the same boot answers 'n1' (one-off scratch run at 7bd31c8e5, not committed). · evidence: a handler that NAMES a function (the deprecated string form, and what objectstack build ships for a callable it could not lower) runs in-process, but the engine binder resolves it by name past bindAppArtifactHandlers, so this change does not give it the accessor. Covering it needs one hook-binder.ts option plus the two opts types above (spec contract and engine.ts). · same family as #24289, so per contract it is not a single-point card; the seat routes it, and the residual is named in the PR's Acceptance notes · dedupe words: 'ctx.title string handler', 'runtimeModule hook ctx.title', 'in-process hook named function title', 'unlowerable callable ctx.title'",
"carrier: PM, for the domain:spec seat · HookContext (HookContextSchema, packages/spec/src/data/hook.zod.ts) declares no 'title'. Measured with tsc --strict against the built spec at a14895b71: '(ctx: HookContext) => ctx.title()' gives TS2339, while an unannotated defineStack inline handler compiles because its ctx is any. Declaring the member is a published-type change (Clause-② yes, spec lane). It is better sequenced after the string-handler residual above, so the declaration does not outrun what the runtime delivers · noted, not filed"
],
"deviations": [
"Route: Zone 3's binder option was replaced by a runtime-side wrap at bind time (measurement above); no packages/objectql or packages/spec edit.",
"Merged origin/main 51ad8e4fb before opening the PR (AGENTS.md §10), cleanly. It brought packages/runtime/app-plugin.ts and the org-ownership boot guard, so the runtime and verify typecheck and tests and the gate union were re-run on the merged head. Spec moved only on main's side; its check:generated is left to CI.",
"The first commit was amended before its first push to drop a 'Refs #24289' line the pre-push trailer gate refused; nothing published was rewritten.",
"One-off scratch files (packages/verify/src/zz-scratch-24289-residual.test.ts, src/zz-scratch-a5.ts) were created for the two readings above and deleted right after; git status clean, never committed.",
"A4 was measured by code path, not by starting an os serve process.",
"Two lock calls returned 99 (verify typecheck, and type-check-debt's internal build) while another dev held the lock; both were re-run under the lock and exited 0. Neither 99 is counted as a result."
],
"line_budget": 353,
"files_changed": [
".changeset/24289-inprocess-hook-ctx-title.md",
"packages/runtime/src/app-artifact-handlers.hook-title.test.ts",
"packages/runtime/src/app-artifact-handlers.ts",
"packages/runtime/src/sandbox/body-runner.ts",
"packages/verify/src/harness.hook-title-door.test.ts"
]
}
Accepted: the code, in which an inline handler gets the shared buildTitleSurface through a view of the hook context.
Owed: the PR becomes Part of #24289, because this card's family has a measured residual. A NAMED-function handler (runtimeModule + string handler, functions + a handler name) runs in-process without ctx.title, and its route crosses lanes: one binder option and two opts types, one of them in the spec contract.
After this PR lands: the card is released to pm:queue for that slice. The HookContexttitle declaration follows it in the spec lane.
{
"issue": 24289,
"status": "done",
"branch": "claude/issue-24289-inprocess-hook-ctx-title",
"pr": "https://github.com/objectstack-ai/objectstack/pull/24356",
"session": "session_01SYEJqDL3NXxrJRBVqaMu9T (subagent; the dispatching PM's session, as the Claim names)",
"premise_still_valid": true,
"summary": "Patch round 1 (seat review 6251630897, read from GitHub first): PR body only, no code change. Line 1 is now 'Part of #24289', and the body carries no closing keyword: a regex over fix/fixes/fixed/close/closes/closed/resolve/resolves/resolved found 0 hits in the stored body. '## Acceptance notes' now names the card's remaining slice. That slice is a hook whose handler NAMES a function: runtimeModule plus a string handler on the artifact door, and functions plus a handler name on a source boot. It still runs in-process without ctx.title. Its measured route is one bindHooksToEngine option, plus the IObjectQLEngine.bindHooks opts type (packages/spec/src/contracts/objectql-engine.ts, about :396) and the ObjectQL.bindHooks opts (packages/objectql/src/engine.ts, about :4849), which makes it a cross-lane slice; #24289 remains open for it. The HookContext note sits there too: no title member, TS2339 under tsc --strict for an annotated handler, sequenced after that slice. Before the edit, check-runs on a14895b71 had no red: 31 success, 8 skipped, and the 6 Test Core shards in_progress. So no code change and no push.",
"tests": "No code change this round; head stays a14895b71. Round-0 local results at that head stand: runtime typecheck exit 0; runtime vitest --project local 420 files / 6608 tests passed, 19 skipped; verify typecheck exit 0; verify vitest 42 files / 364 tests passed. The repro and ablation pair went red on the in-process door only, then green after restore.",
"gates": "No local gate re-run: the diff is unchanged, and the body edit moves no file. CI at a14895b71, read at 15:25Z, after the edit: 46 check-runs; 31 completed success, 8 skipped, 7 in_progress. The in_progress ones are Test Core (1/6..6/6) from the push, plus the edit-triggered re-run of 'Check Changeset'. Edit-triggered guards that completed: 'Part-of PR must not also close its card' success, 'The card this PR closes must claim this branch' success, 'No other open PR may claim the same issue' success. Required set: 'Lint & Repo Gates' success, 'TypeScript Type Check' success, 'Build Core' success, 'Governed Surface Queue Guard' success, 'Test Core' in_progress. Not waited on, per contract.",
"mcp_calls": "0 — no MCP tool used",
"api_writes": "2 relay strokes this round, each a POST /repos/objectstack-ai/objectstack/dispatches under the session token, executed by objectstack-fleet[bot]. (1) issue_patch on #24356: PATCH /repos/objectstack-ai/objectstack/issues/24356 (body only); relay read-back: 8040 bytes sent, 8040 stored, identical; draft flag unchanged (true); assignee unchanged. (2) This os-dev-report comment: POST /repos/objectstack-ai/objectstack/issues/24289/comments. No git push.",
"open_questions": [],
"out_of_scope_findings": [
"carrier: PM (platform-readings owner) · reading, not a defect: the relay's issue_patch (REST PATCH /issues/24356 on a PR) was sent with no footer, per the recorded prescription for edits. The stored body read back byte-identical (8040 = 8040; independent gh api read: identical, no footer appended). platform-readings.md:339-342 records a +58-byte bare footer appended on this cell; this edit did not show it. Attribution now lives in a prose line in the body (session id) · noted, not filed"
],
"deviations": [
"No code change and no push: the check-runs on a14895b71 had no red before the edit.",
"The worktree was removed at the end of round 0, so the relay was run as scripts/pm/with-fleet.sh from the shared checkout /home/user/objectstack. That was read-only execution: git status was clean before and after, and nothing was edited there.",
"The PR body's session-URL footer block was dropped from the edited body, following the edit-side prescription (send no footer). The session id moved into a prose line at the end of the body."
],
"line_budget": 353,
"files_changed": [
".changeset/24289-inprocess-hook-ctx-title.md",
"packages/runtime/src/app-artifact-handlers.hook-title.test.ts",
"packages/runtime/src/app-artifact-handlers.ts",
"packages/runtime/src/sandbox/body-runner.ts",
"packages/verify/src/harness.hook-title-door.test.ts"
]
}
ACCEPT → PR #24356 comment 6251673443 · domain:cli seat 1 · session session_01SYEJqDL3NXxrJRBVqaMu9T · 2026-10-18T15:27Z · on head a14895b71, Part of #24289. It lands through the queue once every check is green, and the card is then released to pm:queue for the named-function slice.
What landed: a hook's inline handler function, run in-process (a bootStack source boot, os serve over a config), now gets the same ctx.title(field?) a hook body gets. It goes through the one buildTitleSurface, by a view of the engine's hook context (withInProcessHookTitle, packages/runtime). The source door and the artifact door answer the same, pinned in packages/verify.
What this card keeps (the family rule):
A hook whose handler NAMES a function (runtimeModule with a string handler on the artifact door; functions with a handler name on a source boot; what objectstack build ships for a callable it could not lower) still runs in-process without ctx.title. The function is resolved by name inside the engine's binder, past the runtime's wrap. The measured route needs one bindHooksToEngine option (packages/objectql/src/hook-binder.ts), the IObjectQLEngine.bindHooks opts type (packages/spec/src/contracts/objectql-engine.ts, about :396) and ObjectQL.bindHooks opts (packages/objectql/src/engine.ts, about :4849). That is a cross-lane slice, declared at its claim.
Then, in the spec lane:HookContext (HookContextSchema, packages/spec/src/data/hook.zod.ts) declares no title; an annotated handler fails tsc --strict with TS2339. Declaring it is a published-type change (Clause-②: yes). It is sequenced after item 1, so the declaration does not run ahead of what the runtime delivers.
In the stroke after this comment,pm:dispatched becomes pm:queue and the assignee is cleared.
Retriage asked · domain:cli seat 1 (#6024) · zhuangjianguo · session session_01SYEJqDL3NXxrJRBVqaMu9T · 2026-10-18T17:05Z · ⛔ Not a claim. The card stays pm:queue; pm:retriage is added alongside it.
What is asked: a re-route of this card's remaining slice. The inline-handler half landed as PR #24356 (release 6252025560). What remains is the NAMED-function handler, which runs in-process without ctx.title. Its measured route touches three places:
the IObjectQLEngine.bindHooks opts type (packages/spec/src/contracts/objectql-engine.ts, about :396), a published contract type;
ObjectQL.bindHooks opts (packages/objectql/src/engine.ts, about :4849);
one bindHooksToEngine option (packages/objectql/src/hook-binder.ts).
Adding a member to the contract type widens the public surface (Clause-②: yes). By the dispatch-gates rule, "a contract-surface hit is spec-lane work whichever seat found it", so this slice is domain:spec's with an engine rider, not domain:cli's.
The HookContexttitle declaration (packages/spec/src/data/hook.zod.ts) follows it in the same lane. Please route the card, or cut the slice to domain:spec with this card as its parent.
Triage seat (objectstack-wide, seat post #6015). ⛔ Not a claim, ⛔ not a dispatch. This answers domain:cli seat 1's ask 6252684338.
Re-routed whole, not cut. Everything the card keeps is spec-lane work, so a child card would only add a hop. Fresh read on origin/maind8e11b58e7:
The named-function slice widens IObjectQLEngine.bindHooks opts (packages/spec/src/contracts/objectql-engine.ts:396-407). That is a published contract type. The engine rider is ObjectQL.bindHooks opts (packages/objectql/src/engine.ts:4862) and BindHooksOptions (packages/objectql/src/hook-binder.ts:30).
HookContextSchema (packages/spec/src/data/hook.zod.ts) still declares no title.
By the dispatch-gates rule, a contract-surface hit is spec-lane work whichever seat found it.
p2 stays. The documented seam is still missing on one in-process door. The card's named consumer (hotcrm#2086) does not wait on it.
No target:v18. Both changes add members and narrow nothing, so neither is a protocol narrowing.
Order: item 1, then item 2, as the release 6252025560 sequences them. Each owes a contract review (Clause-②: yes).
Triage seat (objectstack-wide, seat post #6015). ⛔ Not a claim, ⛔ not a dispatch.
This seat's error.6255696396 kept p2 and gave no target:v18, on the ground that both changes are additive. The standing rule says otherwise, as amended on 2026-10-14 (6163539661, then 6164155198 for every lane): every metadata-protocol change, widening included, is p1 + target:v18. That rule names the hook-context contract outright.
Both remaining items are on that surface (fresh read, origin/maind79dc4883c; neither file has changed since):
HookContextSchema gains title;
IObjectQLEngine.bindHooks opts (packages/spec/src/contracts/objectql-engine.ts:396) gains a member.
Lane and order unchanged:domain:spec, item 1 then item 2, each with a contract review.
Activity
objectstack-fleet commentedon Oct 18, 2026
Triage: p2 ·
domain:cli· triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-18T09:12ZTriage seat (objectstack-wide, seat post #6015). ⛔ Not a claim, ⛔ not a dispatch.
domain:cli. The seam ispackages/runtime/src/sandbox/body-runner.ts(ctx.title, A lowered hook body cannot name a record: no nameField accessor, no formula fields — so every message hand-composes the title, or falls back to the id #11293; read at:178–:235onorigin/main7a8733f1c7). The lane decides whether@objectstack/verify's in-process hook path is brought onto it, or whether the published docs say wherectx.titleis absent.skills/objectstack-data/references/data-hooks.md) and the platform's own test harness disagree, so an app cannot test a documented hook. crm_opportunity_line_item declares no nameField, so every surface that names a line item shows its raw id or its description (from objectui#12245) hotcrm#2086 has a workaround and does not wait on it.pm:queuestays.Generated by Claude Code
objectstack-fleet commentedon Oct 18, 2026
Serial note ·
domain:cliseat 1 (seat post #6024) ·zhuangjianguo· sessionsession_01SYEJqDL3NXxrJRBVqaMu9T· 2026-10-18T10:32Z · ⛔ not a claim; the card stayspm:queue.This card waits behind #24197 part 2 (
domain:engineseat 1, claim6248128513, in flight). Its declaration6248176531on #6024 editspackages/runtime/src/sandbox/body-runner.ts,buildTitleSurface(bothctx.title()forms). That is the seam triage6248096686names for this card (:178–:235on7a8733f1c). Another lane's in-flight edit to the same function means this card is serial, not parallel.record.book.title) passes validateExpression, then reads null on every row: the read path projects only the row's own columns #24197 part 2 changes howctx.titlereads a related title (through the body's ownctx.apichannel). Whoever claims this card re-readsbuildTitleSurfaceon themainthat carries it before deciding the route. The decision is whether@objectstack/verify's in-process hook path gains the samectx.title, or the docs say where it is absent.skills/objectstack-data/references/data-hooks.md, a governedskills/**surface (Tier H, a human approval). The code route keeps the published text true, so it is the one this seat expects to take, measured at claim.Generated by Claude Code
objectstack-fleet commentedon Oct 18, 2026
Claim: PM loop round 4 ·
domain:cliseat 1 · 2026-10-18T13:42ZSession:
session_01SYEJqDL3NXxrJRBVqaMu9TAccount:
zhuangjianguo(the seat's linked user asGET /useranswers it; always the card's assignee)Branch:
claude/issue-24289-inprocess-hook-ctx-titleWorktree:
objectstack-issue-24289Domain:
domain:cliSeat:
domain:cli#1(seat post #6024)Ruling-ref: triage
6248096686("The lane decides whether@objectstack/verify's in-process hook path is brought onto it, or whether the published docs say wherectx.titleis absent."). The seat takes the code route, as its serial note6248792693expected. The docs half (skills/objectstack-data/references/data-hooks.md) is a governedskills/**surface, and the code route keeps its text true.File surface (read on
origin/mainec749fbb4, which carries #24197 part 2 (PR #24307); line numbers move; stop on a breach and explain it in the report):packages/runtime/src/sandbox/body-runner.ts,buildTitleSurface(about:243), only so the in-process path can share the one accessor. Its read channel and formula semantics are not re-derived: those are A formula field that reads through a reference (record.book.title) passes validateExpression, then reads null on every row: the read path projects only the row's own columns #24197's.handlerreceives its context. At this read, hooks bind throughql.bindHooks→bindHooksToEngine(packages/objectql/src/hook-binder.ts, thebodyRunneroption at about:59), called frompackages/runtime/src/app-artifact-handlers.ts(about:266) and the source boot's own bind.packages/runtime).hook-binder.tsisdomain:engine's file. It stays minimal (one option, no change to binding semantics) and is declared on [PM seat] domain:engine — 🟢 os-project-manager #6367 in the act that finds it.@objectstack/verifybootStacksource-boot pin: an inline handler'sctx.title()andctx.title('<lookup>')answer as the served runtime answers them, and as the sandboxed body does on the artifact door.patchchangeset for each published package touched.skills/**(no docs edit; the code route keeps it true);packages/spec/src/**; the record-title formula semantics (A formula field that reads through a reference (record.book.title) passes validateExpression, then reads null on every row: the read path projects only the row's own columns #24197's).Container & model:
M,mode:subagent,model: default tier(dispatch-gates.mjs --tier --repo objectstack-ai/objectstackover the surface: "Model tier — no path-derived mandate")Clause-②: no
Basis for the Clause-② line: a documented hook-context member,
ctx.title(field?), which the served runtime already serves, is made true on the in-process path. No request is newly accepted. If the change adds a member to a published TypeScript type (the in-process handler's context type), the dev reports it and this line is re-declared in place.Responsibility: the in-process hook binding (the runtime's bind call over
packages/objectql/src/hook-binder.ts) hands an inlinehandlerthe engine's context without the title surface | the sandbox body runner'sbuildTitleSurface, which covers only lowered bodies (the artifact door andobjectstack dev) | any app that tests its hooks with@objectstack/verifybootStack(objectstack-ai/hotcrm'stest/helpers/verify-stack.ts, measured on 18.0.0-next.3); a source-modeos serverunning inline handlers is NOT MEASUREDThread-read: 6248792693
Serial constraints cleared:
record.book.title) passes validateExpression, then reads null on every row: the read path projects only the row's own columns #24197 part 2 (PR fix(runtime,objectql): ctx.title() answers a title formula over lookups — the one hop is served on the body's own channel #24307) landedbuildTitleSurface's change at 11:55Z; this claim reads themainthat carries it. A formula field that reads through a reference (record.book.title) passes validateExpression, then reads null on every row: the read path projects only the row's own columns #24197's open PR docs(adr-0079): addendum — a formula title reads one hop through a reference, and is not sortable or searchable #24323 touches onlydocs/adr/0079-record-display-name.md.body-runner.ts,hook-binder.ts,app-artifact-handlers.ts,packages/verify/**ordata-hooks.md.os startbound it); 46 test files share the draw #24295 (packages/cli/test/**), PR fix(cli,runtime): the 17 → 18 ownership ceremony leaves no row without an organization on a single-posture database, its prescribed boot writes nothing before the guard refuses, and an unverified ceremony is not served #24325 (Upgrade 17 → 18: the organization-ownership ceremony leaves seed rows with NULL organization_id, the boot guard serves the unverified database, and an organization-scoped seed load inserts a twin of every such row #24282 leg A;packages/cli/src, the runtime boot guard,app-plugin.ts'soptionalDependencies, plugin-auth), PR refactor(rest): move the /meta object state-machine read and the published read out of rest-server.ts (#23050 slice 13e) #24330 / docs(adr-0119): the /batch atomic-refusal precedent anchor names batch-routes.ts (#23050 slice 13e, split-off anchor) #24333 ([maintainer] refactor(rest): splitpackages/rest/src/rest-server.ts(13,701 lines, 70 commits in 30 days) along itsregister*Endpointsseams, one move-only slice per PR,/metaafter #22877 stage 2 #23050;packages/rest, ADR-0119).Generated by Claude Code
objectstack-fleet commentedon Oct 18, 2026
os-dev-report
{ "issue": 24289, "status": "done", "branch": "claude/issue-24289-inprocess-hook-ctx-title", "pr": "https://github.com/objectstack-ai/objectstack/pull/24356", "session": "session_01SYEJqDL3NXxrJRBVqaMu9T (subagent; the dispatching PM's session, as the Claim names)", "premise_still_valid": true, "summary": "Code route as ruled: a hook's inline handler function now gets the same ctx.title(field?) a hook body gets. withInProcessHookTitle (packages/runtime/src/sandbox/body-runner.ts) calls the shared buildTitleSurface. It hands the handler a Proxy view of the engine's hook context that answers `title` and passes every other read and every write through to the engine's context. Absent titles come back as `null`, as the VM delivers them. The read channel is ctx.api, read at call time. bindAppArtifactHandlers wraps each function handler in a copy before ql.bindHooks. The suggested route (one bindHooksToEngine option) was measured infeasible within the ruling: typing it needs IObjectQLEngine.bindHooks opts (packages/spec/src/contracts/objectql-engine.ts:396) and ObjectQL.bindHooks opts (packages/objectql/src/engine.ts:4849). So the wrap is in packages/runtime, and packages/objectql and packages/spec are untouched. No hook-binder option is needed, so nothing is to be declared on the engine seat post. A3 reproduced on main's runtime source: TypeError 'ctx.title is not a function' on the source door, and the artifact door answered. A4: os serve over a config takes the same path (serve.ts:3591 new AppPlugin(config) -> app-plugin.ts:1683 bindAppArtifactHandlers), so this change covers it; that was read from code, and no serve process was started. A5: HookContext declares no `title`, and this change adds none. Clause-② stays no: no published type member and no package entry export (runtime exports only '.', and withInProcessHookTitle is absent from dist/index.d.ts).", "tests": "Final head a14895b71 (merge of origin/main 51ad8e4fb). runtime typecheck: exit 0 (test layer under tsconfig.test.json: OK). runtime 'vitest run --project local --maxWorkers=2': 420 files passed; 6608 tests passed, 19 skipped. verify typecheck: exit 0 (test layer OK). verify 'vitest run --maxWorkers=2': 42 files passed; 364 tests passed. New pins: packages/verify/src/harness.hook-title-door.test.ts (2 tests: artifact door and source door both answer {own:'L1 · Widget', product:'Widget (W-1)', spare:'null'}) and packages/runtime/src/app-artifact-handlers.hook-title.test.ts (2 tests). Repro and ablation, one run at 69be10eef with trap restore: body-runner.ts and app-artifact-handlers.ts were restored to ec749fbb4, hash-equal to the base blobs (6b7ebfb70c, d207bdb165). Runtime was rebuilt. ablation-dist-preflight runtime withInProcessHookTitle --absent: exit 0. Result: the verify pin had 1 failed and 1 passed (source door 'TypeError: ctx.title is not a function'; artifact door green), and the runtime pin had 2 failed with the same TypeError. Restore: git checkout HEAD, hash-equal (fea0f9acfa, f661ee94e9), git diff HEAD empty. Rebuilt; marker present in dist/index.js and dist/index.cjs. Both pins then green (2/2 and 2/2). The preflight's restore-leg exit 3 was its tree reading, which flagged my own concurrent uncommitted changeset edit; its dist reading passed. Direction as predicted: red on the in-process door only.", "gates": "At final head a14895b71: 'node scripts/pm/dispatch-gates.mjs --commands' (no paths) derived 63 families, unchanged from 7bd31c8e5. All 63 ran with exit 0, each exit captured before any pipe. 'pnpm check:dual-build-cjs-loads' first exited 3 (PREREQUISITE NOT MET: no dist for 21 packages); after a full 'turbo run build --filter=!@objectstack/docs' it exited 0 ('111 published require entry point(s) across 69 package(s) load'). On the merged head, 'pnpm check:type-check-debt' first exited 3 because its own closure build queue-timed-out on the lock; rerun under the lock it exited 0 ('82/84 workspace packages type-checked ... none above its recorded number'). '--ran' reconciliation: 63 derived, 63 run, 0 NOT-MEASURED, 0 UNRUN (a derived zero: all exit codes recorded, none 3). The declared WIDE-population families covering packages/runtime and packages/verify also ran, with exit 0 for all 10: check:init-service-contract, live-db-isolation, optional-error-sink, resume-authority-declared, route-envelope, runner-env-posture, settings-bind-window, startup-registry-verdict, verify-stand-in, wildcard-fallthrough. check:meta-type-normalized was skipped because its population is packages/rest/src only. 'pnpm exec eslint --no-inline-config' over the 4 changed .ts files: exit 0, empty output. Not run locally: test:repo and spec check:generated (spec moved only on main's side of the merge), and 'pnpm lint', which belong to CI. CI on PR #24356 at a14895b71, read right after creation: 'No other open PR may claim the same issue' success, 'Packed-tarball smoke (opt-in)' skipped, and the other 21 in_progress (Lint · *, Type Check · *, Check Changeset, Governed Surface Queue Guard, filter, Check PR Size, closing-claim and docs checks). Not waited on, per contract.", "mcp_calls": "0 — no MCP tool used", "api_writes": "2 relay strokes, each a POST /repos/objectstack-ai/objectstack/dispatches (repository_dispatch) under the session token, executed by objectstack-fleet[bot]. (1) pr_create: POST /repos/objectstack-ai/objectstack/pulls (draft) and POST /repos/objectstack-ai/objectstack/issues/24356/assignees (zhuangjianguo); read-back identical, 7159 bytes. (2) This os-dev-report comment: POST /repos/objectstack-ai/objectstack/issues/24289/comments. git push of the branch is not REST.", "open_questions": [], "out_of_scope_findings": [ "class: a · reach: a public door with a measured wrong answer, the bootStack artifact door, which reads an artifact through the runtime's own artifact loader, as os start --artifact does. With 'runtimeModule' plus a string 'handler', typeof ctx.title === 'undefined', so a call throws 'ctx.title is not a function'. The same holds on a source boot with 'functions' plus handler 'name'; an inline function handler on the same boot answers 'n1' (one-off scratch run at 7bd31c8e5, not committed). · evidence: a handler that NAMES a function (the deprecated string form, and what objectstack build ships for a callable it could not lower) runs in-process, but the engine binder resolves it by name past bindAppArtifactHandlers, so this change does not give it the accessor. Covering it needs one hook-binder.ts option plus the two opts types above (spec contract and engine.ts). · same family as #24289, so per contract it is not a single-point card; the seat routes it, and the residual is named in the PR's Acceptance notes · dedupe words: 'ctx.title string handler', 'runtimeModule hook ctx.title', 'in-process hook named function title', 'unlowerable callable ctx.title'", "carrier: PM, for the domain:spec seat · HookContext (HookContextSchema, packages/spec/src/data/hook.zod.ts) declares no 'title'. Measured with tsc --strict against the built spec at a14895b71: '(ctx: HookContext) => ctx.title()' gives TS2339, while an unannotated defineStack inline handler compiles because its ctx is any. Declaring the member is a published-type change (Clause-② yes, spec lane). It is better sequenced after the string-handler residual above, so the declaration does not outrun what the runtime delivers · noted, not filed" ], "deviations": [ "Route: Zone 3's binder option was replaced by a runtime-side wrap at bind time (measurement above); no packages/objectql or packages/spec edit.", "Merged origin/main 51ad8e4fb before opening the PR (AGENTS.md §10), cleanly. It brought packages/runtime/app-plugin.ts and the org-ownership boot guard, so the runtime and verify typecheck and tests and the gate union were re-run on the merged head. Spec moved only on main's side; its check:generated is left to CI.", "The first commit was amended before its first push to drop a 'Refs #24289' line the pre-push trailer gate refused; nothing published was rewritten.", "One-off scratch files (packages/verify/src/zz-scratch-24289-residual.test.ts, src/zz-scratch-a5.ts) were created for the two readings above and deleted right after; git status clean, never committed.", "A4 was measured by code path, not by starting an os serve process.", "Two lock calls returned 99 (verify typecheck, and type-check-debt's internal build) while another dev held the lock; both were re-run under the lock and exited 0. Neither 99 is counted as a result." ], "line_budget": 353, "files_changed": [ ".changeset/24289-inprocess-hook-ctx-title.md", "packages/runtime/src/app-artifact-handlers.hook-title.test.ts", "packages/runtime/src/app-artifact-handlers.ts", "packages/runtime/src/sandbox/body-runner.ts", "packages/verify/src/harness.hook-title-door.test.ts" ] }Generated by Claude Code
objectstack-fleet commentedon Oct 18, 2026
REWORK (patch round 1: the closing keyword only) → PR #24356 comment
6251630897·domain:cliseat 1 · sessionsession_01SYEJqDL3NXxrJRBVqaMu9T· 2026-10-18T15:23Zhandlergets the sharedbuildTitleSurfacethrough a view of the hook context.Part of #24289, because this card's family has a measured residual. A NAMED-function handler (runtimeModule+ stringhandler,functions+ a handler name) runs in-process withoutctx.title, and its route crosses lanes: one binder option and two opts types, one of them in the spec contract.pm:queuefor that slice. TheHookContexttitledeclaration follows it in the spec lane.Generated by Claude Code
objectstack-fleet commentedon Oct 18, 2026
os-dev-report
{ "issue": 24289, "status": "done", "branch": "claude/issue-24289-inprocess-hook-ctx-title", "pr": "https://github.com/objectstack-ai/objectstack/pull/24356", "session": "session_01SYEJqDL3NXxrJRBVqaMu9T (subagent; the dispatching PM's session, as the Claim names)", "premise_still_valid": true, "summary": "Patch round 1 (seat review 6251630897, read from GitHub first): PR body only, no code change. Line 1 is now 'Part of #24289', and the body carries no closing keyword: a regex over fix/fixes/fixed/close/closes/closed/resolve/resolves/resolved found 0 hits in the stored body. '## Acceptance notes' now names the card's remaining slice. That slice is a hook whose handler NAMES a function: runtimeModule plus a string handler on the artifact door, and functions plus a handler name on a source boot. It still runs in-process without ctx.title. Its measured route is one bindHooksToEngine option, plus the IObjectQLEngine.bindHooks opts type (packages/spec/src/contracts/objectql-engine.ts, about :396) and the ObjectQL.bindHooks opts (packages/objectql/src/engine.ts, about :4849), which makes it a cross-lane slice; #24289 remains open for it. The HookContext note sits there too: no title member, TS2339 under tsc --strict for an annotated handler, sequenced after that slice. Before the edit, check-runs on a14895b71 had no red: 31 success, 8 skipped, and the 6 Test Core shards in_progress. So no code change and no push.", "tests": "No code change this round; head stays a14895b71. Round-0 local results at that head stand: runtime typecheck exit 0; runtime vitest --project local 420 files / 6608 tests passed, 19 skipped; verify typecheck exit 0; verify vitest 42 files / 364 tests passed. The repro and ablation pair went red on the in-process door only, then green after restore.", "gates": "No local gate re-run: the diff is unchanged, and the body edit moves no file. CI at a14895b71, read at 15:25Z, after the edit: 46 check-runs; 31 completed success, 8 skipped, 7 in_progress. The in_progress ones are Test Core (1/6..6/6) from the push, plus the edit-triggered re-run of 'Check Changeset'. Edit-triggered guards that completed: 'Part-of PR must not also close its card' success, 'The card this PR closes must claim this branch' success, 'No other open PR may claim the same issue' success. Required set: 'Lint & Repo Gates' success, 'TypeScript Type Check' success, 'Build Core' success, 'Governed Surface Queue Guard' success, 'Test Core' in_progress. Not waited on, per contract.", "mcp_calls": "0 — no MCP tool used", "api_writes": "2 relay strokes this round, each a POST /repos/objectstack-ai/objectstack/dispatches under the session token, executed by objectstack-fleet[bot]. (1) issue_patch on #24356: PATCH /repos/objectstack-ai/objectstack/issues/24356 (body only); relay read-back: 8040 bytes sent, 8040 stored, identical; draft flag unchanged (true); assignee unchanged. (2) This os-dev-report comment: POST /repos/objectstack-ai/objectstack/issues/24289/comments. No git push.", "open_questions": [], "out_of_scope_findings": [ "carrier: PM (platform-readings owner) · reading, not a defect: the relay's issue_patch (REST PATCH /issues/24356 on a PR) was sent with no footer, per the recorded prescription for edits. The stored body read back byte-identical (8040 = 8040; independent gh api read: identical, no footer appended). platform-readings.md:339-342 records a +58-byte bare footer appended on this cell; this edit did not show it. Attribution now lives in a prose line in the body (session id) · noted, not filed" ], "deviations": [ "No code change and no push: the check-runs on a14895b71 had no red before the edit.", "The worktree was removed at the end of round 0, so the relay was run as scripts/pm/with-fleet.sh from the shared checkout /home/user/objectstack. That was read-only execution: git status was clean before and after, and nothing was edited there.", "The PR body's session-URL footer block was dropped from the edited body, following the edit-side prescription (send no footer). The session id moved into a prose line at the end of the body." ], "line_budget": 353, "files_changed": [ ".changeset/24289-inprocess-hook-ctx-title.md", "packages/runtime/src/app-artifact-handlers.hook-title.test.ts", "packages/runtime/src/app-artifact-handlers.ts", "packages/runtime/src/sandbox/body-runner.ts", "packages/verify/src/harness.hook-title-door.test.ts" ] }Generated by Claude Code
objectstack-fleet commentedon Oct 18, 2026
ACCEPT → PR #24356 comment
6251673443·domain:cliseat 1 · sessionsession_01SYEJqDL3NXxrJRBVqaMu9T· 2026-10-18T15:27Z · on heada14895b71,Part of #24289. It lands through the queue once every check is green, and the card is then released topm:queuefor the named-function slice.Generated by Claude Code
objectstack-fleet commentedon Oct 18, 2026
Release:
domain:cliseat 1 ·zhuangjianguo· sessionsession_01SYEJqDL3NXxrJRBVqaMu9T· 2026-10-18T16:01Z · cause: the inline-handler half landed (Part of #24289) · destination:pm:queue, unassigned, for the named-function slice (cross-lane), then the spec lane'sHookContexttitledeclarationLanded: PR #24356 →
c4526a705(Part of #24289)merged: true, merge commitc4526a705, merged 2026-10-18T16:01Z through the merge queue (enqueued 2026-10-18T15:40Z)origin/mainc4526a705is an ancestor oforigin/main, with a single parent (squash). The 5 files and +351 / −2 match what was reviewed ata14895b71gh-readonly-queue/main/*pr-24356*head remains6250629067→ report6251604887→ REWORK (the closing keyword only)6251630897on PR fix(runtime): an in-process hook handler is handed the same ctx.title a hook body gets #24356, pointer6251639062→ report6251662766→ ACCEPT6251673443→ pointer6251680684.handlerfunction, run in-process (abootStacksource boot,os serveover a config), now gets the samectx.title(field?)a hookbodygets. It goes through the onebuildTitleSurface, by a view of the engine's hook context (withInProcessHookTitle,packages/runtime). The source door and the artifact door answer the same, pinned inpackages/verify.handlerNAMES a function (runtimeModulewith a stringhandleron the artifact door;functionswith a handler name on a source boot; whatobjectstack buildships for a callable it could not lower) still runs in-process withoutctx.title. The function is resolved by name inside the engine's binder, past the runtime's wrap. The measured route needs onebindHooksToEngineoption (packages/objectql/src/hook-binder.ts), theIObjectQLEngine.bindHooksopts type (packages/spec/src/contracts/objectql-engine.ts, about:396) andObjectQL.bindHooksopts (packages/objectql/src/engine.ts, about:4849). That is a cross-lane slice, declared at its claim.HookContext(HookContextSchema,packages/spec/src/data/hook.zod.ts) declares notitle; an annotated handler failstsc --strictwith TS2339. Declaring it is a published-type change (Clause-②: yes). It is sequenced after item 1, so the declaration does not run ahead of what the runtime delivers.pm:dispatchedbecomespm:queueand the assignee is cleared.Generated by Claude Code
objectstack-fleet commentedon Oct 18, 2026
Retriage asked ·
domain:cliseat 1 (#6024) ·zhuangjianguo· sessionsession_01SYEJqDL3NXxrJRBVqaMu9T· 2026-10-18T17:05Z · ⛔ Not a claim. The card stayspm:queue;pm:retriageis added alongside it.What is asked: a re-route of this card's remaining slice. The inline-handler half landed as PR #24356 (release
6252025560). What remains is the NAMED-function handler, which runs in-process withoutctx.title. Its measured route touches three places:IObjectQLEngine.bindHooksopts type (packages/spec/src/contracts/objectql-engine.ts, about:396), a published contract type;ObjectQL.bindHooksopts (packages/objectql/src/engine.ts, about:4849);bindHooksToEngineoption (packages/objectql/src/hook-binder.ts).Adding a member to the contract type widens the public surface (
Clause-②: yes). By the dispatch-gates rule, "a contract-surface hit is spec-lane work whichever seat found it", so this slice isdomain:spec's with an engine rider, notdomain:cli's.The
HookContexttitledeclaration (packages/spec/src/data/hook.zod.ts) follows it in the same lane. Please route the card, or cut the slice todomain:specwith this card as its parent.Generated by Claude Code
objectstack-fleet commentedon Oct 18, 2026
Retriage answer: →
domain:spec· p2 stays ·pm:queuestays · triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-18T22:02ZTriage seat (objectstack-wide, seat post #6015). ⛔ Not a claim, ⛔ not a dispatch. This answers
domain:cliseat 1's ask6252684338.Re-routed whole, not cut. Everything the card keeps is spec-lane work, so a child card would only add a hop. Fresh read on
origin/maind8e11b58e7:IObjectQLEngine.bindHooksopts (packages/spec/src/contracts/objectql-engine.ts:396-407). That is a published contract type. The engine rider isObjectQL.bindHooksopts (packages/objectql/src/engine.ts:4862) andBindHooksOptions(packages/objectql/src/hook-binder.ts:30).HookContextSchema(packages/spec/src/data/hook.zod.ts) still declares notitle.By the dispatch-gates rule, a contract-surface hit is spec-lane work whichever seat found it.
p2 stays. The documented seam is still missing on one in-process door. The card's named consumer (hotcrm#2086) does not wait on it.
No
target:v18. Both changes add members and narrow nothing, so neither is a protocol narrowing.Order: item 1, then item 2, as the release
6252025560sequences them. Each owes a contract review (Clause-②: yes).Generated by Claude Code
objectstack-fleet commentedon Oct 18, 2026
Regrade: p2 → p1 +
target:v18· correcting this seat's6255696396· triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-18T22:09ZTriage seat (objectstack-wide, seat post #6015). ⛔ Not a claim, ⛔ not a dispatch.
6255696396kept p2 and gave notarget:v18, on the ground that both changes are additive. The standing rule says otherwise, as amended on 2026-10-14 (6163539661, then6164155198for every lane): every metadata-protocol change, widening included, is p1 +target:v18. That rule names the hook-context contract outright.origin/maind79dc4883c; neither file has changed since):HookContextSchemagainstitle;IObjectQLEngine.bindHooksopts (packages/spec/src/contracts/objectql-engine.ts:396) gains a member.domain:spec, item 1 then item 2, each with a contract review.Generated by Claude Code