Skip to content

Commit 135daaa

Browse files
feat(spec): agent.guardrails is live, enforced by the cloud AI runtime; tool.outputSchema steers authors to action.ai.outputSchema (#21280)
Part of #20274 Clause-②: no ## What this does This is this repo's half of the card's first slice: the ledger rows that cloud's readers now answer. - **`agent.guardrails` → `live`.** The verdict covers all three children: `maxTokensPerInvocation`, `maxExecutionTimeSec` and `blockedTopics`. - Evidence (`cloud 235c5b29`): `packages/service-ai/src/ai-service.ts#TurnGovernor`, `packages/service-ai/src/agent-runtime.ts#AgentRuntime.resolveTurnGuardrails` and `#matchBlockedTopic`. - `evidenceScope` is `cross-repo` and `verifiedAt` is 2026-10-01. - `producer`: cloud's built-in build agent (`metadata-assistant-agent.ts`) and tenant-authored agents. - The row's note names the reading it rests on: the `repo:cloud#1` seat's comment 5940785002, of cloud `main` `235c5b29`. No seat in this session read cloud. - **The `agent.zod.ts` `guardrails` describe** drops `[EXPERIMENTAL — not enforced]`. It now reads: "Safety guardrails for the agent (token budget, time limit, blocked topics), enforced per user turn by the cloud AI runtime; the open framework edition does not run agents." - **`packages/spec/liveness/README.md`, line 78 and §`live-elsewhere`.** These no longer say the gate refuses `live` on cloud-only evidence. - The gate's boundary pin (`check-liveness.test.ts`, "stays green when the missing path is attributed to ANOTHER repo") deliberately says the opposite. - The corrected text uses only words the ledger already carries: the pin's rationale, `agent.json`'s `_note`, and `manifest.runtime`'s own row note. - No rule, no other row and no gate changes. - **`tool.outputSchema` stays `experimental`**, and now says where output validation lives. - This rests on the cloud seat's comment 5943158888, of cloud `main` `cb62c3ea`. `action-tools.ts#compileOutputContract` validates `action.ai.outputSchema` directly. `AIToolDefinition.outputSchema` is only a copy of it. No authored `tool` record ever becomes a tool definition. - The row's evidence and note are rewritten. The old description-folding sentences are gone, and `verifiedAt` is 2026-10-02, attributed to that reading. - The describe, its TSDoc and `content/docs/ai/tools.mdx` now point an author to `ai.outputSchema` on the action. - **Regenerated:** `content/docs/references/ai/agent.mdx`, `content/docs/references/ai/tool.mdx` and `liveness/state-counts/agent.md`. For `agent`, live goes from 20 to 21 and experimental from 4 to 3. `state-counts/tool.md` is unchanged, because no status moved. - **Changeset:** `.changeset/20274-agent-guardrails-live.md`, `@objectstack/spec` patch. ## What remains on the card - `agent.memory` and `agent.lifecycle` stay `experimental`. Their readers are tracked on objectstack-ai/cloud#2568 and objectstack-ai/cloud#2569. - `agent.structuredOutput` stays `experimental` here. The cloud seat reports in 5943158888 that its enforcement landed. It also raises a contract question for the maintainer: authoring accepts formats the runtime refuses. The PM files that question separately. ## Author-facing change (measured; a warning, not a refusal) I ran `lintLivenessPropertiesFromLedgerDir` over one stack: one agent that sets `guardrails` and one tool that sets `outputSchema`. - **Before** (the ledger at `30c530e5`): 2 findings, both `[liveness-experimental-property]`. One is on `guardrails` and one is on `outputSchema`. - **After** (this branch's ledger): 1 finding, on `outputSchema` only. For `agent.guardrails` the reading goes from 1 finding to 0. The accept set does not change. ## Verification, at `d0a0f125`, re-run on `58fdaac4` - **Patch round 1, at `58fdaac4`** (dev report `5943917260` on #20274), each with exit 0: - spec `build`, `check:liveness` and `check:generated`; - the 12 liveness script test files (347 passed); - `check:nul-bytes`, `check:doc-authoring`, `check:issue-citations` and `check:cross-package-test-inputs`; - the changeset gates; - `dispatch-gates --ran`: 104 families, 103 run, 1 NOT-MEASURED (`check:dual-build-cjs-loads`; CI's `Build Core` concluded `success`). - **At `d0a0f125`:** - `pnpm --filter @objectstack/spec check:liveness` → exit 0. - Verdict: "✓ every governed-type property, at every depth the ledger drills, is classified ...". - Totals: "987 live · 4 experimental · 1 live-elsewhere · 109 dead · 10 planned = 1111 classified". - `pnpm --filter @objectstack/spec check:generated` → exit 0: "✓ All 15 generated artifacts are up to date". Earlier, `--fix` proved exactly `gen:docs` and `gen:liveness-counts` stale and regenerated only those. - `pnpm --filter @objectstack/spec test` → exit 0: 597 test files passed; 17474 tests passed, 1 todo. - `pnpm --filter @objectstack/spec typecheck` → exit 0. - `@objectstack/lint` vitest over the 4 test files that import `lint-liveness-properties` → exit 0, 495 passed. - `pnpm check:doc-authoring` → exit 0. - `pnpm check:nul-bytes` → exit 0: "no raw ASCII control bytes". - `node scripts/pm/dispatch-gates.mjs --commands`: 10 paths against merge base `b91e40bc`, yielding 103 commands. Each was run and its exit code recorded. `--ran` reports: "✓ dispatch-gates --ran: 103 derived famil(ies) accounted for — 102 run, 1 NOT-MEASURED (1 DERIVED from a recorded exit 3)". - **NOT MEASURED:** `pnpm check:dual-build-cjs-loads`. Reason: PREREQUISITE NOT MET, because it reads every package's `dist/` and needs a whole-repo build. Declared to CI. ## Deviations - The PM's R1 refinement fell. Its premise, that the gate refuses `live` on cloud-only evidence, is falsified by the boundary pin. The PM's answer 5942977582 rules `live`, as triage wrote. - The guardrails row gains a `producer` field, following the README's producer discipline. Its content is quoted from 5940785002. - `tool.outputSchema` changed by the PM's scope addition after 5943158888 (the "stay experimental and steer" option). - The PM's message gives the author-lint reading as "2 findings, then 0". Measured per key, `agent.guardrails` goes from 1 to 0. The 2 counts both keys in the probe stack. ## Acceptance notes - **Filed as #21288:** `skills/objectstack-ai/SKILL.md:309-311` still says guardrails are "declared only — no runtime reads them", which has been false since cloud `235c5b29`. Lines `:279-281` still describe `outputSchema` keys as folded into the description. This is published skill text (Tier H), so the PM holds it for its own card, outside this PR. - **Fixed in patch round 1 (`58fdaac4`):** the two gate-script comments that repeated the README's corrected sentence, `packages/spec/scripts/liveness/elsewhere.mts` (header) and `readme-table.mts` (the status-column docblock). They are comments only, with no code change. - **The `action.ai` reader's known gap (objectstack-ai/cloud#2572) is fixed** on cloud `main` `1e0ea49a` (reading `5943779795` on #20274). A schema whose untyped subschema carries a type-scoped keyword is now refused before the action runs. - The authoring side still accepts that shape, for both `action.ai.outputSchema` and `agent.structuredOutput.schema`: filed as #21289. - The `action.json` row is not touched here. - **Filed as #21288, position 3:** `content/docs/protocol/objectui/actions.mdx:494` says `ai.outputSchema` enables "structured tool chaining". No reading names a chaining consumer, and the line is outside this PR's file surface. - `origin/main` (`b91e40bc`) was merged in with `scripts/pm/os-regen-merge.sh`. Nothing overlapped. The spec was rebuilt and every gate above was re-run on the merged head. Size: 12 files, +54 / −26. --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 1371dc9 commit 135daaa

12 files changed

Lines changed: 54 additions & 26 deletions

File tree

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
"@objectstack/spec": patch
3+
---
4+
5+
Liveness ledger: `agent.guardrails` (`maxTokensPerInvocation`, `maxExecutionTimeSec`, `blockedTopics`) is now `live`, not `experimental`. The cloud AI runtime enforces it on every user turn. The token and time limits are checked before each model round, with each limit refusal audited, and a blocked tool name or category is removed from the offer and refused at call time.
6+
7+
Clause-②: no
8+
9+
- The `guardrails` describe drops its `[EXPERIMENTAL — not enforced]` marker. It now says the cloud AI runtime enforces the block and the open framework edition does not run agents. The generated agent reference page follows.
10+
- Author-facing effect: `os lint` / `os validate` no longer warn `liveness-experimental-property` on an agent that sets `guardrails`. A warning is not a refusal, so the accept set is unchanged.
11+
- The ledger row cites the cloud readers and producer, dated to the reading they come from.
12+
- The liveness README no longer says its gate refuses `live` on evidence attributed only to the closed cloud runtime. The gate never did.
13+
- `tool.outputSchema` stays `experimental`, because nothing reads it on a tool record. Its describe and the tools guide now say where output validation actually lives: `ai.outputSchema` on the action, against which the cloud AI runtime checks the action's result. The old claim that the keys are folded into the tool description is gone.
14+
- ⛔ No schema, parse, export or accept-set change. `agent.memory`, `agent.structuredOutput` and `agent.lifecycle` stay `experimental`.

‎content/docs/ai/tools.mdx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ already executes, and it will still be one.
145145
| `label` | ✅ | Human-readable display name |
146146
| `description` | ✅ | The text the **model** reads to decide when to call the tool |
147147
| `parameters` | ✅ | JSON Schema for the tool input — the model generates arguments conforming to it |
148-
| `outputSchema` | optional | ⚠️ **Experimental, not enforced.** Its top-level keys are folded into the description shown to the model; outputs are never validated against it |
148+
| `outputSchema` | optional | ⚠️ **Experimental, not enforced.** Nothing reads it on a tool record. To have a result validated, declare the schema as `ai.outputSchema` on the action instead — the cloud AI runtime checks the action's result against that one and withholds a result that does not conform |
149149
| `objectName` | optional | The object this tool operates on, when there is exactly one |
150150
| `protection` | optional | Package-author lock policy ([ADR-0010](https://github.com/objectstack-ai/objectstack/blob/main/docs/adr/0010-metadata-protection-model.md)) |
151151

‎content/docs/references/ai/agent.mdx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ const result = AIModelConfigSchema.parse(data);
5959
| **permissions** | `string[]` | optional | Required permission-set capabilities |
6060
| **planning** | `{ maxIterations: integer }` | optional | Autonomous reasoning and planning configuration |
6161
| **memory** | `{ longTerm?: object; reflectionInterval?: integer }` | optional | [EXPERIMENTAL — not enforced] Agent memory management. Parsed but no runtime consumer yet. |
62-
| **guardrails** | `{ maxTokensPerInvocation?: integer; maxExecutionTimeSec?: integer; blockedTopics?: string[] }` | optional | [EXPERIMENTAL — not enforced] Safety guardrails for the agent. Parsed but not enforced — real limits come from the quota service. |
62+
| **guardrails** | `{ maxTokensPerInvocation?: integer; maxExecutionTimeSec?: integer; blockedTopics?: string[] }` | optional | Safety guardrails for the agent (token budget, time limit, blocked topics), enforced per user turn by the cloud AI runtime; the open framework edition does not run agents. |
6363
| **structuredOutput** | `{ format: Enum<'json_object' \| 'json_schema' \| 'regex' \| 'grammar' \| 'xml'>; schema?: Record<string, any>; strict: boolean; retryOnValidationFailure: boolean; … }` | optional | [EXPERIMENTAL — not enforced] Structured output format and validation configuration. Parsed but no runtime consumer yet. |
6464
| **protection** | `{ lock: Enum<'none' \| 'no-overlay' \| 'no-delete' \| 'full'>; reason: string; docsUrl?: string }` | optional | Package author protection block — lock policy for this agent. |
6565
| **_lock** | `Enum<'none' \| 'no-overlay' \| 'no-delete' \| 'full'>` | optional | Item-level lock — controls overlay & delete (ADR-0010). |

‎content/docs/references/ai/tool.mdx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ AI tool definition. [READ-ONLY PROJECTION — not an execution entry point] Auth
3434
| **label** | `string` | ✅ | Tool display name |
3535
| **description** | `string` | ✅ | Tool description for LLM function calling |
3636
| **parameters** | `Record<string, any>` | ✅ | JSON Schema for tool parameters |
37-
| **outputSchema** | `Record<string, any>` | optional | [EXPERIMENTAL — not enforced] JSON Schema for tool output. Keys are folded into the tool description only; outputs are not validated. |
37+
| **outputSchema** | `Record<string, any>` | optional | [EXPERIMENTAL — not enforced] JSON Schema for tool output; nothing reads it on a tool record — declare it as `ai.outputSchema` on the action, where the cloud AI runtime validates the action result against it. |
3838
| **objectName** | `string` | optional | Target object name (snake_case) |
3939
| **protection** | `{ lock: Enum<'none' \| 'no-overlay' \| 'no-delete' \| 'full'>; reason: string; docsUrl?: string }` | optional | Package author protection block — lock policy for this tool. |
4040
| **_lock** | `Enum<'none' \| 'no-overlay' \| 'no-delete' \| 'full'>` | optional | Item-level lock — controls overlay & delete (ADR-0010). |

‎packages/spec/liveness/README.md‎

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ registry to fold it back onto — the override *is* its governance.
7575
| `live` | Has a runtime consumer. Cite it in `evidence`, preferably anchored to the consuming symbol — `file#symbol` — with `file:line` as an optional convenience; for another repo's path, prefix the realm — `objectui: packages/app-shell/…` (see below). |
7676
| `experimental` / `planned` | Declared, intentionally not enforced yet. Also read from a spec `.describe()` marker like `[EXPERIMENTAL — not enforced]`. |
7777
| `dead` | Parsed, no consumer **anywhere the census looked**. Tracked for **enforce-or-remove** (ADR-0049). A key that is dead here but enforced in a sibling repo is NOT `dead` — it is `live-elsewhere`, below. |
78-
| `live-elsewhere` | Dead here by measurement, **genuinely enforced in a sibling repo** (#13483). Not deletable, and deliberately unable to satisfy `live`'s local-evidence rules; carries its own gate-executable criteria — see the section below. Ledger-entry-only (no `.describe()` marker). |
78+
| `live-elsewhere` | Dead here by measurement, **genuinely enforced in a sibling repo** (#13483). Not deletable. The template is `manifest.runtime`, "ENFORCED AT THE CLOUD PUBLISH GATE, NOT ENFORCED AT LOAD" — its load side belongs to this repo's loader. A key whose consumer is the closed cloud runtime is `live` with a `cloud`-attributed pointer instead (`agent.json`'s `_note`). Carries its own gate-executable criteria — see the section below. Ledger-entry-only (no `.describe()` marker). |
7979

8080
Resolution per property: **ledger entry → spec `.describe()` marker → UNCLASSIFIED**.
8181
Framework provenance/lock fields (`_lock*`, `_provenance`, `_packageId/Version`,
@@ -280,10 +280,17 @@ The measured template is `manifest.runtime`: two CLI echo lines here, and the
280280
cloud marketplace publish gate hard-rejecting (HTTP 422) an unverified
281281
publisher requesting the `node` tier (#12400). `dead` lies about that key — read
282282
alone it licenses deleting the marketplace's trust-gate input, which the
283-
maintainer ruling of 2026-08-30 (executed by commit a9ee98992) explicitly ruled out — and `live` is
284-
refused by this gate, whose repo-local evidence must resolve against this
285-
checkout. Until #13483 the truth lived in a qualifying sentence inside the
286-
row's `note`; prose is the weakest protection this ledger knows.
283+
maintainer ruling of 2026-08-30 (executed by commit a9ee98992) explicitly ruled out — and `live`
284+
overstates it, because the key's load side belongs to this repo's loader, and the row's own
285+
note records it "ENFORCED AT THE CLOUD PUBLISH GATE, NOT ENFORCED AT LOAD". The gate itself
286+
does not refuse `live` on cloud-only evidence: a cloud-attributed pointer is counted and
287+
never resolved, because failing on one "would make the gate unsatisfiable for every
288+
property whose consumer is the renderer or the closed cloud runtime" (the boundary pin in
289+
`scripts/liveness/check-liveness.test.ts`). So a key consumed only by the closed AI runtime
290+
stays `live` — `agent.json`'s `_note`: "These props are `live` because that cloud runtime
291+
consumes them; the OPEN framework edition does not". Until #13483 the truth lived in a
292+
qualifying sentence inside the row's `note`; prose is the weakest protection this ledger
293+
knows.
287294

288295
The gate cannot resolve another repo's file (deliberate — see the realm-marker
289296
boundary above), so a `live-elsewhere` row is held to criteria the gate CAN

‎packages/spec/liveness/agent.json‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,12 @@
9595
"note": "aspirational autonomy."
9696
},
9797
"guardrails": {
98-
"status": "experimental",
99-
"evidence": "no runtime reader",
100-
"note": "aspirational — real limits via quota service."
98+
"status": "live",
99+
"verifiedAt": "2026-10-01",
100+
"evidenceScope": "cross-repo",
101+
"evidence": "cloud @235c5b29: packages/service-ai/src/ai-service.ts#TurnGovernor — checks maxExecutionTimeSec and maxTokensPerInvocation per user turn in chatWithToolsImpl, streamChatWithTools and runApprovedProposalReplay, before every model round, before a tool batch is recorded and before the forced final call; a refusal is a typed reply plus a sys_ai_audit_log row with event guardrail_refusal; cloud @235c5b29: packages/service-ai/src/agent-runtime.ts#AgentRuntime.resolveTurnGuardrails — resolves that per-turn policy from the agent's guardrails; cloud @235c5b29: packages/service-ai/src/agent-runtime.ts#matchBlockedTopic — blockedTopics, the spec's 'forbidden topics or action names': an exact, case-sensitive match on the tool name, on action_T or on the tool category, removed from the offer and refused at call time, the replay included.",
102+
"producer": "cloud @235c5b29: packages/service-ai-studio/src/agents/metadata-assistant-agent.ts — the built-in build agent authors maxExecutionTimeSec 600 and maxTokensPerInvocation 500000, re-authored from 865 measured turns; any tenant-authored agent is the other producer. No built-in agent authors a blockedTopics value at this ref: all seven were dropped because none matched anything in the tool registry.",
103+
"note": "Flipped from experimental on the cloud seat's reading, not on a reading taken from this repo — no seat in the flipping session could read cloud. The reading: the repo:cloud seat repo:cloud#1 (session_01Wxo1xhh2bU66T73q23jzE4), comment 5940785002 on objectstack-ai/objectstack#20274, of cloud main @235c5b29 (the merge of objectstack-ai/cloud#2559), read 2026-10-01; verifiedAt is that reading's date, and every evidence and producer pointer above is quoted from it. The blanket verdict covers all three children: maxTokensPerInvocation, maxExecutionTimeSec and blockedTopics. These keys are live because the cloud runtime consumes them; the OPEN framework edition does not run agents (this file's _note). ⛔ Re-attest by re-reading cloud, never by re-stamping the date."
101104
},
102105
"structuredOutput": {
103106
"status": "experimental",

‎packages/spec/liveness/state-counts/agent.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@ committed anywhere: `check:liveness` sums the shards when it reads them.
1212

1313
| Type | live | exp | elsewhere | dead | planned | classified |
1414
|---|---|---|---|---|---|---|
15-
| `agent` | 20 | 4 | 0 | 2 | 0 | 26 |
15+
| `agent` | 21 | 3 | 0 | 2 | 0 | 26 |

‎packages/spec/liveness/tool.json‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,10 @@
4343
},
4444
"outputSchema": {
4545
"status": "experimental",
46-
"verifiedAt": "2026-08-29",
46+
"verifiedAt": "2026-10-02",
4747
"evidenceScope": "cross-repo",
48-
"evidence": "cloud @15f55df: packages/service-ai/src/tools/action-tools.ts#outputSchemaKeys lists the top-level property names and packages/service-ai/src/tools/action-tools.ts#buildToolDescription folds them into the LLM-facing description as a trailing Returns-an-object-with line",
49-
"note": "keys folded into description only; no validation exists. Re-closed 2026-08-29 against cloud @15f55df and BOTH halves hold. The fold is real, at the two anchored sites. The negative half is now measured rather than asserted: `outputSchema` occurs on exactly four non-test lines in the entire cloud repo — the two folding sites, the docblock naming them, and the spread that copies action.ai.outputSchema onto the AIToolDefinition field, which nothing reads back. No validator, no chaining consumer, in cloud or in this repo. ⚠ Two scope notes. Both folding sites read `action.ai.outputSchema`, not this key, so what actually carries the verdict is the spec's own `[EXPERIMENTAL — not enforced]` describe marker, which is a legal resolution source in its own right and does not depend on a consumer at all. And objectui HAS since been walked: ToolPreview reads the persisted record's outputSchema and renders it as an 'Output Schema' mirror table. That is a display read, not enforcement — it does not disturb `experimental`, which is a claim about the absence of VALIDATION, and a renderer is not where validation would live."
48+
"evidence": "no reader of this key. cloud @cb62c3ea: packages/service-ai/src/tools/action-tools.ts#compileOutputContract — the action tool's handler validates against action.ai.outputSchema, read directly, never against the tool definition's member; cloud @cb62c3ea: packages/service-ai/src/tools/action-tools.ts#actionToToolDefinition — AIToolDefinition.outputSchema is only a copy of action.ai.outputSchema, and nothing reads it back.",
49+
"note": "Stays experimental: authoring this key changes no runtime behaviour. Output validation IS enforced, but on action.ai.outputSchema, whose row is action.json's `ai` (live): a non-conforming result is withheld with a typed error, and a schema the checker cannot read refuses the action before it runs. This key has no reader because an authored tool record never becomes a tool definition: agents take their tools from the live registry, and the one site that touches tool metadata, cloud's service-ai-studio plugin, mirrors the built-in definitions INTO metadata for display, the other direction, with no outputSchema on any of them. The spec describe therefore steers an author to action.ai.outputSchema. The readings behind this row, both by the repo:cloud seat repo:cloud#1 (session_01Wxo1xhh2bU66T73q23jzE4) on objectstack-ai/objectstack#20274: comment 5940785002, of cloud main @235c5b29 on 2026-10-01, for what compileOutputContract enforces; and comment 5943158888, of cloud main @cb62c3ea on 2026-10-02, for which value it reads and for the absence of any other producer. verifiedAt is the second reading's date; no seat in the session that wrote this row could read cloud. objectui's ToolPreview still renders a persisted record's outputSchema as an 'Output Schema' table (objectui @26896c6): a display read, not validation, so it does not disturb experimental. ⛔ Re-attest by re-reading cloud, never by re-stamping the date."
5050
}
5151
}
5252
}

‎packages/spec/scripts/liveness/elsewhere.mts‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@
99
// measured 2026-08-29 on cloud @15f55df). Neither existing verdict can say
1010
// that. `dead` is true only of the local half — read alone it licenses deleting
1111
// a key with a real cross-repo consumer, and the maintainer ruling of
12-
// 2026-08-30 (#11330) explicitly ruled that deletion OUT. `live` is refused by
13-
// the gate itself: a live verdict's repo-local evidence must resolve against
14-
// this checkout, and cloud's enforcer is not local. The stopgap was a
12+
// 2026-08-30 (#11330) explicitly ruled that deletion OUT. `live` overstates
13+
// it: the key's load side belongs to this repo's loader, which does not
14+
// enforce it. (The gate itself does NOT refuse `live` on cloud-only evidence —
15+
// see the boundary pin in check-liveness.test.ts.) The stopgap was a
1516
// qualifying sentence in the row's `note` — prose, which no check reads, i.e.
1617
// the weakest protection this ledger knows. So: a status that SAYS the split —
1718
// dead here, enforced there — and reads as NOT deletable.

‎packages/spec/scripts/liveness/readme-table.mts‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,8 +304,10 @@ export function stateCountShardName(type: string): string {
304304
* The status columns the table publishes, in the order it publishes them.
305305
* `live-elsewhere` is the deliberate fifth (#13483): dead here by measurement,
306306
* genuinely enforced in a sibling repo — a verdict that must read as NOT
307-
* deletable and must not satisfy `live`'s local-evidence rules (its own
308-
* executable criteria live in elsewhere.mts). Widening this list is an
307+
* deletable, for a key whose load side belongs to this repo's loader, which
308+
* does not enforce it. The gate does not refuse `live` on cloud-only evidence
309+
* (the boundary pin in check-liveness.test.ts); this status's own executable
310+
* criteria live in elsewhere.mts. Widening this list is an
309311
* artifact-shape decision (#7377): `StateCountsRow`, `foldStateCounts` and
310312
* `renderStateCountShard` name every column by hand — move all of them together
311313
* with this line, then regenerate.

0 commit comments

Comments
 (0)