Skip to content

Commit 388abdb

Browse files
docs(vrs): restore the strict validation gate
agent-identity: dev3.direct.omp.43sz6ujq agent-persona: generalist agent-supervisor: unavailable agent-tool: OMP agent-tool-version: 18.1.7 agent-runtime: OMP 18.1.7 tooling-profile: dotfiles@39a19af
1 parent 03b7cdb commit 388abdb

13 files changed

Lines changed: 158 additions & 104 deletions

docs/vrs/.decisions/0005-pi-delivers-natively-through-an-injected-extension.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ the workspace-trust dialog. Codex gets a dedicated app-server daemon, an observe
1111
before the interactive client, thread-ownership binding, and a hard version pin — 4940 lines.
1212
Underneath both sits DING, the screen-scraping transport that exists because neither harness offered
1313
anything better at the time, and whose safety rests on a synchronous adjacent composer proof
14-
([`0004`](0004-only-a-synchronous-proof-authorizes-a-pty-write.md)).
14+
([`0001-ding-harness-dispatch-is-positional-and-harness-owned`](0001-ding-harness-dispatch-is-positional-and-harness-owned.md)).
1515

1616
Adding pi asks which of these shapes it should take. pi answers the question itself: it has no MCP,
1717
no app-server, and no lifecycle-hook mechanism. What it has is an extension API that runs **inside**
@@ -65,7 +65,7 @@ reproducible with no credentials. Full record and captures:
6565
pi is a natively-delivered harness. It declares `deliver "pi-channel"` or a typed `pi {}` driver,
6666
and **no pi arm is added to the DING registry**. The existing rule that refuses `ding` together with
6767
`deliver` (`crates/agent-spec/src/spec.rs`) is what keeps a pi agent off the PTY write path
68-
entirely, so [`0004`](0004-only-a-synchronous-proof-authorizes-a-pty-write.md) is untouched.
68+
entirely, so [`0001-ding-harness-dispatch-is-positional-and-harness-owned`](0001-ding-harness-dispatch-is-positional-and-harness-owned.md) is untouched.
6969

7070
Four things follow, each chosen against a specific failure it prevents:
7171

docs/vrs/.decisions/0007-child-output-capture-is-bounded-and-tail-preserving.md

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,19 @@ the bash judge that can deadlock.
4242
4. **Eval run steps stream to their log files** instead of buffering, and the
4343
bash judge uses null stdio (only its exit status is consumed).
4444

45-
Rejected alternatives: disk spill references for oversized diagnostics
46-
(spill-file lifecycle for no demonstrated consumer) and streaming every
47-
shell-out to log files exec-backend style (changes every error path; revisit
48-
only if a consumer needs full oversized diagnostics).
45+
## Options
46+
47+
| Option | Result | Reason |
48+
| --- | --- | --- |
49+
| Cap diagnostics; keep named payload capture complete | Selected | Bounds memory while preserving structured payload parsing. |
50+
| Spill oversized diagnostics to disk | Rejected | Adds spill-file lifecycle without a demonstrated consumer. |
51+
| Stream every shell-out to log files | Rejected | Changes every error path; revisit only if a consumer needs complete oversized diagnostics. |
52+
53+
## Evidence and Argument
54+
55+
The reproduced 16 MiB and eight-way concurrent probes showed peak RSS scaling
56+
with child output. The selected cap removes that scaling while retaining the
57+
tail that carries failure diagnostics.
4958

5059
## Consequences
5160

docs/vrs/.delta/DELTA-004-stream-dedup-horizon.md

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,40 @@
11
# DELTA-004: stream deduplication is bounded to the receipt ring
22

3-
## Current mismatch
3+
Status: open
4+
5+
## Divergence
6+
7+
Ratified requirements promise replay identity beyond the shipped bounded
8+
receipt horizon.
9+
10+
## VRS
411

512
Ratified [`STREAM-R04`](../04-stream/requirements.md) promises that replaying
613
an event identity always returns its original filename, including after the
714
event is archived. [`STREAM-R05`](../04-stream/requirements.md) says
815
correctness never depends on the bounded ring because unread inbox copies and
916
archive receipts anchor replay identity.
1017

18+
## Implementation
19+
1120
The shipped implementation deliberately keeps only 128 receipts per stream
1221
and performs no inbox or archive identity scan. Within that horizon, replay is
1322
idempotent and conflicting content fails. After eviction, the same event ID is
1423
honestly accepted as a new event. Archive receipts remain authoritative for
1524
their known filenames during crash recovery, but they are not an index from
1625
`(stream, event-id)` to filename.
1726

