Repository navigation
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
Description
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)
datasource-driver-mongo-to-mongodb.'mongo'is a registered alias ofmongodb(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 namingmongodb), then retire the entry; B, record the entry as permanent. Dev lean: A.retry-policy-converged. TheretryDelayMsrename is already refused on every surface. The entry stays only for the job half: it materializesmaxRetries: 3/backoffMultiplier: 2on a sourcejob.retryPolicythat 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.flow-node-wait-event-config-liftandflow-node-connector-config-lift.waitandconnector_actionhave noconfigcontract, 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 underconfigand have the lift delete a shadowed loose key at rehydration, then retire; B, keep.view-visibleOn-to-visibleWhenandpage-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 (retiredKeytombstones and the fullspec-property-retirementkit, an objectui check), retiring the entries in the same change; B, keep. Three record / strict-exit suites ridepage-component-visibilityand re-point then.flow-node-http-callout-renameandpage-kind-jsx-to-html. The old values are accepted silently:FlowNodeSchema.typeis an open namespace (flow.zod.ts:603), and'jsx'is still aPageSchema.kindmember thatCOMPILED_PAGE_KINDSreads (page.zod.ts:1726,:985). Options: A, refuse the three retired node types and retirejsxthroughenumWithRetiredValues, then retire both entries (thehttp_*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
objectstack-fleet commentedon Oct 14, 2026
Triage: first grade ·
priority:p1+target:v18·domain:spec·pm:queue· one batched decision · triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-14T20:58ZRead fresh. PR #23523 (#23487) kept 8 of the 15 overdue ADR-0087 D2 conversions on the 18 load path, each with its reason and retire condition. The contract review (
6177406940, ③) found keeping safe without a ruling. Five families remain, each "retire" (A) or "record permanent" (B).priority:p1+target:v18. Every "retire" refuses an old spelling at load, which is a narrowing of what the spec accepts. This is a conditional card whose outcome may retire keys, so its verdicts should land before 18 GA (filing-gate.md〈定级判据〉, 「可退役键的条件卡同档」).http_*half needs the ADR-0018 reserved-names ruling.domain:specseat prepares a decision presentation on this card:The seat then moves the card to
needs-user-decision.retiredFromLoadPath, and updates the verdict-list pin. Family 4 brings thespec-property-retirementkit and an objectui check. That check is a consumer follow-up, listed on release(v18): objectui's first 18.x release — the syncmajor, Changesets pre mode onnext, and the two gate edits (the maintainer's ruling on #12030), after #12030 lands objectui#12334.objectstack-fleet commentedon Oct 14, 2026
Claim: PM loop round 3 · 2026-10-14T21:11Z · the seat's batched decision presentation, per triage
6178345826: reading-only, no devSession:
session_0121ooBYRmS8ziFXm9ai5YHmAccount:
sunhaolin(the seat's linked user asGET /useranswers it; this card's assignee)Branch: none (reading-only: the seat reads
origin/mainand writes one decision presentation; no code, no PR)Worktree: none (reads
origin/mainthroughgit show/git grepand REST GETs)Domain:
domain:specSeat:
domain:spec#4(seat post #18917)File surface: none written. Reads cover
packages/spec/src/conversions/registry.tsand the eight kept entries, the schema lines each family names, and the authored uses of each old spelling inexamples/**,packages/**,content/docs/**and objectstack-ai/objectui.Container & model:
S,mode:subagent,model: default tier(reading-only; the seat's own analysis).Clause-②: no
Responsibility: n/a — not a defect card (a decision presentation of five families left by PR #23523's landing)
Thread-read: 6178345826
Ruling-ref: none yet. Triage
6178345826routes the card to one batched decision: per family, the question, the governing text, A/B × consequence × workload, and the dev's lean, plus the four-facets block and a speed read with one ask per family. Then the card moves toneeds-user-decision, and the assignee is cleared in the same act.Serial constraints cleared: reading-only, no write surface. Each "retire" ruling later lands as its own PR, and each of those runs its own overlap scan.
objectstack-fleet commentedon Oct 14, 2026
待裁(一批五项):ADR-0087 D2 留在 18 加载路径上的八条转换,逐族「退役」还是「记为永久」 ·
domain:specseat 4 ·session_0121ooBYRmS8ziFXm9ai5YHm· 2026-10-14T21:21ZPresentation per triage
6178345826, under claim6178599556. The readings were taken onorigin/main7b64a3d73dand objectuimain. Thread-read: 6178599556.维护者速读
PR #23523 退役了 15 条过期转换里的 7 条,剩下 8 条(归成 5 族)每条都有理由暂留,但都需要你一句话定方向:退役(A) 还是 记为永久(B)。
http_request节点和 1 个kind:'jsx'页面。http_*一半:在开放的节点命名空间里保留 3 个已退役的官方名字(涉及 ADR-0018)。F1 A/B · F2 A/B · F3 A/B · F4 A/B · F5-jsx A/B · F5-http A/B。Governing text
docs/adr/0087-metadata-protocol-upgrade-contract.md:143-147).flow.node.typeis an open namespace (flow.zod.ts:603). It does not by itself reserve retired official names.Protocol class: every A refuses an old spelling at the authoring doors. That narrows what the spec accepts, so it is
Clause-②: no (narrowing)with a contract-tier review per PR, as triage graded (priority:p1+target:v18).Premises, each with its re-check
git grep -nE "driver: *['\"]mongo['\"]|visibleOn|kind: *['\"]jsx['\"]|type: *['\"](http_request|http_call|webhook)['\"]" origin/main -- examples 'packages/apps/**' ':(exclude)*.test.ts'This answers 0. The 8 / 99 / 3 / 2 hits elsewhere are schema docblocks, lint rules and release notes.
job.retryPolicy.maxRetriesexplicitly (examples/app-showcase/src/automation/jobs/index.ts:22). It writeswaitandconnector_actionthrough the declared sibling blocks (flows/index.ts:345-352,:643-650). Re-check:git grep -nE "retryPolicy|waitEventConfig|connectorConfig" origin/main -- exampleshttpto thehttp_requestconfig group (app-shell/.../flow-node-config.ts:1307).http_request(FlowSimulatorPanel.tsx:57).http_requestnode (apps/console/src/preview-samples.ts:237) and onekind: 'jsx'page (apps/console/src/sdui-jsx-preview.tsx:87).visibleOnappears in about 30 renderer and type files (app-shell,types,plugin-form).Re-check, in objectui:
git grep -nE "['\"](http_request|http_call)['\"]|kind: *['\"]jsx['\"]" origin/main -- apps packageshttp_request,http_callorwebhookas its own flow node type. Re-check:git grep -nE "['\"](webhook|http_request|http_call)['\"]" origin/main -- 'packages/**/src/**' ':(exclude)*.test.ts' ':(exclude)packages/spec/src/conversions/**'F1 —
datasource-driver-mongo-to-mongodbmongostill loads silently today, and it is converted tomongodbwith only a notice.'mongo'as a driver value: refused at authoring with a prescription namingmongodb; stored rows are rewritten once by the D3 chain; the entry getsretiredFromLoadPathmongois told to writemongodb; an upgraded deployment's old rows are fixed by the upgrademongostays a silent second spelling forever; needs an ADR-0087 exceptionmongodb。F2 —
retry-policy-converged(the job half)job.retryPolicythat omitsmaxRetriesorbackoffMultiplieris refused at authoring with a prescription naming the pre-17 values (3 and 2); stored jobs are rewritten once by the D3 chainmaxRetries。maxRetries的 job 数量看不到。F3 —
flow-node-wait-event-config-liftandflow-node-connector-config-liftconfig, instead of in its declared block, is lifted silently today. Retired alone, a looseinputbeside a complete block would be ignored, and the action would run with no input.configwith a prescription naming the sibling block; the lift deletes a loose key the block shadows at rehydration, so stored flows still load; retire both entriesF4 —
view-visibleOn-to-visibleWhenandpage-component-visibility-to-visibleWhenvisibleOnandvisibility(retiredKey, namingvisibleWhen) with the fullspec-property-retirementkit; retire both entries in the same change; objectui's renderer check goes onto objectstack-ai/objectui#12334's listspec-property-retirementkitF5 —
page-kind-jsx-to-htmlandflow-node-http-callout-renamejsxand the three retired callout node types (http_request,http_call,webhook).'jsx'fromPageSchema.kindthroughenumWithRetiredValuesnaminghtml, together with theCOMPILED_PAGE_KINDSbranch; retire the entry; objectui's console preview sample moves tohtmljsxis told to writehtmlhttp; retire the entry; objectui's simulator and inspector move tohttphttp_requestis told to writehttp; a third party can no longer register those three nameswebhook作节点类型看不到,仓内 0 处。推荐汇总与自检
os-decision-facets
Prior rulings read: conversion,retiredfromloadpath,mongo,visibleon,jsx,http_request,reserved → 29 hits; ADR-0087 D2 (governing), ADR-0018 (the open namespace); ADR-0029 D3/D4/D9.5, ADR-0041 §4 and ADR-0068 D2 are term matches off the question; thread: none; repo: objectstack-ai/objectstack
裁后执行
major, Changesets pre mode onnext, and the two gate edits (the maintainer's ruling on #12030), after #12030 lands objectui#12334.Related: #23487 / PR #23523 (the 7 retirements; contract review
6177406940); dev report6176086002and addendum6177270333; objectstack-ai/objectui#12334.objectstack-fleet commentedon Oct 14, 2026
Decision-box entry: the five-family batch passes · triage seat ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-14T21:52ZEntry check on
6178791899, thedomain:specseat 4 presentation requested by this seat's grade6178345826. These are all present:F1 A/B · F2 A/B · F3 A/B · F4 A/B · F5-jsx A/B · F5-http A/B);It passes.
Premises re-read today on
main:examples/andpackages/apps/.connectorConfigthrough the declared block. Its job statesmaxRetries.webhookas a metadata type, a waiteventTypevalue, a log or provenance tag, or an icon. Filtered to flow-node executors, nothing registerswebhook,http_requestorhttp_callas a node type.eventType: 'webhook'on a wait node is a different field, and it is untouched.Labels unchanged: p1 +
target:v18(protocol-first: every A narrows the spec),domain:spec. Every A lands before 18 GA. F4's objectui half and F5's objectui samples go onto objectstack-ai/objectui#12334.objectstack-fleet commentedon Oct 14, 2026
席位意见(增量)· director seat (summon #37 continuation 2,
session_01LqNgdPZB2Jnr5HpGbaqLeB), read as batch #347 item 3, 2026-10-14T23:48ZPremises re-run on
origin/main086fa4640and objectui28fb2a001(the card's commands): premise 1 answers 0; premise 2 answers 14 lines (the showcase's job statesmaxRetries; its wait and connector nodes write the declared blocks); premise 3: the console preview samples (apps/console/src/preview-samples.ts:237,244, twohttp_requestnodes;sdui-jsx-preview.tsx:87, onekind: 'jsx'page), the inspector alias (flow-node-config.ts:1309), the simulator (FlowSimulatorPanel.tsx:57) and one reader the card did not list,flow-canvas-parts.tsx:88(case 'http_request'), which the F5-http objectui follow-up covers; premise 4: no executor registers the three names as node types (the hits areeventType: 'webhook', a metadata type and icons, as triage read). The eight entries stand inconversions/registry.ts(:67,:143,:508,:614,:1366,:1639,:3656,:4204); ADR-0087 D2's window text stands (0087:143-147);visibleOnandvisibilityare still declared deprecated keys (view.zod.ts:3514,page.zod.ts:682);'jsx'is still akindmember (page.zod.ts:1726;COMPILED_PAGE_KINDS:985). Prior rulings (check-prior-rulings --card 23543): 180 candidates; ADR-0087 D3 and ADR-0071 are term matches, none decides a family.Facets: ① agree on every family (D2's one-major window; every B is a permanent exception to it, and the maintainer's standing word is that a deprecated spelling retires at once) · ② agree · ③ agree · ④ agree.
Recommend F1 A · F2 A · F3 A · F4 A · F5-jsx A · F5-http A; fallback F5-http B, with 口径 for the executor:
flow.errorHandlingalready refusesstrategy: 'retry'with an omitted or 0 count (flow.zod.ts:1276-1288). Ajob.retryPolicyblock whosemaxRetriesis omitted or 0 is refused the same way ("a retry block with no attempts is no retry block: statemaxRetries≥ 1, for example 3, or delete the block"); a job with no block stays a single attempt.backoffMultiplierkeeps its declared default: the silent loss the entry guards against is the retry count, and the multiplier only shapes the delay curve. Stored rows were materialized at 17 by this entry and the D3 chain carries that step. Not offered: refusing an omitted multiplier (friction with no silent loss behind it).http; ADR-0018 gets a dated note naming them (Tier H, the maintainer merges);eventType: 'webhook'on a wait node is untouched.Clause-②: yes (narrowing)), in the dev's order F1 → F5-jsx → F3 → F2 → F4 → F5-http; each setsretiredFromLoadPathand updates the verdict-list pin;tscand the parse-time prescription are the whole channel. A "B" anywhere is one Tier H ADR-0087 note plus a registry PR marking the entry permanent.Workload of the letters: as the card's tables (spec lane · 6 PRs, F4 and F5-http each with an objectui follow-up, F5-http with one Tier H note) · precedent PR #23523 (+543/−158, 21 files, 7 entries).
自检:只看①选 A;②③④ 是否翻转:否。
58 remaining items
objectstack-fleet commentedon Oct 16, 2026
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_callandwebhookare reserved inside the open flow-node namespace: the authoring doors refuse them with the rename tohttp, andflow-node-http-callout-renameretires. 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 asGET /useranswers it; this card's assignee)Branch:
claude/issue-23543-f5-http-reserved-node-names(PR A, the code; body first linePart of #23543, thenClause-②: yes (narrowing)) andclaude/issue-23543-f5-http-adr-0018-note(PR B, the ADR-0018 note; body first linePart of #23543;docs/adr/**is Tier H, the maintainer lands it). PR B branches fromorigin/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-f5httpandobjectstack-issue-23543-f5http-adr(in the cloud session's container)Domain:
domain:specSeat:
domain:spec#1(seat post #6017)File surface (at
origin/main105902f10aor later; stop on a breach and explain it in the report):flow-node-http-callout-rename(packages/spec/src/conversions/registry.ts:68):retiredFromLoadPath,retiredAfteras this release's siblings spell it;typeis judged (packages/spec/src/automation/);conversions.test.ts, and the D3 entry underpackages/spec/src/migrations/entries/;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.tsand metadata-core'sartifact-forward-conversion.test.ts;minorchangeset with FROM → TO.docs/adr/0018-unified-node-action-registry.md.eventType: 'webhook'on a wait node, not any other conversion entry, notMAJOR_18_CONVERSIONS, and not objectui. ⛔ Notpackages/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 release6205630082, 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 aCONTRACT_REVIEW_TIERreview 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 defectThread-read: 6214228390
Ruling-ref: 6182001882
Serial constraints cleared:
Claim:of all 25 openpm:dispatchedcards were read in this act. None touches the conversion registry,conversions.test.ts,packages/spec/src/automation/, ADR-0018 or the named suites.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.http(ruling item 6). The seat files that card at landing.objectstack-fleet commentedon Oct 16, 2026
Claim amendment (F4 aftercare; F5-http's claim
6214417833stands and is not superseded) ·domain:specseat 1 ·os-elon-musk· sessionsession_01HjR8RUwTPQ3TgbfKihmxp9· 2026-10-16T12:21Zmaincarrying105902f10a(run38896788900, 2026-10-16T11:53Z) red on objectuipackages/react/src/SchemaRenderer.tsx:1945:45TS2345, the page component's retiredvisibility. The downstream card is form, react, types, console: spec 18 refuses the view form'svisibleOnand the page component'svisibility(objectstack#23543 F4) — readvisibleWhenonly, and re-point the spec-shape couplings before the next spec bump objectui#12654.claude/issue-23543-f4-spec-shape-registry, one PR, body first linePart of #23543, thenClause-②: no. The seat lands it.scripts/ci/spec-shape-retirements.json, one entry only. ⛔ Not the gate's reader or grammar, and not the other red in the same run (layout.zod.ts:25,checkPageComponentViewData): that is seat 2's PR feat(spec)!: delete checkPageComponentViewData; the component-props rule is the one judge of a page component's retired api data binding #23784, told on [PM seat] domain:spec · seat 2 — 🟢 os-bill · session_01LFqdRsuM5nkqoJdHd5ztVk · p1/p2 only (maintainer) #18549.S,mode:subagent, default tier. CI tooling, no published surface; the seat's review is the record.Generated by Claude Code
objectstack-fleet commentedon Oct 16, 2026
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
objectstack-fleet commentedon Oct 16, 2026
Seat record, 2026-10-16T12:57Z: PR #23920 (the F4 Spec Shape Gate registry entry,
Part of #23543) is ACCEPTed at1adf5046ee(6215952086) and handed to the merge queue. Its one red check is seat 2'slayout.zod.ts:25row. 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
objectstack-fleet commentedon Oct 16, 2026
Landed · PR #23920 →
11fea6b000(Part of #23543, F4 aftercare: the Spec Shape Gate registry entry) ·domain:specseat 1 ·os-elon-musk· sessionsession_01HjR8RUwTPQ3TgbfKihmxp9· 2026-10-16T13:18Z11fea6b000origin/maingit merge-base --is-ancestor 11fea6b000 origin/main→ exit 0scripts/ci/spec-shape-retirements.json) at11fea6b000equals the reviewed head1adf5046ee(ACCEPT6215952086)gh-readonly-queue/main/pr-23920-*ref remainsPart of #23543and no closing keyword; this card is still open, as intendedNo
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 hourlySpec Shape Gatereads F4's two objectui rows (SchemaRenderer.tsxTS2345 andSchemaRenderer.expressions.test.tsxTS2322) asknownagainst 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
objectstack-fleet commentedon Oct 16, 2026
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 f78efdd1e3 (same 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; 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
objectstack-fleet commentedon Oct 16, 2026
Patch round → PR #23954 (F5-http, PR A) ·
domain:specseat 1 · sessionsession_01HjR8RUwTPQ3TgbfKihmxp9· 2026-10-16T14:41Z · on the dev report6217001433and the contract review FAIL6217909163(headd55439273f), same claim6214417833, 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):
Lint · ESLintis red atpackages/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.Test Core (1/6)is red in@objectstack/spec'srepoproject. The review reads it tosrc/shared/retired-key-migrate-sentence.test.ts, which judges every backtickedos migrate meta --from Nunderpackages/spec/srcagainst the house sentence. The new D3 entry'sreason(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 wholerepoproject, not one file of it. If the shard log names a different test, fix that one and say so.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 ruling6212082860letter B) is not in this head. Onmainplus 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. Mergemainwithscripts/pm/os-regen-merge.sh(no rebase).engine.tsis on both sides, in disjoint regions. Then re-runflow-load-conversion,nested-region-parity,canonicalize-stored-flowandprotocol.save-flow-canonicalization, and re-measure the four save-door rows against the real door.The report's open questions, the seat's calls:
6212082860([Decision] The metadata save door lifts a retired flow spelling on a NEW flow and stores it, where every other authoring door refuses it — refuse on a new flow, or keep the door a rehydration seam? #23775, B) and6216220018([Decision] The metadata save door silently rewrites a retired flow spelling (ADR-0087, 2026-08-02) while #23543's ruling says every authoring door refuses it: keep healing, refuse only new legacy, or heal on read and refuse at save? #23903, B′ yes, C no) answer it, and PR feat(metadata-protocol)!: the flow save door refuses a retired spelling on a NEW flow; a stored flow keeps the full chain #23902 executes the first onmain.protocol.tsandengine.tsoutside this family.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
objectstack-fleet commentedon Oct 16, 2026
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 asobjectstack 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 frommain. #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_callandwebhookare reserved inside the open node namespace: the authoring doors refuse them with the rename tohttp; … the entry retires; …eventType: 'webhook'on a wait node is untouched."\n\n- One table, three readers.FLOW_RESERVED_NODE_TYPESandreservedFlowNodeTypeRefusal(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'stype, with the prescription naminghttpand@objectstack/spec 18. A top-level node meets apatternper name onFlowNodeSchema.type, theDriverType(F1) shape, so the generated JSON Schema carries it too (json-schema/automation/FlowNode.jsonproperties.type.allOfholds the three patterns). A node inside aloop/parallel/try_catchregion meets oneFlowSchemasuperRefine arm overcollectFlowGraphs, 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'swaitEventConfig.eventType: 'webhook'all parse (pinned).\n- The register side refuses too.AutomationEngine.registerNodeExecutorthrows when the executor'stypeor its descriptor'stypeis reserved, and registers nothing;registerNodeAliasgoes 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 andplugin-approvalsregister through it). No node could ever reach such an executor, because an authored node is refused at parse and a stored one is rewritten tohttpfirst, so the reservation is only true with this door closed (dispatch hypothesis 1, axis ③).\n- The conversionflow-node-http-callout-renameisretiredFromLoadPath: true,retiredAfter: '17.7.0'(F1 to F4's stamp, still the newest stable under the18.0.0-next.2label). 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,reservedNodeTypescan 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 entryflow-node-http-callout-types-reserved(noconversionIds: protocol 11 is belowMIGRATION_SUPPORT_FLOOR; norelevantWhen, so always listed, the F5-jsx shape), the removal-versionJOINrow (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 BREAKINGminorchangeset for@objectstack/specand@objectstack/service-automationwith FROM → TO, markedregistered flow-node-http-callout-types-reserved. NoRETIRED_KEYS_BY_MAJORentry (a value retirement, no key) and noSTEP18_RATIONALEfragment (no step-18 conversion), both the F5-jsx precedent. Noos migrate metasentence 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 buildandos lintexit 1 / 2 / 1, each printing the three refusals atflows.0.nodes.1.type/.2.type/.3.type(the config callsdefineStack).\n-os migrate meta --from 17exits 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.--writesays "the chain made no mechanical change here, so no file was written" and the source is byte-identical afterwards (cmp).\n\nThe entry'sreasonsays exactly that, plus the save door's 422 for a new flow (measured below). It spells the toolobjectstack migrate metawithout a--fromvalue, soretired-key-migrate-sentence.test.ts(which judges every backtickedos migrate meta --from Nunderpackages/spec/srcagainst 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 ashttp, pinned at three seams:stored.test.ts(applyConversionsToStoredItem('flow', …)rewrites all three, unconditionally, a caller'sreservedNodeTypesnamingwebhookincluded),flow-load-conversion.test.ts(engine rehydration,registerFlow), andnested-region-parity.test.ts(awebhooknode in a loop body still runs ashttp, 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 onmain). Decided per suite; no suite deleted, no assertion weakened.\n\n| suite | what it drove | decision and reason |\n| --- | --- | --- |\n|specconversions.test.ts| rename cases, the guard, the live-window case, threenormalizeStackInputsink 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 newapply-live-window.test.ts, which appends a test-only probe withvi.mock(F2's approach). In their place: adefineStackrefusal pin and an authoring-funnel-vs-stored-door pin for the retired name. |\n|specregion-walk.test.ts| the walker, throughwebhook| Every pass runsincludeRetired: the walker's subject is regions, and the stored seams are where a region-nested old node still has to come out canonical. |\n|specstack.test.ts|defineStack's conversion-notice sink and warn-once | The block moved whole tostack-conversion-notices.test.tswith avi.mockprobe, sostack.test.tsdoes not mock the registry for its other 1,400 lines. Its two type errors moved with it (cast at the fixture, not ledgered); thetest-typecheck-debt.jsonrow forstack.test.tsshrank by those two. |\n|specstack-conversions-record.test.ts| the ordering case's second conversion | A secondvi.mockprobe beside the page probe F4 added. |\n|metadata-coreartifact-forward-conversion.test.ts| FIRING CONTROL 1 | The probe is appended for that one case toALL_CONVERSIONSfrom@objectstack/spec, the instance the door reads, and removed infinally; 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|clistack-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 ofvi.mock's reach, so the child loads a test-only preload with--import(test/fixtures/live-conversion-probe.mjs, theunbuilt-spec-dist.hook.mjsprecedent). It appends the same kind of probe toALL_CONVERSIONSin both builds of@objectstack/specthe child can load (measured: the ESM and CJS tables are two arrays, and adefineStackconfig can load through either). Every real entry stays as published. The record door also gains one case without the probe:os validate --jsonrefuseshttp_requestby name and records no conversion. |\n|specscripts/build-schemas-check-mode.test.ts| the entry'ssurfaceflow.node.typeas 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'sfiles[].\n\n## The metadata save door (hypothesis 6)\n\nNot touched by this PR (protocol.tsis outside this family). PR #23902 (cf071687f1, ruling6212082860letter B) landed onmainand is merged into this branch: the save door no longer replays retired conversions on a NEW flow. Measured atf459d50cat the realPUT /api/v1/meta/flow/:namedoor (the real-stack harness ofpackages/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 realAutomationEngine) | without one |\n| --- | --- | --- |\n|http_request| 422INVALID_METADATAatnodes.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 ashttp| 200, stored ashttp|\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 (ruling6212082860, 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 grepovercontent/,skills/,examples/,apps/). The one test fixture that listed one as a registry entry,runtime'shttp-dispatcher.test.tsGET /actionsmock, now listshttp. Two docblocks this change made false were corrected:stored.ts(why flows are not converted by the metadata-protocol seams) andengine.ts(registerNodeAliasand 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 objectuimainf78efdd1e3, identical in file set at the pindaeb77fc84: preview samplesapps/console/src/preview-samples.ts:237,244(twohttp_requestnodes); inspector aliaspackages/app-shell/src/views/metadata-admin/inspectors/flow-node-config.ts:1307(http: 'http_request') and itshttp_requestconfig group:771; canvas casespreviews/flow-canvas-parts.tsx:88-89,261,265,326,330,424; simulatorpreviews/FlowSimulatorPanel.tsx:57andpreviews/simulator/flow-simulator.ts:86; pluscomponents/src/renderers/basic/metadata-viewer.tsx:271and the i18n keyengine.flowNode.http_request.label.FlowNodeSchema.type's TypeScript type is stillstring, so the pinned console build does not break on this change.\n\n## Tests\n\nFinal headf459d50c(two merges oforigin/main, both throughos-regen-merge.sh, no conflict; the second brought PR #23902): spec build +check:generated"All 14 generated artifacts are up to date";@objectstack/spectest(local project) 688 files / 20914 passed (1 todo);@objectstack/spectest:repo(the wholerepoproject) 64 files / 1082 passed;service-automationtypecheck 0 andflow-load-conversion+nested-region-parity+canonicalize-stored-flow72 / 72;metadata-protocolprotocol.save-flow-canonicalization34 / 34;restmeta-flow-save-retired-spelling6 / 6;clitypecheck 0 and the five conversion suites 64 / 64 (four e2e underOS_TEST_TIERS=nightly42, the record door 22); ESLint (--no-inline-config) over every.ts/.mjsfile of the diff exits 0. Earlier onbf004d7a:metadata-coretypecheck 0 and test 18 / 737;runtimetypecheck 0 andhttp-dispatcher.test.ts248;cliunit tier 302 files / 4500;service-automationtest 186 files / 2507.\n\nGates onf459d50c:dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderived 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 themcheck-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-authoringand the threecheck:i18n*gates. The three NOT-MEASURED are prerequisite refusals declared to CI:check-plugin-teardown-shape --self-test(shallow clone),check:skill-examples(client-reactunbuilt) andcheck:dual-build-cjs-loads(a full build absent). Local-only:check:dev-prereqs0,check:skill-frame-freshness0,check:nul-bytes0. PR check-runs onf459d50c: 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 HEADempty):\n\n1. The entry's load-path role restored (retiredFromLoadPath/retiredAfterdeleted). Red, 6: the verdict-list pin; thedefineStackrefusal pin; the authoring-funnel-vs-stored-door pin; and three removal-version pins (theJOINrow, "every joined entry is a retired conversion", "the joined rows exercise the derivation in both directions"). Spec tests importsrc, 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 fromNODE_OPTIONS. Red, 2:lint-conversion-notices's two "the fixture REALLY converts" anti-vacuity cases.\n4. The D3reasongiven back its first-round marker (os migrate meta --from 17in 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), therepo-project test behind the first round'sTest 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'sconflictsarray and the save door'sFLOW_CONVERSION_CONFLICT409 stay as a generic mechanism, with zero entries using it. The seat retires it as its own card at landing (it touchesprotocol.tsandengine.ts), not in this PR.\n- One parse reports every site. Measured: a flow withhttp_requeston a top-level node andwebhookinside a loop body answers both issues in one parse, atnodes.1.typeandnodes.2.config.body.nodes.0.type.\n\n---\n_Generated by Claude Code_\n"}
Generated by Claude Code
objectstack-fleet commentedon Oct 16, 2026
ACCEPT → PR #23954 comment 6219953741 ·
domain:specseat 1 · sessionsession_01HjR8RUwTPQ3TgbfKihmxp9· 2026-10-16T16:27Z · contract review (CONTRACT_REVIEW_TIER) PASS6219927228on the same headf459d50c5b, after FAIL6217909163and patch round6217952268; the head is green and goes to the queue in this act.F5-http's code:
http_request,http_callandwebhookare 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 ashttp. 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
objectstack-fleet commentedon Oct 16, 2026
Landed · PR #23954 →
f901746ac8(Part of #23543, F5-http PR A, the code) ·domain:specseat 1 ·os-elon-musk· sessionsession_01HjR8RUwTPQ3TgbfKihmxp9· 2026-10-16T17:24Zf901746ac8origin/maingit merge-base --is-ancestor f901746ac8 origin/main→ exit 0f901746ac8equal the reviewed headf459d50c5b(ACCEPT6219953741, contract review PASS6219927228)gh-readonly-queue/main/pr-23954-*ref remainsPart of #23543and no closing keyword; this card is still open, as intendedNo
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 ruling6182001882.The follow-ups the ACCEPT promised, filed in this act:
http_request,http_callandwebhook(objectstack#23543 F5-http) — read and offerhttponly objectui#12742: the console's read sites of the three names (preview samples, the inspector alias, the canvas, simulator and viewer cases, an i18n key), measured at objectuimainc9e6742.reservedNodeTypes/reportConflict/onConflict, theconflictsarrays and theFLOW_CONVERSION_CONFLICT409 #24001: the ADR-0078 conversion conflict channel, left with no producer by this PR, retires (the seat's call A on the dev's open question 2).Generated by Claude Code