feat(spec)!: retire agent.lifecycle — a conversation phase is a skill, orchestration is Flow, record transitions are the state_machine rule; the XState StateMachineSchema family leaves with it (#21320) - #21461
Conversation
… (WIP) Claude-Session: https://claude.ai/code/session_01YDt3PzwfrkuFzUBF89WPmM Co-authored-by: Claude <noreply@anthropic.com>
…ate surfaces (WIP) Claude-Session: https://claude.ai/code/session_01YDt3PzwfrkuFzUBF89WPmM Co-authored-by: Claude <noreply@anthropic.com>
…ent; ledger rows follow (WIP) Claude-Session: https://claude.ai/code/session_01YDt3PzwfrkuFzUBF89WPmM Co-authored-by: Claude <noreply@anthropic.com>
…ce; docs follow (WIP) Claude-Session: https://claude.ai/code/session_01YDt3PzwfrkuFzUBF89WPmM Co-authored-by: Claude <noreply@anthropic.com>
…the lifecycle head-noun twin (WIP) Claude-Session: https://claude.ai/code/session_01YDt3PzwfrkuFzUBF89WPmM Co-authored-by: Claude <noreply@anthropic.com>
… (WIP) Claude-Session: https://claude.ai/code/session_01YDt3PzwfrkuFzUBF89WPmM Co-authored-by: Claude <noreply@anthropic.com>
…etired (WIP) Claude-Session: https://claude.ai/code/session_01YDt3PzwfrkuFzUBF89WPmM Co-authored-by: Claude <noreply@anthropic.com>
…ent-lifecycle-retired
… (WIP) Claude-Session: https://claude.ai/code/session_01YDt3PzwfrkuFzUBF89WPmM Co-authored-by: Claude <noreply@anthropic.com>
…ent-lifecycle-retired
…nly the parsing doors refuse it first The changeset said `os lint` stopped warning because the parse refuses the key first. `os lint` lints the unparsed stack, so it now reports `liveness-dead-property` for `agent.lifecycle` (measured with lintLivenessProperties on this tree). `os validate` and the other parsing doors refuse the key before any advisory runs. Claude-Session: https://claude.ai/code/session_01YDt3PzwfrkuFzUBF89WPmM Co-authored-by: Claude <noreply@anthropic.com>
…ent-lifecycle-retired
…ve control reads 659 once the agent lifecycle row leaves The agent form's `lifecycle` row left with the retired key, and with it a row label authored in all three locales. The whole-catalog positive control in the echo-decisions pin counted it (660); it now reads 659, with the reason recorded beside the history of the count. Claude-Session: https://claude.ai/code/session_01YDt3PzwfrkuFzUBF89WPmM Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 2 package(s): 5 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 3 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 138 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 0805e6269e3919c38c16ef4133bba8e7ccd3774f && git checkout 0805e6269e3919c38c16ef4133bba8e7ccd3774f
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 99589f91a7e721dfe846486988024714878196c8 b4e1682e1c2849116a46de9ef40d7b981e04bbfe && git checkout -B drift-repro 99589f91a7e721dfe846486988024714878196c8 && git merge --no-ff b4e1682e1c2849116a46de9ef40d7b981e04bbfe
node scripts/docs-audit/affected-docs.mjs --json 99589f91a7e721dfe846486988024714878196c8
|
Contract reviewServed-tier: Inputs: card #21320 (body + 3 comments: claim ① Derived judgmentsEvery accept-set and public-surface change the diff implies, each named right or wrong.
② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS Generated by Claude Code |
维护者速读(终稿)— PR #21461
改了什么:把 agent 元数据上的 为什么改:裁决 cloud#2569 定为 D(退役)。这个键一直是「声明了但运行时从不读取」,写了等于没写,对 AI 编写元数据是陷阱。实测本仓零读取、零编写,objectui 零 import、零读取。cloud 的零读取沿用裁决卡的普查(cloud @3aadd908),本次未重测。 风险与代价(含回滚):
席位意见:建议批准。四轴同向:零读取、零编写;契约收紧并在编写时响亮拒绝;删掉零消费的导出,少一项永久义务。落地后由本坐席关闭 #20274(这是它的最后一个键)。 你要做的:在 PR #21461 上点 APPROVE。 Generated by Claude Code |
Fixes #21320
Part of #20274
Clause-②: yes (narrowing)
What this does
The maintainer ruled D (retire) on objectstack-ai/cloud#2569 (batch #267 item 5, 「其他同意」). This PR carries out that ruling's spec half through the
spec-property-retirementplaybook.agent.lifecycleis retired. It was parsed and never read. No runtime, in this repository or in cloud, moved an agent through a declared state or refused an undeclared transition. What it reached for is already served elsewhere:instructionsandtools, selected bytriggerConditions(ADR-0064);state_machinevalidation rule (ADR-0020).The XState
StateMachineSchemafamily leaves the package with it, under the card's scope item 3. The census below showsagent.lifecyclewas its last authorable consumer. ADR-0020 implementation note 1 had kept the file only for this door.This run resumed a lost one. The container restarted mid-flight. The predecessor's eight WIP commits survived, but its census and gate results did not. Everything below was re-measured in this run; nothing from before the restart counts as measured. The last section says what was found done and what this run finished.
The retirement kit
AgentSchema.lifecycleis now aretiredKey()(packages/spec/src/ai/agent.zod.ts). Its prescription names the three destinations and ends with the houseos migrate meta --from 17sentence.tscrefuses the key, because its input type isnever.lifecyclecomposite row (agent.form.ts). The fourplatform-objects*.metadata-forms.generated.tscatalogs lose the row's label and help text in every locale.agent-lifecycle-removed. It runs at step 18 withretiredFromLoadPath,retiredAfter17.6.0 and order 57, and it sits in identifier order inMAJOR_18_CONVERSIONS. It deleteslifecyclefrom everyagents[]entry, whatever the key holds, with one notice per agent. The delete is lossless. An object's ADR-0057lifecycleblock shares the name and is not touched; a pin asserts this.RETIRED_KEYS_BY_MAJOR[18]gainsai/Agent:lifecycle.RETIRED_DEFS_BY_MAJOR[18]gains the five published defs:automation/StateMachine,StateNode,Transition,ActionRefandGuardRef. Each is one entry file, written into the generated regions bygen:migration-registry.agent-lifecycle-retired. One entry covers the family. It carries the judgement no conversion can make: which of the three destinations each deleted machine meant. ItsSTEP18_RATIONALEfragment is order 62.automation/state-machine.zod.tsand its test are deleted../automationstops re-exporting the module.StateNodeConfigleaves the root and/aientries, whose only structural mention of it was the tombstoned key.liveness/agent.jsonrowlifecyclemoves fromexperimentaltodead, withverifiedAt2026-10-02 and the REMOVED note. The tombstone keeps the key in the walked shape (therls.priorityprecedent).state-counts/agent.mdis regenerated. The README's agent row no longer says "autonomy tier experimental": noagentrow isexperimentalany more (A6).authorable-surface/{ai,automation}.json(one newai/Agent:lifecycle [RETIRED]row and 18 family rows gone),authorable-defaults,json-schema.manifest(five defs gone),api-surface,export-origins,declaration-map,content/docs/references/**(thestate-machinepage is gone) and the strictness-ledger counts.packages/spec/src/ai/agent-lifecycle-retirement.test.tsis arepo-project test with 14 cases:code, thepathand the prescription;defineStackdoor's ADR-0112 envelope (STACK_SCHEMA_INVALID/ 422);./automation;@objectstack/spec#test, with an anti-vacuity matcher case..changeset/21320-agent-lifecycle-retired.mdbumps@objectstack/specminorand@objectstack/platform-objectspatch. It carries a BREAKING banner, the FROM → TO table, the one-line fix,Clause-②: yes (narrowing)and the ADR-0087registeredmarker naming both ids.The census (measured in this run)
StateMachineSchemafamily consumers atorigin/mainc2c21f357c, before this branch's change:src/ai/agent.zod.ts:7,:341StateMachineSchemaAgentSchema.lifecyclesrc/data/validation.zod.ts:187StateMachineValidationSchemastate_machinerule. It is a different export (a flat{ from: [to] }table) and never imported the familysrc/api/protocol.zod.ts:2614StateMachineSchemastays authorable on the object". That has been false since ADR-0020 retiredobject.stateMachinessrc/automation/state-machine.zod.ts:25src/ui/chart.zod.ts:50StateMachineSchemaas a positive controlmigrations/entries/semantic/17.ui-interaction-config-family-retired.ts:38,17.authoring-schemas-strict-unknown-keys.ts:20src/ai/index.ts:47,src/index.ts:147StateNodeConfigre-exportlifecyclerecursive-schema-input-assertions.ts,union-author-message-pins.test.ts,type-alias-convention.pin.test.ts(778 → 773 pins),sync-retirement.test.ts,scripts/export-origins.test.ts,scripts/liveness/check-liveness.test.tsagent.lifecycleFlowSchema,tool.outputSchema)content/docs/automation/workflows.mdxStateMachineConfigstate_machinerule,os:checkgreenNothing outside
packages/specimports the family:git grepoverpackages/**,examples/**,skills/**andcontent/**finds no import.agent.lifecycleproducers and readers (A3):packages/spec. The pattern.lifecycle/['lifecycle']/"lifecycle"has 62 hits inpackages/**andexamples/**. Every one is an object's ADR-0057 data lifecycle, a service-registration lifecycle, a schema-migration composition or an i18n key path. One hit is agent-related: the form-label pin inobject-lifecycle-panel-echo-decisions.test.ts, which is re-pointed (A2).examples/**contains no agent definition at all, so its control reading is also 0, and that zero is not a census of agent authors. Seventeen files outsidepackages/specnamedefineAgent/AgentSchema, and none of them authorslifecycle.89cad75d55: 0 imports of any family export. The controlFilterConditionis found in 44 files.AgentPreview.tsxdraws nolifecycle.@3aadd908) is attributed, not re-taken.Deviations and conflicts (the reviewer should read these)
skills/**, so it is Tier H. The claim's file surface says "Noskills/**edit"; this breaches it.skills/objectstack-ai/references/_index.mdloses one generated line: the transitive dependencyautomation/state-machine.zod.ts. Onceagent.zod.tsstops importing that file,check:skill-refsfails without that change.agent.lifecyclecauses this, even one that keeps the family file, because the index is computed fromagent.zod.ts's imports.skills/*/references/_index.mdis generator-owned (gen:skill-refs) yet sits inside theskills/**governed-merge fence — every spec PR touching an indexed headline is forced to carry a governed-surface file #11705) does not lift the path. This PR also editspackages/spec/scripts/**, which the exception's co-edit fence treats as the generator tree. The edits there are a liveness witness, an export-origins witness, theundrilled-containersbaseline, and two corrected comments inbuild-skill-references.tsandlib/skill-map-guards.ts.check-governed-merges.mjs --branchanswers exit 3: GOVERNED, landing tier H.workflows.mdx,quick-reference.mdx, the strictness-ledger prose row and its counts;PROTOCOL_MAP.md,llms.txtanddocs-import-surface.baseline.json;vitest.repo-tests.json;api/protocol.zod.ts,ui/chart.zod.ts,ai/index.ts,index.tsandautomation/index.ts.Verification
All of this ran on head
b4e1682e1c, after mergingorigin/main53fd35e3e3throughscripts/pm/os-regen-merge.sh. That merge includes #21431's generated registry entry,analytics-row-wildcard-outside-count-refused. No hunk was hand-resolved, andcheck:migration-registryis green with nothing to regenerate.Gates. Every derived gate ran on head
b4e1682e1c, with each exit code captured before any pipe:node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commandsderived 124 families, and all 124 exited 0. The reconciliationdispatch-gates --ranreads:✓ dispatch-gates --ran: 124 derived famil(ies) accounted for — 124 run, 0 NOT-MEASURED (a DERIVED zero — all 124 recorded an exit code and none of them is 3).check:generated:✓ All 15 generated artifacts are up to date.check:migration-registryreads✓ src/migrations/registry.ts is current (349 semantic, 245 retired-key, 217 retired-def).check:liveness:✓ … state-counts/ is current. Across the shards: 989 live, 1 experimental, 1 live-elsewhere, 110 dead, 10 planned.check:api-surface:@objectstack/spec public API surface + factory signatures unchanged ✓, read against the committed snapshot, which carries the removal.check-adr-0087-registration --base origin/main:✓ … 1 declared-breaking changeset(s), each carrying an ADR-0087 disposition.The arm was read as[BREAKING+bang+clause-②-narrowing] registered agent-lifecycle-removed, agent-lifecycle-retired.check-changeset-no-major:✓ This diff introduces no major bump.check-empty-changeset:✓ No empty-frontmatter changeset introduced by this diff.check:i18n:check-i18n-bundles: OK (9 package(s) — all bundles in sync, no undeclared authoring keys).check:doc-authoring:✓ doc authoring guard: 17266 customer-facing string(s) … clean.check:nul-bytes:check-nul-bytes: OK (… no raw ASCII control bytes).Tests:
pnpm --filter @objectstack/spec testb4e1682e1cpnpm --filter @objectstack/spec test:repod472aaffafpnpm --filter @objectstack/spec typecheckd472aaffafcheck:test-typecheck: OK@objectstack/platform-objectsvitest runandtypecheckb4e1682e1c@objectstack/lintsrc/lint-liveness-properties.test.tsb4e1682e1c@objectstack/dogfoodtest/expression-conformance.test.tsb4e1682e1cThe
d472aaffafrows are the merge commit. Itspackages/spectree is byte-identical tob4e1682e1c; the only later commit edits oneplatform-objectstest.One red was found and fixed in this run. The
platform-objectsecho-decisions positive control failed withexpected 659 to be 660until the count moved with the retired row.Ablation of the tombstone ran on the committed head through
scripts/ablation-replace.mjs, which restores automatically:lifecycle: retiredKey(becamelifecycle_ablated: retiredKey(, a bare delete on the strict schema. The anchor count went 1 → 0, and the blob went80b6593b3953→42c1ebe78de2.agent-lifecycle-retirement.test.tswent to 5 failed / 9 passed (14). The prescription, walked-shape, tsc-channel,defineStack-envelope and boot-door cases went red. The conversion and absence cases stayed green, as they should, because they do not depend on the tombstone.80b6593b3953), andgit diff HEADis empty.@ts-expect-erroris live:tsc -p tsconfig.test.json --listFilesOnlylists the pin (count 1, and the controlagent-memory-store-retirement.test.tsalso counts 1), and the pin carries no debt entry intest-typecheck-debt.json.skills/**readingsskills/objectstack-ai/references/_index.mdgoes from 43 to 42 lines. It is generated, and the change is one deleted line.SKILL.mdis 4397 lines before and 4397 after. NoSKILL.mdis touched.Acceptance notes
skills/**teaching. No text inskills/**teachesagent.lifecycleor the XState family (A7).skills/objectstack-automation/references/state-machines-and-approvals.mdteaches thestate_machinevalidation rule, which is the prescription's destination.StateNodeConfigas one ofdefineStack's structural mentions: the ninescripts/i18n-extract.config.tsheaders,scripts/check-entry-nameability.ts:97andscripts/root-entry-type-nameability.pin.test.ts:16. They are dated records of 8 packages'scripts/i18n-extract.config.tsfail to type-check: TS2883 on an inferreddefaultnaming @objectstack/spec's hashed dist chunks #10868 /@objectstack/spec's root entry does not re-export three types its own public API's inferred types mention — every consumer inferring throughdefineStackhits TS2883 #11350.authorable-surface.base.jsonstill lists the family's rows. Onlygen:authorable-surface-basewrites that anchor, and the anchor is allowed to lag.check:authorable-surfaceis green.packages/spec/ZOD_SCHEMA_AUDIT_REPORT.mdandDEVELOPMENT_PLAN.mdstill name the deleted file.os lint. It reads the unparsed stack, so it now grades an authoredagent.lifecycleliveness-dead-property. This was measured withlintLivenessPropertieson this tree; the controltool.outputSchemastill readsliveness-experimental-property. The parsing doors refuse the key first. The changeset was corrected to say exactly this.Resume record: found done vs finished in this run
b3b1fe8852,4729a31154,f1fd8ebb5f,fbd4e311ea,d41227ffd4,9e40a894aa,f3f5301451and54018d8e6a, plus a merge.origin/maintwice throughos-regen-merge.sh(42bce96be8,d472aaffaf);os lintsentence (d3240440b9);object-lifecycle-panel-echo-decisions.test.tsread 660 and is now 659 (b4e1682e1c);维护者速读(草稿)
改了什么:把 agent 元数据上的
lifecycle(对话状态机)退役,改为编写时报错并给出处方(会话阶段用 skill +triggerConditions,多步流程用 Flow,记录状态流转用state_machine校验规则);随之删掉它唯一还在用的 XState 风格StateMachineSchema一族导出。表单、四语种表单文案、台账、生成物、文档、迁移登记(D2 转换 + D3 说明)同步。为什么改:裁决 cloud#2569 定 D(退役)。这个键一直是「声明了但没有任何运行时读取」——写了等于没写,对 AI 编写元数据是陷阱;实测本仓与 objectui 零读取零编写。
风险与代价(含回滚):
@objectstack/specminor + BREAKING:写了lifecycle的 agent 会在 parse 时被拒(D2 转换会把存量数据里的该键无损删除);外部若有代码 import 这一族导出会编译失败(仓外未测量)。本 PR 因生成的skills/objectstack-ai/references/_index.md少一行而成为 Tier H(人合)。回滚即 revert 本 PR。席位意见:(留空)
你要做的:审阅通过后在本 PR 上 APPROVE(Tier H),席位随后落地。
Generated by Claude Code