18-
## Why the implementation differs
19-
2027
Searching every archive would make emit cost proportional to retained stream
2128
history and contradict the bounded-state goal. An unread-only fallback would
2229
make idempotency change when an agent archives an event. A bounded receipt
2330
window gives a precise operational contract and keeps ingress work independent
2431
of inbox/archive history.
2532

26-
## Required resolution
33+
## Direction
34+
35+
update VRS
36+
37+
## Resolution Signal
2738

2839
Requirements are protected. Maintainer approval is required to amend
2940
STREAM-R04/R05 to make the retained receipt horizon the idempotency boundary.

docs/vrs/.experiments/2026-08-18-pi-harness-integration.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@ Subject: `pi` — the pi coding agent CLI, npm `@earendil-works/pi-coding-agent`
66
`earendil-works/pi`. The older `@mariozechner/pi-coding-agent` (0.73.1) is npm-deprecated in favour of
77
it. `pi` was not on this host's `PATH`; 0.84.2 was installed into a scratch prefix for these runs.
88

9+
## Method
10+
911
All runs used a local fake OpenAI-completions server rather than a real provider, so every result is
1012
reproducible with no credentials and no network. Artifacts are in
1113
[`2026-08-18-pi-captures/`](2026-08-18-pi-captures/): the prototype extension
1214
(`st2-channel.ts`), the fake provider registration (`fake-provider.ts`), the fake model server
1315
(`fake-llm.mjs`), and the two event captures cited below.
1416

15-
## Why this matters for st2
17+
## Question
1618

1719
st2's two existing harnesses each solve native delivery a different way, and neither is cheap:
1820

@@ -26,7 +28,7 @@ pi's extension API changes what is available. An extension runs **inside** the i
2628
process, can inject a user message, and sees a full lifecycle event stream. The measurements below
2729
were taken to decide whether that is real.
2830

29-
## Established facts (measured, not asserted)
31+
## Result
3032

3133
| Fact | Evidence |
3234
|---|---|
@@ -49,14 +51,14 @@ were taken to decide whether that is real.
4951
- No app-server daemon, no observer pre-connection, no thread binding, no protocol version pin: the
5052
channel is in-process and the injection point is a documented API call.
5153
- No screen scraping on the delivery path. The synchronous-proof rule in
52-
[`../.decisions/0004`](../.decisions/0004-only-a-synchronous-proof-authorizes-a-pty-write.md)
54+
[`0001-ding-harness-dispatch-is-positional-and-harness-owned`](../.decisions/0001-ding-harness-dispatch-is-positional-and-harness-owned.md)
5355
governs PTY writes; a natively-delivered agent never enters that path
5456
(`crates/agent-spec/src/spec.rs:887` refuses `ding` together with `deliver`).
5557
- No `pretrust.rs` analogue: `-a` is a launch flag, so nothing mutates ambient user config and the
5658
multi-spawn lost-update race that motivated batching for Claude cannot arise.
5759
- Presence still needs a liveness owner, because SIGKILL is silent. This is unchanged from Claude.
5860

59-
## The implemented slice
61+
## Conclusion
6062

6163
The design these measurements support is implemented on this branch and recorded as
6264
[decision 0005](../.decisions/0005-pi-delivers-natively-through-an-injected-extension.md). One
@@ -140,6 +142,12 @@ Three behaviours were added on review and each was verified, not assumed
140142
calling it, which is the silent failure that would turn every mid-turn delivery into a plain
141143
send.
142144

145+
## VRS Impact
146+
147+
The measurements ground the pi native-delivery specification, its in-process
148+
idle proof, session-replacement channel ownership, and type-checked extension
149+
boundary.
150+
143151
## Host context worth recording
144152

145153
This host already runs pi under a separate agent-management system: two global extensions

docs/vrs/02-agent-spec/requirements.md

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,24 @@ and host-local runtime state are sufficient. It requires no compare-and-swap
2323
implementation gaps. The root st2 VRS has authority for st2 behavior; the
2424
canonical evals Agent Spec remains the authoring authority.
2525

