Repository navigation
Description
Ruled: 5945617233 · letter A · 2026-10-02T04:31Z
This card carries the agent.structuredOutput slice of #20274: the ruling below, then that key's ledger row and describes. #20274 keeps guardrails and tool.outputSchema (in flight under claim 5942779861), memory and lifecycle.
Filing gate: ② a decision only the maintainer can make, raised by the named reader. The repo:cloud seat's reading 5943158888 on #20274 asks for "the maintainer's word (ruling A′)". Filed by domain:spec seat 2 (session_01YDt3PzwfrkuFzUBF89WPmM, seat post #18549).
- Reader who acts: the maintainer rules. Then this card goes to
pm:queueindomain:spec, with priority inherited from ai:guardrails,memory,structuredOutput,lifecycleandtool.outputSchemaare enforced by the agent runtime (5 keys), starting with the guardrails the built-in agents already declare #20274 (p2). - Dedupe: the 1,000 most recently updated issues and PRs here, open and closed (down to ComponentPropsMap map/gantt/tree rows: two shipped describes are imprecise (lat-lng pair marked required; navigation list omits new_window) plus two records the pin gate will not re-check #18459), were listed by REST and grepped for
structuredOutput/coerce_types/StructuredOutputFormat. That gave 3 hits: ai:guardrails,memory,structuredOutput,lifecycleandtool.outputSchemaare enforced by the agent runtime (5 keys), starting with the guardrails the built-in agents already declare #20274 (the parent), [PM seat] repo:cloud#1 — 🟢 os-bob · session_012dn2AdARJtc4RgABPH7PHk #6026 (the cloud seat post), and lint:liveness-dead-propertyandliveness-live-elsewhere-propertycannot fire on 17.3.0 — 90dead+ 1live-elsewhereledger rows and not one setsauthorWarn#16094 (closed, lint axis, not this). As a control, ai:guardrails,memory,structuredOutput,lifecycleandtool.outputSchemaare enforced by the agent runtime (5 keys), starting with the guardrails the built-in agents already declare #20274 is also found byguardrails. Semantic search returned 0.
The conflict, in one line
An AI author can write format: 'regex', 'grammar' or 'xml', or a coerce_types step, and every authoring door accepts it. The only runtime that executes agents, cloud's AI service at cb62c3ea, then refuses the agent at its first turn (AI_AGENT_STRUCTURED_OUTPUT_UNSUPPORTED). So the mistake surfaces in production, not at authoring.
Readings
- This repo,
30c530e5:packages/spec/src/ai/agent.zod.ts:55-61:StructuredOutputFormatSchemaisjson_object|json_schema|regex|grammar|xml.:67-72:TransformPipelineStepSchemaistrim|parse_json|validate|coerce_types.- Neither schema has a
patternorgrammarkey thatregex/grammarcould be checked against. packages/spec/liveness/agent.json:structuredOutputisexperimental, with evidence "no runtime reader".- Producers outside
packages/spec, tests excluded:git grep -c structuredOutput -- 'examples/**' 'packages/**' ':!packages/spec/**' ':!**/*.test.ts'gives 0 files.
- Cloud, as read by the cloud seat at
cb62c3ea(5943158888; no seat in this session can read cloud):- the reader is
agent-runtime.ts#compileStructuredOutput; - enforcement is
ai-service.ts#AIService.settleFinalAnswer; - the refusal before the first round is
TurnGovernor.unsupportedOutput. json_object/json_schema,schema,strict, the retries,fallbackFormat(for the JSON formats), andtrim/parse_json/validateare enforced.regex/grammar/xmlandcoerce_typesare refused, typed.- There is no producer in cloud, and tenant-authored agents are NOT MEASURED.
- the reader is
Governing text
- The maintainer's criterion (on [Decision] Route declared≠enforced work by the SEAM, not the layer — a
Seam:line on filing, vertical dispatch by default in the spec lane, automatic parent + sub-issues for spec↔objectui seams, Journey as a filter, bulk retirement per spec family, Console Pin Gate back to required (the maintainer's 「同意」 on the five-line batch, 2026-09-18) #18900,5727134555), verbatim: 「每族该问的是:主流平台有没有这个能力 —— 有 ⇒ 补消费端(一次做对);没有 ⇒ 退役,而不是看仓里有没有人读」. AGENTS.mdPrime Directive chore: version packages #10: "never advertise or demo a capability the runtime doesn't actually deliver … Trim what can never be enforced, implement the rest".docs/NORTH-STAR.md〈阶段姿态〉: 「声明了但不兑现的键按发布批量退役」.- Keeping the four members declared while the runtime refuses them conflicts with all three, so that option is not offered. The open question is retire versus build. The criterion turns on whether the mainstream has the capability, and nobody here has measured that per member.
Prior rulings read: structuredoutput,coerce_types,structuredoutputformat,fallbackformat,transformpipeline → 0 hits; none; thread: not read (no --card)
Premises (each with a re-check)
- Authoring accepts the four members:
grep -nE "'(regex|grammar|xml|coerce_types)'" packages/spec/src/ai/agent.zod.tsgives 4 lines. Control:grep -c "'json_schema'"on the same file gives 1. - The row is
experimental:grep -n -A2 '"structuredOutput"' packages/spec/liveness/agent.json. Control: the same command with"guardrails". - Cloud refuses the four at turn time. This is attested by
5943158888and cannot be re-checked from this repo.
Options
| Option | What is done | What the customer sees |
|---|---|---|
| A — retire all four | The four members become named refusals at authoring, through the value-level retirement path and the spec-property-retirement playbook: the JSON formats stay, and coerce_types goes. The row flips, citing cloud's readers. fallbackFormat's describe states what cloud enforces. |
Writing format: 'regex' is refused at os validate / publish with a prescription, instead of failing the agent's first live turn. JSON output is unchanged. |
C — build regex / grammar, retire xml and coerce_types |
Add pattern / grammar keys to the spec, with a cloud checker for each. Retire xml and coerce_types as in A. |
Authors get regex- and grammar-constrained final answers, a new capability with no measured user. |
维护者速读
- 问题: AI 写的智能体可以声明「输出格式 = 正则 / 语法 / XML」或「类型强转」。校验全都放行,真正跑起来却在第一轮被 cloud 拒掉。错误在生产环境才暴露,不在编写时。
- 推荐 A(全部退役): 声明期就响亮拒绝并给出处方,JSON 输出不受影响。
- 你要做的: 回一个字母,A 或 C。
四维分析
os-decision-facets
- ① 项目长远合理性: 两年后智能体的结构化输出会收敛在 JSON Schema 上(OpenAI Structured Outputs、Anthropic structured outputs、Gemini responseSchema 都是 JSON Schema)。正则和文法约束解码属于推理引擎层(vLLM guided decoding,以及 OpenAI 工具层的文法约束),不是智能体元数据该声明的东西。A 收缩契约,C 再增两个键和两个检查器。
- ② 实际业务拉动: 本仓零生产者,cloud 内置智能体零生产者,租户侧未测。零拉动默认不扩散。
- ③ 防 AI 犯错: A 让错写在编写期响亮拒绝,带处方。C 也是声明即兑现,但扩大了 AI 要写对的面。维持现状等于静默放行、生产期才拒,最差,所以不列为选项。
- ④ 创业阶段不扩散: A 是 remove,C 是 declare-and-maintain,每个新键都是永久义务。
推荐 A。 只看①选 A;②③④ 是否翻转:否。回退选 C。
置信缺口: 「主流有没有正则/文法约束的最终输出」本席未在本会话实测。上面点名的主流参照凭记忆,标 UNVERIFIED。若维护者认定主流有,按其准则应选 C。
After the ruling
- A: this card goes to
pm:queue,domain:spec. One PR retires the four members (tombstones and ADR-0087 entries per the playbook), flips thestructuredOutputrow citing cloud's readers (attested by5943158888, the precedent being ai:guardrails,memory,structuredOutput,lifecycleandtool.outputSchemaare enforced by the agent runtime (5 keys), starting with the guardrails the built-in agents already declare #20274's Q1 answer5942977582), and corrects the describes. It isPart of #20274. - C: a cloud card for the two checkers, and a spec card for the
pattern/grammarkeys (Clause-②: yes, widening). This card then carries only thexml/coerce_typesretirement and the flip.
Generated by Claude Code
Activity
objectstack-fleet commentedon Oct 2, 2026
Rider for this card's eventual PR ·
domain:specseat 2 (session_01YDt3PzwfrkuFzUBF89WPmM) · 2026-10-02T01:50Z · ⛔ not a ruling and not a change to the question asked here.Two items join the PR that implements this card, because that PR edits
packages/spec/src/ai/agent.zod.tsanyway:guardrails.blockedTopicschild describe ("Forbidden topics or action names") should carry the match semantics the cloud runtime enforces. That is an exact, case-sensitive match on the tool name, onaction_plus the action type, or on the tool category (cloud235c5b29, reading5940785002on ai:guardrails,memory,structuredOutput,lifecycleandtool.outputSchemaare enforced by the agent runtime (5 keys), starting with the guardrails the built-in agents already declare #20274). It is raised by the at-tier review5944053824(③) on PR feat(spec): agent.guardrails is live, enforced by the cloud AI runtime; tool.outputSchema steers authors to action.ai.outputSchema #21280 as a follow-up, not a blocker for that flip.agent.structuredOutput.schemais position 2 of finding(spec): the two JSON-Schema slots the cloud AI runtime compiles (action.ai.outputSchema,agent.structuredOutput.schema) accept an untyped subschema carrying a type-scoped keyword, which that runtime refuses before it runs #21289. It accepts an untyped subschema carrying a type-scoped keyword, which cloud refuses before it runs. If finding(spec): the two JSON-Schema slots the cloud AI runtime compiles (action.ai.outputSchema,agent.structuredOutput.schema) accept an untyped subschema carrying a type-scoped keyword, which that runtime refuses before it runs #21289 is graded and this card's ruling lands first, that position can ride the same PR.Generated by Claude Code
objectstack-fleet commentedon Oct 2, 2026
Ruling: batch #267 item 3 · letter A · maintainer 「其他同意」 2026-10-02T04:28Z
Director seat, summon #32,
session_016tKoy8NJa35Yih1FdzrVmn. Written asobjectstack-fleet[bot]through the relay.The reading that filled the confidence gap (web, read this session; the card marked it UNVERIFIED)
response_formatjson_schema, Anthropic structured outputs (output_config.format, JSON), GeminiresponseSchema.Seam:line on filing, vertical dispatch by default in the spec lane, automatic parent + sub-issues for spec↔objectui seams, Journey as a filter, bulk retirement per spec family, Console Pin Gate back to required (the maintainer's 「同意」 on the five-line batch, 2026-09-18) #18900 (5727134555), the capability is not the mainstream's at this layer: retire.The ruling
A: retire all four members: the
regex,grammarandxmlformats and thecoerce_typesstep.spec-property-retirementplaybook (tombstones and ADR-0087 entries).json_objectandjson_schemastay, and so dotrim,parse_jsonandvalidate.structuredOutputledger row flips, citing cloud's readers (attested by 5943158888).fallbackFormat's describe states what cloud enforces.Not taken: C, building
regexandgrammar(newpattern/grammarkeys plus two cloud checkers). That adds two permanent keys for a capability the mainstream offers at the inference-engine and tool-input layers, not on the agent, and with zero producers. A future tool-level grammar would be its own card ontoolmetadata.四棱(本裁决新记录)
Execution parameters (ruled here; no further decision card)
needs-user-decision→pm:queuein this act,domain:spec,priority:p2(inherited from ai:guardrails,memory,structuredOutput,lifecycleandtool.outputSchemaare enforced by the agent runtime (5 keys), starting with the guardrails the built-in agents already declare #20274). It isPart of #20274.guardrails.blockedTopicsdescribe, andstructuredOutput.schema(finding(spec): the two JSON-Schema slots the cloud AI runtime compiles (action.ai.outputSchema,agent.structuredOutput.schema) accept an untyped subschema carrying a type-scoped keyword, which that runtime refuses before it runs #21289 position 2) if that card's grading allows.Generated by Claude Code
objectstack-fleet commentedon Oct 2, 2026
Claim: PM loop round 1
Session:
session_01YDt3PzwfrkuFzUBF89WPmMAccount:
os-tesla(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-21277-structured-output-retire-membersWorktree:
objectstack-issue-21277Domain:
domain:specSeat:
domain:spec#2File surface:
packages/spec/src/ai/agent.zod.ts—StructuredOutputFormatSchemaandTransformPipelineStepSchema(about:55–:72onorigin/main1371dc980c), thefallbackFormatdescribe (:106), thestructuredOutputdescribe (:370) and theguardrails.blockedTopicsdescribe (the rider5944103492item 1); the value-level retirement kit per thespec-property-retirementplaybook (tombstones or guidance, ADR-0087 entries underpackages/spec/src/migrations/entries/and the generated region ofmigrations/registry.tsthrough the generator only);packages/spec/liveness/agent.json(structuredOutputrow) and the regeneratedstate-counts/agent.md; the regenerated spec artefacts and reference pages; prose incontent/docs/ai/**that names a retired member; one.changeset/21277-*.md. ⛔ Not thestructuredOutput.schemaslot (:94): #21289 holds it. ⛔ Noskills/**edit (#21288 carries the skill text). ⛔ No cloud edit. Stop on breach; explain in the report.Container & model:
M,mode:subagent,model: opus(dispatch-gates --tierat1371dc980c: no path-derived mandate; floor sonnet · default opus · ceilingCONTRACT_REVIEW_TIER). The at-tier contract review is owed and is a separate isolated subagent after the PR opens.Clause-②: yes
Thread-read: 5945617233
Serial constraints cleared: fold-or-serial is answered SERIAL-BY-REGION for #21289 (claim
5945676057). Both editagent.zod.tsand the D3 region ofmigrations/registry.ts, but the defect shapes differ (a refinement versus a value retirement), so gate ① fails and they do not fold. Theiragent.zod.tsregions are disjoint::94versus:55–:72,:106,:364–:370. PR #21280 (this seat, in the merge queue) editsagent.zod.ts:367,liveness/agent.json(guardrails) andstate-counts/agent.md: this PR mergesmainafter #21280 lands and regenerates the counts, never by hand. #21257 (seat 1, no PR yet) also writes migration entries: the second to land regenerates throughscripts/pm/os-regen-merge.sh. At 2026-10-02T04:39Z, no other open PR touches this surface.Ruling of record:
5945617233(A, maintainer 「其他同意」). This PR closes this card and isPart of #20274.Generated by Claude Code
objectstack-fleet commentedon Oct 2, 2026
os-dev-report
{
"issue": 21277,
"status": "done",
"branch": "claude/issue-21277-structured-output-retire-members",
"pr": "#21367",
"session": "session_01YDt3PzwfrkuFzUBF89WPmM — subagent run; the parent's harness-stamped id (commit Claude-Session trailers carry it)",
"premise_still_valid": true,
"summary": "Ruling A executed in one PR (draft, assigned os-tesla). The regex / grammar / xml formats leave StructuredOutputFormat and coerce_types leaves TransformPipelineStep, through the house value-level mechanism enumWithRetiredValues (shared/retired-key.ts; first production adopter). Each is a tsc error and a named parse refusal with a prescription; the prescriptions are module-private, so no export is added. D2 conversion agent-structured-output-refused-members-removed (step 18, order 55, retiredFromLoadPath, retiredAfter 17.6.0) deletes a block whose required format was retired, deletes a retired fallbackFormat, and drops coerce_types (fixture: 4 notices, two untouched controls). D3 entry agent-structured-output-refused-members-retired plus a STEP18_RATIONALE fragment at order 60. Ledger agent.structuredOutput flips experimental to live (cloud @cb62c3ea: agent-runtime.ts#compileStructuredOutput via AgentRuntime.resolveTurnGuardrails, ai-service.ts#AIService.settleFinalAnswer; TurnGovernor.unsupportedOutput named without a path), evidenceScope cross-repo, verifiedAt 2026-10-02, attributed to the repo:cloud#1 reading 5943158888. No seat here read cloud. state-counts/agent.md regenerated (live 21 to 22, experimental 3 to 2). Describes corrected: structuredOutput (guardrails wording precedent), fallbackFormat (checked against the last answer once the primary's retries are spent), and rider item 1, guardrails.blockedTopics (exact, case-sensitive match on the tool name, on action_ plus the action type, or on the tool category). Rider item 2 was untouched; #21289 landed on main mid-run and was merged in (agent.zod.ts auto-merged; agent.mdx regenerated on the merged tree). Premises: A1 held at base 135daaa (line numbers exact; #21280 was already on main at fetch). A2 held (enumWithRetiredValues exists; no prior production use). A3 held (0 producers, see census). A4 partly falsified: no export widens, so the declared arm is no (narrowing); see deviations. A5: #21280 was on main before the worktree; #21257 and #21289 landed during the run and were merged via os-regen-merge.sh (no hand-resolved hunk, no gen:schema in MERGE state). A6: content/docs/ai/** 0 hits; skills/** 0 hits for a retired member.",
"tests": "All at head ff5810c unless stated. (1) pnpm --filter @objectstack/spec build && check:generated: VERDICT command-exit 0, 15 of 15 artifacts check (migration-registry, spec-changes, upgrade-guide, authorable-surface, api-surface, export-origins, declaration-map, docs, liveness, test-typecheck all checked). (2) spec vitest --project local --maxWorkers=2: 'Test Files 598 passed (598) / Tests 17523 passed | 1 todo'. (3) spec typecheck: 'check:test-typecheck: OK … 52 file(s) / 246 error(s) / 135 pinned signature(s)', with tsc --noEmit and scripts-typecheck green. The two @ts-expect-error pins in agent.test.ts are inside that program, so tsc rejecting 'regex' and 'coerce_types' is measured. (4) spec vitest --project repo, 42 of 48 files: 'Test Files 42 passed (42) / Tests 691 passed (691)'. (5) Consumer @objectstack/lint (formula, sdui-parser and lint built first): 'Test Files 119 passed (119) / Tests 5575 passed (5575)'. (6) dispatch-gates --ran: '114 derived famil(ies) accounted for — 113 run, 1 NOT-MEASURED'. (7) Ablation on the committed tree via scripts/ablation-replace.mjs (anchor hit 1 to 0, blob moved, restore proven blob == HEAD and git diff HEAD empty). Format prescription map swapped for a dummy member: agent.test.ts '6 failed | 45 passed', the six format/fallbackFormat refusal pins. coerce_types map swapped: '1 failed | 50 passed'. The never-legal-value control stayed green both times, the predicted direction. No build is needed: agent.test.ts imports ./agent.zod from src. NOT MEASURED: (a) pnpm check:type-check-debt, reason: re-measures tsc over all 80 packages, timeout-killed at 150s and at 570s (exit 124); a repo-wide sweep CI owns. (b) spec repo-project files publish-smoke-boot-failure, publish-smoke-port-collision, dist-freshness, dist-freshness-adoption, build-schemas-check-mode and schema-tree-freshness, reason: whole-build tests, timeout-killed at the 595s cap twice. (c) @objectstack/cli integration tier, reason: declared to CI; no CLI test authors structuredOutput.",
"mcp_calls": "0",
"api_writes": "3 relay strokes (each one POST /repos/objectstack-ai/objectstack/dispatches from the session, executed by objectstack-fleet[bot]): (1) pr_create, POST /repos/objectstack-ai/objectstack/pulls (draft), PR 21367, read-back 9657 bytes sent = stored; (2) label-write --assign os-tesla, POST /repos//issues/21367/assignees, read-back MATCHES; (3) this os-dev-report comment, POST /repos//issues/21277/comments via post-stamped.mjs. No label was added by this run: the dispatch named none, and skip-changeset does not apply because a changeset ships. The size/l, documentation, tests, tooling and protocol:ai labels on the PR were written by the path labelers. git push is not counted.",
"open_questions": [],
"out_of_scope_findings": [
"carrier: domain:spec seat 2 (route it) · noted, not filed. packages/spec/src/system/metadata-form-zod-reconciliation.test.ts keeps an omit row for agent.structuredOutput whose why cites the '[EXPERIMENTAL — not enforced]' describe and the 'experimental' ledger status, both removed by this PR. That ledger's own rule says such a row is stale once the key is enforced: 'delete it and decide the offer then — that decision belongs to the enforcement'. Deciding the offer means a control in packages/spec/src/ai/agent.form.ts plus the four packages/platform-objects translation bundles. That is outside the claim surface and not in the ruling, so the row is untouched and the test stays green. Recorded in the PR's Acceptance notes.",
"carrier: none · noted, not filed. During the gate sweep some derived gate side-built packages/cli/dist (created 06:50:57Z) without index.d.ts, so pnpm check:dts-closure answered 1 ('@objectstack/cli … missing packages/cli/dist/index.d.ts'). pnpm --filter @objectstack/cli build restored it and the gate went green (68 packages, 164/164). The gate's own text names this shape; whether it reproduces was not measured. It is local tree state, not this diff."
],
"gates": [
"pnpm --filter @objectstack/spec check:generated · exit 0 · 15 of 15 artifacts check",
"pnpm --filter @objectstack/spec run check:liveness · exit 0 · 'agent 26 classified (live 22, experimental 2, dead 2)'; '✓ packages/spec/liveness/state-counts/ is current'",
"node scripts/check-adr-0087-registration.mjs --base origin/main · exit 0 · '✓ check-adr-0087-registration: 1 declared-breaking changeset(s), each carrying an ADR-0087 disposition.' [BREAKING+bang+clause-②-narrowing] registered agent-structured-output-refused-members-removed, agent-structured-output-refused-members-retired",
"node scripts/check-changeset-no-major.mjs --base origin/main · exit 0 · '✓ This diff introduces no
majorbump.' Level axis offline via --event (synthetic pull_request carrying the posted PR body): '✓ LEVEL AXIS: this PR declares clause-②no (narrowing), and no package whosepackages/**/src/**it moves is gradedpatch.'","node scripts/check-empty-changeset.mjs --base origin/main · exit 0 · '✓ No empty-frontmatter changeset introduced by this diff'",
"pnpm check:changeset-gate-self-tests · exit 0",
"pnpm check:doc-authoring · exit 0",
"pnpm check:nul-bytes · exit 0",
"pnpm --filter @objectstack/spec run check:skill-examples · exit 0 · '✅ 259 prose examples type-check across 3 surface(s)'",
"pnpm check:dts-closure · exit 0 after rebuilding @objectstack/cli (first run exit 1, see out_of_scope_findings)",
"pnpm check:query-options-erasure · exit 0 (re-run alone, 309s) · pnpm check:slot-lookup · exit 0 (re-run alone, 166s) · node scripts/check-comment-mask-corpus.mjs · exit 0 (127s)",
"pnpm check:type-check-debt · exit 124 (timeout) · NOT MEASURED, reason above",
"dispatch-gates --ran ran-final.list · exit 0 · '✓ dispatch-gates --ran: 114 derived famil(ies) accounted for — 113 run, 1 NOT-MEASURED (0 DERIVED from a recorded exit 3, 1 a KILL code with a stated reason).'"
],
"line_budget": "570 changed lines (+528 / -42) over 9 files vs origin/main, under the 5000 human-merge threshold. No skills/** file is touched, so the skill line budget does not apply. No governed surface is touched, so the PR is not Tier S or Tier H.",
"deviations": [
"Clause-② value: the claim declares 'Clause-②: yes'; the PR body and changeset declare 'Clause-②: no (narrowing)'. The criterion asks whether the card widens the accept set or the public surface. Measured: no new export (prescriptions module-private, api-surface byte-identical), no accept-set growth, and one narrowing. That is A4's falsified half (A4 assumed an exported guidance constant). 'no (narrowing)' is also the house spelling for a retirement (the connector-triggers retirement changeset). Gate outcome is the same either way: minor, breaking, ADR-0087 marker owed. If the seat wants the claim's 'yes' kept, rewrite line 5 of the PR body to 'Clause-②: yes (narrowing)' and the same line in the changeset; nothing else changes.",
"PR body correction owed (written once, not patched): in the 'Fixture census' section, 'Ten refusal pins and one type-level pin were added' is wrong. It should read 'Seven refusal pins (three formats at format and at fallbackFormat, plus coerce_types), one never-legal-value control and one type-level pin were added' (9 new tests; agent.test.ts goes from 42 to 51).",
"No form, i18n or reconciliation-test edit. The stale omit row is left for routing (out_of_scope_findings 1).",
"Default PR labels: none written. The dispatch named no label, and skip-changeset does not apply."
],
"files_changed": [
".changeset/21277-agent-structured-output-json-only.md",
"content/docs/references/ai/agent.mdx (regenerated)",
"packages/spec/liveness/agent.json",
"packages/spec/liveness/state-counts/agent.md (regenerated)",
"packages/spec/src/ai/agent.test.ts",
"packages/spec/src/ai/agent.zod.ts",
"packages/spec/src/conversions/registry.ts",
"packages/spec/src/migrations/entries/semantic/18.agent-structured-output-refused-members-retired.ts",
"packages/spec/src/migrations/registry.ts (STEP18_RATIONALE fragment by hand; semantic region via gen:migration-registry)"
],
"fixture_census": "Producers outside packages/spec, tests excluded (git grep -c structuredOutput -- 'examples/' 'packages/' ':!packages/spec/' ':!/*.test.ts'): 0 files. Tests and fixtures outside packages/spec matching structuredOutput, coerce_types, fallbackFormat or transformPipeline: 1 file, packages/lint/src/lint-liveness-properties.test.ts, a comment that asserts nothing about the row. The lit control guardrails / blockedTopics hits 4 files. Consumer readings: @objectstack/lint 119/119 files green. No @objectstack/cli test authors the keys, so its integration tier is declared to CI. Inside packages/spec, agent.test.ts pinned the old acceptance three times (the five-format list, a pipeline with coerce_types, format 'regex' beside a fallback); all three were flipped. Other spec test hits on 'xml' or 'regex' belong to unrelated enums (export, odata, mapping) and stay green in the full local run. objectui at the pinned 31971ff: 0 hits (control blockedTopics / AgentSchema: 3 files). content/docs/ai/: 0. skills/: 0 for a retired member.",
"semver": "@objectstack/spec minor. BREAKING banner, a 'feat(spec)!:' summary, and 'Clause-②: no (narrowing)' in the changeset body and at a PR-body line start. ADR-0087 marker: registered agent-structured-output-refused-members-removed, agent-structured-output-refused-members-retired. Gate lines are in gates (adr-0087-registration [BREAKING+bang+clause-②-narrowing]; no-major '✓ This diff introduces no
majorbump.' and LEVEL AXIS ✓). check-changeset-no-major did not refuse the level."}
Generated by Claude Code
objectstack-fleet commentedon Oct 2, 2026
ACCEPT — PR #21367 @
ff5810c0domain:specseat 2 (session_01YDt3PzwfrkuFzUBF89WPmM), holder of claim5945711087· 2026-10-02T08:23Zmain.Fixes #21277.Part of #20274stands on its own line, with no closing verb.agent.zod.ts:94, finding(spec): the two JSON-Schema slots the cloud AI runtime compiles (action.ai.outputSchema,agent.structuredOutput.schema) accept an untyped subschema carrying a type-scoped keyword, which that runtime refuses before it runs #21289) is untouched; finding(spec): the two JSON-Schema slots the cloud AI runtime compiles (action.ai.outputSchema,agent.structuredOutput.schema) accept an untyped subschema carrying a type-scoped keyword, which that runtime refuses before it runs #21289 landed mid-run and was merged in.5948049962on this exact head.ff5810c0: 38 success and 4 skipped by design (the secondAuto LabelandCheck PR Sizeruns,Console Pin Gatewith no.objectui-shachange, and the opt-in packed-tarball smoke). The same skip set was accepted on PR fix(spec): a bound action's translation is read only under its own object, never from globalActions #21344.check-governed-merges --pr 21367reads NOT governed, 570 changed lines.5945617233), item by item:regex/grammar/xmlandcoerce_typesleave throughenumWithRetiredValues, the house value-level mechanism. Each is refused by name with a prescription, andtscrejects it. The prescriptions are module-private, so no export is added.action-block-endpoint-to-targetprecedent) and a D3 entry.livewithevidenceScope: cross-repo, citing cloudcb62c3eaas read by therepo:cloud#1seat (5943158888). The note says no seat here read cloud.structuredOutput,fallbackFormat, and rider item 1 (guardrails.blockedTopics).Clause-②: no (narrowing), against the claim'syes.api-surfacebyte-identical, no accept-set growth.registered).structuredOutput/fallbackFormat/blockedTopicsdescribes;Out-of-scope findings:
packages/spec/src/system/metadata-form-zod-reconciliation.test.ts:410-414keeps anomitrow foragent.structuredOutput. Itswhycites the[EXPERIMENTAL — not enforced]describe and theexperimentalrow, both of which this PR removes.:307–:309): "Once a key is enforced its row is stale: delete it and decide the offer then — that decision belongs to the enforcement".agent.form.tsand the fourplatform-objectsbundles. That is outside this claim and the ruling.structuredOutput.schemais a free-form JSON Schema, so whether a composite control can carry it is a measurement, not a copy of theguardrailsprecedent.domain:specseat 2, decided after landing.packages/cli/distwithoutindex.d.tsmadecheck:dts-closureanswer 1 once, and a rebuild cleared it. → noted, not filed: local tree state, not this diff; reproduction not measured.Next: ready, auto-merge, the queue.
Generated by Claude Code
objectstack-fleet commentedon Oct 2, 2026
Landed: PR #21367 →
3937ad2f32domain:specseat 2 (session_01YDt3PzwfrkuFzUBF89WPmM), holder of claim5945711087· 2026-10-02T08:51Z3937ad2f32, with one parent (f39760864c). This card closedcompletedby itsFixesline.ff5810c0(ACCEPT5948131311, at-tier PASS5948049962): 9 of 9 files are blob-equal, the generatedmigrations/registry.tsregion and the agent reference page included.5945617233):agent.structuredOutputis JSON-only. Theregex/grammar/xmlformats and thecoerce_typesstep are refused by name with a prescription, at parse and intsc.live(cloudcb62c3ea, attested by5943158888).fallbackFormatandguardrails.blockedTopicsdescribes state what the runtime enforces.guardrails,memory,structuredOutput,lifecycleandtool.outputSchemaare enforced by the agent runtime (5 keys), starting with the guardrails the built-in agents already declare #20274 (parent,Part of): this closes itsstructuredOutputmember. Thememoryspec half stays in the decision box (5947436041), andlifecycleis spec(ai): retireagent.lifecycle— phase-scoped instructions and tools are skills withtriggerConditions, process orchestration is Flow (ruled on cloud#2569) #21320.omitrow and the Studio offer) now holds onmain. The enforcement card is closed, so the gate's "decide the offer then" has no carrier. It is filed as its own card in this act, and named in the next comment.pm:dispatchedis removed in this act. Domain, area and type labels stay.Generated by Claude Code
objectstack-fleet commentedon Oct 2, 2026
Pointer from
domain:specseat 2 (session_01YDt3PzwfrkuFzUBF89WPmM) · 2026-10-02T08:53Z. The landing comment5948520307names this. The stale reconciliationomitrow foragent.structuredOutput, and the Studio offer the gate's rule assigns to the enforcement, are filed as #21374 (bare,domain:spec; grading is triage's).Generated by Claude Code
docs(skills): objectstack-ai says guardrails is enforced per turn and…
docs(protocol): the actions.mdx outputSchema bullet says the cloud AI…
feat(spec)!: the AI runtime's two JSON-Schema slots refuse an untyped…
feat(spec)!: an agent's structuredOutput is JSON-only — retire the re…