Problem
The folder catalog currently makes one mutable agent.kdl carry several
different identities at once:
authored bytes
desired selection
publication generation
runtime reconciliation input
That works for hand-edited static catalogs, but it does not give generated or
dynamic Agent Specs a transaction boundary.
Three concrete failures make the distinction load-bearing:
- Publishing new bytes under the same task ID is immediately visible to the
resident watcher, while reconciliation may adopt the old process. Desired
bytes can say g2 while the process still executes g1
(#40,
#44).
- Per-seat atomic files cannot preserve catalog-wide invariants. Two changes
can each validate against the same base yet combine into duplicate lowered
task IDs or dangling supervisor references. A multi-seat rename/swap may
have a valid final catalog but no valid first per-seat write.
- Agent Spec requirements and durable resource bindings have no shared
admission identity. Publishing the spec first can expose missing/old
bindings; publishing bindings first can expose extraneous or over-broad
access.
The existing exact-byte publication proposal
(#41) is the right starting
point, but an atomic agent.kdl replacement alone cannot close the
catalog-wide or spec/resource admission gaps.
The original runnable reproduction remains:
https://github.com/schickling-repros/2026-07-st2-dynamic-agent-spec-lifecycle
The corresponding portable eval direction is tracked in
compoundingtech/evals#37.
Proposed incubation model
Use a Git-like immutable object graph with one catalog-wide visibility point:
mutable catalog head --CAS--> immutable catalog-root commit
`-- seat -> immutable Seat Admission
|-- ref commit
| `-- revision/tree/blobs
`-- resource-binding commit
The identities are deliberately separate:
- Revision: exact accepted Agent Spec bytes plus catalog-owned immutable
materialization inputs.
- Ref commit: per-seat manager custody, lineage, operation identity, and
target revision/tombstone. Expected-parent CAS closes A -> B -> A.
- Seat Admission: exact join of one ref commit and its compatible typed
resource-binding commit.
- Catalog-root commit: complete seat map and the only catalog-wide atomic
visibility boundary.
- Realization receipt: later runtime evidence for the exact
root/admission/revision/launch actually running; not part of this first store
slice.
Publication is nondestructive:
prepare/import immutable closure
-> construct manager-scoped patch
-> validate complete candidate catalog
-> write immutable objects
-> CAS one catalog head
It does not imply materialization, replacement, running, or readiness.
Why a catalog root is required
Catalog-wide validation plus a daemon mutex is insufficient if readers can see
seat files one at a time. For example:
old seat owns task T
dependent seat points to old seat
desired atomic patch:
remove old seat
add new seat owning task T
repoint dependent seat to new seat
Every first per-seat write is invalid:
- add new first: duplicate task T;
- remove old first: dangling supervisor/reference;
- repoint dependent first: dangling destination.
An immutable complete root followed by one head CAS exposes either the complete
old catalog or complete new catalog across crashes and concurrent readers.
Proposed first PR slice
Incubate, rather than prematurely standardize, these primitives:
- exact-byte immutable spec/revision objects;
- immutable ref commits with manager, parent, operation ID, and replay-safe
terminal outcome;
- immutable resource-binding commits and Seat Admissions;
- immutable complete catalog-root commits plus expected-root CAS;
- whole-catalog validation before root visibility;
- safe rebase across unrelated changes only when touched-seat preconditions
still match and every foreign seat is preserved byte-for-byte;
- a small explicitly experimental JSON CLI used by executable evals; and
- proposed VRS plus crash/concurrency evidence.
The first slice should remain policy-free. A manager identity is stored and
fenced, but caller authentication and authorization policy are separate work.
Required eval outcomes
The model-free agent-spec-lifecycle-catalog-* family should prove:
- prepare/import persists exact immutable closure without moving the head;
- source mutation cannot poison an already prepared object;
- concurrent stale publishers have one winner;
- request replay after a lost acknowledgement returns the same commit/root;
- ref-commit CAS rejects stale publication after
A -> B -> A;
- separately valid seat patches cannot create an invalid union;
- a multi-seat patch becomes visible through one root commit;
- a desired revision never becomes visible without its compatible resource
binding;
- crash barriers expose complete old or complete new roots, never dangling
objects or mixed admissions; and
- corrupt objects fail closed when consumed.
Stable state boundary
Writable resources, inbox, context, status, progress, secrets, runtime handles,
and observed-task pins remain outside immutable desired objects. A stable
host-qualified agent-state directory survives revision and catalog-root
changes.
The immutable Seat Admission references the binding generation; it does not
content-address mutable payload bytes. Detaching desired access also does not
prove an already-open runtime handle was revoked.
Follow-up work, not hidden in this slice
- daemon-local control API and sole online linearizer;
- backend-issued generation/launch receipts;
- explicit realize/replace with durable crash recovery;
- authoritative retirement/tombstone after all PTY and exec tasks are absent
(#42);
- authenticated managers and resource authorities;
- host moves/ownership transfer;
- physical garbage collection, replication, signing, and distributed
consensus.
Non-goals
- no SeatIntent, persona, harness-profile, or Nix grammar in st2;
- no automatic process restart on publication;
- no mutable resource payloads in the content-addressed store;
- no
/nix/store runtime dependency, derivations, or substitution protocol;
- no compatibility dual writes or fallback reads as permanent architecture;
- no claim that hashes provide authorization or runtime readiness.
Acceptance direction
The VRS/implementation PR should remain draft while the API is incubating. The
eval PR should contain real product-conformance cells that invoke st2 directly,
not a green shim. Individual cells land in maintained evals only with the st2
commit that makes their target outcomes green.
Posted on behalf of @schickling
| field |
value |
agent_name |
co2-pine |
agent_session_id |
cdd15622-c01a-4731-bbfe-ab8cce0cad54 |
agent_tool |
Codex CLI |
agent_tool_version |
0.145.0 |
agent_runtime |
Codex CLI 0.145.0 |
agent_model |
unknown |
runtime_profile |
/nix/store/ph8rlhdj25mg71v81jsfzy6dq4xpcs9m-coding-agent-runtime-profile/share/coding-agents/profile.json |
skills_manifest |
/nix/store/lsykz8x5481xrpbgk280xh3pypk1c5jy-agent-skills-corpus/share/agent-skills/manifest.json |
worktree |
tmp |
machine |
dev3 |
tooling_profile |
dotfiles@3649b53 |
Problem
The folder catalog currently makes one mutable
agent.kdlcarry severaldifferent identities at once:
That works for hand-edited static catalogs, but it does not give generated or
dynamic Agent Specs a transaction boundary.
Three concrete failures make the distinction load-bearing:
resident watcher, while reconciliation may adopt the old process. Desired
bytes can say g2 while the process still executes g1
(#40,
#44).
can each validate against the same base yet combine into duplicate lowered
task IDs or dangling supervisor references. A multi-seat rename/swap may
have a valid final catalog but no valid first per-seat write.
admission identity. Publishing the spec first can expose missing/old
bindings; publishing bindings first can expose extraneous or over-broad
access.
The existing exact-byte publication proposal
(#41) is the right starting
point, but an atomic
agent.kdlreplacement alone cannot close thecatalog-wide or spec/resource admission gaps.
The original runnable reproduction remains:
https://github.com/schickling-repros/2026-07-st2-dynamic-agent-spec-lifecycle
The corresponding portable eval direction is tracked in
compoundingtech/evals#37.
Proposed incubation model
Use a Git-like immutable object graph with one catalog-wide visibility point:
The identities are deliberately separate:
materialization inputs.
target revision/tombstone. Expected-parent CAS closes
A -> B -> A.resource-binding commit.
visibility boundary.
root/admission/revision/launch actually running; not part of this first store
slice.
Publication is nondestructive:
It does not imply materialization, replacement, running, or readiness.
Why a catalog root is required
Catalog-wide validation plus a daemon mutex is insufficient if readers can see
seat files one at a time. For example:
Every first per-seat write is invalid:
An immutable complete root followed by one head CAS exposes either the complete
old catalog or complete new catalog across crashes and concurrent readers.
Proposed first PR slice
Incubate, rather than prematurely standardize, these primitives:
terminal outcome;
still match and every foreign seat is preserved byte-for-byte;
The first slice should remain policy-free. A manager identity is stored and
fenced, but caller authentication and authorization policy are separate work.
Required eval outcomes
The model-free
agent-spec-lifecycle-catalog-*family should prove:A -> B -> A;binding;
objects or mixed admissions; and
Stable state boundary
Writable resources, inbox, context, status, progress, secrets, runtime handles,
and observed-task pins remain outside immutable desired objects. A stable
host-qualified agent-state directory survives revision and catalog-root
changes.
The immutable Seat Admission references the binding generation; it does not
content-address mutable payload bytes. Detaching desired access also does not
prove an already-open runtime handle was revoked.
Follow-up work, not hidden in this slice
(#42);
consensus.
Non-goals
/nix/storeruntime dependency, derivations, or substitution protocol;Acceptance direction
The VRS/implementation PR should remain draft while the API is incubating. The
eval PR should contain real product-conformance cells that invoke st2 directly,
not a green shim. Individual cells land in maintained evals only with the st2
commit that makes their target outcomes green.
Posted on behalf of @schickling
agent_nameagent_session_idagent_toolagent_tool_versionagent_runtimeagent_modelruntime_profileskills_manifestworktreemachinetooling_profile