|
| 1 | +--- |
| 2 | +'@objectstack/spec': minor |
| 3 | +'@objectstack/platform-objects': patch |
| 4 | +--- |
| 5 | + |
| 6 | +feat(spec)!: an agent's `memory` contract states exactly what the runtime honours — `maxEntries` and `reflectionInterval` are required once long-term memory is enabled, `longTerm.store` is retired, and the block is `live`, enforced by the cloud AI runtime (#20274) |
| 7 | + |
| 8 | +**BREAKING** — `agent.memory` narrows to what the cloud AI runtime, the one runtime |
| 9 | +that executes agents, actually does with it. That runtime recalls the newest |
| 10 | +`maxEntries` distilled notes for the user before the first round, writes one note |
| 11 | +every `reflectionInterval` delivered interactions, evicts notes beyond `maxEntries`, |
| 12 | +and keeps them in its own database store. Before an agent's first turn it refused |
| 13 | +exactly the declarations this spec still accepted, so authoring now refuses them, |
| 14 | +by name, with a prescription (ADR-0049 enforce-or-remove): |
| 15 | + |
| 16 | +- **`longTerm.maxEntries` and `reflectionInterval` are required when |
| 17 | + `longTerm.enabled` is true.** No default is declared for either: none has a |
| 18 | + measured basis, and the runtime adds none. |
| 19 | +- **`reflectionInterval` is refused without an enabled `longTerm`** — a reflection |
| 20 | + writes a long-term note, so with none enabled it would do nothing. |
| 21 | +- **`longTerm.store` is retired as a whole key.** The memory store is platform |
| 22 | + infrastructure, not agent metadata: the runtime keeps the notes in its own |
| 23 | + database store, and refused `vector` (the key's default, so what an omitted |
| 24 | + `store` parsed to) and `redis`. Its old spellings `backend`, `storage` and |
| 25 | + `provider` under `longTerm` are answered with the same prescription instead of |
| 26 | + being steered onto `store`. |
| 27 | + |
| 28 | +`longTerm.enabled` is unchanged. |
| 29 | + |
| 30 | +### FROM → TO |
| 31 | + |
| 32 | +| before | what to write instead | |
| 33 | +| --- | --- | |
| 34 | +| `memory.longTerm.store` — any value, `database` included | delete the key; where the notes are kept is the platform's choice. | |
| 35 | +| `longTerm: { enabled: true, … }` without `maxEntries` | add `maxEntries`: how many distilled notes are kept for each user (an integer of at least 1). | |
| 36 | +| `longTerm: { enabled: true, … }` without `memory.reflectionInterval` | add `reflectionInterval`: how many delivered interactions pass between the reflections that write a note (an integer of at least 1). | |
| 37 | +| `memory.reflectionInterval` without `longTerm.enabled: true` | enable long-term memory with both numbers, or delete `reflectionInterval`. | |
| 38 | + |
| 39 | +**The one-line fix: declare `maxEntries` and `reflectionInterval` when `longTerm.enabled`; delete `store`.** |
| 40 | +`os migrate meta --from 17` lists the mechanical edits for existing sources (the |
| 41 | +`store` deletion); the two numbers are the author's to choose. |
| 42 | + |
| 43 | +Each refusal is a parse error at the key's own path, naming the key and the fix, and |
| 44 | +`store` also fails `tsc` (its input type is `never`). |
| 45 | + |
| 46 | +### The retirement kit |
| 47 | + |
| 48 | +- **Tombstone.** `longTerm.store` is a `retiredKey()` carrying the prescription; the |
| 49 | + three old alias spellings moved from `aliases` to `guidance`, because an alias may |
| 50 | + not steer an author onto a tombstone. |
| 51 | +- **The contract check** is a refinement on `memory` (`reflectionInterval` is |
| 52 | + `longTerm`'s sibling), one `custom` issue per missing or misplaced key. A JSON |
| 53 | + Schema cannot state a value-conditioned requirement in the closed projection list, |
| 54 | + so the published `ai/Agent` schema (and the four installed-package schemas that |
| 55 | + embed agents) names the site in `x-dropped-refinements`, recorded in |
| 56 | + `dropped-refinements.baseline.json`. |
| 57 | +- **D2 conversion `agent-memory-long-term-store-removed`** (step 18, retired from the |
| 58 | + load path): it deletes `store` from `memory.longTerm`, whatever it holds — the |
| 59 | + delete is lossless, because no value of it ever chose a backend. Stored |
| 60 | + `sys_metadata` agent rows and built artifacts replay it; one notice per agent. It |
| 61 | + supplies neither number. |
| 62 | +- **D3 entry `agent-memory-store-retired-and-limits-required`** carries the judgement |
| 63 | + the conversion cannot make: the two numbers an enabled `longTerm` now requires. |
| 64 | +- **`RETIRED_KEYS_BY_MAJOR[18]`** registers `ai/Agent:memory.longTerm.store`. |
| 65 | +- **No deprecation window**, per the project's startup-stage posture. |
| 66 | + |
| 67 | +### Describes and the liveness ledger |
| 68 | + |
| 69 | +- `agent.memory` drops `[EXPERIMENTAL — not enforced]`: it states that the cloud AI |
| 70 | + runtime enforces it and that the open framework edition does not run agents. |
| 71 | + `longTerm`, `enabled`, `maxEntries` and `reflectionInterval` each state what the |
| 72 | + runtime does with them. |
| 73 | +- The ledger row moves `experimental` → `live`, citing the cloud reader |
| 74 | + `agent-runtime.ts#compileAgentMemory` (via `AgentRuntime.resolveTurnGuardrails`), |
| 75 | + the enforcement in `ai-service.ts` and the store `agent-memory.ts#AgentMemoryStore`, |
| 76 | + as attested by the cloud seat's reading at cloud `ef5a4344`, `verifiedAt` |
| 77 | + 2026-10-02. `os lint` / `os validate` no longer warn |
| 78 | + `liveness-experimental-property` on an agent that sets `memory`. |
| 79 | +- ⚠️ **The window, stated.** At `ef5a4344` the cloud reader still reads `store`: it |
| 80 | + honours `database` only and refuses `vector` and `redis`. Cloud drops `store` in |
| 81 | + that one reader once this release reaches its pin, and no earlier. |
| 82 | + |
| 83 | +### The agent form's help texts |
| 84 | + |
| 85 | +- The `memory` row's help text on the agent metadata form named short-term memory, |
| 86 | + a key the schema refuses. It now states what memory does and that `maxEntries` |
| 87 | + and `reflectionInterval` are required once long-term memory is enabled. |
| 88 | +- The neighbouring `planning` row named a strategy and a replan switch the schema |
| 89 | + does not declare; it now states the one key it has, the iteration cap. |
| 90 | +- The `platform-objects` metadata-form catalogs follow: the English leaves are |
| 91 | + regenerated, and the `zh-CN`, `ja-JP` and `es-ES` leaves are authored, not copied. |
| 92 | + |
| 93 | +⚠️ **The out-of-repo consumer population is NOT MEASURED.** `@objectstack/spec` is |
| 94 | +published, and tenant-authored agents were not measured. This repo authors no |
| 95 | +`longTerm` outside `packages/spec`, and no cloud built-in agent declares one. |
| 96 | + |
| 97 | +Clause-②: yes (narrowing) |
| 98 | + |
| 99 | +<!-- adr-0087: registered agent-memory-long-term-store-removed, agent-memory-store-retired-and-limits-required --> |
0 commit comments