Commit 6e33b67
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-retirement` playbook.
**`agent.lifecycle` is 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:
- a conversation phase is a **skill** with its own `instructions` and
`tools`, selected by `triggerConditions` (ADR-0064);
- a multi-step process is a **Flow** (ADR-0019);
- a record's status transitions are the `state_machine` **validation
rule** (ADR-0020).
**The XState `StateMachineSchema` family leaves the package with it,**
under the card's scope item 3. The census below shows `agent.lifecycle`
was 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
- **Tombstone.** `AgentSchema.lifecycle` is now a `retiredKey()`
(`packages/spec/src/ai/agent.zod.ts`). Its prescription names the three
destinations and ends with the house `os migrate meta --from 17`
sentence. `tsc` refuses the key, because its input type is `never`.
- **Form.** The agent form drops its `lifecycle` composite row
(`agent.form.ts`). The four `platform-objects`
`*.metadata-forms.generated.ts` catalogs lose the row's label and help
text in every locale.
- **D2 conversion `agent-lifecycle-removed`.** It runs at step 18 with
`retiredFromLoadPath`, `retiredAfter` 17.6.0 and order 57, and it sits
in identifier order in `MAJOR_18_CONVERSIONS`. It deletes `lifecycle`
from every `agents[]` entry, whatever the key holds, with one notice per
agent. The delete is lossless. An object's ADR-0057 `lifecycle` block
shares the name and is not touched; a pin asserts this.
- **Registration.** `RETIRED_KEYS_BY_MAJOR[18]` gains
`ai/Agent:lifecycle`. `RETIRED_DEFS_BY_MAJOR[18]` gains the five
published defs: `automation/StateMachine`, `StateNode`, `Transition`,
`ActionRef` and `GuardRef`. Each is one entry file, written into the
generated regions by `gen:migration-registry`.
- **D3 entry `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. Its `STEP18_RATIONALE` fragment
is order 62.
- **Family deletion.** `automation/state-machine.zod.ts` and its test
are deleted. `./automation` stops re-exporting the module.
`StateNodeConfig` leaves the root and `/ai` entries, whose only
structural mention of it was the tombstoned key.
- **Ledger.** The `liveness/agent.json` row `lifecycle` moves from
`experimental` to `dead`, with `verifiedAt` 2026-10-02 and the REMOVED
note. The tombstone keeps the key in the walked shape (the
`rls.priority` precedent). `state-counts/agent.md` is regenerated. The
README's agent row no longer says "autonomy tier experimental": no
`agent` row is `experimental` any more (A6).
- **Generated baselines.** These are regenerated, not hand-edited:
`authorable-surface/{ai,automation}.json` (one new `ai/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/**` (the
`state-machine` page is gone) and the strictness-ledger counts.
- **Pins.** `packages/spec/src/ai/agent-lifecycle-retirement.test.ts` is
a `repo`-project test with 14 cases:
- the refusal for every value, with the issue `code`, the `path` and the
prescription;
- the `defineStack` door's ADR-0112 envelope (`STACK_SCHEMA_INVALID` /
422);
- the stored-row replay and the boot-door before/after;
- idempotence and load-path retirement;
- the registration;
- the family's runtime absence from `./automation`;
- a tree-scoped absence walk over the five roots declared for
`@objectstack/spec#test`, with an anti-vacuity matcher case.
- **Changeset.** `.changeset/21320-agent-lifecycle-retired.md` bumps
`@objectstack/spec` `minor` and `@objectstack/platform-objects` `patch`.
It carries a **BREAKING** banner, the FROM → TO table, the one-line fix,
`Clause-②: yes (narrowing)` and the ADR-0087 `registered` marker naming
both ids.
## The census (measured in this run)
**`StateMachineSchema` family consumers at `origin/main` `c2c21f357c`,
before this branch's change:**
| site | symbol | what it was | disposition |
|---|---|---|---|
| `src/ai/agent.zod.ts:7`, `:341` | `StateMachineSchema` | **the one
authorable consumer**: `AgentSchema.lifecycle` | tombstoned |
| `src/data/validation.zod.ts:187` | `StateMachineValidationSchema` |
the ADR-0020 `state_machine` rule. It is a **different export** (a flat
`{ from: [to] }` table) and never imported the family | unchanged; it is
the prescription's destination |
| `src/api/protocol.zod.ts:2614` | comment | claimed
"`StateMachineSchema` stays authorable on the object". That has been
false since ADR-0020 retired `object.stateMachines` | corrected |
| `src/automation/state-machine.zod.ts:25` | docblock | named the agent
lifecycle as the surviving door | file deleted |
| `src/ui/chart.zod.ts:50` | comment | named `StateMachineSchema` as a
positive control | updated |
|
`migrations/entries/semantic/17.ui-interaction-config-family-retired.ts:38`,
`17.authoring-schemas-strict-unknown-keys.ts:20` | text | historical
witnesses inside released D3 entries | left, because they are dated
records |
| `src/ai/index.ts:47`, `src/index.ts:147` | `StateNodeConfig` re-export
| entry-nameability only; it was mentioned solely through `lifecycle` |
removed |
| `recursive-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.ts` | tests and type probes |
their probes and witnesses were the family or `agent.lifecycle` |
removed or re-pointed (`FlowSchema`, `tool.outputSchema`) |
| `content/docs/automation/workflows.mdx` | `StateMachineConfig` |
**taught** the XState type for record lifecycles | rewritten to the
`state_machine` rule, `os:check` green |
Nothing outside `packages/spec` imports the family: `git grep` over
`packages/**`, `examples/**`, `skills/**` and `content/**` finds no
import.
**`agent.lifecycle` producers and readers (A3):**
- **Readers: 0** outside `packages/spec`. The pattern `.lifecycle` /
`['lifecycle']` / `"lifecycle"` has 62 hits in `packages/**` and
`examples/**`. 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 in
`object-lifecycle-panel-echo-decisions.test.ts`, which is re-pointed
(A2).
- **Producers: 0.** `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 outside `packages/spec` name `defineAgent` /
`AgentSchema`, and none of them authors `lifecycle`.
- **objectui at the pin `89cad75d55`:** 0 imports of any family export.
The control `FilterCondition` is found in 44 files. `AgentPreview.tsx`
draws no `lifecycle`.
- **Cloud:** NOT MEASURED here, because this session has no cloud
checkout. The card's cloud zero-reader census (cloud `@3aadd908`) is
attributed, not re-taken.
## Deviations and conflicts (the reviewer should read these)
1. **This PR touches `skills/**`, so it is Tier H.** The claim's file
surface says "No `skills/**` edit"; this breaches it.
- `skills/objectstack-ai/references/_index.md` loses one generated line:
the transitive dependency `automation/state-machine.zod.ts`. Once
`agent.zod.ts` stops importing that file, `check:skill-refs` fails
without that change.
- Any retirement of `agent.lifecycle` causes this, even one that keeps
the family file, because the index is computed from `agent.zod.ts`'s
imports.
- The generated-surface exception (#11705) does not lift the path. This
PR also edits `packages/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, the `undrilled-containers` baseline,
and two corrected comments in `build-skill-references.ts` and
`lib/skill-map-guards.ts`.
- `check-governed-merges.mjs --branch` answers exit 3: **GOVERNED,
landing tier H**.
- Landing therefore needs the maintainer's hand, or an authorized
APPROVED review.
2. **These files are outside the claim's declared file surface.** Each
is a consequence of retiring the family:
- hand-written docs: `workflows.mdx`, `quick-reference.mdx`, the
strictness-ledger prose row and its counts;
- `PROTOCOL_MAP.md`, `llms.txt` and `docs-import-surface.baseline.json`;
- the spec test, witness and baseline files in the census table;
- `vitest.repo-tests.json`;
- comment corrections in `api/protocol.zod.ts`, `ui/chart.zod.ts`,
`ai/index.ts`, `index.ts` and `automation/index.ts`.
## Verification
All of this ran on head `b4e1682e1c`, after merging `origin/main`
`53fd35e3e3` through `scripts/pm/os-regen-merge.sh`. That merge includes
#21431's generated registry entry,
`analytics-row-wildcard-outside-count-refused`. No hunk was
hand-resolved, and `check:migration-registry` is green with nothing to
regenerate.
**Gates.** Every derived gate ran on head `b4e1682e1c`, with each exit
code captured before any pipe:
- **The derived union.** `node scripts/pm/dispatch-gates.mjs --repo
objectstack-ai/objectstack --commands` derived 124 families, and all 124
exited 0. The reconciliation `dispatch-gates --ran` reads: `✓
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-registry` reads `✓ 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:**
| command | head | result |
|---|---|---|
| `pnpm --filter @objectstack/spec test` | `b4e1682e1c` | 600 files,
17689 passed, 1 todo |
| `pnpm --filter @objectstack/spec test:repo` | `d472aaffaf` | 50 files,
877 passed |
| `pnpm --filter @objectstack/spec typecheck` | `d472aaffaf` | exit 0;
`check:test-typecheck: OK` |
| `@objectstack/platform-objects` `vitest run` and `typecheck` |
`b4e1682e1c` | 59 files, 949 passed; exit 0 |
| `@objectstack/lint` `src/lint-liveness-properties.test.ts` |
`b4e1682e1c` | 95 passed |
| `@objectstack/dogfood` `test/expression-conformance.test.ts` |
`b4e1682e1c` | 7 passed |
The `d472aaffaf` rows are the merge commit. Its `packages/spec` tree is
byte-identical to `b4e1682e1c`; the only later commit edits one
`platform-objects` test.
**One red was found and fixed in this run.** The `platform-objects`
echo-decisions positive control failed with `expected 659 to be 660`
until the count moved with the retired row.
**Ablation of the tombstone** ran on the committed head through
`scripts/ablation-replace.mjs`, which restores automatically:
- **The mutation.** The anchor ` lifecycle: retiredKey(` became `
lifecycle_ablated: retiredKey(`, a bare delete on the strict schema. The
anchor count went 1 → 0, and the blob went `80b6593b3953` →
`42c1ebe78de2`.
- **The prediction:** turns red.
- **The observation:** `agent-lifecycle-retirement.test.ts` went 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.
- **The restore.** The blob after the restore equals HEAD
(`80b6593b3953`), and `git diff HEAD` is empty.
- **The tsc channel.** The pin's `@ts-expect-error` is live: `tsc -p
tsconfig.test.json --listFilesOnly` lists the pin (count 1, and the
control `agent-memory-store-retirement.test.ts` also counts 1), and the
pin carries no debt entry in `test-typecheck-debt.json`.
## `skills/**` readings
- **The changed file.** `skills/objectstack-ai/references/_index.md`
goes from 43 to 42 lines. It is generated, and the change is one deleted
line.
- **The whole package.** The sum of every `SKILL.md` is 4397 lines
before and 4397 after. No `SKILL.md` is touched.
## Acceptance notes
- **`skills/**` teaching.** No text in `skills/**` teaches
`agent.lifecycle` or the XState family (A7).
`skills/objectstack-automation/references/state-machines-and-approvals.md`
teaches the `state_machine` validation rule, which is the prescription's
destination.
- **Historical comments left as written.** These comments still describe
`StateNodeConfig` as one of `defineStack`'s structural mentions: the
nine `scripts/i18n-extract.config.ts` headers,
`scripts/check-entry-nameability.ts:97` and
`scripts/root-entry-type-nameability.pin.test.ts:16`. They are dated
records of #10868 / #11350.
- **The authorable-surface anchor.** `authorable-surface.base.json`
still lists the family's rows. Only `gen:authorable-surface-base` writes
that anchor, and the anchor is allowed to lag.
`check:authorable-surface` is green.
- **Historical audit files.** `packages/spec/ZOD_SCHEMA_AUDIT_REPORT.md`
and `DEVELOPMENT_PLAN.md` still name the deleted file.
- **Out-of-repo consumers are NOT MEASURED.** That covers
tenant-authored agents and code outside this repository, cloud included,
that imports the family's exports. The changeset says so, and the
prescription and the D2 replay cover stored agent rows.
- **`os lint`.** It reads the unparsed stack, so it now grades an
authored `agent.lifecycle` `liveness-dead-property`. This was measured
with `lintLivenessProperties` on this tree; the control
`tool.outputSchema` still reads `liveness-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
- **Found done.** The predecessor's WIP commits held the whole kit:
`b3b1fe8852`, `4729a31154`, `f1fd8ebb5f`, `fbd4e311ea`, `d41227ffd4`,
`9e40a894aa`, `f3f5301451` and `54018d8e6a`, plus a merge.
- **Finished in this run:**
- re-measured the census, and with it the go-ahead to retire the whole
family;
- merged `origin/main` twice through `os-regen-merge.sh` (`42bce96be8`,
`d472aaffaf`);
- corrected the changeset's `os lint` sentence (`d3240440b9`);
- fixed a red the predecessor missed: the metadata-form catalog's
per-locale positive control in
`object-lifecycle-panel-echo-decisions.test.ts` read 660 and is now 659
(`b4e1682e1c`);
- ran the whole gate set and the ablation.
## 维护者速读(草稿)
**改了什么**:把 agent 元数据上的 `lifecycle`(对话状态机)退役,改为编写时报错并给出处方(会话阶段用 skill +
`triggerConditions`,多步流程用 Flow,记录状态流转用 `state_machine` 校验规则);随之删掉它唯一还在用的
XState 风格 `StateMachineSchema` 一族导出。表单、四语种表单文案、台账、生成物、文档、迁移登记(D2 转换 + D3
说明)同步。
**为什么改**:裁决 cloud#2569 定 D(退役)。这个键一直是「声明了但没有任何运行时读取」——写了等于没写,对 AI
编写元数据是陷阱;实测本仓与 objectui 零读取零编写。
**风险与代价(含回滚)**:`@objectstack/spec` minor + 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](https://claude.ai/code/session_01YDt3PzwfrkuFzUBF89WPmM)_
---------
Co-authored-by: Claude <noreply@anthropic.com>
1 parent aa46322 commit 6e33b67
63 files changed
Lines changed: 978 additions & 1255 deletions
File tree
- .changeset
- content/docs
- automation
- getting-started
- references
- ai
- automation
- docs/audits
- 2026-07-unknown-key-strictness-ledger.counts
- packages
- platform-objects/src/apps/translations
- spec
- api-surface
- authorable-defaults
- authorable-surface
- declaration-map
- export-origins
- json-schema.manifest
- liveness
- state-counts
- scripts
- lib
- liveness
- src
- ai
- api
- automation
- conversions
- migrations
- entries
- retired-defs
- retired-keys
- semantic
- ui
- skills/objectstack-ai/references
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
11 | | - | |
| 11 | + | |
12 | 12 | | |
13 | 13 | | |
14 | 14 | | |
| |||
60 | 60 | | |
61 | 61 | | |
62 | 62 | | |
63 | | - | |
64 | | - | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
65 | 67 | | |
66 | 68 | | |
67 | 69 | | |
68 | | - | |
69 | | - | |
70 | | - | |
71 | | - | |
72 | | - | |
73 | | - | |
74 | | - | |
75 | | - | |
76 | | - | |
77 | | - | |
78 | | - | |
79 | | - | |
80 | | - | |
81 | | - | |
82 | | - | |
83 | | - | |
84 | | - | |
85 | | - | |
86 | | - | |
87 | | - | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
88 | 100 | | |
89 | 101 | | |
90 | | - | |
91 | | - | |
92 | | - | |
93 | | - | |
94 | | - | |
| 102 | + | |
| 103 | + | |
95 | 104 | | |
96 | 105 | | |
97 | | - | |
98 | | - | |
| 106 | + | |
| 107 | + | |
99 | 108 | | |
100 | 109 | | |
101 | 110 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
151 | 151 | | |
152 | 152 | | |
153 | 153 | | |
154 | | - | |
| 154 | + | |
155 | 155 | | |
156 | | - | |
| 156 | + | |
157 | 157 | | |
158 | 158 | | |
159 | 159 | | |
160 | 160 | | |
161 | 161 | | |
162 | | - | |
163 | 162 | | |
164 | 163 | | |
165 | 164 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
49 | 49 | | |
50 | 50 | | |
51 | 51 | | |
52 | | - | |
| 52 | + | |
53 | 53 | | |
54 | 54 | | |
55 | 55 | | |
| |||
80 | 80 | | |
81 | 81 | | |
82 | 82 | | |
83 | | - | |
84 | | - | |
85 | | - | |
86 | | - | |
87 | | - | |
88 | | - | |
89 | | - | |
90 | | - | |
91 | | - | |
92 | | - | |
93 | | - | |
94 | 83 | | |
95 | 84 | | |
96 | 85 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
4 | | - | |
| 4 | + | |
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
| |||
20 | 20 | | |
21 | 21 | | |
22 | 22 | | |
23 | | - | |
24 | 23 | | |
25 | 24 | | |
26 | 25 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
9 | | - | |
10 | 9 | | |
11 | 10 | | |
12 | 11 | | |
| |||
0 commit comments