26-
Field lookup: [F01](./spec.md#f01), [F02](./spec.md#f02),
27-
[F03](./spec.md#f03), [F04](./spec.md#f04), [F05](./spec.md#f05),
28-
[F06](./spec.md#f06), [F07](./spec.md#f07), [F08](./spec.md#f08),
29-
[F09](./spec.md#f09), [F10](./spec.md#f10), [F11](./spec.md#f11),
30-
[F12](./spec.md#f12), [F13](./spec.md#f13), [F14](./spec.md#f14),
31-
[F15](./spec.md#f15), [F16](./spec.md#f16), [F17](./spec.md#f17), and F18-F20
32-
in the same field-rules specification.
26+
Field lookup: [F01](./spec.md#f01-source-form-or-path),
27+
[F02](./spec.md#f02-agent-id-and-legacy-identity),
28+
[F03](./spec.md#f03-host), [F04](./spec.md#f04-type),
29+
[F05](./spec.md#f05-role), [F06](./spec.md#f06-workspace),
30+
[F07](./spec.md#f07-resource-name-or-uri),
31+
[F08](./spec.md#f08-render-operation-template-or-resolved-target),
32+
[F09](./spec.md#f09-task-set-pty-exec-or-compact-ding),
33+
[F10](./spec.md#f10-task-name-or-explicit-id),
34+
[F11](./spec.md#f11-spawn-inputs),
35+
[F12](./spec.md#f12-future-policy-r31),
36+
[F13](./spec.md#f13-retired-true),
37+
[F14](./spec.md#f14-compact-agent-fields),
38+
[F15](./spec.md#f15-provider-and-ignored-fields),
39+
[F16](./spec.md#f16-invalid-or-incomplete-state),
40+
[F17](./spec.md#f17-agent-name-and-description),
41+
[F18](./spec.md#f18-desired-state-and-reason),
42+
[F19](./spec.md#f19-agent-stream), and
43+
[F20](./spec.md#f20-agent-address).
3344

3445
## Shared invariants
3546

docs/vrs/02-agent-spec/spec.md

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ core publication and do not claim managed admission.
185185

186186
## Field rules
187187

188-
<h3 id="f01">F01 Source form or path</h3>
188+
### F01 Source form or path
189189

190190
Formatting, comments, order, and a source path change are `no-op` only when all
191191
normalized fields, render plans, task IDs, fallback `cwd`, exact resolved paths,
@@ -197,7 +197,7 @@ Authoring: [pinned discovery, identity, and host][evals-discovery]. st2 source:
197197
[KDL parser](../../../crates/agent-spec/src/kdl_format.rs). Evidence:
198198
[discovery](../../../crates/agent-spec/src/discovery.rs).
199199

200-
<h3 id="f02">F02 Agent <code>id</code> and legacy <code>identity</code></h3>
200+
### F02 Agent `id` and legacy `identity`
201201

202202
The target `id` field is the immutable catalog-global agent ID. IDs are unique
203203
across live and structurally archived subjects, across hosts and desired states.
@@ -238,7 +238,7 @@ writer emits it yet; positional `identity` is still the durable key. That gap is
238238
fenced by
239239
[DELTA-003](../.delta/DELTA-003-agent-address-not-implemented.md).
240240

241-
<h3 id="f03">F03 <code>host</code></h3>
241+
### F03 `host`
242242

243243
Each supervisor evaluates only local membership. A complete present-to-absent
244244
change removes locally; absent-to-present adds locally. This is not migration,
@@ -249,7 +249,7 @@ Authoring: [pinned discovery and host][evals-discovery]. st2 source:
249249
[`AgentSpec::host`](../../../crates/agent-spec/src/spec.rs). Evidence:
250250
[host filtering](../../../src/reconcile.rs).
251251

252-
<h3 id="f04">F04 <code>type</code></h3>
252+
### F04 `type`
253253

254254
An omitted value and `service` have the same effect. Any other value refuses
255255
changes to the related agent, tasks, and files before launch, write, or teardown.
@@ -258,7 +258,7 @@ Authoring: [pinned complete declaration][evals-fields]. st2 source:
258258
[`JobType` and `RawSpec::job_type`](../../../crates/agent-spec/src/spec.rs).
259259
Evidence: [validation](../../../src/validate.rs).
260260

261-
<h3 id="f05">F05 <code>role</code></h3>
261+
### F05 `role`
262262

263263
Update observable declaration metadata only. Do not change the fingerprint,
264264
workspace files, notification state, or a healthy task.
@@ -267,7 +267,7 @@ Authoring: [pinned complete declaration][evals-fields]. st2 source:
267267
[`AgentSpec::role`](../../../crates/agent-spec/src/spec.rs). Evidence:
268268
[KDL lowering](../../../crates/agent-spec/src/kdl_format.rs).
269269

270-
<h3 id="f06">F06 <code>workspace</code></h3>
270+
### F06 `workspace`
271271

272272
For a healthy survivor, keep the process and commit the new live context. After
273273
commit, write one durable event with the old and new paths, then try
@@ -281,7 +281,7 @@ Authoring: [pinned complete declaration][evals-fields]. st2 source:
281281
[`AgentSpec::workspace`](../../../crates/agent-spec/src/spec.rs). Evidence:
282282
[`cwd` resolution](../../../src/run.rs).
283283

284-
<h3 id="f07">F07 Resource <code>name</code> or <code>uri</code></h3>
284+
### F07 Resource `name` or `uri`
285285

286286
Update Resource data without changing the launch fingerprint. Notify a
287287
survivor once after commit. New or replaced work reads the latest state at boot
@@ -292,7 +292,7 @@ st2 `9887b28` predate Resource bindings. Current st2 source:
292292
[`Resource`](../../../crates/agent-spec/src/spec.rs). Evidence:
293293
[declared Resource projection](../../../src/agents.rs).
294294

295-
<h3 id="f08">F08 <code>render {}</code> operation, template, or resolved target</h3>
295+
### F08 `render {}` operation, template, or resolved target
296296

297297
Prove ownership for every affected local owner before writing. Conflicts refuse
298298
all affected owners. Write changed bytes and enforce the declared mode. The
@@ -307,7 +307,7 @@ declaration.
307307
Authoring: [pinned render contract][evals-render]. st2 implementation and
308308
evidence: [materializer](../../../src/materialize.rs).
309309

310-
<h3 id="f09">F09 Task set: <code>pty</code>, <code>exec</code>, or compact <code>ding</code></h3>
310+
### F09 Task set: `pty`, `exec`, or compact `ding`
311311

312312
Add only the unique missing child. Remove and clean only an old child with exact
313313
ownership proof. A compact DING is a derived child: it starts only after its
@@ -329,7 +329,7 @@ Authoring: [pinned compact and explicit tasks][evals-tasks]. st2 source:
329329
[`Task` and `TaskKind`](../../../crates/agent-spec/src/spec.rs). Evidence:
330330
[task reconciliation](../../../src/reconcile.rs).
331331

332-
<h3 id="f10">F10 Task <code>name</code> or explicit <code>id</code></h3>
332+
### F10 Task `name` or explicit `id`
333333

334334
Remove the exact old ID and add the new ID. Do not infer one incarnation.
335335
Report both actions, or `hold` or `refuse` when ownership proof is missing.
@@ -338,7 +338,7 @@ Authoring: [pinned explicit tasks][evals-tasks]. st2 source:
338338
[`Task::name` and `Task::id`](../../../crates/agent-spec/src/spec.rs). Evidence:
339339
[task reconciliation](../../../src/reconcile.rs).
340340

341-
<h3 id="f11">F11 Spawn inputs</h3>
341+
### F11 Spawn inputs
342342

343343
Task `kind`, `command`, `argv`, explicit `cwd`, and task `env`, plus agent
344344
`env`, `tags`, `supervisor`, and any other start input form the versioned launch
@@ -354,7 +354,7 @@ Authoring: [pinned tasks][evals-tasks] and [environment][evals-environment]. The
354354
Current st2 source: [`AgentSpec` and `Task`](../../../crates/agent-spec/src/spec.rs).
355355
Evidence: [spawn construction](../../../src/run.rs).
356356

357-
<h3 id="f12">F12 Future policy (R31)</h3>
357+
### F12 Future policy (R31)
358358

359359
```text
360360
canonical catalog folder + host = supervisor scope
@@ -416,7 +416,7 @@ Authoring: [pinned complete declaration][evals-fields]. The
416416
[`execute`](../../../src/run.rs). Evidence:
417417
[policy planning](../../../src/reconcile.rs).
418418

419-
<h3 id="f13">F13 <code>retired #true</code></h3>
419+
### F13 `retired #true`
420420

421421
Fence, stop, and clean every declared task ID with exact ownership proof, and
422422
prevent relaunch. Retirement preserves the agent ID, removes the subject from
@@ -429,7 +429,7 @@ Authoring: [pinned complete declaration][evals-fields]. st2 source:
429429
[`AgentDesiredState`](../../../crates/agent-spec/src/spec.rs). Evidence:
430430
[retirement planning](../../../src/reconcile.rs).
431431

432-
<h3 id="f14">F14 Compact agent fields</h3>
432+
### F14 Compact agent fields
433433

434434
Compact `command`, `argv`, `env`, `lifecycle`, and `ding` convert to the
435435
generated agent PTY and derived sidecar. The tasks use F09, F11, and F12;
@@ -441,7 +441,7 @@ predate compact `argv` and `lifecycle`. Current st2 source:
441441
[KDL fields](../../../crates/agent-spec/src/kdl_format.rs). Evidence:
442442
[`RawSpec` lowering](../../../crates/agent-spec/src/spec.rs).
443443

444-
<h3 id="f15">F15 Provider and ignored fields</h3>
444+
### F15 Provider and ignored fields
445445

446446
Core st2 ignores `harness`, `model`, `persona`, `permissions`, `transport`,
447447
`strategy`, `meta`, and provider extensions. They do not change core equality,
@@ -452,7 +452,7 @@ Authoring: [pinned complete declaration][evals-fields]. st2 source:
452452
[KDL field boundary](../../../crates/agent-spec/src/kdl_format.rs). Evidence:
453453
[`RawSpec` lowering](../../../crates/agent-spec/src/spec.rs).
454454

455-
<h3 id="f16">F16 Invalid or incomplete state</h3>
455+
### F16 Invalid or incomplete state
456456

457457
Refuse changes to an agent, task, or file when its desired or actual state is
458458
unreadable, invalid, ambiguous, or conflicting. Keep last-known-good ownership
@@ -464,7 +464,7 @@ source: [`RawSpec` and `AgentSpec`](../../../crates/agent-spec/src/spec.rs).
464464
Evidence: [validation](../../../src/validate.rs) and
465465
[reconciliation](../../../src/reconcile.rs).
466466

467-
<h3 id="f18">F18 <code>desired-state</code> and <code>reason</code></h3>
467+
### F18 `desired-state` and `reason`
468468

469469
`desired-state` is one of `running`, `suspended`, or `retired`. Its omission is
470470
running. A suspended or new-style retired declaration carries exactly one
@@ -517,7 +517,7 @@ st2 source: [`AgentDesiredState`](../../../crates/agent-spec/src/spec.rs),
517517
[authoring](../../../tests/agent_desired_state.rs), and
518518
[planning](../../../tests/reconcile.rs).
519519

520-
<h3 id="f17">F17 Agent <code>name</code> and <code>description</code></h3>
520+
### F17 Agent `name` and `description`
521521

522522
Update observable declaration and runtime presentation metadata only. Neither
523523
field participates in agent ID, address routing, selection, authorization,
@@ -546,11 +546,11 @@ change lands. st2 source: [`AgentSpec`](../../../crates/agent-spec/src/spec.rs),
546546
Evidence: parser, roster, exact-ID metadata, and no-restart presentation tests.
547547

548548

549-
<h3 id="f19">F19 Agent <code>stream</code></h3>
549+
### F19 Agent `stream`
550550

551551
A `stream "<name>" {}` declares one agent-owned event ingress endpoint. Names
552-
are 1..=40 characters matching
553-
`[a-z0-9]([a-z0-9-]*[a-z0-9])?` and cannot collide with an authored task named
552+
are 1..=40 lowercase alphanumeric characters with optional interior hyphens
553+
and cannot collide with an authored task named
554554
`stream-<name>`. The declaration contains at most one launch: `command` is an
555555
opaque shell command, `argv` is a non-empty structured argument vector, and an
556556
empty body means external ingress. Unknown children, including the reserved
@@ -571,7 +571,7 @@ lands. st2 source: [`Stream`](../../../crates/agent-spec/src/spec.rs),
571571
[`streams_are_typed_and_only_launched_streams_lower_to_derived_exec_tasks`](../../../crates/agent-spec/tests/discovery.rs)
572572
and stream lifecycle tests in [`tests/run.rs`](../../../tests/run.rs).
573573

574-
<h3 id="f20">F20 Agent <code>address</code></h3>
574+
### F20 Agent `address`
575575

576576
`address` is an optional mutable semantic alias for human routing. Its omission
577577
uses positional `identity` as the effective legacy address. Its presence

docs/vrs/02-doctor/requirements.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# Doctor requirements
22

33
Doctor checks one catalog from one host. It follows the root
4-
[vision](../vision.md). It refines [R03](../requirements.md#L46-L47),
5-
[R04](../requirements.md#L51-L54), and [R08](../requirements.md#L92-L95).
4+
[vision](../vision.md). It refines [R03](../requirements.md),
5+
[R04](../requirements.md), and [R08](../requirements.md).
66
It does not define fleet health.
77

88
## Requirements
@@ -34,6 +34,6 @@ It does not define fleet health.
3434
is a failed check that says the agent cannot send. An unavailable ledger is
3535
healthy because no sender history exists.
3636

37-
The [Retirement health invariant](../../../INVARIANTS.md#L20) and its tests prove
37+
The [Retirement health invariant](../../../INVARIANTS.md) and its tests prove
3838
the retirement rule. The [specification](spec.md) owns the mechanism, check
3939
groups, and known gaps.

0 commit comments

Comments
 (0)