Skip to content

spec(conversions): eight ADR-0087 D2 conversions stay on the 18 load path after #23487 — five families each need a ruling before they can retire #23543

Closed

Description

@objectstack-fleet

Ruled: 6182001882 · letter A/A/A/A/A/A · 2026-10-15T01:06Z

Filing gate ③: questions left by a landing. PR #23523 (#23487, merged 5fd2c76d6) retired 7 of the 15 overdue ADR-0087 D2 conversions from the 18 load path and KEPT 8, each with its reason and retire condition in its docblock (packages/spec/src/conversions/registry.ts), pinned by name in conversions.test.ts (every entry whose window ran out before 18 is retired or kept by name). The contract-tier review (6177406940, ③) confirmed that keeping each entry is safe without a ruling. Filed by domain:spec seat 3 (#18883) · baozhoutao · session session_01D6F9axfoPzR7t8G1J7Ytzz. ⛔ Not a claim; lane and grade are triage's.

reach: an @objectstack/spec 18 author who still writes one of the old spellings below: today it is converged silently at load (with a notice) instead of refused with a prescription.

Reader who acts: triage, to grade, split and route; some halves may be the maintainer's call (a default flip, a reserved-name ruling).

The five families (from the dev's open_questions, report 6176086002 and addendum 6177270333 on #23487)

  1. datasource-driver-mongo-to-mongodb. 'mongo' is a registered alias of mongodb (config-registry.zod.ts:183), so there is no refusal for a retirement to hand the author to. Options: A, retire 'mongo' as a value (refused with a prescription naming mongodb), then retire the entry; B, record the entry as permanent. Dev lean: A.
  2. retry-policy-converged. The retryDelayMs rename is already refused on every surface. The entry stays only for the job half: it materializes maxRetries: 3 / backoffMultiplier: 2 on a source job.retryPolicy that omits them, so retiring would silently drop such a job from 3 retries to 0. Options: A, retire once the job default flip is ruled for authored sources; B, record as permanent.
  3. flow-node-wait-event-config-lift and flow-node-connector-config-lift. wait and connector_action have no config contract, so once retired a loose key beside the declared block would pass silently. Refusing those loose keys would also refuse stored flows whose loose key the block shadows (the rehydration seam parses the same schema). Options: A, refuse the named loose keys under config and have the lift delete a shadowed loose key at rehydration, then retire; B, keep.
  4. view-visibleOn-to-visibleWhen and page-component-visibility-to-visibleWhen. The schemas still declare the deprecated key and fold it at parse (view.zod.ts:3514, :3784; page.zod.ts:682), so retiring the entry alone is unobservable. Options: A, retire the aliases themselves (retiredKey tombstones and the full spec-property-retirement kit, an objectui check), retiring the entries in the same change; B, keep. Three record / strict-exit suites ride page-component-visibility and re-point then.
  5. flow-node-http-callout-rename and page-kind-jsx-to-html. The old values are accepted silently: FlowNodeSchema.type is an open namespace (flow.zod.ts:603), and 'jsx' is still a PageSchema.kind member that COMPILED_PAGE_KINDS reads (page.zod.ts:1726, :985). Options: A, refuse the three retired node types and retire jsx through enumWithRetiredValues, then retire both entries (the http_* half needs the open-namespace / reserved-names ruling, ADR-0018); B, keep.

What done looks like

Each family has a ruling (retire, or recorded permanent), and each "retire" lands as its own PR that refuses the old spelling with its prescription and then sets retiredFromLoadPath on the entry, with the verdict-list pin updated.

Dedupe

MCP search_issues on objectstack-ai/objectstack, query ADR-0087 conversions kept on load path mongo driver alias retry policy converged wait connector config lift visibleOn visibility jsx http callout retire: 4 hits, #22256, #21107, #7159, #4220, all closed and none about these entries' retirement.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Ruling: batch #347 item 3 · letter A/A/A/A/A/A · maintainer 「同意」 2026-10-15T01:05Z

    Director seat, summon #37 (continuation 2), session_01LqNgdPZB2Jnr5HpGbaqLeB, on the seat's presentation 6178791899 (F1 A · F2 A · F3 A · F4 A · F5-jsx A · F5-http A; fallback F5-http B), triage's entry 6179319387 and the seat's delta 6181021557; the maintainer's 「同意」 takes the recommendation on every family, so the letters are F1 A · F2 A · F3 A · F4 A · F5-jsx A · F5-http A and the fallback is not taken.

    What the ruling binds:

    1. F1 A: 'mongo' retires as a datasource.driver value, refused with the prescription naming mongodb; stored rows are rewritten once by the D3 chain; datasource-driver-mongo-to-mongodb sets retiredFromLoadPath.
    2. F2 A, the loud form: a job.retryPolicy block whose maxRetries is omitted or 0 is refused, in the shape flow.errorHandling already uses for strategy: 'retry' (flow.zod.ts:1276-1288): "a retry block with no attempts is no retry block: state maxRetries ≥ 1, for example 3, or delete the block". A job with no block stays a single attempt; backoffMultiplier keeps its declared default and is not refused. retry-policy-converged then sets retiredFromLoadPath; the 17 materialization lives on in the D3 chain.
    3. F3 A: the named loose keys under a wait or connector_action node's config are refused with the prescription naming the sibling block; the lift deletes a loose key the block shadows at rehydration, so stored flows keep loading; both entries set retiredFromLoadPath.
    4. F4 A: visibleOn (view) and visibility (page component) retire as keys: retiredKey tombstones naming visibleWhen with the full spec-property-retirement kit (ADR-0087 markers, baselines, forms, docs, pins); both entries retire in the same change; the three record / strict-exit suites re-point. objectui's renderer and Studio half is the consumer first-release card on objectui#12334, graded p1 only if the designer would write the refused key, which the follow-up measures first.
    5. F5-jsx A: 'jsx' retires from PageSchema.kind through enumWithRetiredValues naming html, together with the COMPILED_PAGE_KINDS branch; the entry retires; objectui's console sample moves to html (one line, on objectui#12334).
    6. F5-http A: http_request, http_call and webhook are reserved inside the open node namespace: the authoring doors refuse them with the rename to http; ADR-0018 gets a dated note naming the three reserved retired names (Tier H, the maintainer's merge); the entry retires; objectui's simulator, inspector alias, canvas case and preview samples move to http (on objectui#12334). eventType: 'webhook' on a wait node is untouched.
    7. Every family is its own PR, Part of #23543, with a contract-tier review (Clause-②: yes (narrowing)), a BREAKING changeset and the verdict-list pin in conversions.test.ts updated; order F1 → F5-jsx → F3 → F2 → F4 → F5-http; tsc and the parse-time prescription are the whole channel, no staged window and no double spelling.

    Workload of the letters (the card's tables): spec lane · 6 PRs (F4 and F5-http each with an objectui follow-up; F5-http with one Tier H ADR-0018 note) · precedent PR #23523 (+543/−158, 21 files, 7 entries).

    Execution: this card is the execution card: needs-user-decision removed and pm:queue added in this act for domain:spec (priority:p1 + target:v18 stand); the body's first line carries Ruled:. The card closes when all six have landed and the verdict-list pin reads no kept-without-ruling entry.

  2. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1 (second shift) · 2026-10-15T01:22Z · family F1 of ruling 6182001882: 'mongo' retires as a datasource.driver value. The PR is Part of #23543; F5-jsx, F3, F2, F4 and F5-http follow on this card one at a time, in the ruling's order.
    Session: session_01LFqdRsuM5nkqoJdHd5ztVk
    Account: os-bill (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/issue-23543-retire-mongo-driver-alias
    Worktree: objectstack-issue-23543
    Domain: domain:spec
    Seat: domain:spec#2 (seat post #18549)
    File surface (at origin/main cdc42eb49 or later; stop on a breach and explain it in the report):

  3. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 23543,
    "status": "done",
    "branch": "claude/issue-23543-retire-mongo-driver-alias",
    "pr": "#23600",
    "session": "session_01LFqdRsuM5nkqoJdHd5ztVk (subagent = parent's; transcript Claude-Session line)",
    "premise_still_valid": true,
    "summary": "F1 only. An authored datasource.driver 'mongo' is now refused at parse by DriverType with the prescription naming mongodb. The refusal is spelled as a JSON-Schema-projectable pattern derived from a new retiredAliases column on the driver vocabulary row (exported RETIRED_DRIVER_ID_GUIDANCE). 'mongo' left the boot selection face, so both hosts refuse OS_DATABASE_DRIVER=mongo with their Supported-drivers list naming mongodb. datasource-driver-mongo-to-mongodb now sets retiredFromLoadPath with retiredAfter 17.7.0, and D3 entry 18.datasource-driver-mongo-alias-retired joins it. The verdict-list pin moves the entry to the retired side. Mechanism assumption 1 is partly falsified: deleting the alias outright (measured on fa6a608) made a raw stored legacy 'mongo' row serve all ten mongodb passthrough secrets in cleartext through redactStoredMetadataBody, and turned 4 stored-row/contract pins red. So the spelling stays on the CONTRACT face only (resolveDriverId('mongo') = mongodb), the memory engine's posture. With it there, no D2 reorder was needed. F5-jsx, F3, F2, F4 and F5-http stay on the card.",
    "tests": "Readings on head acf0e6c (origin/main 32e03d2 merged via os-regen-merge.sh). spec: pnpm --filter @objectstack/spec test = 678 files / 20738 passed; typecheck (tsc + scripts + test layer) exit 0; test:repo 61 / 1033 passed (run before the PM's 03:40Z lock note); build + check:generated = 'All 14 generated artifacts are up to date' (api-surface/data.json and export-origins/data.json regenerated for the one new export). cli: vitest --project unit full tier = 290 files pass (288 in the first run + the 2 build-dependent published-subpath pins, which failed only with 'packages/cli is not built' and passed 2/29 after pnpm --filter @objectstack/cli build); typecheck exit 0 (check:test-typecheck OK). The six touched or pinning cli files: 6 / 113 passed. runtime: typecheck exit 0; vitest --project local 382 files / 5717 passed, 19 skipped. service-datasource: typecheck exit 0; vitest 45 files / 838 passed. drivers: no packages/drivers/driver-* src reads a datasource.driver value (zero hits for resolveDriverId / resolveDatabaseDriverId / DRIVER_ID_ALIASES / DatasourceSchema / DriverType in src), so no driver suite is owed. Ablation (one behaviour, through scripts/ablation-replace.mjs, with on-disk proof: anchor 1->0, blob 3ae04c6f21b1->2a33e628bb45, injected text grep -c 1): with DriverType's retired-spelling patterns emptied, 6 tests went red across conversions.test.ts, config-registry.test.ts and retired-key-removal-version.pin.test.ts (direction: red). The restore was proven blob == HEAD and git diff HEAD empty. Spec tests resolve src, so no dist rebuild leg applies. Premise measurement: an in-memory retirement probe on dist showed driver 'mongo' passing defineStack silently, with no refusal, before this change.",
    "gates": "dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 117 commands at acf0e6c (identical to the 81eb862 derivation). Each was run one by one with its exit code captured before any pipe, one log per command. dispatch-gates --ran: '117 derived famil(ies) accounted for — 112 run, 5 NOT-MEASURED (5 DERIVED from a recorded exit 3)', exit 0. 111 of the 112 run families exit 0, including check-adr-0087-registration --base origin/main ('BREAKING+bang+clause-②-narrowing, registered datasource-driver-mongo-alias-retired (new here)'), check:api-surface, check:generated, check:docs, check:liveness, check:doc-authoring and check:nul-bytes. The 112th, pnpm check:platform-checklist, exits 1 on anchors outside this diff (attachments-storage / search areas: protocol.ts#countable is absent on origin/main itself; zero overlap with the diff); it is kept out of per-PR CI by decision (checklist-status.yml:18). NOT MEASURED, each a PREREQUISITE NOT MET exit 3: check-plugin-teardown-shape --self-test (shallow clone), spec check:skill-examples (client SDK not built), check:dual-build-cjs-loads (full build absent), check:i18n-coverage (examples' connector-slack dist absent; check:i18n and check:i18n-walk-parity went green on a rerun after the cli build), check:type-check-debt (its inner lock call timed out). PR check-runs read once on acf0e6c: 41 total, 36 success and 5 skipped, 0 failing or pending. This includes Lint & Repo Gates, TypeScript Type Check, Test Core (1-6/6), Build Core, Governed Surface Queue Guard, Check Changeset, Dogfood Regression Gate, Console Pin Gate, Spec property liveness and Temporal Conformance, all success.",
    "mcp_calls": "0",
    "api_writes": "2 relay dispatches (POST /repos/objectstack-ai/objectstack/dispatches, objectstack-fleet[bot]): (1) pr_create, which executed POST /repos/objectstack-ai/objectstack/pulls (draft #23600; 9086 bytes sent, 9086 stored, identical) and POST /repos//issues/23600/assignees (os-bill, confirmed); (2) this os-dev-report comment, POST /repos//issues/23543/comments. label-write: zero writes (none named; skip-changeset not applicable). git push is not counted. REST reads only otherwise: the issue, its comments, and the commit check-runs.",
    "open_questions": [
    {
    "question": "The claim's line Clause-②: yes is copied verbatim to the PR body's head, as instructed. Ruling item 7 spells it Clause-②: yes (narrowing), and the diff does both: it widens the public surface (export RETIRED_DRIVER_ID_GUIDANCE) and narrows the accept set. The changeset carries the ruling's yes (narrowing). Should the PR body line gain the arm?",
    "options": [
    "A: the seat amends the PR body line to Clause-②: yes (narrowing) (dev wrote the body once and does not PATCH it)",
    "B: leave it; Check Changeset reads yes (minor) and the ADR-0087 gate reads the changeset's arm"
    ],
    "recommendation": "A, because the ruling names the arm and the body is the carrier check-changeset-no-major reads; both gates are green either way today"
    }
    ],
    "out_of_scope_findings": [
    "carrier: 承接者:无 · noted, not filed — check:platform-checklist is red on origin/main 32e03d2's tree. docs/qa/platform-checklist areas/search.json cites packages/metadata-protocol/src/protocol.ts#countable, which git grep finds absent on origin/main, and areas/attachments-storage.json reports SYMBOL ANCHORS LOST, 27 against a floor of 28. The family is kept out of per-PR CI; its daily watchdog is the patrol that owns it. Zero overlap with this diff. Dedupe words: platform-checklist anchor countable attachment-access-hooks canEdit floor",
    "carrier: the F3 and F2 PRs on #23543 · noted, not filed — after this PR, the load-path conversions that os migrate meta --from 16 replays are retry-policy-converged and F3's two lifts. The re-pointed suites (cli migrate-meta-load-conversions, migrate-meta-composed-load-conversions, the load-path case of migrate-meta-composed, spec stack-authored-input) lose their last real subject when F3 and F2 land, and need a synthetic probe or retirement there. Dedupe words: load-path conversion authored-source shim retryDelayMs stack-authored-input"
    ],
    "deviations": [
    "Mechanism assumption 1 changed route: the alias left the selection face and authoring, and kept the contract face (retiredAliases column), instead of being deleted. Evidence is above. The refusal is a regex pattern, not enumWithRetiredValues, because driver is an open z.string(). A first superRefine spelling was refused by the build's dropped-refinement gate.",
    "A new public export, RETIRED_DRIVER_ID_GUIDANCE (api-surface +1). DriverType reads it cross-module.",
    "Files outside the claim's literal list, each a pin-sweep or false-text hit: packages/spec stack-authored-input.test.ts, retired-key-removal-version.pin.test.ts, datasource.test.ts, driver/mongo.zod.ts and mongo.test.ts (comments), liveness/datasource.json (note); cli driver-vocabulary-parity.test.ts, src/utils/config.ts (docblocks), test/migrate-meta-load-conversions.test.ts, test/migrate-meta-composed-load-conversions.test.ts, test/migrate-meta-composed.test.ts; service-datasource src/driver-catalog.ts (comment); drivers/driver-mongodb/README.md (published, hence a patch row in the changeset); content/docs/data-modeling/drivers.mdx. MAJOR_18_CONVERSIONS and every other conversion entry are untouched.",
    "Declared narrowing: per the PM's 03:40Z note, no package test:repo after that point, so runtime test:repo is left to CI (Test Core green). The spec test:repo run (61 files) happened before the note.",
    "One locked closure build was wrapped in timeout 590 and the wrapper killed turbo mid-run (runtime and service-automation build tasks force-killed). It was re-run clean under the lock: 60/60, 47 cached.",
    "The harness reminder's model-named Co-Authored-By trailer was not used. Commits carry the model-free pair the pre-push hook checks, and check:commit-card-trailers was green on every push."
    ],
    "line_budget": "n/a — no skills/** file and no line-ratcheted ledger in the diff",
    "files_changed": "23 files, +557/-162 vs merge-base: .changeset/23543-f1-retire-mongo-driver-alias.md; content/docs/data-modeling/drivers.mdx; packages/cli/src/utils/config.ts; packages/cli/src/utils/driver-vocabulary-parity.test.ts; packages/cli/test/migrate-meta-composed-load-conversions.test.ts; packages/cli/test/migrate-meta-composed.test.ts; packages/cli/test/migrate-meta-load-conversions.test.ts; packages/drivers/driver-mongodb/README.md; packages/services/service-datasource/src/driver-catalog.ts; packages/spec/api-surface/data.json; packages/spec/export-origins/data.json; packages/spec/liveness/datasource.json; packages/spec/src/conversions/conversions.test.ts; packages/spec/src/conversions/registry.ts; packages/spec/src/data/datasource.test.ts; packages/spec/src/data/datasource.zod.ts; packages/spec/src/data/driver/config-registry.test.ts; packages/spec/src/data/driver/config-registry.zod.ts; packages/spec/src/data/driver/mongo.test.ts; packages/spec/src/data/driver/mongo.zod.ts; packages/spec/src/migrations/entries/semantic/18.datasource-driver-mongo-alias-retired.ts; packages/spec/src/shared/retired-key-removal-version.pin.test.ts; packages/spec/src/stack-authored-input.test.ts"
    }


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT → PR #23600 comment 6184470731 · domain:spec seat 2 · session session_01LFqdRsuM5nkqoJdHd5ztVk · 2026-10-15T04:32Z · family F1; the contract review at CONTRACT_REVIEW_TIER is owed before the queue.

  5. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Release: session session_01LFqdRsuM5nkqoJdHd5ztVk (domain:spec seat 2) · F1 landed as Part of; claim 6182201116 covered F1 only · back to pm:queue for domain:spec, next family F5-jsx · 2026-10-15T05:33Z

    Landing record, PR #23600 (F1 of ruling 6182001882):

    Probe Reading
    origin/main bc0538a429 "feat(spec)!: retire the datasource driver spelling mongo …" (git branch -r --contains → origin/main)
    merge queue no gh-readonly-queue/main/* ref names #23600
    squash vs reviewed head git patch-id --stable equal: 1bb5ac36786f for both acf0e6c1f (ACCEPT 6184470731, contract review PASS on that head) and the squash
    card open, Part of: nothing closed it (closed_by none)

    Left on this card, in the ruling's order (item 7): F5-jsx → F3 → F2 → F4 → F5-http. Each family is its own PR, Part of #23543, with a contract-tier review (Clause-②: yes (narrowing)), a BREAKING changeset and the verdict-list pin in conversions.test.ts. The last family's PR is Fixes #23543.

    Carry-forward for the next dispatch:

  6. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 2 (second shift) · 2026-10-15T05:36Z · family F5-jsx of ruling 6182001882 (item 5): 'jsx' retires from PageSchema.kind naming html, together with the COMPILED_PAGE_KINDS branch; the page-kind-jsx-to-html entry retires. The PR is Part of #23543; F3, F2, F4 and F5-http follow one at a time, in the ruling's order.
    Session: session_01LFqdRsuM5nkqoJdHd5ztVk (the seat; the dev is a cloud session whose draft PR carries its own session link)
    Account: os-bill (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/issue-23543-retire-jsx-page-kind
    Worktree: objectstack-issue-23543
    Domain: domain:spec
    Seat: domain:spec#2 (seat post #18549)
    File surface (at origin/main bc0538a42 or later; stop on a breach and explain it in the report):

  7. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 23543,
    "status": "done",
    "branch": "claude/issue-23543-retire-jsx-page-kind",
    "pr": "#23638",
    "session": "session_01DdfPiKZUYAduc1ERcEvDso (cloud dev; dispatched by seat session_01LFqdRsuM5nkqoJdHd5ztVk)",
    "premise_still_valid": true,
    "summary": "F5-jsx only. PageSchema.kind is now enumWithRetiredValues(['full','slotted','html','react'], PAGE_KIND_RETIRED_GUIDANCE): an authored kind 'jsx' fails tsc and is refused at parse with the prescription naming html (defineStack: STACK_SCHEMA_INVALID / 422 at pages.0.kind). COMPILED_PAGE_KINDS is ['html']; page-kind-jsx-to-html sets retiredFromLoadPath with retiredAfter 17.7.0; D3 entry 18.page-kind-jsx-retired (no conversionIds: protocol 11 is below the migration floor, so no step replays it, and the prescription carries no os migrate meta sentence). Every non-test 'jsx' reader in metadata-protocol, cli and lint dropped its branch. Mechanism assumption 1, first branch, holds: the stored-row seams replay the retired entry (applyConversionsToStoredItem, includeRetired), so a stored jsx page loads as html, which is pinned; the save door does not convert pages and refuses jsx with a 422. Assumption 5 holds too: jsx was the live-conversion subject of 3 cli e2e suites, stack-conversions-record, conversions.test cases and a metadata-core firing control, all re-pointed (flow-node-http-callout-rename / page-component-visibility-to-visibleWhen).",
    "tests": "Final head 831a9fa (origin/main f7cd580 merged via os-regen-merge.sh, no conflict, check:generated 'All 14 generated artifacts are up to date'). Post-merge: spec src/conversions+migrations+ui+shared+stack-conversions-record 195 files / 6977 passed; metadata-core 18 / 719 passed; metadata-protocol 236 files / 20550 passed, 19 skipped. Pre-merge (5bf2584): spec full suite 740 files, 21785 passed with 4 failures in one file (page-requires-compiled-kinds.test.ts), which was fixed and re-run at 8 files / 567 passed; spec typecheck exit 0; lint 139 / 6771 passed plus typecheck; metadata-protocol 237 / 28429 passed plus typecheck; metadata-core 18 / 701 passed plus typecheck; cli unit tier 290 files / 4323 passed plus typecheck; the 3 edited nightly-tier cli e2e suites (OS_TEST_TIERS=nightly) 3 / 35 passed; pnpm check:i18n OK. Ablation via scripts/ablation-replace.mjs: kind back to a bare z.enum of the four kinds, so the prescription is dropped; anchor 1->0, blob 4ceaa5dffafc->35fbaad1835c; 2 tests went red (conversions.test defineStack refusal; retired-key-removal-version pin row), direction red; restore blob == HEAD and git diff HEAD empty; spec tests resolve src, so no dist leg.",
    "gates": "dispatch-gates --commands --repo objectstack-ai/objectstack derived 118 commands on 5bf2584; each was run with its exit code captured before any pipe, one log per command. --ran (the record carries exit codes): '118 derived famil(ies) accounted for - 116 run, 2 NOT-MEASURED (2 DERIVED from a recorded exit 3)', exit 0. 115 exit 0, including check-adr-0087-registration, check:spec-changes, check:upgrade-guide, check:docs, check:liveness, check:doc-authoring, check:nul-bytes, check:i18n-stale-fill, check:api-surface, check:generated and check:i18n-coverage; the last three first exited 3 on a stale spec dist or a missing example build and were re-run green after a rebuild. 1 exit 1: check:platform-checklist, ABSENT SYMBOL anchors in metadata-protocol/src/protocol.ts and service-storage attachment-access-hooks.ts, neither touched by this diff (the same main-tree red F1 reported). NOT MEASURED: check-plugin-teardown-shape --self-test (shallow clone) and check:dual-build-cjs-loads (full build absent). PR check-runs read once on 831a9fa: 24 total, 22 in_progress, 1 success, 1 skipped, 0 failing (in_progress is the honest value; not waited on).",
    "mcp_calls": "0",
    "api_writes": "2 relay dispatches (POST /repos/objectstack-ai/objectstack/dispatches as objectstack-fleet[bot]): (1) pr_create, which executed POST /repos/objectstack-ai/objectstack/pulls (draft #23638; 11432 bytes sent, 11432 stored, identical) and POST /repos//issues/23638/assignees (os-bill, confirmed); (2) this os-dev-report comment, POST /repos//issues/23543/comments. label-write: zero (none named). git push not counted. Reads were unauthenticated REST only.",
    "line_budget": "n/a - no skills/** file and no line-ratcheted ledger in the diff",
    "files_changed": "44 files vs merge-base (+~400/-~200): .changeset/23543-f5-jsx-retire-page-kind-jsx.md; content/docs/ui/pages.mdx; content/docs/ui/react-pages.mdx; content/docs/references/ui/page.mdx (generated); packages/spec: src/ui/page.zod.ts, src/ui/page.form.ts, src/conversions/registry.ts, src/conversions/walk.ts, src/conversions/conversions.test.ts, src/migrations/entries/semantic/18.page-kind-jsx-retired.ts (new), 18.page-requires-non-compiled-kind-refused.ts, 18.ui-html-page-div-refused.ts, src/migrations/registry.ts.template, src/shared/retired-key-removal-version.pin.test.ts, src/stack-conversions-record.test.ts, src/ui/object-refinement-check-exports.test.ts, src/ui/page-print.test.ts, src/ui/page-requires-compiled-kinds.test.ts, liveness/page.json; packages/metadata-protocol: src/runtime-authoring-gate.ts, src/protocol.batch-verb-driver-text.test.ts (comment); packages/metadata-core: src/artifact-forward-conversion.test.ts; packages/cli: src/utils/sdui-manifest.ts, src/utils/sdui-manifest.test.ts, src/utils/i18n-extract.ts, test/lint-conversion-notices.e2e.test.ts, test/build-json-failure-conversions.e2e.test.ts, test/validate-json-failure-conversions.e2e.test.ts; packages/lint: src/page-walk.ts, src/page-walk.test.ts, src/page-walk-conversion-parity.test.ts, src/validate-jsx-pages.ts, src/validate-jsx-pages.test.ts, src/validate-page-source-styling.ts, src/validate-page-source-styling.test.ts, src/validate-action-name-refs.test.ts, src/authoring-rules.ts, src/rule-explanations.ts, src/validate-translation-references.ts; packages/platform-objects: src/apps/translations/{en (generated),zh-CN,ja-JP,es-ES}.metadata-forms.generated.ts",
    "deviations": [
    "Files beyond the claim's surface, each a pin-sweep or false-text hit: metadata-core artifact-forward-conversion.test.ts; spec stack-conversions-record, object-refinement-check-exports, page-print and page-requires-compiled-kinds tests; walk.ts and liveness/page.json; two D3 entries and one step-18 rationale paragraph whose text named jsx as live; cli e2e suites; content/docs/ui/pages.mdx and react-pages.mdx; and three hand-written translated help-text values (zh-CN, ja-JP, es-ES), where editing a value is allowed and the key set is unchanged. MAJOR_18_CONVERSIONS and every other conversion entry are untouched.",
    "Changeset bumps metadata-protocol, cli and lint at patch, beside spec minor, because their runtime readers changed.",
    "The worktree was created from origin/main 9a6f790 (newer than the dispatch's bc0538a) after detaching the primary checkout, which had the branch checked out.",
    "The harness reminder's model-named Co-Authored-By trailer was not used; commits carry the model-free pair the pre-push hook checks (check:commit-card-trailers green on every push)."
    ],
    "open_questions": [
    {
    "question": "skills/objectstack-ui/rules/pages.md:138 still says kind 'jsx' is a deprecated alias for 'html', which is false after this PR. The file is a governed Tier H surface, so editing it here would make this whole PR Tier H. Left untouched.",
    "options": [
    "A: the seat files or sends a one-line skills-only PR (Tier H, maintainer merge) that drops the sentence",
    "B: fold it into this PR and accept Tier H landing"
    ],
    "recommendation": "A, because it keeps this contract-tier PR landable by the seat; the one sentence is a doc fix, not a contract change"
    }
    ],
    "out_of_scope_findings": [
    "carrier: objectstack-ai/objectui#12334 (the ruling's objectui half) - noted, not filed. At the pinned .objectui-sha b9814b3, objectui reads the retired value in more places than the one console sample: packages/types/src/layout.ts:1795 overrides PageNodeSchema.kind with a union including 'jsx' on an interface that extends the spec Page minus PAGE_SPEC_EXCLUDED (kind is not excluded). Once objectui's own spec dependency moves to this release, by reading, that is an interface-incorrectly-extends tsc error (not compiled here). Also packages/components/src/renderers/layout/page.tsx:611 has a kind === 'jsx' branch, and the types zod mirror (SpecPageFields) will refuse jsx at runtime. The Console Pin Gate is unaffected today: build-console.sh injects this tree's spec only at the vite bundle step. Dedupe words: PageNodeSchema kind jsx union layout.ts sdui-jsx-preview objectui types",
    "carrier: the F5-http PR on #23543 - noted, not filed. The suites re-pointed here ride flow-node-http-callout-rename, which retires last; when it does, those suites and F1's re-pointed migrate-meta load-path suites have no live conversion left. Dedupe words: live conversion subject e2e conversions field load-path suites http_request",
    "carrier: 承接者:无 - noted, not filed. check:platform-checklist is red on main's tree (absent symbol anchors in protocol.ts and attachment-access-hooks.ts), as F1 recorded; its daily watchdog owns it. Dedupe words: platform-checklist anchor countable canEdit anonymousFormIntake envWideRawViewRows"
    ]
    }


    Generated by Claude Code

  8. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT → PR #23638 comment 6187645640 · domain:spec seat 2 · session session_01LFqdRsuM5nkqoJdHd5ztVk · 2026-10-15T08:16Z · F5-jsx on 831a9fa8ea; the skills pages.md jsx sentence rides #23610's Tier H PR on the same file; contract review at CONTRACT_REVIEW_TIER before ready.

  9. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 23543,
    "status": "done",
    "branch": "claude/issue-23543-retire-jsx-page-kind",
    "pr": "#23638",
    "session": "session_01DdfPiKZUYAduc1ERcEvDso",
    "round": "patch round on contract review 6187937404 (FAIL on its second part), as the seat's message asked",
    "head": "2e1b65d0 (one commit on top of 831a9fa; the PR body is untouched)",
    "edits": [
    "1 (the FAIL) .changeset/23543-f5-jsx-retire-page-kind-jsx.md: the frontmatter gains '@objectstack/platform-objects': patch, and the body gains the row: the package publishes the Studio page form's source help text in four locales (en, zh-CN, ja-JP, es-ES), and that text no longer names jsx.",
    "2 (residual 8) packages/spec/liveness/page.json, the requires row's note: before 'the key exists only on kind 'html' / 'jsx' pages, the kinds compiled at save'; after 'the key exists only on kind 'html' pages, the kind compiled at save'.",
    "3 (residual 9) packages/spec/src/ui/page.form.ts:51 (a comment): before 'only the three source-compiled kinds ever read it'; after 'only the two source kinds (html / react) ever read it'. It is a comment, so no generated output changes; check:generated stays up to date.",
    "4 (residual 10) The changeset and D3 entry 18.page-kind-jsx-retired.ts: before 'every door that parses a page (defineStack, os validate, os build, os lint, the metadata save door)'; after 'at os validate, os build, the metadata save door and defineStack, so under os lint too when the config calls it' (the D3 text spells the CLI 'objectstack')."
    ],
    "gates": "Each run on 2e1b65d with its exit code captured before any pipe. check-adr-0087-registration --base origin/main: exit 0 ('[BREAKING+bang+clause-②-narrowing] registered page-kind-jsx-retired'). check-changeset-no-major --base origin/main: exit 0. check-empty-changeset --base origin/main: exit 0. pnpm changeset status --since=origin/main: exit 0, and @objectstack/platform-objects is now listed. After a spec build (exit 0): spec check:liveness exit 0; spec check:generated exit 0 ('All 14 generated artifacts are up to date'). Spec tests: src/ui, src/migrations, src/conversions and the src tests that read the liveness ledger, 182 files / 6880 passed, exit 0.",
    "mcp_calls": "0",
    "api_writes": "1 relay dispatch (POST /repos/objectstack-ai/objectstack/dispatches): this comment, POST /repos//issues/23543/comments. Plus one send_message to the seat session (not a GitHub write). git push is not counted.",
    "deviations": [],
    "open_questions": []
    }


    Generated by Claude Code

  10. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Release: session session_01LFqdRsuM5nkqoJdHd5ztVk (domain:spec seat 2) · F5-jsx landed as Part of, and claim 6185261661 covered F5-jsx only · back to pm:queue for domain:spec, next family F3 · 2026-10-15T09:54Z

    Landing record, PR #23638 (F5-jsx of ruling 6182001882):

    Probe Reading
    origin/main c5dd7fce30 "feat(spec)!: retire the page kind jsx …", merged 2026-10-15T09:48Z (git branch -r --contains → origin/main)
    merge queue no gh-readonly-queue/main/* ref names #23638
    squash vs reviewed head The squash tree f9861d1dd97d equals git merge-tree --write-tree of its parent a647783d46 with 2e1b65d066. That head carries the contract review PASS 6188246285, which follows FAIL 6187937404 on the missing @objectstack/platform-objects row.
    card open, Part of: nothing closed it

    Left on this card, in the ruling's order (item 7): F3 → F2 → F4 → F5-http.

    • Each family is its own PR, Part of #23543, with a contract-tier review (Clause-②: yes (narrowing)), a BREAKING changeset and the verdict-list pin in conversions.test.ts.
    • The last family's PR is Fixes #23543.
    • conversions.test.ts's kept-without-ruling list now holds exactly those four families' six entries.

    Carry-forward for the next dispatches (from the contract review's item 8):

    • F4: metadata-core's artifact-forward-conversion.test.ts FIRING CONTROL 1 now drives page-component-visibility-to-visibleWhen, F4's entry. F4's dispatch order names it, so the dev re-points it.
    • F5-http: these now drive flow-node-http-callout-rename: the three cli e2e suites (build-json-failure-conversions, validate-json-failure-conversions and lint-conversion-notices, all nightly tier), stack-conversions-record.test.ts, and two conversions.test.ts cases. F5-http's dispatch order names them, because that family retires that entry last.
    • F3 and F2: their dispatch orders name the os migrate meta load-path suites, as F1's record said.
    • Every family is a build-heavy closure (packages/spec plus the readers). Until [Decision] Three spec contract dev agents in one container queued ~70 min each on the shared verify lock: leave package test:repo to CI, and send build-heavy cards to cloud sessions? #23607 is ruled, this seat sends them as cloud sessions.

    The objectui half: the ruling put the console sample's move on objectstack-ai/objectui#12334, which closed at 01:40Z without it. Under cross-repo rule 3, this seat filed objectstack-ai/objectui#12464, with Blocked-by: this PR. It names four sites on objectui main cf430cd10:

    • the sample, apps/console/src/sdui-jsx-preview.tsx:87;
    • PageNodeSchema.kind, packages/types/src/layout.ts:1795;
    • the renderer branch, packages/components/src/renderers/layout/page.tsx:682;
    • a test comment.

    The ACCEPT's "types zod mirror" does not exist: packages/types/src/zod/ carries no 'jsx' page kind.

    Rides elsewhere: skills/objectstack-ui/rules/pages.md:138 still calls jsx an alias of html. That file is governed, so the sentence rides #23610's Tier H PR on the same file (ACCEPT item 6).

  11. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 7 (second shift, parallel again) · 2026-10-15T22:12Z · family F3 of ruling 6182001882 (item 3): the named loose keys under a wait or connector_action node's config are refused, with the prescription naming the sibling block. The lift deletes a loose key the block shadows at rehydration, so stored flows keep loading, and flow-node-wait-event-config-lift and flow-node-connector-config-lift set retiredFromLoadPath. The PR is Part of #23543; F2, F4 and F5-http follow one at a time, in the ruling's order.
    Session: session_01LFqdRsuM5nkqoJdHd5ztVk (the seat; the dev is a cloud session whose draft PR carries its own session link)
    Account: os-bill (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/issue-23543-retire-wait-connector-config-lift
    Worktree: objectstack-issue-23543
    Domain: domain:spec
    Seat: domain:spec#2 (seat post #18549)
    File surface (at origin/main 9bb93706f or later; stop on a breach and explain it in the report):

  12. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 23543,
    "status": "done",
    "branch": "claude/issue-23543-retire-wait-connector-config-lift",
    "pr": "#23742",
    "session": "session_011ZyGVR3TdcTDLhuzyEbkBN (dev cloud session; dispatched by seat session_01LFqdRsuM5nkqoJdHd5ztVk under claim 6203354520, whose Branch line names this branch)",
    "premise_still_valid": true,
    "summary": "F3 of ruling 6182001882: FlowSchema's collectFlowGraphs walk refuses every named loose key under a wait / connector_action node's config (wait: eventType, timerDuration, duration, signalName, signal, timeoutMs; connector_action: connectorId, actionId, input) at nodes.N.config.KEY, with a prescription naming the waitEventConfig / connectorConfig key (timeoutMs -> timerDuration as a string). The key tables moved byte for byte from conversions/registry.ts into a non-barrel leaf (automation/flow-sibling-block-loose-keys.ts) that both the refusal and the two lifts read. At rehydration each lift now DELETES a loose key the block shadows (and a loose null), with a notice, so stored rows keep loading with the block alone. flow-node-wait-event-config-lift and flow-node-connector-config-lift set retiredFromLoadPath / retiredAfter 17.7.0; the D3 entry 18.flow-sibling-block-loose-config-keys-refused carries both ids; the verdict-list pin now keeps 4 entries; the removal-version JOIN gains 2 rows; one BREAKING changeset (spec minor, service-automation patch).",
    "tests": "Pre-merge head cb5a4f9: @objectstack/spec full test 679 files / 20770 passed (1 todo), typecheck exit 0; @objectstack/service-automation full test 186 files / 2487 passed, typecheck exit 0; @objectstack/lint the 2 edited files 2 / 305 passed; @objectstack/cli unit tier, the 3 migrate-meta load-path suites 3 / 18 passed (full cli tiers declared to CI: no cli file touched). Post-merge head 23bebd6 (merged origin/main 3b46855, incl. #23418, via os-regen-merge.sh, no conflicts, template equals main): spec src/conversions+automation+migrations+shared+stack* 113 files / 3883 passed; check:generated 'All 14 generated artifacts are up to date' (no generated file changed, before or after the merge). Ablation 1 (refusal unwired in the flow walk, scripts/ablation-replace.mjs): anchor 1->0, blob f69316ecce7b->95cf82982a02; 9 tests red across conversions.test.ts, retired-key-removal-version.pin.test.ts, connector-action-config-required.test.ts (direction: red); restore blob == HEAD, git diff HEAD empty. Ablation 2 (connector lift drop branch re-inserts the loose key): anchor 1->0, blob 940997a39a4e->9450deebd49e; 3 tests red (direction: red); restore proven. Spec tests import src: no dist leg.",
    "gates": "Local, final head 23bebd6: dispatch-gates --commands --repo objectstack-ai/objectstack derived 111; each run one by one, exit code captured before any pipe; --ran: '111 derived famil(ies) accounted for - 110 run, 1 NOT-MEASURED (1 DERIVED from a recorded exit 3)' - the one is check-plugin-teardown-shape --self-test (shallow clone). Round 1 on cb5a4f9 read 107 run / 4 NOT-MEASURED (check:skill-examples and check:dual-build-cjs-loads exit 3, check:dts-closure exit 1 recorded as a claimed NOT-MEASURED because my closure build ran with OS_SKIP_DTS=1); all three exit 0 in round 2. CI on 23bebd6 at report time: TypeScript Type Check success, Lint & Repo Gates success, Build Core success, Governed Surface Queue Guard success, Check Changeset success, Test Core 1/6 2/6 4/6 5/6 6/6 success, Test Core 3/6 in_progress, Type Check workspace/consumer/source/debt ledger success, Lint ESLint/docs/repo/tooling/PM dispatch-gates/scoped x3 success, Spec property liveness success, Part-of PR must not also close its card success, Build Docs success, Check PR Size success; Console Pin Gate, Temporal Conformance, Dogfood shards, Packed-tarball smoke skipped (PR fast set).",
    "mcp_calls": "4 - issue_read get, issue_read get_comments (#23543), pull_request_read get, pull_request_read get_check_runs (#23742); no write tool",
    "api_writes": "2 relay strokes - pr_create (POST /repos/objectstack-ai/objectstack/pulls draft + POST issues/23742/assignees os-bill, run 38823295311, body read back byte-identical); comment (POST issues/23543/comments, this report). git push is not a REST write.",
    "line_budget": "+621 / -129 over 16 files vs origin/main (PR #23742: additions 621, deletions 129)",
    "files_changed": [
    ".changeset/23543-f3-retire-wait-connector-config-lift.md",
    "content/docs/automation/flows.mdx",
    "packages/lint/src/lint-flow-patterns.test.ts",
    "packages/lint/src/validate-expressions.flow-cel-root.test.ts",
    "packages/services/service-automation/src/builtin/connector-nodes.test.ts",
    "packages/services/service-automation/src/builtin/connector-nodes.ts",
    "packages/services/service-automation/src/builtin/wait-node.test.ts",
    "packages/services/service-automation/src/builtin/wait-node.ts",
    "packages/services/service-automation/src/run-summary.test.ts",
    "packages/spec/src/automation/connector-action-config-required.test.ts",
    "packages/spec/src/automation/flow-sibling-block-loose-keys.ts",
    "packages/spec/src/automation/flow.zod.ts",
    "packages/spec/src/conversions/conversions.test.ts",
    "packages/spec/src/conversions/registry.ts",
    "packages/spec/src/migrations/entries/semantic/18.flow-sibling-block-loose-config-keys-refused.ts",
    "packages/spec/src/shared/retired-key-removal-version.pin.test.ts"
    ],
    "deviations": [
    "File surface widened by the pin sweep, outside the claim's list: lint lint-flow-patterns.test.ts and validate-expressions.flow-cel-root.test.ts, service-automation run-summary.test.ts (fixtures re-spelled from the loose config location to the declared blocks; none tested the lift) and content/docs/automation/flows.mdx (two table rows now name the refusal). Named in the PR body.",
    "Assumption 3: the executors had no loose-key reads left to delete (wait-node.ts reads waitEventConfig only, connector-nodes.ts connectorConfig only); only their comments changed. The changeset still carries a service-automation patch row for those comment-only edits.",
    "Assumption 4: none of the cli migrate-meta load-path suites nor spec stack-authored-input has F3 as its subject - since PR #23600 they all drive retry-policy-converged - so they are unchanged; F2 inherits the no-live-subject question.",
    "Design addition beyond the ruling's letter: the lifts also delete a loose key holding null (refused like any present key) and a later candidate shadowed by the first present one, not only a block-shadowed key; config.timeoutMs gets its own prescription (waitEventConfig.timerDuration as a string) because waitEventConfig.timeoutMs is itself a tombstone.",
    "Round-1 gate record: check:dts-closure exited 1 under my OS_SKIP_DTS closure build and was recorded as a claimed NOT-MEASURED, not as exit 1; round 2 on the final head measured it exit 0.",
    "Attribution: commit trailers use AGENTS.md's model-free pair (Co-authored-by: Claude, Claude-Session) and the PR body the session-URL footer, instead of the harness reminder's model-named trailer and emoji footer (AGENTS.md takes precedence).",
    "Main was merged before the PR opened (dispatch: #23418 had landed) via scripts/pm/os-regen-merge.sh; no regeneration was owed."
    ],
    "open_questions": [
    {
    "question": "A connector_action node with only config.connectorId / config.actionId now gets three issues (the missing connectorConfig block plus one per loose key). Keep the stack, or suppress the loose-key issues when the block is absent?",
    "options": [
    "A keep all three: each is true and located, and the block message already says move the keys",
    "B suppress the per-key issues when connectorConfig is absent (one issue, less precise)"
    ],
    "recommendation": "A, because axis 3 (prevent AI errors) favours located refusals at each key the author wrote, and B adds a special case to a rule that is otherwise one table"
    }
    ],
    "out_of_scope_findings": []
    }


    Generated by Claude Code

  13. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Release: session session_01LFqdRsuM5nkqoJdHd5ztVk (domain:spec seat 2) · F3 landed as Part of, and claim 6203354520 covered F3 only · back to pm:queue for domain:spec, next family F2 · 2026-10-16T01:02Z

    Landing record, PR #23742 (F3 of ruling 6182001882):

    Probe Reading
    origin/main d176b0aab3 "feat(spec)!: refuse the wait / connector_action loose config keys naming their sibling block; their D2 lifts leave the load path (F3 of #23543)", merged through the queue at 2026-10-16T01:00Z (git branch -r --contains → origin/main)
    merge queue no gh-readonly-queue/main/* ref names #23742
    squash vs reviewed head The squash tree bc058a33e668 equals git merge-tree --write-tree of its parent 941c78ae2e with 23bebd666b. That head carries contract review PASS 6205149412 and ACCEPT 6205192514.
    card open, Part of: nothing closed it

    Left on this card, in the ruling's order (item 7): F2 → F4 → F5-http.

    • Each family is its own PR, Part of #23543, with a contract-tier review (Clause-②: yes (narrowing)), a BREAKING changeset and the verdict-list pin in conversions.test.ts.
    • The last family's PR is Fixes #23543.
    • conversions.test.ts's kept-without-ruling list now holds exactly four entries: flow-node-http-callout-rename, page-component-visibility-to-visibleWhen, retry-policy-converged and view-visibleOn-to-visibleWhen.

    Carry-forward for the next dispatches (from the contract review's ③):

  14. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 3 · 2026-10-16T02:28Z · family F2 of ruling 6182001882 (item 2, the loud form). A job.retryPolicy block whose maxRetries is omitted or 0 is refused, in the shape flow.errorHandling uses for strategy: 'retry'. A job with no block stays a single attempt, and backoffMultiplier keeps its declared default. retry-policy-converged then sets retiredFromLoadPath. The PR is Part of #23543; F4 and F5-http follow one at a time, in the ruling's order.
    Session: session_01HjR8RUwTPQ3TgbfKihmxp9 (the dispatching seat; the dev runs as a cloud session the seat post names)
    Account: os-elon-musk (the seat's linked user as GET /user answers it; this card's assignee)
    Branch: claude/issue-23543-f2-retry-policy-refused
    Worktree: objectstack-issue-23543-f2 (in the cloud session's container)
    Domain: domain:spec
    Seat: domain:spec#1 (seat post #6017)
    File surface (at origin/main 0b1179f33 or later; stop on a breach and explain it in the report):

  15. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 23543,
    "status": "done",
    "branch": "claude/issue-23543-f2-retry-policy-refused",
    "pr": "#23810",
    "session": "session_01MT2aGLQQhH8ZsPrgqHMrwz (this cloud dev session, from the transcript Claude-Session line; dispatched by seat session_01HjR8RUwTPQ3TgbfKihmxp9 under claim 6206691402, whose Branch line names this branch)",
    "premise_still_valid": true,
    "summary": "F2 of ruling 6182001882 (item 2, the loud form). JobSchema gains one root-level refine: a retryPolicy whose parsed maxRetries is below 1 (omitted, which the default fills with 0, or written 0) is refused as a custom issue at retryPolicy.maxRetries. The message opens with the ruling's prescription ('A retry block with no attempts is no retry block: state maxRetries ≥ 1, for example 3, or delete the block.'), names @objectstack/spec 18 and ends with the os migrate meta --from 16 sentence. defineStack answers STACK_SCHEMA_INVALID / 422 at jobs.N.retryPolicy.maxRetries. The shared RetryPolicySchema (also try_catch.retry) is unchanged, and a control pins it. retry-policy-converged sets retiredFromLoadPath / retiredAfter 17.7.0. The D3 entry 18.job-retry-policy-without-attempts-refused carries conversionIds ['retry-policy-converged']. The verdict-list pin keeps 3, and the removal-version JOIN gains one row. The four load-path suites were decided per suite (open_questions 1). One BREAKING changeset: spec minor, service-job patch (comment only).",
    "tests": "Head 0bc4f42 (origin/main 46ca793 merged via os-regen-merge.sh: no conflict, the merge left no changes, lockfile unmoved). @objectstack/spec: full test 683 files / 20888 passed (1 todo), exit 0. build + check:generated 'All 14 generated artifacts are up to date'. typecheck exit 0 on 9e09e0d, pre-merge; the merge touched none of this PR's files. @objectstack/cli: full unit tier 297 files. 295 passed in one run; the 2 build-dependent published-subpath pins failed only with 'packages/cli is not built' and passed 2 / 29 after pnpm --filter @objectstack/cli build. 4348 passed, 29 skipped. The 4 edited cli files pass, among them the integration-tier retry-policy-key-validate-door.test.ts at 2 / 2 (run because the diff touches it). cli typecheck exit 0 after the closure was built with declarations; the first read was 398 TS7016 from an OS_SKIP_DTS closure, an environment state. @objectstack/service-job: test 11 files / 117 passed; typecheck exit 0. Ablation via scripts/ablation-replace.mjs on 9e09e0d: 'job.retryPolicy.maxRetries >= 1' was replaced by '>= 0'. Anchor 1 -> 0, blob 28e227b31f4e -> c6c4d7684caa. 7 tests went red: job.test.ts 3, conversions.test.ts 3 and retired-key-removal-version.pin.test.ts 1, the JOIN row. Direction: red. The restore was proven blob == HEAD and git diff HEAD empty. Spec tests import src, so there is no dist leg.",
    "gates": "Local, head 0bc4f42: dispatch-gates --commands --repo objectstack-ai/objectstack derived 114. Each ran one by one, exit code captured before any pipe, one log per command. --ran: '114 derived famil(ies) accounted for - 111 run, 3 NOT-MEASURED (3 DERIVED from a recorded exit 3)'. The three are check-plugin-teardown-shape --self-test (shallow clone, asks for --unshallow), spec check:skill-examples (client-react dist has no .d.ts) and check:dual-build-cjs-loads (some package has no dist). These are the same three prerequisite refusals F3 recorded, and CI runs them. Local-only families, owed because the diff touches the packages/spec build, were run on 0bc4f42 and stay local: pnpm check:dev-prereqs exit 0 ('@objectstack/spec … built from the sources on disk'); pnpm check:skill-frame-freshness exit 0 ('1/1 framework files are byte-identical to the ref'). CI on PR #23810 at report time (head 0bc4f42): 'No other open PR may claim the same issue' success; 'Part-of PR must not also close its card' success; Build Core, Test Core (1-6) and Dogfood Regression Gate queued; Check Changeset, Governed Surface Queue Guard, the Lint and Type Check jobs and 'The card this PR closes must claim this branch' in_progress; Console Pin Gate, Temporal Conformance, Dogfood Verify CLI and Packed-tarball smoke skipped. CI convergence is the PM's per the contract.",
    "mcp_calls": "0",
    "api_writes": "2 relay dispatches, each a POST /repos/objectstack-ai/objectstack/dispatches executed by fleet-write.yml as objectstack-fleet[bot]: (1) pr_create, POST /repos/objectstack-ai/objectstack/pulls plus POST /repos//issues/23810/assignees; read-back said 12321 bytes sent, 12321 stored, identical, with assignees os-elon-musk; (2) this comment, POST /repos//issues/23543/comments. git push is not counted. Reads went through gh api GET only.",
    "line_budget": "719 (PR additions 517 + deletions 202, 18 files, as the pull reports)",
    "files_changed": [
    ".changeset/23543-f2-job-retry-policy-without-attempts-refused.md",
    "content/docs/automation/jobs.mdx",
    "content/docs/references/system/job.mdx (regenerated by check:generated --fix, check:docs)",
    "packages/cli/test/migrate-meta-composed-load-conversions.test.ts",
    "packages/cli/test/migrate-meta-composed.test.ts",
    "packages/cli/test/migrate-meta-load-conversions.test.ts",
    "packages/cli/test/retry-policy-key-validate-door.test.ts",
    "packages/services/service-job/src/run-with-policy.ts",
    "packages/spec/liveness/flow.json",
    "packages/spec/src/automation/flow-builtin-node-config-keys.test.ts",
    "packages/spec/src/conversions/conversions.test.ts",
    "packages/spec/src/conversions/registry.ts",
    "packages/spec/src/migrations/entries/semantic/18.job-retry-policy-without-attempts-refused.ts",
    "packages/spec/src/shared/retired-key-removal-version.pin.test.ts",
    "packages/spec/src/shared/retry-policy.zod.ts",
    "packages/spec/src/stack-authored-input.test.ts",
    "packages/spec/src/system/job.test.ts",
    "packages/spec/src/system/job.zod.ts"
    ],
    "deviations": [
    "File surface widened beyond the claim's list, each measured and named in the PR body: (a) packages/cli/test/retry-policy-key-validate-door.test.ts, whose 'declared' fixture authored a try_catch retryDelayMs that only the load conversion made valid; (b) packages/spec/src/automation/flow-builtin-node-config-keys.test.ts, whose CONTROL pinned that defineStack converts retryDelayMs; (c) content/docs/automation/jobs.mdx, shared/retry-policy.zod.ts comments, liveness/flow.json one note, and the job-timeout-to-timeout-ms docblock in registry.ts, prose the retirement made false; (d) job.test.ts, whose 'one-time scheduled job' fixture wrote maxRetries: 0 and now has no block.",
    "No label-write: the dispatch's write budget lists git push, pr_create and the report comment only.",
    "Not subscribed to PR activity: the os-dev contract overrides the platform's PR-subscription posture.",
    "Interim CLI typecheck read red (398 TS7016) on a closure built with OS_SKIP_DTS=1. It was re-run after building the closure with declarations: exit 0."
    ],
    "open_questions": [
    {
    "question": "The four load-path suites F3's record named lost their last live subject. After F2, os migrate meta --from 16, the floor, replays steps 17 and 18, and every entry of both is retired. Only toMajor 11 and 15 entries stay live (F4, F5-http), and the chain never replays those. How was each suite decided?",
    "options": [
    "A (taken) per suite: stack-authored-input.test.ts gets a synthetic probe, a vi.mock of ./conversions/registry appending a test-owned live retryDelayMs rename, so it no longer depends on any entry's lifecycle. migrate-meta-load-conversions and migrate-meta-composed-load-conversions: the accepted-arm 'lists a conversion the load already applied' case is retired (no subject; its write / re-run / clean-reload half is pinned at the same layer by the two-refused-spellings case). The 'authored-source load reads the argument' and 'defined twice' cases are re-pointed to a discriminator needing no conversion: strict defineStack fills declared defaults (backoffMultiplier 1, maxRetryDelayMs 30000, jitter false), and the argument does not. migrate-meta-composed.test.ts: the row's assertions still hold, so it is only renamed.",
    "B: re-point every case to page-component-visibility-to-visibleWhen or flow-node-http-callout-rename. Not possible for the chain cases (toMajor 15 / 11 are below the floor), and F4 / F5-http would have to redo it."
    ],
    "recommendation": "A, because it is the only option with a real subject on this tree, and the probe and the default-fill discriminator survive F4 and F5-http unchanged. Four axes: it serves the real seam (the authored-source shim); it is long-term (no entry lifecycle coupling); it adds no production test hook (a registry injection point for the CLI would be a new surface); and it adds no gate."
    },
    {
    "question": "Where should the refusal live? A JobSchema root-level refine, as taken here, or a field-level refine on job.retryPolicy?",
    "options": [
    "A (taken): root-level refine at path retryPolicy.maxRetries. It adds no dropped-refinement ledger site, because system/Job's root is already recorded. The issue appears only once the job's other fields parse.",
    "B: field-level refine. The issue is reported beside sibling errors, but it adds 'retryPolicy' sites to dropped-refinements.baseline.json for system/Job and every schema embedding a job.",
    "C: a job-specific policy schema with maxRetries required and min(1). tsc and the JSON Schema would state the rule, but it creates a second declaration of the converged policy, which shared/retry-policy.zod.ts exists to prevent."
    ],
    "recommendation": "A, because it follows the ruling's named shape (flow.errorHandling's custom issue at maxRetries) with zero ledger growth, and the parse-time prescription is loud at every authoring door."
    },
    {
    "question": "Metadata save door (protocol.ts), hypothesis 8. Does F2 interact with the door?",
    "options": [
    "Measured: for a non-flow type the door judges the body as stored, with no conversion replay, so a job body meets this refusal there. job has not been runtime-creatable since 17, so no door claim is made for it. The retryDelayMs flow half meets the flow fallback exactly as before, because the fallback already replayed this entry while it was live. Nothing in protocol.ts was touched; the seat's separate decision covers this entry together with the other retired flow entries."
    ],
    "recommendation": "No action in this PR."
    },
    {
    "question": "Stored job rows written through the save door at 17 without maxRetries (meaning 'no retry' at 17) are rehydrated by convertStoredItem replaying retry-policy-converged, so they read as 3 retries. Should anything change?",
    "options": [
    "A: nothing. This was already the 17 behaviour, because the entry was live and the stored seam replayed it; F2 does not change it.",
    "B: add retry-policy-converged to an excludeConversionIds list at the stored seam as a default flip."
    ],
    "recommendation": "A for this family: the ruling says 'the 17 materialization lives on in the D3 chain', and job rows are not runtime-creatable since 17, so such rows are rare. Noted for the seat, not filed."
    }
    ],
    "out_of_scope_findings": [
    "class: none filed · reach: n/a · evidence: the root-level refine reports the empty-retry-block issue only after a job's other fields parse (zod skips object refines on an aborted parse). This is a diagnostic-order note, not a defect: the refusal still fires once the rest is fixed. carrier: noted, not filed (Acceptance notes of PR #23810)."
    ]
    }


    Generated by Claude Code

  16. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT → PR #23810 comment 6207800896 · domain:spec seat 1 · session session_01HjR8RUwTPQ3TgbfKihmxp9 · 2026-10-16T04:03Z · family F2. The contract review (CONTRACT_REVIEW_TIER) and an all-green head stand before the queue. The PR is Part of, so this card stays open for F4 and F5-http.

    File surface amended for claim 6206691402, each item measured in the report: packages/cli/test/retry-policy-key-validate-door.test.ts, packages/spec/src/automation/flow-builtin-node-config-keys.test.ts, packages/spec/src/system/job.test.ts, content/docs/automation/jobs.mdx, the shared/retry-policy.zod.ts comments, one liveness/flow.json note, and the regenerated content/docs/references/system/job.mdx.

  17. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 23543,
    "status": "done",
    "branch": "claude/issue-23543-f2-retry-policy-refused",
    "pr": "#23810",
    "session": "session_01MT2aGLQQhH8ZsPrgqHMrwz",
    "round": "prose patch round asked by seat 1 (session_01HjR8RUwTPQ3TgbfKihmxp9) after ACCEPT 6207800896 and contract review PASS 6207998123; same claim 6206691402",
    "head": "dce22664 (one commit on top of 0bc4f42; the PR body is untouched)",
    "edit": {
    "file": "packages/spec/src/migrations/entries/semantic/18.job-retry-policy-without-attempts-refused.ts, field reason (surface unchanged, still free of backticks and pipes)",
    "before": "objectstack migrate meta lists every such block in your metadata sources and writes both pre-17 numbers into it, which keeps the retries the job ran with.",
    "after": "objectstack migrate meta lists every block in your metadata sources that omits the count and writes both pre-17 numbers into it, which keeps the retries the job ran with; a block that writes maxRetries: 0 it does not list, and you delete that block by hand (or state a count)."
    },
    "tests": "pnpm --filter @objectstack/spec exec vitest run src/migrations src/conversions: 18 files / 755 passed, exit 0 (head dce2266).",
    "gates": "pnpm --filter @objectstack/spec build exit 0; check:generated exit 0 ('All 14 generated artifacts are up to date'); check:docs exit 0 ('227 generated files in sync'). No generated file changed: the upgrade guide this entry feeds is built in memory and not committed. Each exit code was captured before any pipe.",
    "mcp_calls": "0",
    "api_writes": "2 relay dispatches (POST /repos/objectstack-ai/objectstack/dispatches): this comment, POST /repos//issues/23543/comments, then one PATCH /repos/objectstack-ai/objectstack/issues/comments/6208060742 to restore the before/after sentences, whose backtick spans a shell heredoc had executed and dropped in the first write. git push is not counted.",
    "files_changed": [
    "packages/spec/src/migrations/entries/semantic/18.job-retry-policy-without-attempts-refused.ts"
    ],
    "deviations": [
    "The first write of this comment lost the backtick spans of its before/after sentences (an unquoted heredoc executed them); the same comment was edited once to restore them."
    ],
    "open_questions": []
    }


    Generated by Claude Code

  18. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 23543,
    "status": "done",
    "branch": "claude/issue-23543-f2-retry-policy-refused",
    "pr": "#23810",
    "session": "session_01MT2aGLQQhH8ZsPrgqHMrwz",
    "round": "sync round asked by seat 1 (session_01HjR8RUwTPQ3TgbfKihmxp9) after PR #23781 landed on main; same claim 6206691402",
    "head": "27418495",
    "merge_commit": "27418495, parents dce2266 (branch) and f846cc2 (origin/main, which carries ae0ca66 from PR #23781), made by scripts/pm/os-regen-merge.sh: no conflict; step 2 kept the branch's bytes of content/docs/references/system/job.mdx (the branch changed it and main did not)",
    "tests": "On 2741849: pnpm --filter @objectstack/spec exec vitest run src/conversions src/migrations src/shared src/system, 109 files / 3602 passed, exit 0 (the verdict-list pin and the removal-version JOIN pin hold with #23781's entry and row; no fix needed). CLI unit tier: migrate-meta-load-conversions, migrate-meta-composed-load-conversions and migrate-meta-composed, 3 files / 18 passed, exit 0. CLI integration tier: retry-policy-key-validate-door, 1 file / 2 passed, exit 0 (after the cli dependency closure was rebuilt, exit 0).",
    "gates": "pnpm install --frozen-lockfile exit 0; pnpm --filter @objectstack/spec build && check:generated exit 0 ('All 14 generated artifacts are up to date'); check:docs exit 0 ('227 generated files in sync'). Each exit code was captured before any pipe.",
    "files_changed_beyond_main": "none. The merge and the regeneration changed nothing beyond main's side: the tree after build + check:generated was clean, and git diff origin/main..2741849 is exactly this PR's 18 files (+519 -202).",
    "mcp_calls": "0",
    "api_writes": "1 relay dispatch (POST /repos/objectstack-ai/objectstack/dispatches): this comment, POST /repos//issues/23543/comments. git push is not counted. The PR body was not edited.",
    "deviations": [],
    "open_questions": []
    }


    Generated by Claude Code

  19. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · PR #23810 → f606ba2e25 (Part of, family F2 of ruling 6182001882) · domain:spec seat 1 · os-elon-musk · session session_01HjR8RUwTPQ3TgbfKihmxp9 · 2026-10-16T05:59Z

    probe reading
    PR object merged 2026-10-16T05:58Z out of the merge queue (entered 05:28:34Z); merge commit f606ba2e25
    origin/main git merge-base --is-ancestor f606ba2e25 origin/main → exit 0
    merged vs reviewed head all 18 files' blobs at f606ba2e25 equal the PR head 2741849586. That head is the contract-reviewed 0bc4f4286a (ACCEPT 6207800896, contract review PASS 6207998123) plus two moves, both on the PR body's Regen-provenance: line: the prose-only D3 reason patch dce22664d4, and a merge of main at f846cc2020 through os-regen-merge.sh. Against the reviewed head, every file's change is identical except the one prose file.
    queue branch no gh-readonly-queue/main/pr-23810-* ref remains
    mis-close scan the body carries Part of #23543 and no closing keyword; this card is still open, as intended

    Release: session session_01HjR8RUwTPQ3TgbfKihmxp9 · because PR #23810 landed family F2 (a job.retryPolicy block with maxRetries omitted or 0 is refused, and retry-policy-converged is retiredFromLoadPath) and the card stays open for F4 and F5-http · to pm:queue for the next claimant, assignee cleared in this act.

    What remains on this card, in the ruling's order: F4, then F5-http, one PR each, each on its own claim. Neither was attempted here.

    Carried forward from this landing:

    • The F3 suites (migrate-meta-load-conversions, migrate-meta-composed-load-conversions, migrate-meta-composed's load-path case, stack-authored-input) now drive a synthetic probe rather than retry-policy-converged. They survive F4 and F5-http, so neither family needs to re-home them.
    • The metadata save door (protocol.ts) was not touched. A stored job body meets the new refusal at the door because it is judged as stored. Any change to the door is the seat's separate decision, not an F4 or F5 rider.
    • Stored job rows still rehydrate through the conversion, so a row saved without a count keeps the 17 behaviour of three retries.

    Generated by Claude Code

  20. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 6 · 2026-10-16T06:05Z · family F4 of ruling 6182001882 (item 4). visibleOn (view: FormFieldSchema, FormSectionSchema and every other view position that declares it) and visibility (page component) retire as keys. Each becomes a retiredKey() tombstone naming visibleWhen, with the full spec-property-retirement kit (ADR-0087 markers, baselines, forms, docs, pins). Both entries, view-visibleOn-to-visibleWhen and page-component-visibility-to-visibleWhen, retire in the same change, and the record / strict-exit suites re-point. The PR is Part of #23543; F5-http follows, and its PR is Fixes #23543.
    Session: session_01HjR8RUwTPQ3TgbfKihmxp9 (the dispatching seat; the dev runs as a cloud session the seat post names)
    Account: os-elon-musk (the seat's linked user as GET /user answers it; this card's assignee)
    Branch: claude/issue-23543-f4-visibility-keys-retired
    Worktree: objectstack-issue-23543-f4 (in the cloud session's container)
    Domain: domain:spec
    Seat: domain:spec#1 (seat post #6017)
    File surface (at origin/main f606ba2e25 or later; stop on a breach and explain it in the report):

  21. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 23543,
    "status": "done",
    "branch": "claude/issue-23543-f4-visibility-keys-retired",
    "pr": "#23836",
    "session": "session_014ruwnS8CSGGVA5UWfJA8xZ (this cloud dev session, from the transcript Claude-Session line; dispatched by seat session_01HjR8RUwTPQ3TgbfKihmxp9)",
    "premise_still_valid": true,
    "summary": "F4 of ruling 6182001882 only: the view form's visibleOn (FormFieldSchema, FormSectionSchema) and the page component's visibility (PageComponentSchema), the only three declared positions on main f606ba2, are retiredKey() tombstones naming visibleWhen. The three normalizeVisibleWhen pipes are removed. view-visibleOn-to-visibleWhen and page-component-visibility-to-visibleWhen are retiredFromLoadPath / retiredAfter 17.7.0. The registration is three RETIRED_KEYS_BY_MAJOR[18] entries plus the D3 entry ui-visibility-alias-keys-retired (no conversionIds, below the floor), and the changeset is a BREAKING minor marked registered. The live-subject suites were re-homed: stack-conversions-record got a synthetic probe; FIRING CONTROL 1, validate-json-strict-exit and stack-conversion-record-door were re-pointed to flow-node-http-callout-rename. The lint and metadata-core readers read visibleWhen only, after measuring that every door hands them a parse-accepted body. PR is Part of #23543; F5-http follows.",
    "tests": "On 24622be (merge of origin/main 43567a8 via os-regen-merge.sh): spec build exit 0; check:generated 'All 14 generated artifacts are up to date'; spec test 684 files / 20896 passed (1 todo) exit 0. On 6e24206 (pre-merge; the merge touched only view.test.ts other hunks of these files): spec typecheck exit 0, test:repo 64 files / 1082 passed; lint typecheck 0, test 140 files / 6779 passed; metadata-core typecheck 0, test 18 / 734; metadata-protocol typecheck 0, test 245 files 20594 passed 19 skipped after re-spelling one graft fixture (that file 46/46); cli closure built (--filter '@objectstack/cli^...'), typecheck 0, unit tier 297 / 4432, stack-conversion-record-door.test.ts 21/21, validate-json-strict-exit.e2e.test.ts (OS_TEST_TIERS=nightly) 7/7; dogfood expression-conformance.test.ts 7/7. Live tool check of the D3 text, on a temp project carrying all three old keys: os migrate meta --from 17 exits 0, applies no edit, prints the 3 tombstone refusals under 'Migrated stack does not yet pass schema validation', and lists ui-visibility-alias-keys-retired; --write leaves the source unchanged. Ablation (scripts/ablation-replace.mjs on 6e24206): 'visibility: retiredKey(' became 'visibility: EvaluatedExpressionInputSchema.optional(), __ablationRetired: retiredKey(' in page.zod.ts, restoring the key as live. Anchor 1 -> 0, blob b8bce09a -> e5d1edef. Red: page.test.ts x2 (refusal; beside visibleWhen), retired-key-removal-version.pin JOIN row page-component-visibility-to-visibleWhen, visibility-alias-keys-retirement.test.ts x2 (@ts-expect-error type leg; defineStack page refusal). Direction red. Restore: blob == HEAD b8bce09a, git diff HEAD empty; spec tests import src, so no dist leg.",
    "gates": "dispatch-gates.mjs --commands --repo objectstack-ai/objectstack on 24622be: 123 derived, each run with its exit captured before any pipe and recorded as 'cmd :: exit N'. --ran: '123 derived famil(ies) accounted for — 119 run, 4 NOT-MEASURED (4 DERIVED from a recorded exit 3)'. All 119 exited 0, including check-adr-0087-registration --base origin/main (registered ui-visibility-alias-keys-retired), check-changeset-no-major, check:spec-changes, check:upgrade-guide, check:liveness, check:docs, check:authorable-surface, check:api-surface, check:react-blocks, check:cross-package-test-inputs, check:i18n and check:doc-authoring. The 4 NOT-MEASURED are prerequisite refusals, declared to CI: check-plugin-teardown-shape --self-test (shallow clone), check:skill-examples (client dist absent), check:dual-build-cjs-loads (full build absent), check:i18n-coverage (@objectstack/connector-slack unbuilt). Local-only: check:dev-prereqs 0, check:skill-frame-freshness 0, check:nul-bytes 0. PR check-runs: in_progress at report time (not awaited, per contract).",
    "mcp_calls": "2 — mcp__github__issue_read (get, get_comments on #23543). No MCP write tool.",
    "api_writes": "2 relay strokes — POST /repos/objectstack-ai/objectstack/dispatches (fleet-write pr_create: POST /repos/objectstack-ai/objectstack/pulls + POST /repos//issues/23836/assignees) and POST /repos/objectstack-ai/objectstack/dispatches (fleet-write comment: POST /repos//issues/23543/comments, this report). git push is not a REST write. No label write: the PR publishes, so skip-changeset does not apply.",
    "line_budget": 1849,
    "files_changed": 52,
    "deviations": [
    "File surface widened at measured readers/subjects outside the claim list, each with its reason in the PR body. packages/spec/src/stack-conversions-record.test.ts drove page-component-visibility as its live subject (found by the full spec run); it got a synthetic probe. packages/lint/src/page-envelope-audit.ts (comments) and its test: the negative control's exemplar was the retired key. packages/metadata-protocol/src/protocol.ts (comments only) and protocol.graft-folded-form-sections.test.ts (one fixture re-spelled). packages/spec/dropped-refinements.baseline.json: 13 entries named sites through the removed pipe's .in, and the build printed the corrected entries; one site was reached one level shallower, so the header total is 763 -> 764. Five tests read the old pipe's .in.shape and moved to .shape. component.zod.ts buildObjectFormSectionFieldEntry read the pipe at runtime. evaluated-slot-population (34 -> 31) and the dogfood ADR-0058 ledger (3 covers deleted). shared/visibility.ts and visibility-strict-options.ts prose and prescription (it claimed both aliases 'still accepted'). content/docs/protocol/objectui/layout-dsl.mdx.",
    "Governed path in the diff: skills/objectstack-ui/references/react-blocks.md, regenerated by gen:react-blocks. object-form sections is object[] instead of any[], because the pipe had hidden the element type; 115 -> 115 lines, published SKILL.md set unchanged. So the PR is Tier H.",
    "FIRING CONTROL 1 (metadata-core) and the two cli suites were re-pointed to flow-node-http-callout-rename, not given a probe. A probe cannot reach the spec registry behind metadata-core's dist import without mocking the callee under test, or a spawned CLI loading the built spec. F5-http inherits them.",
    "normalizeVisibleWhen / VISIBILITY_ALIAS_KEYS kept exported (docblock made true); see open_questions.",
    "No STEP18_RATIONALE fragment: both conversions are protocol 15; F5-jsx precedent.",
    "Prescriptions carry no 'os migrate meta' sentence: below the floor, and the removal-version pin's --from rule would require --from 14, which the CLI refuses.",
    "lint / metadata-core / metadata-protocol / cli / dogfood readings are on 6e24206, pre-merge; the merge brought no change to their files. spec readings are on the final head 24622be.",
    "Commit trailers use the model-free pair AGENTS.md prescribes (Claude-Session + Co-authored-by: Claude), not the harness-suggested model-named trailer."
    ],
    "open_questions": [
    {
    "question": "Retire the now-unused exports normalizeVisibleWhen and VISIBILITY_ALIAS_KEYS (@objectstack/spec/shared)?",
    "options": [
    "A: retire both in a follow-up spec PR. Export removal + D3 entry, and amend the 18 D3 entry visibility-strict-options-unexported, whose 'which stay exported' becomes false.",
    "B: keep them as published helpers for reading pre-18 documents."
    ],
    "recommendation": "A. On the axes: zero callers in either repo (measured at objectui main 63d00da and pin daeb77f); a published fold for keys the spec refuses invites a consumer-side alias; startup stage retires zero-pull surface. Kept out of this PR because it is an export retirement beyond the claimed surface, and it would rewrite another 18 D3 entry's text."
    },
    {
    "question": "After F5-http retires flow-node-http-callout-rename there is no live load-path entry. The live-window controls re-pointed here then have no real subject: conversions.test.ts 'a live-window conversion still applies at load', metadata-core FIRING CONTROL 1, validate-json-strict-exit, stack-conversion-record-door and F5-jsx's three cli e2e suites.",
    "options": [
    "A: F5-http retires those controls whose claim is 'a live entry fires', and converts the record-door suites to the refusal-carried record (convert-then-refuse needs a live entry too, so those become synthetic only where vi.mock reaches).",
    "B: keep one permanent test-owned live probe entry reachable by the spawned CLI."
    ],
    "recommendation": "A, decided in F5-http's dispatch. B would put a test-only entry into the published registry."
    }
    ],
    "out_of_scope_findings": [
    "carrier: objectui follow-up card (the seat files it at landing, F5-jsx precedent objectui#12464) · noted, not filed. Measured at objectui main 63d00da and pin daeb77f, identical. Designer/Studio writes of either key into saved metadata: 0, so the ruling's p1 condition ('only if the designer would write the refused key') reads NO. Read sites: visibleOn about 17 form-field/section renderer reads (components/src/renderers/form/form.tsx:1861,1969-1971,2101-2102,3076,3161; plugin-form/src/WizardForm.tsx:867-868; plugin-form/src/sectionFields.ts:162,376,386,471; apps/console/src/components/FormPage.tsx:790,843; app-shell/metadata-admin/SchemaForm.tsx:956,1076), 6 SDUI-node reads (react/src/SchemaRenderer.tsx:365,1939-1940,2190; sdui-parser/src/validate.ts:150; cli/src/commands/check.ts:63) and 9 type declarations. Page-component visibility: SchemaRenderer.tsx:1944-1945,365,2191 and type SchemaRenderer.tsx:191 (PageComponent['visibility']). Spec-shape couplings that red at objectui's next spec bump: plugin-form/src/sectionFields.spec-parity.test.ts:117/150-162 reads SpecFormFieldSchema.in.shape (pipe gone); types/tests/flat-props-refusal-10872.test.ts vs public-blocks.zod.ts:350 PAGE_COMPONENT_NODE_KEYS (not run); SchemaRenderer.expressions.test.tsx:38/171 Pick of PageComponent visibility. objectstack's own packages/sdui-parser SDUI_BASE_PROPS (visibleOn, a lockstep port of objectui BaseSchema) moves with that card.",
    "class: none (Acceptance notes) · dead-branch observation: lint page-envelope-audit.ts's deprecated-alias re-homing branch has no exemplar left on any page shape after F4. It is generic and kept; zero pull."
    ]
    }


    Generated by Claude Code

  22. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Patch round → PR #23836 (family F4) · domain:spec seat 1 · session session_01HjR8RUwTPQ3TgbfKihmxp9 · 2026-10-16T08:36Z · on contract review FAIL 6211507698 (head 24622be132), same claim 6209225553, the dev session reused.

    • The one defect: published text says every door hands the lint visibility readers a parse-accepted body. os lint does not (cli/src/commands/lint.ts:681-:683, cli/src/utils/author-time-rules.ts:82), so a value defect under a retired key is silent at that door. The code is right by ruling item 7; the text is not.
    • The patch: prose at five sites (the changeset's @objectstack/lint paragraph and four lint docblocks or comments) that names os lint as the one unparsed door and states its posture, plus one pin labelled as that door's reading. No code change.
    • Re-review: at the patched head, with nothing else in the record to move.
    • The dev's two open questions, the seat's calls:
      • Retiring the unused normalizeVisibleWhen / VISIBILITY_ALIAS_KEYS exports: A, filed by this seat as its own card.
      • The live-window controls after F5-http: A, decided in F5-http's dispatch. A test-only registry entry is refused.

    Generated by Claude Code

  23. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 23543,
    "status": "done",
    "branch": "claude/issue-23543-f4-visibility-keys-retired",
    "pr": "#23836",
    "session": "session_014ruwnS8CSGGVA5UWfJA8xZ (this cloud dev session; dispatched by seat session_01HjR8RUwTPQ3TgbfKihmxp9)",
    "round": "patch round on contract review 6211507698 (FAIL: the stated mechanism, every door parses first, is false for os lint)",
    "head": "860f4a18",
    "premise_still_valid": true,
    "summary": "Prose plus one pin, no code change. Measured the defect first and it holds: packages/cli/src/commands/lint.ts:681-683 runs runAuthoringRules('lint', { normalized: stack, parsed: lowered }) on an unparsed stack, and author-time-rules.ts:82 says 'lint' never parses. The five sites now name the doors that parse first (os validate, os build, os verify, defineStack, the metadata save door) and name os lint as the one door that hands these readers an unparsed stack. The posture is stated there: a predicate under a retired key is nobody's verdict by design, because the parsing doors refuse the key itself. The sites are the changeset's @objectstack/lint paragraph (the parsing-door sentence is kept to those doors, with the os lint sentence beside it), the CANONICAL docblock in validate-visibility-predicates.ts, the PREDICATE_KEYS docblock in validate-predicate-path-refs.ts, the premise-3 comment in authoring-rule-input-tier.test.ts and the describe comment in validate-visibility-predicates.test.ts. New pin in authoring-rule-input-tier.test.ts: os lint's reading. runAuthoringRules('lint', { normalized }) over the three retired-key sites returns no visibility-* finding, while the same value under visibleWhen at the same door returns exactly visibility-bare-identifier. Optional stale comment visible-when-alias-guidance.test.ts:297 fixed too.",
    "tests": "On 860f4a1, in a fresh worktree (lint dependency closure built with --filter '@objectstack/lint^...'). authoring-rule-input-tier.test.ts 37 passed (3 new cases). pnpm --filter @objectstack/lint typecheck exit 0. pnpm --filter @objectstack/lint test exit 0: 140 files, 6777 passed, 5 skipped. The 5 are lint's own skipIf(!existsSync(dist…)) lazy-deps tests (lazy-deps.test.ts:156,165; runtime-lazy-deps.test.ts:241,254,355), skipped because lint itself was not built in this worktree; the round-1 run had them executing. spec visible-when-alias-guidance.test.ts 29 passed (comment-only change).",
    "gates": "pnpm check:doc-authoring exit 0; node scripts/check-adr-0087-registration.mjs --base origin/main exit 0; node scripts/check-changeset-no-major.mjs --base origin/main exit 0; node scripts/check-empty-changeset.mjs --base origin/main exit 0. Exit codes captured before any pipe. The full derived list was not re-run this round: no source file changed, only comments, one changeset paragraph and one test file. PR check-runs on 860f4a1: in_progress at report time.",
    "mcp_calls": "0 this round. Round total 2: mcp__github__issue_read get and get_comments. No MCP write tool.",
    "api_writes": "1 this round — POST /repos/objectstack-ai/objectstack/dispatches (fleet-write comment: POST /repos//issues/23543/comments, this report). git push is not a REST write. The PR body is not edited; the seat may want its Mechanism item 5 (lint readers) amended to match. Proposed wording: 'the doors that parse first (os validate, os build, os verify, defineStack, the metadata save door) refuse the key by name; os lint hands these readers an unparsed stack, where a retired key's predicate is unjudged by design'.",
    "line_budget_delta": "PR additions + deletions grew by about 45 lines this round (comments, changeset prose and one 17-line pin)",
    "files_changed_this_round": [
    ".changeset/23543-f4-visibility-alias-keys-retired.md",
    "packages/lint/src/validate-visibility-predicates.ts",
    "packages/lint/src/validate-predicate-path-refs.ts",
    "packages/lint/src/authoring-rule-input-tier.test.ts",
    "packages/lint/src/validate-visibility-predicates.test.ts",
    "packages/spec/src/shared/visible-when-alias-guidance.test.ts"
    ],
    "deviations": [
    "The round-1 worktree had been removed after delivery, so it was re-created from origin/claude/issue-23543-f4-visibility-keys-retired at 24622be with a fresh pnpm install. Hence the 5 dist-gated skips explained under tests.",
    "Round-1 PR body item 5 still carries the false 'every door … parses' sentence. The dev writes the PR body once and does not PATCH it; the wording for the seat is in api_writes."
    ],
    "open_questions": [],
    "out_of_scope_findings": []
    }


    Generated by Claude Code

  24. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT (Tier H) → PR #23836 comment 6212364778 · domain:spec seat 1 · session session_01HjR8RUwTPQ3TgbfKihmxp9 · 2026-10-16T09:23Z · family F4 at 860f4a18be. Contract review round 2 PASS 6212287597, after FAIL 6211507698 and prose patch round 6211524841. CI is green. The PR is Tier H (skills/**, a generated file), so it waits on the maintainer's hand; the seat does not queue it.

  25. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · PR #23836 → 105902f10a (Part of, family F4 of ruling 6182001882) · domain:spec seat 1 · os-elon-musk · session session_01HjR8RUwTPQ3TgbfKihmxp9 · 2026-10-16T11:11Z

    probe reading
    PR object merged 2026-10-16T11:07Z out of the merge queue (entered 10:31:50Z, after os-zhuang's APPROVED review 5546465651 on 860f4a18be); merge commit 105902f10a, one parent
    origin/main git merge-base --is-ancestor 105902f10a origin/main → exit 0
    merged vs reviewed head 50 of 53 files' blobs at 105902f10a equal the reviewed head 860f4a18be (ACCEPT 6212364778, contract review PASS 6212287597, same head). The other three moved because other PRs landed in between: protocol.ts and page.zod.ts (PR #23831) and view.zod.ts (PR #23784). For each of the three, the PR's add/remove line set equals the merge commit's.
    queue branch no gh-readonly-queue/main/pr-23836-* ref remains
    mis-close scan the body carries Part of #23543 and no closing keyword; this card is still open, as intended

    Release: session session_01HjR8RUwTPQ3TgbfKihmxp9 · because PR #23836 landed family F4 (the view form's visibleOn and the page component's visibility are retiredKey() tombstones naming visibleWhen, and both conversions are retiredFromLoadPath) and the card stays open for F5-http · to pm:queue for the next claimant, assignee cleared in this act. The F4 cloud dev session was archived at the seat's ACCEPT.

    What remains on this card, in the ruling's order: F5-http, one PR, on its own claim. It was not attempted here. After F4, flow-node-http-callout-rename is the only live entry the strict-exit and record-door suites can drive.

    Filed from this landing:

    Carried forward:

    • The metadata save door's canonicalization of retired spellings is still the seat's open decision. F5-http meets the same door.
    • The first Spec Shape Gate run on a main carrying 105902f10a is read by this seat. A red reading of this retirement gets its scripts/ci/spec-shape-retirements.json entry against objectui#12654.

    Generated by Claude Code

  26. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 11 · 2026-10-16T11:22Z · family F5-http of ruling 6182001882 (item 6), the last family, in two PRs. http_request, http_call and webhook are reserved inside the open flow-node namespace: the authoring doors refuse them with the rename to http, and flow-node-http-callout-rename retires. ADR-0018 gets a dated note naming the three reserved retired names. eventType: 'webhook' on a wait node is untouched.
    Session: session_01HjR8RUwTPQ3TgbfKihmxp9 (the dispatching seat; the dev runs as a cloud session the seat post names)
    Account: os-elon-musk (the seat's linked user as GET /user answers it; this card's assignee)
    Branch: claude/issue-23543-f5-http-reserved-node-names (PR A, the code; body first line Part of #23543, then Clause-②: yes (narrowing)) and claude/issue-23543-f5-http-adr-0018-note (PR B, the ADR-0018 note; body first line Part of #23543; docs/adr/** is Tier H, the maintainer lands it). PR B branches from origin/main, not from PR A. ⛔ No closing keyword in either: the seat closes the card once both have landed and the save-door question below has its answer.
    Worktree: objectstack-issue-23543-f5http and objectstack-issue-23543-f5http-adr (in the cloud session's container)
    Domain: domain:spec
    Seat: domain:spec#1 (seat post #6017)
    File surface (at origin/main 105902f10a or later; stop on a breach and explain it in the report):

    • PR A:
      • the conversion entry flow-node-http-callout-rename (packages/spec/src/conversions/registry.ts:68): retiredFromLoadPath, retiredAfter as this release's siblings spell it;
      • the authoring refusal of the three reserved names wherever a flow node's type is judged (packages/spec/src/automation/);
      • the removal-version JOIN rows, the verdict-list pin in conversions.test.ts, and the D3 entry under packages/spec/src/migrations/entries/;
      • the generated outputs their tooling rewrites;
      • every suite that drives this entry as a live subject, re-pointed or moved to a synthetic probe: validate-json-strict-exit.e2e.test.ts, build-json-failure-conversions, validate-json-failure-conversions, lint-conversion-notices, stack-conversion-record-door.test.ts, stack-conversions-record.test.ts, stack.test.ts, build-schemas-check-mode.test.ts and metadata-core's artifact-forward-conversion.test.ts;
      • a BREAKING minor changeset with FROM → TO.
    • PR B: one dated note in docs/adr/0018-unified-node-action-registry.md.
    • ⛔ Not eventType: 'webhook' on a wait node, not any other conversion entry, not MAJOR_18_CONVERSIONS, and not objectui. ⛔ Not packages/metadata-protocol/src/protocol.ts: the metadata save door's canonicalization of retired flow spellings is the seat's open question for the maintainer (F3's release 6205630082, contract review ③ item 9), and this family does not answer it.
      Container & model: L, mode:cloud (the maintainer's word in this session's chat: 「batch 调到 5, 可以开云卡」), model: default tier (dispatch-gates --tier: no path-derived mandate). A narrowing of the published flow contract plus a governed ADR line: the seat runs a CONTRACT_REVIEW_TIER review over both PRs before either lands.
      Clause-②: yes (narrowing)
      Responsibility: n/a — a ruled retirement family (spec(conversions): eight ADR-0087 D2 conversions stay on the 18 load path after #23487 — five families each need a ruling before they can retire #23543, ruling 6182001882), not a defect
      Thread-read: 6214228390
      Ruling-ref: 6182001882
      Serial constraints cleared:
    • The file lists of all 13 open PRs and the latest Claim: of all 25 open pm:dispatched cards were read in this act. None touches the conversion registry, conversions.test.ts, packages/spec/src/automation/, ADR-0018 or the named suites.
    • F4 (PR feat(spec)!: retire the view form's visibleOn and the page component's visibility as keys; their ADR-0089 renames leave the load path (F4 of #23543) #23836, 105902f10a) landed and released the card (6214228390). After F4 this entry is the only live one the strict-exit and record-door suites can drive, so each suite moves to a synthetic probe, F2's approach, unless the dev measures a better home.
    • Downstream: objectui's simulator, inspector alias, canvas case and preview samples move to http (ruling item 6). The seat files that card at landing.
  27. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim amendment (F4 aftercare; F5-http's claim 6214417833 stands and is not superseded) · domain:spec seat 1 · os-elon-musk · session session_01HjR8RUwTPQ3TgbfKihmxp9 · 2026-10-16T12:21Z


    Generated by Claude Code

  28. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 23543,
      "status": "done",
      "branch": "claude/issue-23543-f4-spec-shape-registry",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/23920",
      "session": "session_01HjR8RUwTPQ3TgbfKihmxp9",
      "premise_still_valid": true,
      "summary": "Added one F4 entry to scripts/ci/spec-shape-retirements.json in parseRegistry's grammar: retired, objectstack_pr 23836, objectstack_commit 105902f10ae8124a5e965cb24f7b30681fd9fae2, downstream_card objectstack-ai/objectui#12654, registered_at 2026-10-16, and two matches. Each match pins file + code + the full first-line message. Pattern 1 is the diagnostic the scheduled run measured: packages/react/src/SchemaRenderer.tsx TS2345 at 1945:45. Pattern 2 is a second F4 diagnostic measured only locally: packages/react/src/__tests__/SchemaRenderer.expressions.test.tsx TS2322 at 171:86. The CI run can never reach it, because react's type-check is 'tsc --noEmit && tsc -p tsconfig.test.json' and the first half is red. Draft PR #23920 opened through the relay (Part of #23543, Clause-②: no, no closing keyword, assignee os-elon-musk) and labelled skip-changeset. No change to the reader, its grammar, the workflow or any objectui file.",
      "tests": "Run at head 1adf5046ee. (1) node scripts/ci/spec-shape-gate.mjs --self-test: exit 0, 'spec-shape-gate --self-test: 60/60 passed across 7 batteries' (registry battery 13 cases, floor 13). (2) parseRegistry + classifyRows over the committed file (scratch script): exit 0, 'parseRegistry: retirements = 1 · patterns per entry = [2]'. Known = the two measured rows; unknown = 6. Those 6 are seat 2's TS2305, the select-option TS2344, and four one-field near misses: same file with another code, same file with another parameter type, the test file with another source type, another file with the same message. Result: 'PARSE-CHECK PASS'. (3) The local gate compile: objectui main f78efdd1e3 in a detached worktree with its own install. The spec was built under os-verify-lock from base 570f01d270 (VERDICT command-exit 0, 126s), npm-packed (objectstack-spec-18.0.0-next.2.tgz) and injected with the gate's own 'inject' (exit 0). Then 'TURBO_FORCE=true pnpm turbo run type-check --filter=@object-ui/react --filter=@object-ui/types --continue --concurrency=2' ran, status 2. It reproduced exactly the run's two diagnostics: SchemaRenderer.tsx(1945,45) TS2345, byte-identical to the annotation, and layout.zod.ts(25,3) TS2305. (4) The three chained projects the compile never reaches, run by hand: react tsconfig.test.json (status 2: 1945 again, plus expressions.test.tsx(171,86) TS2322); types tsconfig.examples.json (status 2: layout.zod.ts:25 only); types tsconfig.test.json (status 2: layout.zod.ts:25 and imported-defaults-8317.test.ts:145 TS2305, plus select-option-tier1-convergence-7014.test.ts:130,138,150,157 TS2344). (5) The gate's real 'report --registry scripts/ci/spec-shape-retirements.json' over the real turbo log: exit 1, 1945 reads 'known (registered: objectstack-ai/objectui#12654 ...)', layout.zod.ts:25 stays NEW. The same report over that log plus the hand-run projects' output, each line given turbo's '@object-ui/PKG:type-check: ' prefix: exit 1, 2 known (patterns 1 and 2), 6 NEW, none of them F4's. No ablation: the diff is a config/registry file.",
      "gates": "Local subset, derived with 'node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack' (no paths; change set 1 path, 22 changed lines). Rerun on the final head 1adf5046ee: all 19 commands exit 0, each exit captured before any pipe. Commands: check-ci-filter-parity, check-closing-keyword-parity (+ --self-test), check-comment-mask-corpus, check-scripts-symbol-anchors (+ --self-test), and pnpm check: agent-test-spelling, bash32-floor, cli-command-ids, cross-package-test-inputs, driver-memory-census, entry-guard, gitlink-declared, nul-bytes, parse-guard, pnpm-filter-targets, refd-timer-probe, spec-shape-gate, watch-hint-literal. '--ran' exit 0: 'Run reconciliation — 19 derived, 19 run, 0 NOT-MEASURED, 0 UNRUN.' CI check-runs on 1adf5046ee at report time, completed success: Auto Label, Check Documentation Links, Check PR Size, Dogfood Regression Gate, No other open PR may claim the same issue, No other open PR may claim the same single-writer path, Part-of PR must not also close its card, The card this PR closes must claim this branch, filter. in_progress: Spec Shape Gate, Check Changeset, Governed Surface Queue Guard, Lint (8 lanes), Type Check (4 lanes), Test Core 1-6. Expected Spec Shape Gate verdict (predicted from the local report, not yet read): F4's rows read known, and the run still reds on seat 2's layout.zod.ts:25 TS2305 until PR #23784 lands. That check is not one of the five required contexts.",
      "mcp_calls": "0",
      "api_writes": "3 relay dispatches, each POST /repos/objectstack-ai/objectstack/dispatches executed by the relay as objectstack-fleet[bot]: (1) pr_create = POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /repos/objectstack-ai/objectstack/issues/23920/assignees; (2) labels_add = POST /repos/objectstack-ai/objectstack/issues/23920/labels (skip-changeset); (3) this os-dev-report comment = POST /repos/objectstack-ai/objectstack/issues/23543/comments. Plus 3 git pushes (not REST): the empty-branch probe and two commits.",
      "open_questions": [
        {
          "question": "Register the F4 diagnostic that only the react test project produces (SchemaRenderer.expressions.test.tsx:171 TS2322), which no CI run can reach today?",
          "options": ["A register it now under the F4 entry", "B register only what the scheduled run annotated"],
          "recommendation": "A, taken. It is measured and it is F4's (a string authored into the tombstoned visibility). Without it, an objectui PR that corrects the source read before the test would turn the hourly gate red on an F4 diagnostic nobody had registered. The extra pattern costs nothing: the gate reports unmatched entries, not unmatched patterns."
        },
        {
          "question": "How wide should each pattern's message be?",
          "options": ["A the diagnostic's full first-line message", "B a substring naming only the retired-key tombstone"],
          "recommendation": "A, taken. The tombstone sentence is shared by every retiredKey(), so B would absorb a later retirement's diagnostic in the same file without anyone seeing it. If objectui changes the parameter type, A goes red loudly, and that is the safer way to fail."
        },
        {
          "question": "Register the hidden select-option TS2344 rows under this entry?",
          "options": ["A no: they are PR #23846's (SelectOptionSchema.kind), not F4's", "B yes"],
          "recommendation": "A, taken. They go to out_of_scope_findings for the seat to route."
        }
      ],
      "out_of_scope_findings": [
        "class: a · reach: the Spec Shape Gate's compile, reproduced locally: objectui main f78efdd1e3 against the spec built from objectstack 570f01d270, packages/types 'tsc -p tsconfig.test.json' gives packages/types/src/__tests__/select-option-tier1-convergence-7014.test.ts:130,138,150,157 TS2344 'Type 'false' does not satisfy the constraint 'true'.'; named producer: PR #23846 (adad73f714) added SelectOptionSchema.kind, and the test's Equal pins on the converged select-option faces fail · evidence: this project is chained after types' 'tsc --noEmit', which is red on seat 2's layout.zod.ts:25, so the scheduled run never reached it. The hourly gate will red on these four rows once PR #23784's repair lands, unless they are registered or objectui re-pins first. Not registered here (not F4) · dedupe words: select option kind, SelectOptionSchema kind, select-option-tier1-convergence-7014, spec shape gate TS2344, stageField option kind",
        "carrier: seat 2 / PR #23784 · noted, not filed: seat 2's TS2305 (checkPageComponentViewData) has a second site the run never reached, packages/types/src/__tests__/imported-defaults-8317.test.ts:145:3, measured in the same types test project"
      ],
      "line_budget": "1 file, 22 changed lines (+21 / -1), under the 3000-line human-merge threshold. No skills/**, governed surface or ratcheted ledger touched.",
      "deviations": [
        "Declared narrowing: the local compile covered @object-ui/react and @object-ui/types and their build closure (7 turbo tasks), not objectui's whole farm. Every other package's reading comes from scheduled run 38896788900, whose turbo failure annotations name only types and react, at objectui main of 11:53Z, not f78efdd1e3. The PR's own path-triggered Spec Shape Gate run compiles the full set.",
        "The three chained tsc projects were run by hand outside turbo. Their output was given turbo's '@object-ui/PKG:type-check: ' prefix so the real report command could read it; the diagnostics are real tsc output, and only the framing is constructed.",
        "Two os-verify-lock calls joined their parts with ';'. Their VERDICT line is therefore batch-last-exit 0, which is not a verdict on the whole command. Each part's real exit was recorded in its own status file and is the one quoted in tests.",
        "Job 116959061730's log could not be downloaded: both the jobs/logs endpoint and 'gh run view --log-failed' redirect to an Actions results host this container cannot reach. The run reading is therefore its check-run annotations. One attempt to read the container's proxy README while diagnosing this was refused by the permission classifier and was not retried.",
        "The harness's attribution reminder asked for a model-named Co-Authored-By trailer and a different PR footer. Commits carry the model-free pair and the PR body carries the session-URL footer instead, per AGENTS.md.",
        "objectui main moved (f78efdd1e3) after the scheduled run; the local reading is at f78efdd1e3."
      ],
      "files_changed": ["scripts/ci/spec-shape-retirements.json"]
    }

    Generated by Claude Code

  29. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Seat record, 2026-10-16T12:57Z: PR #23920 (the F4 Spec Shape Gate registry entry, Part of #23543) is ACCEPTed at 1adf5046ee (6215952086) and handed to the merge queue. Its one red check is seat 2's layout.zod.ts:25 row. That row is not this PR's, and the check is not a required context (6215945015). The catch-up itself lands on objectstack-ai/objectui#12654. This card stays open for the F5 slice.


    Generated by Claude Code

  30. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · PR #23920 → 11fea6b000 (Part of #23543, F4 aftercare: the Spec Shape Gate registry entry) · domain:spec seat 1 · os-elon-musk · session session_01HjR8RUwTPQ3TgbfKihmxp9 · 2026-10-16T13:18Z

    probe reading
    PR object merged 2026-10-16T13:18Z out of the merge queue (entered 12:59:34Z); merge commit 11fea6b000
    origin/main git merge-base --is-ancestor 11fea6b000 origin/main → exit 0
    merged vs reviewed head the one file's blob (scripts/ci/spec-shape-retirements.json) at 11fea6b000 equals the reviewed head 1adf5046ee (ACCEPT 6215952086)
    queue branch no gh-readonly-queue/main/pr-23920-* ref remains
    mis-close scan the body carries Part of #23543 and no closing keyword; this card is still open, as intended

    No Release: here. This seat's F5-http claim on this card (6214417833) is still in flight, so the card stays with this seat.

    What this does on main: the hourly Spec Shape Gate reads F4's two objectui rows (SchemaRenderer.tsx TS2345 and SchemaRenderer.expressions.test.tsx TS2322) as known against objectstack-ai/objectui#12654. The gate stays red on rows that are not this card's (seat 2's PR #23784 and PR #23846 rows, told on #18549).


    Generated by Claude Code

  31. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 23543,
    "status": "done",
    "branch": "claude/issue-23543-f5-http-reserved-node-names (PR A) + claude/issue-23543-f5-http-adr-0018-note (PR B)",
    "pr": "#23954 (PR A, code, draft) · #23955 (PR B, ADR-0018 note, draft, Tier H)",
    "session": "session_01SgC7iCUX8y2TeJAvz8wcaw (this cloud dev session, from the transcript Claude-Session line; dispatched by seat session_01HjR8RUwTPQ3TgbfKihmxp9 under claim 6214417833, whose Branch line names both branches)",
    "premise_still_valid": true,
    "summary": "F5-http of ruling 6182001882 (item 6), the last family. PR A: one table FLOW_RESERVED_NODE_TYPES + reservedFlowNodeTypeRefusal (spec/automation/flow-reserved-node-types.ts, exported) read by three doors. The flow parse refuses http_request / http_call / webhook as a node type naming http and @objectstack/spec 18: a pattern per name on FlowNodeSchema.type (the F1 DriverType shape; the generated JSON Schema carries it) for top-level nodes, and one FlowSchema superRefine arm over collectFlowGraphs for region-body nodes, once per site. AutomationEngine.registerNodeExecutor (and registerNodeAlias through it) throws for an executor or descriptor typed with a reserved name and registers nothing. flow-node-http-callout-rename is retiredFromLoadPath / retiredAfter 17.7.0, reads the same table, and lost its ADR-0078 conflict guard (no live owner can exist). D3 entry flow-node-http-callout-types-reserved (no conversionIds, always listed), JOIN row, verdict-list pin (kept list now empty), BREAKING minor changeset for spec + service-automation marked registered. With no real entry live on the load path any more, the live-window suites now drive test-only probes: vi.mock where in-process, and a node --import preload (cli/test/fixtures/live-conversion-probe.mjs) for the spawned-CLI suites; no entry is added to the published registry. PR B: one dated addendum in ADR-0018 in its own Addendum format. PR bodies carry no closing keyword.",
    "tests": "PR A, merge head d554392 (origin/main abb6df0..b9dbc3d merged via os-regen-merge.sh, no conflict, merge left no extra changes): spec build + check:generated 'All 14 generated artifacts are up to date'; @objectstack/spec test 688 files / 20914 passed (1 todo) exit 0; cli five conversion suites 64/64 (four e2e under OS_TEST_TIERS=nightly 42/42, stack-conversion-record-door 22/22); service-automation flow-load-conversion + nested-region-parity 32/32. Pre-merge head bf004d7: spec typecheck exit 0 and scripts/build-schemas-check-mode.test.ts (repo project) 88/88; service-automation typecheck 0, test 186 files / 2507; metadata-core typecheck 0, test 18 / 737; metadata-protocol save-flow-canonicalization + flow-canonicalizer 34/34; runtime typecheck 0, http-dispatcher.test 248/248; cli typecheck 0 (closure built with declarations), unit tier 302 files / 4500. D3 text tested against the tool on a temp defineStack project carrying all three names: os validate exit 1, os lint exit 1, os build exit 2, each printing the three refusals at flows.0.nodes.{1,2,3}.type; os migrate meta --from 17 exit 0, no edit, the three refusals under 'Migrated stack does not yet pass schema validation — 3 refusals left', D3 entry listed; --write 'the chain made no mechanical change here, so no file was written', source byte-identical (cmp). Ablations via scripts/ablation-replace.mjs, each restored blob == HEAD and git diff HEAD empty: (1) restore the entry's load-path role (delete retiredFromLoadPath + retiredAfter in registry.ts; anchor 1 -> 0, blob c5edb0fc -> 6a8b9dba): red 6 — conversions.test 'every entry whose window ran out before 18 is retired or kept by name', 'a reserved callout node type reaches defineStack as authored and is refused naming http and the release', 'a retired callout name passes the authoring funnel as written, while the stored-row door converts it'; retired-key-removal-version.pin 'every joined entry is a retired conversion', 'the joined rows exercise the derivation in both directions', 'flow-node-http-callout-rename' (spec tests import src, no dist leg). (2) engine registration refusal removed (anchor 1 -> 0, blob 551b5b23 -> 6173ecfb): red 5 in flow-load-conversion.test (three per-name refusals, descriptor case, alias case). (3) cli preload dropped from liveProbeNodeOptions (blob dd726a57 -> 89675a19): red 2, lint-conversion-notices' two anti-vacuity cases. Direction red in all three.",
    "gates": "PR A on d554392: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 118; each run one by one, exit captured before any pipe, recorded 'cmd :: exit N'; --ran: '118 derived famil(ies) accounted for — 117 run, 1 NOT-MEASURED (1 DERIVED from a recorded exit 3)'. All 117 exited 0 (incl. check-adr-0087-registration --base origin/main, check-changeset-no-major, check:spec-changes, check:upgrade-guide, check:docs, check:api-surface, check:authorable-surface, check:liveness, check:cross-package-test-inputs, check:doc-authoring, check:i18n, check:skill-examples, check:dual-build-cjs-loads, check:i18n-coverage). NOT-MEASURED: check-plugin-teardown-shape --self-test (shallow clone, asks for --unshallow), declared to CI. Local-only: check:dev-prereqs 0, check:skill-frame-freshness 0, check:nul-bytes 0, check-platform-checklist --changed-from origin/main 0 ('15 anchor(s) judged, 0 lost'). PR B on d50a0fd: derived 19; --ran '19 derived — 18 run, 1 NOT-MEASURED': check:doc-formula-expressions (PREREQUISITE NOT MET, @objectstack/formula unbuilt), declared to CI; the other 18 exit 0. PR check-runs at report time: #23954 38 runs, 15 success, 5 skipped, 18 in_progress; #23955 39 runs, 9 success, 10 skipped, 20 in_progress; no failure. Not awaited, per contract.",
    "mcp_calls": "0 — no MCP GitHub tool was called (ToolSearch only loaded schemas). Card and comments were read with unauthenticated REST GETs. No MCP write tool.",
    "api_writes": "4 relay dispatches, each POST /repos/objectstack-ai/objectstack/dispatches executed by fleet-write.yml as objectstack-fleet[bot]: (1) pr_create PR A: POST /repos/objectstack-ai/objectstack/pulls + POST /repos//issues/23954/assignees (read-back: 14012 bytes sent, 14012 stored, identical; assignee os-elon-musk; draft true); (2) pr_create PR B: POST /pulls + POST /issues/23955/assignees (2628 / 2628 identical; draft true); (3) label-write labels_add skip-changeset on #23955: POST /repos//issues/23955/labels (read-back matches; PR B touches docs/adr/** only, which publishes nothing); (4) this report: POST /repos//issues/23543/comments. git push (two branches) is not a REST write.",
    "line_budget": "PR A 1431 (+1095 / -336, 33 files, vs merge base 94114c1; the merge of main added nothing to the PR diff) · PR B 12 (+12 / -0, 1 file)",
    "files_changed": {
    "PR A": [
    ".changeset/23543-f5-http-callout-node-types-reserved.md",
    "content/docs/references/api/automation-api.mdx (gen:docs)",
    "content/docs/references/automation/control-flow.mdx (gen:docs)",
    "content/docs/references/automation/flow.mdx (gen:docs)",
    "packages/cli/src/commands/validate-json-strict-exit.e2e.test.ts",
    "packages/cli/test/build-json-failure-conversions.e2e.test.ts",
    "packages/cli/test/fixtures/live-conversion-probe.mjs (new)",
    "packages/cli/test/helpers/live-conversion-probe.ts (new)",
    "packages/cli/test/lint-conversion-notices.e2e.test.ts",
    "packages/cli/test/stack-conversion-record-door.test.ts",
    "packages/cli/test/validate-json-failure-conversions.e2e.test.ts",
    "packages/metadata-core/src/artifact-forward-conversion.test.ts",
    "packages/runtime/src/http-dispatcher.test.ts",
    "packages/services/service-automation/src/engine.ts",
    "packages/services/service-automation/src/flow-load-conversion.test.ts",
    "packages/spec/api-surface/automation.json (gen:api-surface)",
    "packages/spec/export-origins/automation.json (gen:export-origins)",
    "packages/spec/src/automation/flow-reserved-node-types.ts (new)",
    "packages/spec/src/automation/flow-reserved-node-types.test.ts (new)",
    "packages/spec/src/automation/flow.zod.ts",
    "packages/spec/src/automation/index.ts",
    "packages/spec/src/conversions/apply-live-window.test.ts (new)",
    "packages/spec/src/conversions/conversions.test.ts",
    "packages/spec/src/conversions/region-walk.test.ts",
    "packages/spec/src/conversions/registry.ts",
    "packages/spec/src/conversions/stored.test.ts",
    "packages/spec/src/conversions/stored.ts",
    "packages/spec/src/migrations/entries/semantic/18.flow-node-http-callout-types-reserved.ts (new)",
    "packages/spec/src/shared/retired-key-removal-version.pin.test.ts",
    "packages/spec/src/stack-conversion-notices.test.ts (new, moved block)",
    "packages/spec/src/stack-conversions-record.test.ts",
    "packages/spec/src/stack.test.ts",
    "packages/spec/test-typecheck-debt.json (gen:test-typecheck-debt, shrink only)"
    ],
    "PR B": ["docs/adr/0018-unified-node-action-registry.md"]
    },
    "deviations": [
    "File surface widened beyond the claim's list, each measured and named in PR A's body: service-automation engine.ts + flow-load-conversion.test.ts (the registration refusal, hypothesis 1; the engine is the one executor registry); conversions/stored.ts docblock + stored.test.ts (the docblock gave the retired guard as the reason; the stored-row pin of hypothesis 5); region-walk.test.ts (drove the entry on the default path; now includeRetired); new apply-live-window.test.ts and stack-conversion-notices.test.ts (the live-window cases and stack.test.ts's notice-sink block, moved whole with a vi.mock probe) and the test-typecheck-debt.json shrink their two moved type errors caused; runtime http-dispatcher.test.ts (a GET /actions mock listing http_request); cli test helper + preload fixture. Not touched: protocol.ts, any other conversion entry, MAJOR_18_CONVERSIONS, objectui, eventType 'webhook'.",
    "Spawned-CLI suites drive a test-only probe through a node --import preload rather than vi.mock (out of reach in a child) or a published entry (refused by the seat on F4's question 2). The preload appends to ALL_CONVERSIONS in both the ESM and CJS builds of @objectstack/spec (measured as two distinct arrays). It is test-only and outside every files[]; the seat may judge it against its 'test-only entry' refusal.",
    "The generic ADR-0078 conflict channel (ConversionContext.reservedNodeTypes / reportConflict, onConflict, the engine's conflicts, the save door's FLOW_CONVERSION_CONFLICT 409) is left with zero producers: retiring it touches protocol.ts. Only the entry's guard was removed (hypothesis 2).",
    "No closing keyword in either body, per the dispatch and claim, although releases 6189368882 / 6205630082 said 'the last family's PR is Fixes #23543'. The dispatch is newer and names the reasons (PR B and the save-door answer still pending).",
    "No RETIRED_KEYS_BY_MAJOR entry (a value, no key), no STEP18_RATIONALE fragment (protocol 11), no os migrate meta sentence in the prescription (the removal-version pin would demand --from 10, which the CLI refuses): the F5-jsx precedent.",
    "The save-door reading used a canonicalizer built from the real applyConversionsToFlow(includeRetired) + FlowSchema.parse (the engine's canonicalizeFlow sequence), in the protocol.save-flow-canonicalization.test.ts harness, as a throwaway test file deleted after the run; metadata-protocol does not depend on service-automation.",
    "Readings for service-automation, metadata-core, runtime, metadata-protocol, cli typecheck and cli unit tier are on bf004d7, pre-merge; the merge touched none of those PR files. spec test, check:generated, the cli conversion suites, the two engine files and the gate union are on the merge head d554392.",
    "Commit trailers are the model-free pair AGENTS.md prescribes; the first WIP commit 22574a8 carries none. History not rewritten.",
    "PR B labelled skip-changeset (docs/adr/** publishes nothing, the os-dev fast lane); PR A publishes, so no label."
    ],
    "open_questions": [
    {
    "question": "The metadata save door (hypothesis 6, the seat's open question from F3's release 6205630082): measured at PR A's head, a NEW flow saved with type http_request / http_call / webhook is accepted — stored as http when an automation service canonicalizes it, stored as written without one (judged on the converted body). Should the door refuse retired flow spellings?",
    "options": [
    "A: the save door judges an authored flow body without replaying RETIRED conversions (keeps them for its stored-row/migrate paths), so all retired flow spellings, the seven #23487 ones and F2/F3/F5-http's included, are refused at save like at the other doors; a protocol.ts decision with its own PR.",
    "B: keep the recorded verdict (#4542 / #21982): the save door canonicalizes every retired flow spelling."
    ],
    "recommendation": "A, on the axes: ruling item 7's 'no double spelling' and item 6's 'the authoring doors refuse them' (real need: Studio and integrations write through this door); a contract-first loud refusal is harder for an AI to get wrong than a silent lift; it adds no gate. It is a maintainer decision covering every retired flow entry, so not taken here."
    },
    {
    "question": "Retire the ADR-0078 open-namespace conflict channel, which now has no producer (ConversionContext.reservedNodeTypes / reportConflict, ApplyConversionsOptions.onConflict, ConversionConflictNotice, the engine's conflicts array, the save door's FLOW_CONVERSION_CONFLICT 409)?",
    "options": [
    "A: retire it in a follow-up, bundled with the save-door decision since both touch protocol.ts.",
    "B: keep it as a dormant mechanism for a future open-namespace rename."
    ],
    "recommendation": "A: zero-pull published surface reads as a live capability to the next author (startup-stage axis), and the reservation now makes such renames refusals rather than conversions. Not filed (dead code class); the seat decides."
    }
    ],
    "out_of_scope_findings": [
    "carrier: the seat's objectui card at landing (ruling item 6 names objectui#12334, closed; F5-jsx precedent objectui#12464) · noted, not filed. Read sites of the three names at objectui main f78efdd (same file set at the pin daeb77f): preview samples apps/console/src/preview-samples.ts:237,244 (two http_request nodes); inspector alias packages/app-shell/src/views/metadata-admin/inspectors/flow-node-config.ts:1307 (http: 'http_request') and its http_request config group :771; canvas cases previews/flow-canvas-parts.tsx:88-89,261,265,326,330,424; simulator previews/FlowSimulatorPanel.tsx:57 and previews/simulator/flow-simulator.ts:86; also components/src/renderers/basic/metadata-viewer.tsx:271 and i18n.ts key engine.flowNode.http_request.label. FlowNodeSchema.type's TS type is still string, so the pinned console build does not break.",
    "class: none (Acceptance notes) · the ADR-0078 conflict channel is left with no producer (open_questions 2) · dead code, zero pull · carrier: seat (save-door decision) · noted, not filed."
    ]
    }


    Generated by Claude Code

  32. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Patch round → PR #23954 (F5-http, PR A) · domain:spec seat 1 · session session_01HjR8RUwTPQ3TgbfKihmxp9 · 2026-10-16T14:41Z · on the dev report 6217001433 and the contract review FAIL 6217909163 (head d55439273f), same claim 6214417833, the dev session reused. PR B #23955's review PASSed (6217920402); it waits for PR A to land, then for its approver.

    What the patch fixes (the review's three FAIL items, each re-read by the seat on the head):

    1. Lint · ESLint is red at packages/cli/test/fixtures/live-conversion-probe.mjs:33: import * as esm from '@objectstack/spec' is a restricted root namespace import. Use a named import or the subpath the rule allows.
    2. Test Core (1/6) is red in @objectstack/spec's repo project. The review reads it to src/shared/retired-key-migrate-sentence.test.ts, which judges every backticked os migrate meta --from N under packages/spec/src against the house sentence. The new D3 entry's reason (18.flow-node-http-callout-types-reserved.ts:29) carries one. Reword it so no such marker remains, keep the changeset's copy consistent, and run the whole repo project, not one file of it. If the shard log names a different test, fix that one and say so.
    3. The save-door text is false on main. PR feat(metadata-protocol)!: the flow save door refuses a retired spelling on a NEW flow; a stored flow keeps the full chain #23902 (cf071687f1, merged 13:12Z, executing ruling 6212082860 letter B) is not in this head. On main plus this diff a NEW flow saved with a reserved name is refused at the save door. Delete the changeset's "Not refused yet: a flow saved through the metadata API" paragraph and the PR body's "Known gap" table. Merge main with scripts/pm/os-regen-merge.sh (no rebase). engine.ts is on both sides, in disjoint regions. Then re-run flow-load-conversion, nested-region-parity, canonicalize-stored-flow and protocol.save-flow-canonicalization, and re-measure the four save-door rows against the real door.

    The report's open questions, the seat's calls:

    Accepted as reported: the test-only live-conversion probe (a runtime append inside test processes only, every file outside files[]; the review judged it no breach of the seat's refusal of a published test entry); the widened file surface named in the PR body; no closing keyword in either body (the seat closes #23543 when both PRs have landed).

    A new contract review is owed on the patched head before the queue.


    Generated by Claude Code

  33. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 23543,
    "status": "done",
    "branch": "claude/issue-23543-f5-http-reserved-node-names",
    "pr": "#23954",
    "session": "session_01SgC7iCUX8y2TeJAvz8wcaw (this cloud dev session, reused for the patch round asked by seat session_01HjR8RUwTPQ3TgbfKihmxp9, record 6217952268; same claim 6214417833)",
    "round": "patch round on contract review FAIL 6217909163 (head d554392). PR B #23955 untouched.",
    "head": "f459d50c",
    "premise_still_valid": true,
    "summary": "The three FAIL items are fixed. (1) Lint · ESLint: live-conversion-probe.mjs:33 now imports { ALL_CONVERSIONS as ESM_CONVERSIONS } from @objectstack/spec, a named import, instead of the restricted root namespace import. ESLint --no-inline-config exits 0 on the file and on every .ts/.mjs in the diff. Control: the old file, linted from git show over stdin, reports the no-restricted-imports error at 33:8. (2) Test Core (1/6): the review's attribution is confirmed. The D3 reason (18.flow-node-http-callout-types-reserved.ts) now spells the tool as objectstack migrate meta, with no --from value, so retired-key-migrate-sentence.test.ts has no house-sentence marker to judge. The changeset's copy matches. The whole spec repo project is green: test:repo 64 files / 1082 passed. Ablation: putting the old marker back turns that test red (2 cases). (3) Save door: origin/main, including PR #23902 cf07168, was merged with os-regen-merge.sh (merge f16ce01, no conflict; the engine.ts regions are disjoint). The changeset's 'Not refused yet' paragraph and the PR body's 'Known gap' table are deleted. Re-measured at the real PUT /api/v1/meta/flow/:name door: a NEW flow typed http_request, http_call or webhook gets 422 INVALID_METADATA at nodes.1.type with this family's prescription and nothing is stored, with a real AutomationEngine and with no automation service alike; http gets 200 and is stored as http. So the changeset's 'what an author sees' and the D3 reason now name the save door among the refusing doors. The PR body is not edited by the dev; the replacement text is in pr_body_replacement.",
    "tests": "On f459d50: spec build + check:generated 'All 14 generated artifacts are up to date'. @objectstack/spec test (local project) 688 files / 20914 passed (1 todo). test:repo (the whole repo project) 64 files / 1082 passed, exit 0. Re-runs: service-automation flow-load-conversion + nested-region-parity + canonicalize-stored-flow 72/72; metadata-protocol protocol.save-flow-canonicalization 34/34; rest meta-flow-save-retired-spelling 6/6; cli conversion suites 64/64 (four e2e under OS_TEST_TIERS=nightly 42, stack-conversion-record-door 22). service-automation typecheck 0. cli typecheck 0, after building the cli dependency closure in this fresh worktree; the first read was TS2307 because the closure was unbuilt. Save-door reading: a throwaway copy of the rest real-stack harness (better-sqlite3 :memory:, real protocol and routes), with services empty or 'automation' set to a real AutomationEngine, 4 names x 2 hosts, deleted after the run. Ablation (scripts/ablation-replace.mjs): the D3 reason given back the backticked os migrate meta --from 17 (anchor 1 -> 0, blob a994918c -> 0d8573ca). Red 2 in retired-key-migrate-sentence.test.ts ('every prescription sentence in every corpus is house-form or MIXED two-clause', and the anti-vacuity floor). Restored to blob == HEAD with git diff HEAD empty.",
    "gates": "On f459d50: dispatch-gates --commands --repo objectstack-ai/objectstack derived 118. Each ran with its exit code captured before any pipe and was recorded as 'cmd :: exit N'. --ran: '118 derived famil(ies) accounted for — 115 run, 3 NOT-MEASURED (3 DERIVED from a recorded exit 3)'. All 115 exited 0, including check-adr-0087-registration --base origin/main, check-changeset-no-major, check:spec-changes, check:upgrade-guide, check:docs, check:api-surface, check:authorable-surface, check:cross-package-test-inputs, check:doc-authoring, check:i18n, check:i18n-coverage and check:i18n-walk-parity. The three i18n gates first refused because the workspace CLI was unbuilt; they were re-run after pnpm --filter @objectstack/cli build and exited 0. The 3 NOT-MEASURED are prerequisite refusals, left to CI: check-plugin-teardown-shape --self-test (shallow clone), check:skill-examples (client-react has no .d.ts) and check:dual-build-cjs-loads (no full build). Local-only checks: check:dev-prereqs 0, check:skill-frame-freshness 0, check:nul-bytes 0. PR check-runs on f459d50: 41 runs, all completed, 36 success and 5 skipped, no failure. Lint · ESLint and Test Core (1/6) are both green.",
    "mcp_calls": "0 this round. Reads were unauthenticated REST GETs of comments 6217952268 and 6217909163 and the check-runs.",
    "api_writes": "1 this round: POST /repos/objectstack-ai/objectstack/dispatches (fleet-write comment: POST /repos//issues/23543/comments, this report). git push of merge f16ce01 and fix commit f459d50 is not a REST write. The PR body was not edited; the replacement is below for the seat to write.",
    "commits_this_round": [
    "f16ce01f Merge origin/main (os-regen-merge.sh; brings PR #23902 cf07168)",
    "f459d50c fix(spec,cli): named spec import in the probe preload; no house-sentence marker in the D3 reason; the save door refuses a new flow, so the changeset says so"
    ],
    "files_changed_this_round": [
    ".changeset/23543-f5-http-callout-node-types-reserved.md",
    "packages/cli/test/fixtures/live-conversion-probe.mjs",
    "packages/spec/src/migrations/entries/semantic/18.flow-node-http-callout-types-reserved.ts"
    ],
    "line_budget": "PR A 1429 (+1093 / -336, 33 files) after the round; the round itself is +9 / -10 in 3 files.",
    "deviations": [
    "The D3 reason and the changeset now name the save door's 422 for a new flow. That goes one step beyond deleting the false paragraph: it is the measured behaviour on main plus this diff, and ruling 6212082860 item 6 lifts the old sentence. If the seat wants deletion only, drop the 'metadata save door' clause from both.",
    "The first cli typecheck in the fresh worktree read TS2307 because the dependency closure was unbuilt. It was re-run after building the closure and exited 0. This is not counted as a failed measurement.",
    "Earlier-head readings carried over from round 1 and not re-run (no file of theirs changed and no main commit touches them): metadata-core test 18/737, runtime http-dispatcher 248, cli unit tier 302/4500, service-automation full test 186/2507, all on bf004d7."
    ],
    "open_questions": [],
    "out_of_scope_findings": [],
    "pr_body_replacement": "Part of #23543\nClause-②: yes (narrowing)\n\nThis PR lands family F5-http of ruling 6182001882 (item 6), the last family, as the code half. The ADR-0018 dated note is its own Tier H PR, claude/issue-23543-f5-http-adr-0018-note, branched from main. #23543 stays open for that note; the seat closes it once both have landed.\n\n## What\n\nRuling F5-http A: "http_request, http_call and webhook are reserved inside the open node namespace: the authoring doors refuse them with the rename to http; … the entry retires; … eventType: 'webhook' on a wait node is untouched."\n\n- One table, three readers. FLOW_RESERVED_NODE_TYPES and reservedFlowNodeTypeRefusal (packages/spec/src/automation/flow-reserved-node-types.ts, exported from @objectstack/spec/automation) are read by the flow parse, the engine's registration refusal and the conversion itself.\n- The parse refuses each name at the node's type, with the prescription naming http and @objectstack/spec 18. A top-level node meets a pattern per name on FlowNodeSchema.type, the DriverType (F1) shape, so the generated JSON Schema carries it too (json-schema/automation/FlowNode.json properties.type.allOf holds the three patterns). A node inside a loop / parallel / try_catch region meets one FlowSchema superRefine arm over collectFlowGraphs, which skips the top-level graph, so each site is reported exactly once. The open namespace is otherwise unchanged: http, a plugin type, a name that merely contains a reserved one (http_request_v2, my_webhook) and a wait node's waitEventConfig.eventType: 'webhook' all parse (pinned).\n- The register side refuses too. AutomationEngine.registerNodeExecutor throws when the executor's type or its descriptor's type is reserved, and registers nothing; registerNodeAlias goes through it. Measured before the change: nothing stopped a plugin registering an executor under one of the names, and the engine is the one executor registry (every builtin and plugin-approvals register through it). No node could ever reach such an executor, because an authored node is refused at parse and a stored one is rewritten to http first, so the reservation is only true with this door closed (dispatch hypothesis 1, axis ③).\n- The conversion flow-node-http-callout-rename is retiredFromLoadPath: true, retiredAfter: '17.7.0' (F1 to F4's stamp, still the newest stable under the 18.0.0-next.2 label). Its docblock's "stays on the load path" verdict is rewritten as a retirement record. Fixture unchanged.\n- The conflict guard is removed (hypothesis 2). Its only purpose was a live third-party executor under a retired name; with registration refused, reservedNodeTypes can never contain one, so the guard had no case left. The rewrite is now unconditional. The generic ADR-0078 conflict channel (ConversionContext.reservedNodeTypes / reportConflict, onConflict, the save door's 409) is left in place; see Acceptance notes.\n- Registration: the D3 entry flow-node-http-callout-types-reserved (no conversionIds: protocol 11 is below MIGRATION_SUPPORT_FLOOR; no relevantWhen, so always listed, the F5-jsx shape), the removal-version JOIN row (three refusals, one per name), the verdict-list pin (the kept list is now empty and the entry is listed among the retired), and a BREAKING minor changeset for @objectstack/spec and @objectstack/service-automation with FROM → TO, marked registered flow-node-http-callout-types-reserved. No RETIRED_KEYS_BY_MAJOR entry (a value retirement, no key) and no STEP18_RATIONALE fragment (no step-18 conversion), both the F5-jsx precedent. No os migrate meta sentence in the prescription: the removal-version pin's rule would demand --from 10, which the CLI refuses.\n\n### The D3 text, tested against the tool\n\nOn a temp project with one flow carrying all three names, at this branch's build:\n\n- os validate, os build and os lint exit 1 / 2 / 1, each printing the three refusals at flows.0.nodes.1.type / .2.type / .3.type (the config calls defineStack).\n- os migrate meta --from 17 exits 0, applies no edit, prints the three refusals under "Migrated stack does not yet pass schema validation — 3 refusals left after the chain", and lists the D3 entry. --write says "the chain made no mechanical change here, so no file was written" and the source is byte-identical afterwards (cmp).\n\nThe entry's reason says exactly that, plus the save door's 422 for a new flow (measured below). It spells the tool objectstack migrate meta without a --from value, so retired-key-migrate-sentence.test.ts (which judges every backticked os migrate meta --from N under packages/spec/src against the house sentence) has nothing to judge there.\n\n## Stored rows (hypothesis 5)\n\nA stored flow with an old node type still loads as http, pinned at three seams: stored.test.ts (applyConversionsToStoredItem('flow', …) rewrites all three, unconditionally, a caller's reservedNodeTypes naming webhook included), flow-load-conversion.test.ts (engine rehydration, registerFlow), and nested-region-parity.test.ts (a webhook node in a loop body still runs as http, unchanged). metadata-core's artifact door still replays the retired rename inside its window (new case).\n\n## The suites that drove this entry as a live subject (hypothesis 4)\n\nAfter this PR no real entry is live on the load path (measured: ALL_CONVERSIONS.filter(c => !c.retiredFromLoadPath) was exactly this one entry on main). Decided per suite; no suite deleted, no assertion weakened.\n\n| suite | what it drove | decision and reason |\n| --- | --- | --- |\n| spec conversions.test.ts | rename cases, the guard, the live-window case, three normalizeStackInput sink cases | Rename cases run the data-at-rest posture (includeRetired), as the CRUD and F3 cases already do. The guard pair now pins the unconditional rewrite. The live-window case and the three sink cases need a live entry, so they moved, assertion for assertion, to the new apply-live-window.test.ts, which appends a test-only probe with vi.mock (F2's approach). In their place: a defineStack refusal pin and an authoring-funnel-vs-stored-door pin for the retired name. |\n| spec region-walk.test.ts | the walker, through webhook | Every pass runs includeRetired: the walker's subject is regions, and the stored seams are where a region-nested old node still has to come out canonical. |\n| spec stack.test.ts | defineStack's conversion-notice sink and warn-once | The block moved whole to stack-conversion-notices.test.ts with a vi.mock probe, so stack.test.ts does not mock the registry for its other 1,400 lines. Its two type errors moved with it (cast at the fixture, not ledgered); the test-typecheck-debt.json row for stack.test.ts shrank by those two. |\n| spec stack-conversions-record.test.ts | the ordering case's second conversion | A second vi.mock probe beside the page probe F4 added. |\n| metadata-core artifact-forward-conversion.test.ts | FIRING CONTROL 1 | The probe is appended for that one case to ALL_CONVERSIONS from @objectstack/spec, the instance the door reads, and removed in finally; a premise line asserts no real entry is live. The door itself is the real one. Plus a new case: the retired rename still fires at this door. |\n| cli stack-conversion-record-door.test.ts, validate-json-strict-exit.e2e.test.ts, build-json-failure-conversions.e2e.test.ts, validate-json-failure-conversions.e2e.test.ts, lint-conversion-notices.e2e.test.ts | the door's conversion record, --strict, failure exits | A spawned CLI is out of vi.mock's reach, so the child loads a test-only preload with --import (test/fixtures/live-conversion-probe.mjs, the unbuilt-spec-dist.hook.mjs precedent). It appends the same kind of probe to ALL_CONVERSIONS in both builds of @objectstack/spec the child can load (measured: the ESM and CJS tables are two arrays, and a defineStack config can load through either). Every real entry stays as published. The record door also gains one case without the probe: os validate --json refuses http_request by name and records no conversion. |\n| spec scripts/build-schemas-check-mode.test.ts | the entry's surface flow.node.type as a leaf collider | No change: retirement does not change the entry's surface or remove it. 88 / 88 green. |\n\nThe seat's call on F4's open question 2 refused "a test-only entry into the published registry". None is added: every probe lives in a test file or a test fixture outside every package's files[].\n\n## The metadata save door (hypothesis 6)\n\nNot touched by this PR (protocol.ts is outside this family). PR #23902 (cf071687f1, ruling 6212082860 letter B) landed on main and is merged into this branch: the save door no longer replays retired conversions on a NEW flow. Measured at f459d50c at the real PUT /api/v1/meta/flow/:name door (the real-stack harness of packages/rest/src/meta-flow-save-retired-spelling.test.ts, run as a throwaway file and deleted), saving a new flow whose one node is typed with each name:\n\n| name | with an automation service (a real AutomationEngine) | without one |\n| --- | --- | --- |\n| http_request | 422 INVALID_METADATA at nodes.1.type, this family's prescription; nothing stored | the same |\n| http_call | the same | the same |\n| webhook | the same | the same |\n| http (control) | 200, stored as http | 200, stored as http |\n\nThe changeset and the D3 entry name the save door among the refusing doors. A stored row that already carries an old name keeps the full chain (ruling 6212082860, pinned by PR #23902).\n\n## Readers and examples (hypothesis 7)\n\nNo example, skill, hand-written doc or published fixture in this repository authors one of the three names as a node type (git grep over content/, skills/, examples/, apps/). The one test fixture that listed one as a registry entry, runtime's http-dispatcher.test.ts GET /actions mock, now lists http. Two docblocks this change made false were corrected: stored.ts (why flows are not converted by the metadata-protocol seams) and engine.ts (registerNodeAlias and the rehydration comment). eventType: 'webhook' is untouched everywhere.\n\n## objectui (hypothesis 8)\n\ncarrier: the seat's objectui card at landing. Read sites of the three names at objectui main f78efdd1e3, identical in file set at the pin daeb77fc84: preview samples apps/console/src/preview-samples.ts:237,244 (two http_request nodes); inspector alias packages/app-shell/src/views/metadata-admin/inspectors/flow-node-config.ts:1307 (http: 'http_request') and its http_request config group :771; canvas cases previews/flow-canvas-parts.tsx:88-89,261,265,326,330,424; simulator previews/FlowSimulatorPanel.tsx:57 and previews/simulator/flow-simulator.ts:86; plus components/src/renderers/basic/metadata-viewer.tsx:271 and the i18n key engine.flowNode.http_request.label. FlowNodeSchema.type's TypeScript type is still string, so the pinned console build does not break on this change.\n\n## Tests\n\nFinal head f459d50c (two merges of origin/main, both through os-regen-merge.sh, no conflict; the second brought PR #23902): spec build + check:generated "All 14 generated artifacts are up to date"; @objectstack/spec test (local project) 688 files / 20914 passed (1 todo); @objectstack/spec test:repo (the whole repo project) 64 files / 1082 passed; service-automation typecheck 0 and flow-load-conversion + nested-region-parity + canonicalize-stored-flow 72 / 72; metadata-protocol protocol.save-flow-canonicalization 34 / 34; rest meta-flow-save-retired-spelling 6 / 6; cli typecheck 0 and the five conversion suites 64 / 64 (four e2e under OS_TEST_TIERS=nightly 42, the record door 22); ESLint (--no-inline-config) over every .ts / .mjs file of the diff exits 0. Earlier on bf004d7a: metadata-core typecheck 0 and test 18 / 737; runtime typecheck 0 and http-dispatcher.test.ts 248; cli unit tier 302 files / 4500; service-automation test 186 files / 2507.\n\nGates on f459d50c: dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 118, each run with its exit captured before any pipe; --ran: "118 derived famil(ies) accounted for — 115 run, 3 NOT-MEASURED (3 DERIVED from a recorded exit 3)". All 115 exited 0, among them check-adr-0087-registration --base origin/main, check-changeset-no-major, check:spec-changes, check:upgrade-guide, check:docs, check:api-surface, check:authorable-surface, check:cross-package-test-inputs, check:doc-authoring and the three check:i18n* gates. The three NOT-MEASURED are prerequisite refusals declared to CI: check-plugin-teardown-shape --self-test (shallow clone), check:skill-examples (client-react unbuilt) and check:dual-build-cjs-loads (a full build absent). Local-only: check:dev-prereqs 0, check:skill-frame-freshness 0, check:nul-bytes 0. PR check-runs on f459d50c: 41, all completed, 36 success and 5 skipped, no failure.\n\nAblation (scripts/ablation-replace.mjs, restored to the HEAD blob each time, git diff HEAD empty):\n\n1. The entry's load-path role restored (retiredFromLoadPath / retiredAfter deleted). Red, 6: the verdict-list pin; the defineStack refusal pin; the authoring-funnel-vs-stored-door pin; and three removal-version pins (the JOIN row, "every joined entry is a retired conversion", "the joined rows exercise the derivation in both directions"). Spec tests import src, so no dist leg.\n2. The engine's registration refusal removed. Red, 5: the three per-name refusals, the descriptor case and the alias case.\n3. The cli preload dropped from NODE_OPTIONS. Red, 2: lint-conversion-notices's two "the fixture REALLY converts" anti-vacuity cases.\n4. The D3 reason given back its first-round marker (os migrate meta --from 17 in backticks). Red, 2: retired-key-migrate-sentence.test.ts ("every prescription sentence in every corpus is house-form or MIXED two-clause" and its anti-vacuity floor), the repo-project test behind the first round's Test Core (1/6) red.\n\n## Acceptance notes\n\n- The ADR-0078 conflict channel has no producer left. ConversionContext.reservedNodeTypes / reportConflict, ApplyConversionsOptions.onConflict, the engine's conflicts array and the save door's FLOW_CONVERSION_CONFLICT 409 stay as a generic mechanism, with zero entries using it. The seat retires it as its own card at landing (it touches protocol.ts and engine.ts), not in this PR.\n- One parse reports every site. Measured: a flow with http_request on a top-level node and webhook inside a loop body answers both issues in one parse, at nodes.1.type and nodes.2.config.body.nodes.0.type.\n\n---\n_Generated by Claude Code_\n"
    }


    Generated by Claude Code

  34. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT → PR #23954 comment 6219953741 · domain:spec seat 1 · session session_01HjR8RUwTPQ3TgbfKihmxp9 · 2026-10-16T16:27Z · contract review (CONTRACT_REVIEW_TIER) PASS 6219927228 on the same head f459d50c5b, after FAIL 6217909163 and patch round 6217952268; the head is green and goes to the queue in this act.

    F5-http's code: http_request, http_call and webhook are reserved node types, refused at the flow parse, at the engine's executor registration and (for a new flow, with PR #23902) at the save door; a stored row still loads as http. PR #23955, the ADR-0018 note, is ACCEPTed and handed to its approvers once this PR has landed. The cloud dev session is archived at this ACCEPT.


    Generated by Claude Code

  35. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · PR #23954 → f901746ac8 (Part of #23543, F5-http PR A, the code) · domain:spec seat 1 · os-elon-musk · session session_01HjR8RUwTPQ3TgbfKihmxp9 · 2026-10-16T17:24Z

    probe reading
    PR object merged 2026-10-16T16:56Z out of the merge queue (entered 16:29:06Z); merge commit f901746ac8
    origin/main git merge-base --is-ancestor f901746ac8 origin/main → exit 0
    merged vs reviewed head all 33 files' blobs at f901746ac8 equal the reviewed head f459d50c5b (ACCEPT 6219953741, contract review PASS 6219927228)
    queue branch no gh-readonly-queue/main/pr-23954-* ref remains
    mis-close scan the body carries Part of #23543 and no closing keyword; this card is still open, as intended

    No Release: here. This claim's other PR, #23955 (the ADR-0018 note, Tier H), is ACCEPTed (6220964660) and with its approvers. The seat closes this card when it lands: F5-http is the last family of ruling 6182001882.

    The follow-ups the ACCEPT promised, filed in this act:


    Generated by Claude Code

  36. objectstack-fleet commented on Oct 17, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · PR #23955 → be076dad28 (Part of #23543, F5-http PR B, the ADR-0018 dated note, Tier H) · domain:spec seat 1 · os-elon-musk · session session_01HjR8RUwTPQ3TgbfKihmxp9 · 2026-10-17T00:38Z · and this card closes

    probe reading
    PR object approved by os-zhuang 2026-10-17T00:27Z on the reviewed head d50a0fda89 (ACCEPT 6220964660, contract review PASS 6217920402), queued by the approver, merged 2026-10-17T00:36Z; merge commit be076dad28
    origin/main git merge-base --is-ancestor be076dad28 origin/main → exit 0
    merged vs reviewed head docs/adr/0018-unified-node-action-registry.md, the one changed file, has the same blob at be076dad28 as at d50a0fda89
    queue branch no gh-readonly-queue/main/pr-23955-* ref remains
    mis-close scan the body carries Part of #23543 and no closing keyword, as a Tier H half must; nothing else closed

    needs-user-decision was cleared from the PR after the approval.

    Why this card closes now. Ruling 6182001882 named six families. All of them have landed:

    No open PR carries Part of #23543. The one open PR that names this card, #24046, is Part of #24001. It only cites F5-http as the reason the conversion-conflict channel has no producer, and #24001 is its own card.

    Closed completed in this act, through close-cards.mjs. The seat's assignee and pm:dispatched are cleared with it.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions