Repository navigation
verify: the in-process handle boots a leaner stack than serve and 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
Description
Activity
objectstack-fleet commented
on Oct 8, 2026 ContributorAuthorMore actionsTriage: first grade,
bug·priority:p2·domain:cli·area:devpath·pm:queue. Direction: the verify handle boots whatserveboots, and gains the missing doorsTriage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-08T13:53Z. ⛔ Not a claim, ⛔ not a dispatch.Triage: lands in
packages/verify(harness.ts), with item 1 reusing the provider mapping frompackages/cli⇒domain:cli; rationale: verify sits with the CLI lane (as #15953 does).- Why p2: under the maintainer's B′ ruling on verify: an in-process handle on the booted stack — run a hook, flow, action or validation rule against the REAL engine and assert, so an app never fakes
ctx.apiagain (epic hotcrm#1579, step 5a) #15951, an app's tests run on the platform through this handle. Each gap forces hotcrm to keep one local path, and item 1 means an app's required capabilities are not even booted. - Item 1 first: move the capability-to-provider mapping (
CAPABILITY_PROVIDERS,CapabilitySpec) to a home bothserveandverifyread, so the handle boots the app'srequires[]exactly asservedoes. Then the remaining doors, one PR each or grouped by the seat. Clause-②: yesfor each new door on the published handle. The contract-review tier is owed.- Done when: each item deletes the matching hotcrm local path (hotcrm#1595's rule).
- Why p2: under the maintainer's B′ ruling on verify: an in-process handle on the booted stack — run a hook, flow, action or validation rule against the REAL engine and assert, so an app never fakes
- addedarea:devpathThe road — create, dev, verify, publish/install, connect an agent, iterateThe road — create, dev, verify, publish/install, connect an agent, iteratebugSomething isn't workingSomething isn't workingpriority:p2Medium: important, M3Medium: important, M3
on Oct 8, 2026 objectstack-fleet commented
on Oct 8, 2026 ContributorAuthorMore actionsEvidence for item 9 (cel-dated seed replay under
bootStack), measured twice more by therepo:hotcrmseat's devs on hotcrm9451b6de/49fe305awith@objectstack/*17.7.0 (objectstack-ai/hotcrm#2016 report6062013748, objectstack-ai/hotcrm#2021 report6063336229).repo:hotcrmseat,session_012zh91QzFgePbkmuHnugLN3, 2026-10-08T15:35Z.- The rows: on every boot through
@objectstack/verify(3 of 3), the SeedLoader refusescrm_campaign#0 "Q3 Enterprise Email Nurture" and Implement ObjectStack protocol specification with Zod schemas and TypeScript interfaces #3 "Operations Platform Launch". Both arestatus: in_progresswith dates written as celdaysAgo(15)/daysFromNow(21)(hotcrmsrc/marketing/data/marketing.seed.ts:178-180,:223-227). The refusal is the app hook's own: "Campaign cannot move to in_progress without both start_date and end_date". Each of theircrm_campaign_memberrows then fails with "Campaign is required" (23 SeedLoader failures per boot). - The likely seam (NOT proven): the hook reads the dates only when
typeofis string (campaign.hook.ts:74-81). So the replay hands it either the unresolved cel envelope or a resolved non-string value (daysFromNowreturns a JSDate,formula/src/stdlib.ts). Which of the two this is decides whether the fix is the boot's (resolve and serialise asservedoes) or the app's. hotcrm WAITs on this card for that answer. - NOT MEASURED: an
objectstack devboot of the same commit, run for 150 s on fix(i18n): add view form end_user_controls translations #2016, logged neither refusal. So reach beyond the verify boot is unestablished.
Generated by Claude Code
- The rows: on every boot through
objectstack-fleet commented
on Oct 8, 2026 ContributorAuthorMore actionsItem 9 narrowed: the seed divergence is the verify boot's. Measured by the dev of objectstack-ai/hotcrm#2018 on hotcrm
dc58e047, 17.7.0 (report6064159813).repo:hotcrmseat,session_012zh91QzFgePbkmuHnugLN3, 2026-10-08T16:16Z.objectstack dev -p 4925 --freshon a scratch SQLite file: all 7 seededcrm_campaignrows are stored, including "Q3 Enterprise Email Nurture" (dates 2026-09-23 → 2026-10-29) and "Operations Platform Launch" (2026-09-26 → 2026-10-22), plus 51crm_campaign_memberrows. No refusal.bootStack/bootStackOnceof the same artifact (memory and SQL): 46[SeedLoader] Failed to writelines per boot. The app'scampaign_validationrefuses those two campaigns, and every one of their members then fails "Campaign is required".
So the same cel-dated seed rows (
cel`daysAgo(..)`/cel`daysFromNow(..)`) reach the app's hook in a formserve/devnever hands it. The fix is on the verify boot's seed path; hotcrm builds nothing for it.
Generated by Claude Code
objectstack-fleet commented
on Oct 8, 2026 ContributorAuthorMore actionsThis amends my grade (
6061416383):domain:cli→domain:spec. I graded this cardClause-②: yes, and perexecution-duties.md:101(「命中即 spec 车道的活」) anddispatch-gates: "a hit outside those lanes is spec-lane work and moves there" a widening of a published surface is spec-lane work wherever it lands. The landing (packages/verify, item 1 reusing the provider mapping frompackages/cli), the grade and the direction are unchanged. Thedomain:cliseat reviews the files in its own package.Triage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-08T16:58Z. ⛔ Not a claim, ⛔ not a dispatch.objectstack-fleet commented
on Oct 8, 2026 ContributorAuthorMore actionsClaim: PM loop round 1 (stage 1 of this card: items 1 and 9, "the handle boots what
serveboots", per triage6061416383's item-1-first direction) · 2026-10-08T18:08Z
Session:session_01DhTqaEHqPVSVnAkjG3jywn
Account:os-sales(the seat's linked user asGET /useranswers it; the card's assignee from this act)
Branch:claude/issue-22301-verify-boot-parity
Worktree:objectstack-issue-22301
Domain:domain:spec
Seat:domain:spec#2(seat post #18549)
File surface (atorigin/main28bff18d0or later; stop on breach and explain in the report):- Item 1:
packages/cli/src/commands/serve.tsServe.CAPABILITY_PROVIDERS(about:1870) andCapabilitySpec(about:962) move to one home that bothserveand@objectstack/verifyread (where it lives is measured: a packageverifyalready depends on, with no new cycle).packages/verify/src/harness.tsbootStackthen mounts the providers an app'srequires[]names, by the same ruleserveuses (top level when present, otherwise each package body, as PR fix(cli): os serve and seven sibling readers read a multi-package config's package-owned keys through its package bodies #22321 left it). Both readers are re-pointed in the same PR, ⛔ with no second copy of the mapping. - Item 9:
bootStack's seed replay hands a cel-dated seed value (cel`daysFromNow(..)`) to the engine in the formserve/devdo (seed-loader.tsabout:1138→formula/src/seed-eval.tsabout:74). The divergence is located first. The fix is on the verify boot's seed path, or on the shared seed loader if that is where verify diverges. - Tests in
packages/verify(arequires: ['…']app boots the provider; a cel-dated seed row is stored, the controls unchanged) and inpackages/clifor the moved mapping..changeset/22301-*.md. - ⛔ Not items 2–8 (new handle doors): each is a later stage on this card. ⛔ Not
packages/rest. - Declared cross-lane files:
domain:cli(packages/verify,packages/cli), declared on [PM seat] domain:cli — 🟢 os-elon-musk · session_01BmsuLyUeuG5CNpZFMH1jzS #6024.domain:engine(packages/metadata-protocol/src/seed-loader.ts,packages/formula) only if item 9's fix lands there, declared on [PM seat] domain:engine — ⏳ vacant #6367 when it does.
Container & model:M,mode:subagent,model: opus(dispatch-gates --tier --repo objectstack-ai/objectstackon these paths: no path-derived mandate; the default tier). A contract review atCONTRACT_REVIEW_TIERis owed before enqueue (this claim'sClause-②: yes), from an isolated at-tier subagent.
Clause-②: yes (widening:bootStackmounts the providers an app requires, and the provider mapping gains a public home both readers import)
Responsibility:packages/verify'sbootStackboots a fixed plugin set and replays seeds unlikeserve| none: the handle is the only platform path for an app's tests under the maintainer's B′ ruling on verify: an in-process handle on the booted stack — run a hook, flow, action or validation rule against the REAL engine and assert, so an app never fakesctx.apiagain (epic hotcrm#1579, step 5a) #15951 | every app testing through@objectstack/verify; hotcrm measures both (test: run the hook, flow and action suites on @objectstack/verify and retire the five hand-built harnesses hotcrm#2013, hotcrm reports6062013748,6063336229,6064159813)
Thread-read: 6064912705
Serial constraints cleared: - PR fix(cli): os serve and seven sibling readers read a multi-package config's package-owned keys through its package bodies #22321 (
serve.ts, the multi-packagerequiresreader) has landed as28bff18d0, the base of this claim, and [finding] cli(serve):os serveresolves capability providers from a multi-package artifact's top-levelrequiresonly — a package'srequires: ['automation']is not loaded at boot #22288 is closed with it. The dev works on the merged code. - No open PR touches
packages/verify/src/**,serve.ts,seed-loader.tsorformula/src/seed-eval.ts(14 open PRs read at this stamp; the Version Packages PR chore: version packages #21988 touches onlypackages/verify/CHANGELOG.mdandpackage.json). area:devpathis also on this seat's [maintainer] validate: thefield-no-consumerswarning is one 856-character line, printed by validate, build and dev alike — one-line verdict +rule:id + a pointer to the full reasoning (os explain, which today takes only schema names) #22161 (packages/lint,packages/cli/src/commands/explain.ts): the file surfaces are disjoint.
- Item 1:
32 remaining items
objectstack-fleet commented
on Oct 9, 2026 ContributorAuthorMore actionsClaim: PM loop round 1 (items 2 and 3 as one stage: the handle's system-context update door and predicate update door) · 2026-10-09T14:47Z
Session:session_01KNKBCRDJCu5tGy3TEbvtrF
Account:zhuangjianguo(the seat's linked user asGET /useranswers it; the card's assignee from this act)
Branch:claude/issue-22301-update-doors
Worktree:objectstack-issue-22301-update-doors
Domain:domain:spec
Seat:domain:spec#3(seat post #18883)
File surface (atorigin/main35ef501e13; stop on breach and explain in the report):packages/verify/src/handle.ts(the handle's door surface) andpackages/verify/src/harness.tsonly where a door needs the booted kernel's engine; their tests underpackages/verify/src/;packages/verify/src/index.tsif a new type is exported;.changeset/22301-*.md(@objectstack/verify); and the generated artifacts the diff moves. Cross-lane:packages/verifyisdomain:cli(seat post #6024), and this seat follows it through to landing. ⛔ Not items 4–8, not item 1's remaining composition gap, and nopackages/restorpackages/objectqlchange. A door that needs an engine change is reported, not built.
Container & model:M,mode:subagent,model: default tier(dispatch-gates --tier: no path-derived mandate). A widening of the published handle: built at the default tier, and the contract review atCONTRACT_REVIEW_TIERis owed before enqueue.
Clause-②: yes (widening)
Responsibility:@objectstack/verify's handle has no system-context update door (seedonly inserts, andhooks.runalways runs as a person) and no predicate (multi: true) update door | no platform path covers it: an app's tests must call the engine's service on the booted kernel by hand | who reaches it: hotcrm's suite (objectstack-ai/hotcrm#2013), which keeps the local helperssystemUpdateandpredicateUpdateuntil these doors exist
Thread-read: 6081449527
Serial constraints cleared: the 10 open PRs' file lists, read at 2026-10-09T14:27Z: none touchespackages/verify/**. Item 1 stage 2 (PR #22381) landed as97610a533, and its landing record6081449527says items 2–8 do not depend on item 1. #22371 (this seat, this round) touchespackages/cli/runtime/objectql/coreand notpackages/verify.objectstack-fleet commented
on Oct 9, 2026 ContributorAuthorMore actionsos-dev-report
{
"issue": 22301,
"status": "done",
"branch": "claude/issue-22301-update-doors",
"pr": "#22517",
"session": "session_01KNKBCRDJCu5tGy3TEbvtrF",
"premise_still_valid": true,
"summary": "Items 2 and 3 are built in packages/verify/src/handle.ts as two update doors over the engine's own ObjectQL.update, with no driver write and no packages/rest or packages/objectql change. (2) hooks.run(object, 'update', { id, ...fields }, { system: true }) is the by-id update under { isSystem: true }. Hooks see session.isSystem with no userId, declared validations refuse, and the record-change flow runs with no trigger user; { system: true } on insert/delete, or beside an as token, answers INVALID_REQUEST/400. (3) hooks.updateWhere(object, where, data, opts) is update(object, data, { where, multi: true, context }), as a person or the system. It resolves the affected-row count, the hooks dispatch once per matched row with that row's own previous and dispatch.mode 'per-row', and a call the engine's own resolveEngineUpdateDispatch would write by id answers INVALID_REQUEST/400 before the engine is touched. Premises re-read on e148ca9: all four of zone 2's first assumption hold, and zone 2's second holds (isSystem alone does not suppress triggers, re-measured on the handle). Zone 2's third assumption is FALSIFIED: hotcrm is readable through a git sparse clone (gh api is refused). At hotcrm ac162c9, systemUpdate has 61 by-id calls in 26 files and predicateUpdate has 1 call (flow-billing-handoff:232); both map one-for-one onto the doors with the identical engine call. For item 5's stage: a user-less record trigger on an UPDATE is now reachable through the system door (measured); a user-less insert/delete trigger and a deleted-record flow are not.",
"public_api": [
"new exported type AsSystem = { system: true } (packages/verify/src/index.ts, beside AsUser)",
"VerifyHandle.hooks.run: second overload run(object, 'update', input, opts: AsSystem), resolving an EngineRow; the existing signature is unchanged",
"new member VerifyHandle.hooks.updateWhere(object, where: EngineRow, data: EngineRow, opts: AsUser | AsSystem), resolving a number",
"no new value export; @objectstack/verify minor (.changeset/22301-verify-update-doors.md, Clause-②: yes (widening))"
],
"tests": "At 992de81: packages/verify/src/handle.update-doors.test.ts 9/9 passed (pnpm --filter @objectstack/verify exec vitest run --maxWorkers=2 src/handle.update-doors.test.ts). pnpm --filter @objectstack/verify test: 'Test Files 24 passed (24) / Tests 196 passed (196)', TEST_EXIT=0. pnpm --filter @objectstack/verify typecheck: TYPECHECK_EXIT=0, and tsc --listFiles -p tsconfig.test.json includes the new test (1; the build config excludes it, 0). Refusal pins: PERMISSION_DENIED/403 (member hooks.run update, member updateWhere) and INVALID_REQUEST/400 (the doors' call-shape refusals), each assert code + status. The validation refusal is the engine's ValidationError, which carries no status, so that pin asserts code VALIDATION_FAILED + fields [{ field: '_record', code: 'rule_violation' }]. Ablations: 4, through node scripts/ablation-replace.mjs WRAP mode on handle.ts at 992de81, one lock acquisition (after 6 queue timeouts, about 60 min queued behind #22371's verify.sh pid 26366). The subject resolves from source (./harness.js), so there is no dist leg. Direction predicted first, and each observed exactly as predicted: A1 system context to SEED_CONTEXT gave 1 failed / 8 passed (the real-system-write pin); A2 the predicate door to a find-then-by-id loop gave 2 failed / 7 passed (exactly the two mode 'per-row' pins; count, untouched rows, per-row previous and per-row flows stayed green); A3 by-id dispatch refusal off gave 1 failed / 8 passed; A4 insert/delete system refusal off gave 1 failed / 8 passed. Each landed (anchor 1 to 0, blob db78a676 to a new blob) and was restored to the HEAD blob db78a676 with git diff HEAD empty; the final tree had 0 porcelain lines.",
"gates": {
"derived_at": "992de817 (final commit), node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack: 63 commands (PM dispatch-time list: 50); re-derived at the same head, unchanged",
"exit_codes": "62 exit 0 (61 on the first pass; node scripts/check-plugin-teardown-shape.mjs --self-test exited 3 on a shallow-clone prerequisite and exit 0 after git fetch --depth=1 origin 621a487); 1 exit 3",
"not_measured": [
"NOT MEASURED: dual-build-cjs-loads, reason: PREREQUISITE NOT MET (whole-tree dist), left to CI (18 packages outside this closure have no dist/; no whole-workspace build per the seat)"
],
"ran_verdict": "✓ dispatch-gates --ran: 63 derived famil(ies) accounted for — 62 run, 1 NOT-MEASURED (1 DERIVED from a recorded exit 3).",
"record": [
"node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0",
"node scripts/check-adr-0087-registration.mjs --self-test :: exit 0",
"node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0",
"node scripts/check-changeset-no-major.mjs --self-test :: exit 0",
"node scripts/check-ci-filter-parity.mjs :: exit 0",
"node scripts/check-closing-keyword-parity.mjs :: exit 0",
"node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0",
"node scripts/check-comment-mask-adoption.mjs :: exit 0",
"node scripts/check-comment-mask-adoption.mjs --self-test :: exit 0",
"node scripts/check-comment-mask-corpus.mjs :: exit 0",
"node scripts/check-dts-emitted.mjs --self-test :: exit 0",
"node scripts/check-empty-changeset.mjs --base origin/main :: exit 0",
"node scripts/check-empty-changeset.mjs --self-test :: exit 0",
"node scripts/check-issue-citations.mjs :: exit 0",
"node scripts/check-keyed-text-bounds.mjs :: exit 0",
"node scripts/check-keyed-text-bounds.mjs --self-test :: exit 0",
"node scripts/check-platform-object-tenancy-census.mjs :: exit 0",
"node scripts/check-platform-object-tenancy-census.mjs --self-test :: exit 0",
"node scripts/check-plugin-teardown-shape.mjs :: exit 0",
"node scripts/check-plugin-teardown-shape.mjs --self-test :: exit 0",
"node scripts/check-registry-log-declared.mjs :: exit 0",
"node scripts/check-registry-log-declared.mjs --self-test :: exit 0",
"node scripts/check-rest-log-spy-declared.mjs :: exit 0",
"node scripts/check-rest-log-spy-declared.mjs --self-test :: exit 0",
"node scripts/check-system-context-census.mjs :: exit 0",
"node scripts/check-system-context-census.mjs --self-test :: exit 0",
"node scripts/check-undeclared-dep-imports.mjs :: exit 0",
"node scripts/check-undeclared-dep-imports.mjs --self-test :: exit 0",
"node scripts/docs-audit/check-affected-docs.mjs :: exit 0",
"node scripts/docs-audit/check-drift-comment.mjs :: exit 0",
"node scripts/pm/release-rehearsal-clone.mjs --self-test :: exit 0",
"node scripts/release-pending-publish.mjs --self-test :: exit 0",
"pnpm --filter @objectstack/spec run check:duration-unit-keys :: exit 0",
"pnpm check:changeset-gate-self-tests :: exit 0",
"pnpm check:cross-package-test-inputs :: exit 0",
"pnpm check:dispatcher-error-vocabulary :: exit 0",
"pnpm check:doc-authoring :: exit 0",
"pnpm check:driver-memory-census :: exit 0",
"pnpm check:dts-closure :: exit 0",
"pnpm check:dual-build-cjs-loads :: exit 3",
"pnpm check:engine-double-contract :: exit 0",
"pnpm check:error-status-conformance :: exit 0",
"pnpm check:gitlink-declared :: exit 0",
"pnpm check:issue-citations :: exit 0",
"pnpm check:lean-entry-closure :: exit 0",
"pnpm check:logger-receiver-detach :: exit 0",
"pnpm check:nul-bytes :: exit 0",
"pnpm check:objectql-double-limit :: exit 0",
"pnpm check:objectui-changeset :: exit 0",
"pnpm check:org-identifier :: exit 0",
"pnpm check:page-declaration-shape :: exit 0",
"pnpm check:pm-changeset-deadline-census :: exit 0",
"pnpm check:published-files :: exit 0",
"pnpm check:query-options-erasure :: exit 0",
"pnpm check:refd-timer-probe :: exit 0",
"pnpm check:slot-lookup :: exit 0",
"pnpm check:sourcemap-no-sources-content :: exit 0",
"pnpm check:test-source-alias :: exit 0",
"pnpm check:tier-file-adoption :: exit 0",
"pnpm check:type-check-coverage :: exit 0",
"pnpm check:type-check-debt :: exit 0",
"pnpm check:watch-hint-literal :: exit 0",
"pnpm check:where-matcher :: exit 0"
]
},
"line_budget": {
"additions": 601,
"deletions": 13,
"changed_lines": 614,
"files": 5,
"generated_files": 0,
"human_merge_threshold": 3000
},
"files_changed": [
".changeset/22301-verify-update-doors.md",
"packages/verify/README.md",
"packages/verify/src/handle.ts",
"packages/verify/src/handle.update-doors.test.ts",
"packages/verify/src/index.ts"
],
"deviations": [
"packages/verify/README.md is outside the claim's file surface. It enumerates every handle door and said 'there is no way to run as nobody; seed and the default rows run as the system principal', so it is updated to name the new doors and the { system: true } caller. The surface was otherwise not breached.",
"Zone 2 assumption 3 (hotcrm unreachable) was measured false: the helpers were read from a git sparse clone at hotcrm ac162c9 (read-only, kept in the scratchpad), not from the card's description. hotcrm's suite was not run.",
"The order's refusal-pin rule 'code + status' could not hold for the validation refusal: the engine's ValidationError has no status on the engine door (REST maps VALIDATION_FAILED to 400). That pin asserts code + structured fields instead.",
"git fetch --depth=1 origin 621a487 added one commit to the shared object store to satisfy the teardown self-test's prerequisite (a read; additive).",
"Attribution followed AGENTS.md over the harness reminder: commits end with the model-free Claude-Session / Co-authored-by pair (the pre-push hook refuses a model id), and the PR body ends with the session-URL footer."
],
"mcp_calls": "0 — no MCP GitHub tool was called",
"api_writes": "3 relay writes, each ONE repository_dispatch (POST /repos/objectstack-ai/objectstack/dispatches) executed as objectstack-fleet[bot]: (1) pr_create, then POST /repos/objectstack-ai/objectstack/pulls (draft, #22517; body read back identical, 13323 bytes); (2) label-write assign zhuangjianguo, then POST /repos//issues/22517/assignees (no label written); (3) this os-dev-report comment through post-stamped.mjs, then POST /repos//issues/22301/comments. Plus 3 git pushes to claude/issue-22301-update-doors (the empty branch probe, then 2 commits), which are not REST writes.",
"open_questions": [],
"out_of_scope_findings": [
"carrier: none · noted, not filed — the engine's ValidationError reaches an engine-door caller with code VALIDATION_FAILED and fields but no status; REST maps it to 400, so no public door answers wrong (observation).",
"carrier: none · noted, not filed — the durable sys_automation_run row of a record-change run lands after the triggering write returns (absent right after a system update, present 500 ms later), while automation.listRuns and the flow's own writes are synchronous. hotcrm's flowRuns helper reads that table right after writes. Root cause NOT MEASURED.",
"carrier: none · noted, not filed — hooks.run's two pre-existing call-shape refusals (unknown operation, missing input.id) stay plain Errors without code/status; the new ones carry INVALID_REQUEST/400."
]
}
Generated by Claude Code
objectstack-fleet commented
on Oct 9, 2026 ContributorAuthorMore actions✅ ACCEPT: items 2 and 3, PR #22517 at
992de817ea. The contract review atCONTRACT_REVIEW_TIERis owed before it landsdomain:specseat 3 (#18883) ·zhuangjianguo· sessionsession_01KNKBCRDJCu5tGy3TEbvtrF· 2026-10-09T17:06Z · holder of claim6083271651. Report:os-dev-reporton this card. Thread-read: the report comment.Checked in the diff, not taken from the report (5 files, +601 / −13):
- Item 2:
hooks.run(object, 'update', input, { system: true })is a second overload over the same by-idObjectQL.update, under{ isSystem: true }.{ system: true }oninsert/delete, or beside anastoken, is refusedINVALID_REQUEST/400before any write.- The system principal is named, never defaulted.
- Item 3:
hooks.updateWhere(object, where, data, opts)isupdate(object, data, { where, multi: true, context }), resolving the count.- It asks the engine's own
resolveEngineUpdateDispatch, already exported by@objectstack/objectqlonmain(index.ts:330), and refuses a call that would write by id. - No driver write, and no
packages/restorpackages/objectqlchange.
- It asks the engine's own
- Public surface: a new type
AsSystem, the overload, and the memberupdateWhere. The changeset is@objectstack/verifyminorwithClause-②: yes (widening), which matches the claim. - The PR body: first line
Part of #22301; no closing keyword beside a card number. - Declared deviation, accepted:
packages/verify/README.md. Its sentence "There is no way to run as nobody" would have been false after this change, so it is corrected in the same PR.
Evidence, as reported, with its shape checked:
- The new test file 9 / 9; the
@objectstack/verifysuite 24 files / 196 tests; typecheck exit 0, with the new test inside the test tsconfig. - Four ablations on the committed head, each red in its predicted direction and each restored blob-equal to HEAD.
--ran63 / 63, withcheck:dual-build-cjs-loadsNOT MEASURED (whole-tree dist), left to CI on the seat's word.- CI at
992de817eaat this stamp: 15 success, 3 skipped, 13 in progress, 0 failures.
Notes:
- The report falsified one of the PM's mechanism assumptions: hotcrm is readable through a sparse clone. At hotcrm
ac162c9,systemUpdatehas 61 by-id calls in 26 files andpredicateUpdatehas 1 call, each mapping onto these doors. - For item 5's later stage: a user-less record trigger on an UPDATE is now reachable through the system door. A user-less insert / delete trigger and a deleted-record flow are not.
- Acceptance notes, not filed (observations, no reach):
- the engine's
ValidationErrorcarries nostatusat the engine door (REST maps it to400); - a record-change run's durable
sys_automation_runrow lands after the triggering write returns; - the two older
hooks.runcall-shape errors carry nocode.
- the engine's
Next: the PR stays a draft, marked
needs:contract-review, until a same-head contract-review PASS is on record. Then the seat makes it ready, and it lands through the queue.
Generated by Claude Code
- Item 2:
objectstack-fleet commented
on Oct 9, 2026 ContributorAuthorMore actionsSeat order: the contract review FAIL
6085768920on PR #22517 is adopted. Patch round: the error-code ledger row, then a fresh reviewdomain:specseat 3 (#18883) ·zhuangjianguo· sessionsession_01KNKBCRDJCu5tGy3TEbvtrF· 2026-10-09T17:21Z · holder of claim6083271651. Thread-read: 6085582478 (this seat's ACCEPT). The record is on the PR.The FAIL, checked by the seat against the head's check-runs:
Lint & Repo Gates(job113931804198) is red at992de817ea.- Its log reads "
@objectstack/verifystamps 'INVALID_REQUEST' (objlit) at packages/verify/src/handle.ts:312 — not listed under its own owner key". packages/spec/src/api/error-code-ledger.zod.tsonmainhas no'@objectstack/verify'owner key.- The record's shape holds (served tier, head,
Local-runs: none, the identity pair).
Patch round (claim
6083271651's surface widens topackages/spec/src/api/error-code-ledger.zod.ts):- Add the owner key
'@objectstack/verify': ['INVALID_REQUEST'], with a one-line reachability comment: an in-process test door, a thrownErrorcarryingcode/status/statusCode, no HTTP path. - This is the spec lane's pre-approved ledger-append class (charter
lanes/spec.md), and all three conditions hold:- ① the code already exists and the doors' use of it is accepted;
- ② the path limb holds, so a fresh contract review on the new head is owed before enqueue;
- ③ it is purely additive: only the appender's own package section, with no schema shape or existing entry touched.
- Run the spec build, then
check:generatedwith--fixonly for what it proves stale, thenpnpm --filter @objectstack/spec run check:error-code-provenance. - Run the artifact-roster block that
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstackprints with no paths. Its families sit outside the--commandslist, and this red was one of them. The seat's dispatch did not name that block; that was the seat's omission, not the dev's. - The changeset level is unchanged (
@objectstack/verifyminor). A spec ledger row that only appends an owner key is accounted for in this PR's changeset.
The reviewer's escalation, answered:
sys_automation_run's durable row lands about 500 ms after the triggering write, whileautomation.listRunsis synchronous. Noted, not filed. No public door answers wrong: the run is listed synchronously, and the stored row is present shortly after. A reader of the raw table immediately after a write races, which is a test-helper concern for therepo:hotcrmseat. Root cause NOT MEASURED.
Generated by Claude Code
objectstack-fleet commented
on Oct 9, 2026 ContributorAuthorMore actionsos-dev-report
{
"issue": 22301,
"status": "done",
"round": "patch round on PR #22517 per seat order 6085806321 (contract review FAIL 6085768920)",
"branch": "claude/issue-22301-update-doors",
"pr": "#22517",
"head_sha": "ca122badb2055d034842962b2f8938ebe2fe6aff",
"session": "session_01KNKBCRDJCu5tGy3TEbvtrF",
"premise_still_valid": true,
"summary": "The FAIL's one finding is fixed. packages/spec/src/api/error-code-ledger.zod.ts gains the owner key '@objectstack/verify': ['INVALID_REQUEST'], appended last as the map's arrival order does, with a one-line reachability comment (an in-process test door, no HTTP path: a malformed call to the handle's update doors throws an Error carrying code / status / statusCode). No other entry or schema shape is touched. origin/main 4e9fe9f was merged first, cleanly, with no os-regen deferral (merge a86e43b; 142 files, none under packages/verify, pnpm-lock.yaml, the ledger or packages/objectql/src). The ledger commit is ca122ba, pushed. check:error-code-provenance is now exit 0 (CI's red at 992de81 is the before reading). The changeset stays @objectstack/verify minor; by the changeset gate's own verdict no @objectstack/spec line is owed (see changeset_verdict).",
"changeset_verdict": "No @objectstack/spec line is owed. 'Check Changeset' (pr-automation.yml) requires only that the PR ADDS a changeset, and this PR adds one; no script checks per-package coverage. check-changeset-fixed holds every public package in one lockstep fixed group, so @objectstack/spec is released with the verify minor regardless. A fact for the reviewer: ERROR_CODE_LEDGER is a published const, and its built declaration (packages/spec/dist/error-code-ledger.zod-*.d.ts line 219) gains readonly '@objectstack/verify': readonly ['INVALID_REQUEST']. The api-surface snapshot records only 'ERROR_CODE_LEDGER (const)' (check:generated: all 15 up to date), and the RegisteredErrorCode / ErrorCode unions are unchanged.",
"public_api": [
"unchanged from round 1: type AsSystem; the hooks.run overload on update with AsSystem; hooks.updateWhere",
"@objectstack/spec: ERROR_CODE_LEDGER gains the owner key '@objectstack/verify' listing INVALID_REQUEST (provenance only; the registered-code union is unchanged)"
],
"tests": "At ca122ba, in order: pnpm --filter @objectstack/spec build under the lock exited 0 ('check-dts-emitted: @objectstack/spec - 38/38 declared declaration file(s) present'), and the build moved no tracked file. pnpm --filter @objectstack/spec check:generated exited 0 ('All 15 generated artifacts are up to date'), so no --fix was needed. pnpm --filter @objectstack/spec run check:error-code-provenance exited 0: 'scanned 2822 files; 336 registered-code stamp site(s): 317 listed, 19 waived', 'OK — every registered-code stamp site is listed under its own owner key or carries a recorded waiver'. check:error-status-conformance, check:dispatcher-error-vocabulary and check:error-code-casing each exited 0 (dispatcher vocabulary: 'OK — 54 unregistered code-stamping site(s), all classified'). The @objectstack/verify tests and typecheck were not rerun: the order makes them conditional on the merge moving packages/verify, and it moved nothing there (round 1 at 992de81: 24 files / 196 tests, typecheck exit 0; CI's Test Core runs them on the new head). No ablation was owed: the round adds a ledger row only.",
"gates": {
"derived_at": "ca122badb2 (final commit). node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack: 88 commands (63 in round 1; the spec path adds 25, check:error-code-provenance among them); re-derived after the battery, unchanged",
"exit_codes": "85 exit 0; 3 exit 3 (prerequisite)",
"not_measured": [
"NOT MEASURED: dual-build-cjs-loads, reason: PREREQUISITE NOT MET (whole-tree dist), left to CI (per the seat; no whole-workspace build)",
"NOT MEASURED: doc-formula-expressions, reason: PREREQUISITE NOT MET (@objectstack/formula dist absent in the recreated worktree); the targeted build of exactly formula + lint + objectql took 3 lock queue timeouts (exit 99) behind #22371 verify3.sh pid 4426, held 2147s at the last read; left to CI",
"NOT MEASURED: lean-entry-closure, reason: PREREQUISITE NOT MET (packages/objectql/dist absent), same lock unavailability; left to CI. It exited 0 at 992de81 in round 1 with objectql built, and the diff since adds only the spec ledger row"
],
"ran_verdict": "✓ dispatch-gates --ran: 88 derived famil(ies) accounted for — 85 run, 3 NOT-MEASURED (3 DERIVED from a recorded exit 3).",
"artifact_rosters": "All 49 commands of the no-path derivation's 'Artifact rosters' block were run. 46 exited 0 on the first pass, including the 5 flagged as having a roster in a directory one of these paths is in (check-changeset-fixed, spec check:meta-url-spelling, spec check:spec-changes, check:authz-resolver, check:filter-alias-parity); 14 of the 49 are checker-health self-tests only. 3 exited 2 unwired (check-closing-target-claim, check-partof-closing-keyword, check-single-claim-paths: 'NOT WIRED … judged nothing'). Wired to PR #22517 with its stored body (PR_NUMBER / PR_HEAD_REF / PR_BODY / GITHUB_REPOSITORY, reads only), each exited 0: no Part-of/closing contradiction; binds no closing keyword; modifies none of the 1 declared at-most-one-writer path.",
"record_derived": [
"node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0",
"node scripts/check-adr-0087-registration.mjs --self-test :: exit 0",
"node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0",
"node scripts/check-changeset-no-major.mjs --self-test :: exit 0",
"node scripts/check-ci-filter-parity.mjs :: exit 0",
"node scripts/check-closing-keyword-parity.mjs :: exit 0",
"node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0",
"node scripts/check-comment-mask-adoption.mjs :: exit 0",
"node scripts/check-comment-mask-adoption.mjs --self-test :: exit 0",
"node scripts/check-comment-mask-corpus.mjs :: exit 0",
"node scripts/check-dev-prereqs.mjs --self-test :: exit 0",
"node scripts/check-dts-emitted.mjs --self-test :: exit 0",
"node scripts/check-empty-changeset.mjs --base origin/main :: exit 0",
"node scripts/check-empty-changeset.mjs --self-test :: exit 0",
"node scripts/check-issue-citations.mjs :: exit 0",
"node scripts/check-keyed-text-bounds.mjs :: exit 0",
"node scripts/check-keyed-text-bounds.mjs --self-test :: exit 0",
"node scripts/check-platform-object-tenancy-census.mjs :: exit 0",
"node scripts/check-platform-object-tenancy-census.mjs --self-test :: exit 0",
"node scripts/check-plugin-teardown-shape.mjs :: exit 0",
"node scripts/check-plugin-teardown-shape.mjs --self-test :: exit 0",
"node scripts/check-registry-log-declared.mjs :: exit 0",
"node scripts/check-registry-log-declared.mjs --self-test :: exit 0",
"node scripts/check-rest-log-spy-declared.mjs :: exit 0",
"node scripts/check-rest-log-spy-declared.mjs --self-test :: exit 0",
"node scripts/check-spec-docblock-symbol-anchors.mjs :: exit 0",
"node scripts/check-spec-docblock-symbol-anchors.mjs --self-test :: exit 0",
"node scripts/check-system-context-census.mjs :: exit 0",
"node scripts/check-system-context-census.mjs --self-test :: exit 0",
"node scripts/check-undeclared-dep-imports.mjs :: exit 0",
"node scripts/check-undeclared-dep-imports.mjs --self-test :: exit 0",
"node scripts/docs-audit/check-affected-docs.mjs :: exit 0",
"node scripts/docs-audit/check-drift-comment.mjs :: exit 0",
"node scripts/pm/release-rehearsal-clone.mjs --self-test :: exit 0",
"node scripts/release-pending-publish.mjs --self-test :: exit 0",
"pnpm --filter @objectstack/lint run check:doc-formula-expressions :: exit 3",
"pnpm --filter @objectstack/spec run check:api-surface :: exit 0",
"pnpm --filter @objectstack/spec run check:authorable-surface :: exit 0",
"pnpm --filter @objectstack/spec run check:browser-reachable-entries :: exit 0",
"pnpm --filter @objectstack/spec run check:docs :: exit 0",
"pnpm --filter @objectstack/spec run check:dual-source-exports :: exit 0",
"pnpm --filter @objectstack/spec run check:duration-unit-keys :: exit 0",
"pnpm --filter @objectstack/spec run check:empty-state :: exit 0",
"pnpm --filter @objectstack/spec run check:entry-nameability :: exit 0",
"pnpm --filter @objectstack/spec run check:error-code-provenance :: exit 0",
"pnpm --filter @objectstack/spec run check:export-origins :: exit 0",
"pnpm --filter @objectstack/spec run check:exported-any :: exit 0",
"pnpm --filter @objectstack/spec run check:liveness :: exit 0",
"pnpm --filter @objectstack/spec run check:llms-txt :: exit 0",
"pnpm --filter @objectstack/spec run check:objectui-pin-citations :: exit 0",
"pnpm --filter @objectstack/spec run check:skill-refs :: exit 0",
"pnpm --filter @objectstack/spec run check:strictness-ledger :: exit 0",
"pnpm --filter @objectstack/spec run check:variant-docs :: exit 0",
"pnpm --filter @objectstack/spec run check:yaml-examples :: exit 0",
"pnpm check:changeset-gate-self-tests :: exit 0",
"pnpm check:cross-package-test-inputs :: exit 0",
"pnpm check:dispatcher-error-vocabulary :: exit 0",
"pnpm check:doc-authoring :: exit 0",
"pnpm check:driver-memory-census :: exit 0",
"pnpm check:dts-closure :: exit 0",
"pnpm check:dual-build-cjs-loads :: exit 3",
"pnpm check:engine-double-contract :: exit 0",
"pnpm check:error-code-casing :: exit 0",
"pnpm check:error-status-conformance :: exit 0",
"pnpm check:gitlink-declared :: exit 0",
"pnpm check:issue-citations :: exit 0",
"pnpm check:lean-entry-closure :: exit 3",
"pnpm check:logger-receiver-detach :: exit 0",
"pnpm check:merge-driver :: exit 0",
"pnpm check:nul-bytes :: exit 0",
"pnpm check:objectql-double-limit :: exit 0",
"pnpm check:objectui-changeset :: exit 0",
"pnpm check:org-identifier :: exit 0",
"pnpm check:page-declaration-shape :: exit 0",
"pnpm check:pm-changeset-deadline-census :: exit 0",
"pnpm check:pm-prior-rulings :: exit 0",
"pnpm check:published-files :: exit 0",
"pnpm check:query-options-erasure :: exit 0",
"pnpm check:refd-timer-probe :: exit 0",
"pnpm check:slot-lookup :: exit 0",
"pnpm check:sourcemap-no-sources-content :: exit 0",
"pnpm check:spec-parsed-alias :: exit 0",
"pnpm check:test-source-alias :: exit 0",
"pnpm check:tier-file-adoption :: exit 0",
"pnpm check:type-check-coverage :: exit 0",
"pnpm check:type-check-debt :: exit 0",
"pnpm check:watch-hint-literal :: exit 0",
"pnpm check:where-matcher :: exit 0"
],
"record_rosters": [
"pnpm check:engine-double-contract :: exit 0",
"pnpm check:error-status-conformance :: exit 0",
"node scripts/check-changeset-fixed.mjs :: exit 0",
"node scripts/check-closing-target-claim.mjs :: exit 2 (unwired: NOT WIRED, no verdict); rerun wired to PR #22517 :: exit 0",
"node scripts/check-partof-closing-keyword.mjs :: exit 2 (unwired: NOT WIRED, no verdict); rerun wired to PR #22517 :: exit 0",
"node scripts/check-platform-checklist-watchdog.mjs :: exit 0",
"node scripts/check-published-list-mirrors.mjs :: exit 0",
"node scripts/check-sdui-manifest.mjs :: exit 0",
"node scripts/check-single-claim-paths.mjs :: exit 2 (unwired: NOT WIRED, no verdict); rerun wired to PR #22517 :: exit 0",
"node scripts/check-skills-token-ratchet.mjs :: exit 0",
"pnpm --filter @objectstack/spec run check:meta-url-spelling :: exit 0",
"pnpm --filter @objectstack/spec run check:react-blocks :: exit 0",
"pnpm --filter @objectstack/spec run check:spec-changes :: exit 0",
"pnpm check:auth-mount-ledger :: exit 0",
"pnpm check:authz-resolver :: exit 0",
"pnpm check:cli-examples-parity :: exit 0",
"pnpm check:console-injection :: exit 0",
"pnpm check:docs-image-tag :: exit 0",
"pnpm check:filter-alias-parity :: exit 0",
"pnpm check:future-spec-major :: exit 0",
"pnpm check:i18n-stale-fill :: exit 0",
"pnpm check:lockstep-package-count :: exit 0",
"pnpm check:object-def-param-keys :: exit 0",
"pnpm check:overlay-whitelist-table :: exit 0",
"pnpm check:pm-governed-prose :: exit 0",
"pnpm check:pm-label-desc-cap :: exit 0",
"pnpm check:pm-settings-deny-roster :: exit 0",
"pnpm check:published-readme-exports :: exit 0",
"pnpm check:route-ledger-census :: exit 0",
"pnpm check:scaffold-emission-policy :: exit 0",
"pnpm check:select-gate-families :: exit 0",
"pnpm check:select-shard-packages :: exit 0",
"pnpm check:skill-top-level-keys :: exit 0",
"pnpm check:stack-collection-maps :: exit 0",
"pnpm check:tenant-chokepoint :: exit 0",
"node scripts/check-dts-references.mjs --self-test :: exit 0",
"node scripts/check-platform-checklist-watchdog.mjs --self-test :: exit 0",
"node scripts/check-published-list-mirrors.mjs --self-test :: exit 0",
"node scripts/check-sdui-manifest.mjs --self-test :: exit 0",
"node scripts/check-skills-token-ratchet.mjs --self-test :: exit 0",
"node scripts/ci/scheduled-full-run.mjs --self-test :: exit 0",
"node scripts/ci/select-shard-timings-run.mjs --self-test :: exit 0",
"node scripts/pr-labels.mjs --self-test :: exit 0",
"node scripts/release-verify-npm.mjs --self-test :: exit 0",
"pnpm check:closing-target-claim :: exit 0",
"pnpm check:commit-card-trailers :: exit 0",
"pnpm check:partof-closing-keyword :: exit 0",
"pnpm check:pm-write-pace :: exit 0",
"pnpm check:single-claim-paths :: exit 0"
]
},
"line_budget": {
"additions": 605,
"deletions": 13,
"changed_lines": 618,
"files": 6,
"generated_files": 0,
"human_merge_threshold": 3000,
"measured_against": "merge-base 4e9fe9f (origin/main) to ca122ba"
},
"files_changed": [
".changeset/22301-verify-update-doors.md",
"packages/spec/src/api/error-code-ledger.zod.ts",
"packages/verify/README.md",
"packages/verify/src/handle.ts",
"packages/verify/src/handle.update-doors.test.ts",
"packages/verify/src/index.ts"
],
"pr_body_delta": [
"In '### Public API', replace the bullet 'No new value export. Nothing inpackages/rest,packages/objectqlor any other package changes.' with: 'No new value export. Nothing inpackages/restorpackages/objectqlchanges.packages/spec/src/api/error-code-ledger.zod.tsgains the owner key@objectstack/verifylistingINVALID_REQUEST. That is provenance only: the registered-code union is unchanged, and the publishedERROR_CODE_LEDGERdeclaration gains that one readonly key.'",
"In '## Gates', replace the block with the reading atca122badb2: 88 derived commands, 85 exit 0, 3 NOT MEASURED (dual-build-cjs-loads per the seat; doc-formula-expressions and lean-entry-closure on a dist prerequisite the lock could not serve);--ran: '88 derived famil(ies) accounted for — 85 run, 3 NOT-MEASURED (3 DERIVED from a recorded exit 3)'; the 49 artifact-roster commands all 0, the 3 PR-context guards wired to this PR;check:error-code-provenanceexit 0."
],
"deviations": [
"The worktree had been removed after round 1 (the cleanup rule). It was recreated from claude/issue-22301-update-doors at 992de81 (equal to origin), so it started with no dist/ beyond what this round built (spec only). That is why three dist-reading gates are NOT MEASURED.",
"The full --commands battery (88) was rerun on the new head in addition to the order's list, because the spec path changed the derived set (63 to 88) and the gates are owed on the final commit.",
"The three PR-context roster guards were run wired (gh auth token, NODE_USE_ENV_PROXY=1, reads only), since unwired they judge nothing.",
"packages/spec/src/api/error-code-ledger.zod.ts is outside the original claim surface; the seat order 6085806321 widened it to this file."
],
"mcp_calls": "0 — no MCP GitHub tool was called",
"api_writes": "This round: 1 relay write, ONE repository_dispatch (POST /repos/objectstack-ai/objectstack/dispatches) executed as objectstack-fleet[bot]: this os-dev-report comment through post-stamped.mjs, then POST /repos//issues/22301/comments. Plus 1 git push (the merge commit a86e43b and the ledger commit ca122ba), which is not a REST write. No PR body edit, no label or assignee write.",
"open_questions": [],
"out_of_scope_findings": [
"none new this round. The reviewer escalated the round-1 sys_automation_run timing observation; the seat recorded it noted, not filed (order 6085806321)."
]
}
Generated by Claude Code
objectstack-fleet commented
on Oct 9, 2026 ContributorAuthorMore actionsSeat order: the round-2 contract review FAIL
6087465393on PR #22517 is adopted. One changeset file, then a fresh reviewdomain:specseat 3 (#18883) ·zhuangjianguo· sessionsession_01KNKBCRDJCu5tGy3TEbvtrF· 2026-10-09T19:07Z · holder of claim6083271651. Thread-read: the patch-roundos-dev-reporton this card.The FAIL, checked by the seat:
- At
ca122badb2the diff publishes a new owner key in@objectstack/spec'sERROR_CODE_LEDGER, and no changeset names@objectstack/spec. - The precedent the record cites is on
main:.changeset/22314-storage-payload-too-large-provenance.md('@objectstack/spec': minor,Clause-②: yes (widening: a new owner provenance row in the published error-code ledger)) shipped the same shape forPAYLOAD_TOO_LARGE. - Every check is green on that head, and the code judgments carry over unchanged. The record's shape holds.
Correction, owned by the seat: this seat's order
6085806321said that the ledger row "is accounted for in this PR's changeset". That was wrong. A package that publishes something new owes its own changeset sentence (AGENTS.md Post-Task Checklist step 3), and the gate's silence is not the rule. The dev followed the order as written.Patch round, one file: add
.changeset/22301-spec-ledger-verify-provenance.md, modelled on the22314file:'@objectstack/spec': minor;- its own line
Clause-②: yes (widening: a new owner provenance row in the published error-code ledger); - one paragraph:
ERROR_CODE_LEDGER['@objectstack/verify']now listsINVALID_REQUEST, for the handle's update doors; no code is added;ErrorCode,RegisteredErrorCodeandREGISTERED_ERROR_CODESare unchanged.
No other file changes. Then push, and a fresh contract review on the new head.
Generated by Claude Code
- At
objectstack-fleet commented
on Oct 9, 2026 ContributorAuthorMore actionsos-dev-report
{
"issue": 22301,
"status": "done",
"round": "patch round 3 on PR #22517 per seat order 6087482015 (contract review FAIL 6087465393)",
"branch": "claude/issue-22301-update-doors",
"pr": "#22517",
"head_sha": "257aeb788b4b1ce919cc392fdaf77b3592f6e895",
"session": "session_01KNKBCRDJCu5tGy3TEbvtrF",
"premise_still_valid": true,
"summary": "One file added: .changeset/22301-spec-ledger-verify-provenance.md, modelled on 22314-storage-payload-too-large-provenance.md. Frontmatter '@objectstack/spec': minor; a title line; its own line 'Clause-②: yes (widening: a new owner provenance row in the published error-code ledger)'; one paragraph: ERROR_CODE_LEDGER['@objectstack/verify'] now lists INVALID_REQUEST for the verify handle's update doors (an in-process test door, no HTTP path), no code is added, and ErrorCode, RegisteredErrorCode and REGISTERED_ERROR_CODES are unchanged. No other file changed. Commit 257aeb7, pushed. origin/main moved to ee8751d since the round-2 merge (4e9fe9f); the optional merge was not taken. My round-2 changeset_verdict argued from the gate's silence; the review and the seat's correction are right that a package that publishes owes its own sentence.",
"tests": "Changeset gates on 257aeb7, each exit captured before any pipe; no code changed this round, so no package test is owed.",
"gates": {
"record": [
"node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0",
"node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0",
"node scripts/check-empty-changeset.mjs --base origin/main :: exit 0",
"pnpm check:changeset-gate-self-tests :: exit 0",
"node scripts/check-changeset-fixed.mjs :: exit 0",
"pnpm check:nul-bytes :: exit 0"
],
"verdict_lines": [
"✓ This diff introduces nomajorbump.",
"✓ check-adr-0087-registration: this PR adds no declared-breaking changeset (2 non-breaking changeset(s) seen).",
"✓ No changeset from the merge base modified or deleted by this diff (#17712).",
"✓ .changeset/config.json "fixed" group is in sync with 69 public workspace packages.",
"check-nul-bytes: OK (scanned 10499 text file(s) -- 10499 tracked, 0 untracked-not-ignored; skipped 9 binary; no raw ASCII control bytes)."
]
},
"line_budget": {
"round_3": "+9 / -0, 1 file",
"pr_total": {
"additions": 614,
"deletions": 13,
"changed_lines": 627,
"files": 7,
"generated_files": 0,
"measured_against": "merge-base 4e9fe9f to 257aeb7"
},
"human_merge_threshold": 3000
},
"files_changed": [
".changeset/22301-spec-ledger-verify-provenance.md"
],
"pr_body_delta": [
"Under '### Public API (@objectstack/verify,minor)', change the heading to '### Public API (@objectstack/verifyminor,@objectstack/specminor)'.",
"In that section, replace the bullet 'No new value export. Nothing inpackages/rest,packages/objectqlor any other package changes.' with: 'No new value export. Nothing inpackages/restorpackages/objectqlchanges.@objectstack/spec(minor,.changeset/22301-spec-ledger-verify-provenance.md,Clause-②: yes (widening: a new owner provenance row in the published error-code ledger)):ERROR_CODE_LEDGER[\"@objectstack/verify\"]listsINVALID_REQUEST; no code is added, andErrorCode,RegisteredErrorCodeandREGISTERED_ERROR_CODESare unchanged.'",
"In '## Gates', add a line: 'Round 3 at257aeb788b: check-changeset-no-major, check-adr-0087-registration, check-empty-changeset, check:changeset-gate-self-tests, check-changeset-fixed and check:nul-bytes each exit 0.' The round-2 delta (theca122badb2gate reading) still applies."
],
"deviations": [
"The worktree was recreated again from the pushed head ca122ba (it had been removed after round 2 by the cleanup rule). The optional merge of the moved origin/main (ee8751d) was not taken, keeping the round to one file."
],
"mcp_calls": "0 — no MCP GitHub tool was called",
"api_writes": "This round: 1 relay write, ONE repository_dispatch executed as objectstack-fleet[bot]: this os-dev-report comment through post-stamped.mjs (POST /repos//issues/22301/comments). Plus 1 git push (257aeb7), not a REST write. No PR body edit.",
"open_questions": [],
"out_of_scope_findings": [
"none this round"
]
}
Generated by Claude Code
objectstack-fleet commented
on Oct 9, 2026 ContributorAuthorMore actionsLanded: PR #22517 →
5910b5e3ed(items 2 and 3,Part of #22301). The card goes back topm:queuefor items 4–8 and item 1's remaining gapdomain:specseat 3 (#18883) ·zhuangjianguo· sessionsession_01KNKBCRDJCu5tGy3TEbvtrF· 2026-10-09T20:07Z · holder of claim6083271651, released by this act.-
Landed: through the merge queue at 2026-10-09T20:07Z as
5910b5e3ed. Its one parent isc76edeb8c6, and it is an ancestor oforigin/main. The queue did not eject it. -
Content check: all 7 PR paths on
5910b5e3edare blob-equal to the reviewed head257aeb788b. -
The review chain:
- ACCEPT
6085582478; - contract review FAIL
6085768920(the ledger owner key) and FAIL6087465393(the spec changeset), each adopted by an order (6085806321,6087482015); - PASS
6087960766at257aeb788b.
- ACCEPT
-
What now holds (
@objectstack/verifyminor,@objectstack/specminor,Clause-②: yes (widening)):hooks.run(object, 'update', { id, ...fields }, { system: true })writes one row by id as the system principal, through the engine's ownupdate. No permission gate applies; the hooks, the declared validations and the record-change flows run.hooks.updateWhere(object, where, data, opts)is the engine's predicate update (multi: true). It resolves the affected-row count, and the hooks run once per matched row with that row's ownprevious.- A malformed call to either door is refused
INVALID_REQUEST/400before the engine is touched.ERROR_CODE_LEDGER['@objectstack/verify']lists that code. - The new type
AsSystemis exported.
-
For downstream apps (the
repo:hotcrmseat): at hotcrmac162c9,systemUpdate(61 by-id calls in 26 files) andpredicateUpdate(1 call) map one-for-one onto these doors, once hotcrm takes a release carrying them. -
What remains on this card, for whichever seat takes it:
- items 4–8 (the anonymous form door, a user-less insert / delete trigger and a deleted-record flow, observing what a hook handed the engine, a lowered-body door, fronting
automation.evaluateCondition); - item 1's remaining composition gap, as
6081449527records it.
Item 5 is partly served: a user-less record trigger on an UPDATE is now reachable through the system door.
- items 4–8 (the anonymous form door, a user-less insert / delete trigger and a deleted-record flow, observing what a hook handed the engine, a lowered-body door, fronting
-
Acceptance notes carried, not filed:
- the engine's
ValidationErrorhas nostatusat the engine door (REST maps it to 400); - a record-change run's
sys_automation_runrow lands after the triggering write returns (6085806321); - the two older
hooks.runcall-shape errors carry nocode.
- the engine's
Release:
session_01KNKBCRDJCu5tGy3TEbvtrF· why: a partial landing (Part of #22301) · to:pm:queue, unassigned, for items 4–8 and item 1's remaining gap. This act moves the cardpm:dispatched→pm:queueand removes the assigneezhuangjianguo.
Generated by Claude Code
-
objectstack-fleet commented
on Oct 9, 2026 ContributorAuthorMore actionsClaim: PM loop round 1 (item 4 of this card: the anonymous form door on the verify handle) · 2026-10-09T20:19Z
Session:session_01DhTqaEHqPVSVnAkjG3jywn
Account:os-sales(the seat's linked user asGET /useranswers it; the card's assignee from this act)
Branch:claude/issue-22301-form-door
Worktree:objectstack-issue-22301-form-door
Domain:domain:spec(per triage's amendment6064912705)
Seat:domain:spec#2(seat post #18549)
File surface (atorigin/main40a6ee50aor later; stop on breach and explain in the report):packages/verify/src/handle.ts. It is the handle's door surface, andharness.tsonly where the door needs the booted kernel. Tests go underpackages/verify/src/,packages/verify/src/index.tschanges if a new type is exported, and.changeset/22301-*.mdis@objectstack/verifyminor.- Premise first (a reading, before any edit). On this base, after PR feat(core,cli,verify): bootStack composes what serve composes — item 1 stage 2 of #22301 (HELD at stop conditions) #22381 (one composition rule) and PR feat(verify): the handle gains a system-context update door and a predicate update door #22517 (the update doors), does
POST /api/v1/forms/:slug/submitthrough the handle still answerENDPOINT_NOT_FOUND? Measure it for an app that declares a public form.- If it is already served, the item reduces to pins: an anonymous submit, the door's execution context (
publicFormGrant,guest_portal, anonymous), and a refusal control. - If it is not served, the handle gains the door, with the same execution context the REST door builds, reused and not re-derived.
- If it is already served, the item reduces to pins: an anonymous submit, the door's execution context (
- ⛔ No change in
packages/rest,packages/runtimeorpackages/objectql. If serving the door needs one, stop and report (domain:cli/domain:engine). - Done when (triage
6061416383): hotcrm's matching local path can be deleted. The report names that path from hotcrm, read-only, if it can be read; otherwise it says so.
Container & model:M,mode:subagent,model: opus. The contract review atCONTRACT_REVIEW_TIERis owed before enqueue (a new door on the published handle).
Clause-②: yes (widening: a new door on@objectstack/verify's published handle), ornoif the premise shows the door is already served and only pins are added
Responsibility: the verify handle's dispatcher does not serve the anonymous form route thatRestServerregisters |servecomposes it, and PR feat(core,cli,verify): bootStack composes what serve composes — item 1 stage 2 of #22301 (HELD at stop conditions) #22381 brought the handle's composition in line withserve, so it may already reach it (the premise) | every app test of a web-to-lead / web-to-case branch, which today rebuilds the door's context by hand (hotcrm)
Thread-read: 6088415799
Serial constraints cleared: the 14 open PRs' file lists were read at this stamp, and none touchespackages/verify/src/{handle,harness,index}.tsorrest-server.ts. Items 2–3 (PR feat(verify): the handle gains a system-context update door and a predicate update door #22517, seat 3) landed at5910b5e3eand released this card (6088415799).
Generated by Claude Code
Ruled: 6070767186 · letter A (item 1) · 2026-10-08T23:05Z
Filing gate: ① product defects in a published package, reach measured. Class (a). reach: named producer. objectstack-ai/hotcrm's test suite was ported onto
@objectstack/verify17.7.0 (PR objectstack-ai/hotcrm#2013 for objectstack-ai/hotcrm#1595, the hotcrm consequence of objectstack#15951). Each item below was measured there with the handle's own calls.Who acts on it: the objectstack triage seat routes it; the fixes land in
packages/verify(item 1 also touchespackages/cli). Found by the dev of hotcrm#1595 (sessionsession_012zh91QzFgePbkmuHnugLN3); therepo:hotcrmseat located the sites. ⛔ Not a claim.Why it matters: the maintainer's B′ ruling (2026-09-05, on objectstack#15951) put test execution on the platform: an app's tests reach the real engine through this handle and nothing hand-built. hotcrm#1595's rule: "a behaviour the handle cannot express is a platform finding … keep that one local helper path until the fix is pinned … ⛔ never re-grow a local stand-in". hotcrm therefore keeps exactly one local path per item, in
test/helpers/verify-stack.ts. Each path calls the engine's own service on the verify-booted kernel; none re-implements the engine. Every item closed here deletes one of them.The gaps (measured on 17.7.0; sites at the
@objectstack/*@17.7.0commit)bootStackignores the app'srequires[].objectstack servemounts the capability providers an app requires.verify/src/harness.ts:516-730boots a fixed plugin set, offering onlyautomationandextraPlugins. The mapping lives on theServeclass (CAPABILITY_PROVIDERS,cli/src/commands/serve.ts:1867;CapabilitySpecunexported at:959). The handle cannot reuse it, so an app names the plugins by hand. Measured on hotcrm without them: nosys_inbox_message, nosys_approval_request, nosys_activity, and no record-change flow fired on a write. hotcrm names five: triggers, approvals, messaging, audit, email.seedonly inserts (handle.ts:401-405), andhooks.runalways runs as a person.multi: true) update door.hooks.runaddresses one row byinput.id, and RESTupdateManyiterates by id. The engine's predicate path, where 17.7.0 binds each row's pre-image, has no handle door.POST /api/v1/forms/:slug/submit(registered byrest/src/rest-server.ts:10720) answersENDPOINT_NOT_FOUNDthrough the handle's dispatcher. An app's web-to-lead / web-to-case branches can only be reached by reproducing the door's execution context (publicFormGrant,guest_portal, anonymous).seedskips record-change flows. An integration's or system job's write, and a record deleted between the trigger and the flow'sget_record, cannot be driven.async: truehook's completion is invisible (the write that fired it has already returned), and a refusal cannot be staged without a spy on the engine.automation.evaluateConditionis not fronted. A truth table over row shapes that no write produces needs the kernel service.bootStackrefuses cel date values. hotcrm's seed uses the documentedcel`daysFromNow(..)`form (content/docs/data-modeling/seed-data.mdx:387-397). Each verify boot logs ~478 insert WARNs "must be a valid datetime (ISO-8601)" (campaign, case, event, opportunity, lead and account seeds), and the rows are missing.serveresolves these (seed-loader.ts:1138→formula/src/seed-eval.ts:74). The only warn-level insert-failure line is AppPlugin's raw-insert fallback (runtime/src/app-plugin.ts:1527-1534,:1542-1548), which runs when no metadata service is mounted or SeedLoaderService throws. Root cause NOT MEASURED. objectstack#21663 (closed) named these raw-cel paths.Acceptance
Each item gets a handle door, or a stated decision that the door is out of scope. Each then lets hotcrm delete the matching local path in
test/helpers/verify-stack.ts:extraPluginslist,systemUpdate,predicateUpdate,guestInsert,runRecordFlow,recordEngineWrites,runShippedHook,conditionHolds. Item 9: a verify boot of an app with cel-dated seeds stores those rows.Duplicate check
gh searchis refused in this container (GraphQL and REST search answer 403). So all 9,565 objectstack issues were listed and matched case-insensitively:verify handle: 82 (open: verify: classify hotcrm's "platform-semantics pins" — each becomes a derived proof family in@objectstack/verifyor a platform regression test in dogfood, never an app test (epic hotcrm#1579, step 5c) #15953, docs + scaffold:plugin-spec.mdxstops promising the non-existent@objectstack/testingand points at@objectstack/verify; thecreate-objectstackblank template ships a test story (epic hotcrm#1579, step 5b) #15952, [PM seat] domain:cli — 🟢 os-elon-musk · session_01BmsuLyUeuG5CNpZFMH1jzS #6024)CAPABILITY_PROVIDERS: 10 (all closed, serve-side)bootStack requires: 7verify systemUpdate: 0evaluateCondition verify: 0forms submit ENDPOINT_NOT_FOUND: 1 (a QA run)seed cel valid datetime: 8None is a duplicate. The origin is #15951 (closed). Open #15953 (derived proof families) and #15952 (docs + scaffold) are siblings; #21663 (closed) is item 9's nearest record.
Generated by Claude Code