docs(agent): condense harness specification

This commit is contained in:
Mario Zechner 2026-08-27 00:22:46 +02:00
parent eb3e9feed1
commit 2d675d069a
4 changed files with 594 additions and 2058 deletions

File diff suppressed because it is too large Load diff

View file

@ -150,6 +150,14 @@ Path/identity/close items that share writer ownership belong in WP07. Determinis
Define cross-backend query-limit semantics in agent conformance, then chunk SQLite ID lookups. This is a storage-contract hardening package, not part of lease fencing.
### Harness contract and conformance closure
- The public `OperationStatus` includes `"running"`, but lane inspection, snapshots, and `reduceLaneSnapshot` currently produce only `"open"` or `"aborting"`. Define and implement its producer or remove the dead variant.
- The pre-rewrite abort contract bound/published `operation_abort` before resolving the cancellation promise and signalling the live gate. Current `Lane.command()` materializes the result — resolving/signalling — before constructing and binding the event batch, although it still binds recipients before releasing the Session mutation line. Decide whether to change the implementation or retain/document the current no-interleaving order; add an explicit ordering test.
- Part 9 of `harness.md` is the required conformance matrix. Existing focused tests cover the graph extensively, including cancellation reconciliation over all 13 leaves, but there is no audited one-to-one proof that every close/reopen leaf case and every race row has both deterministic orders. Audit the matrix and add only the missing cases rather than claiming blanket completion.
Keep this package separate from telemetry, RemoteSession, and M11; it is local contract/test closure.
### Disabled real worker persistence regression
`packages/coding-agent/test/experimental-remote-runtime.test.ts` still skips “completes and persists a prompt through the worker-owned Harness” with the obsolete note “Re-enable with runtime no-tool execution.” No-tool execution now exists. Re-enable or replace it with a deterministic faux-provider real-worker persistence test; do not use a real paid provider.
@ -229,15 +237,16 @@ These are not blockers for the durable Harness:
The order is by data safety first, then dependencies. Independent tracks may proceed in parallel only when they do not edit the same contracts.
1. **WP07 — SQLite ownership fencing.** Atomic lease assertion with commits, exclusive deletion, path/source identity, close draining, and documentation correction.
2. **Remote Session decision (decision only).** Resolve the false normative boundary early. If process-local wins, repair the docs. If raw RemoteSession wins, later create a dedicated protocol/client/server/worker package; do not fold it into telemetry or R12.
3. **Client watch/subscription staleness** and **repository lifecycle contract.** Small independent correctness packages; complete them before expanding server/worker lifecycle semantics. The lifecycle package must also address Memory's fail-fast repository close.
4. **JSONL snapshot compaction.** Implement the already-normative physical reclamation path and metrics.
5. **M11 durable frame volume.** Memory/SQLite measurement can start earlier; set final JSONL budgets only with compaction measured, and preserve all recovery boundaries.
6. **R12 session-wide watch.** Complete the only Harness method stub before building revisioned Transcript/session-wide remote observation.
7. **Telemetry, if retained:** reconcile schemas, then local instrumentation, then RPC propagation, then an optional exporter. RPC propagation follows the Remote Session/product-boundary decision.
8. **SQLite branch/fork/query performance hardening.** Keep separate from lease correctness and require benchmarks.
9. **S3 search.** Resolve its API/filter/cursor decisions, then implement catch-up and the standalone FTS projection.
10. **R11 migrations.** Activate immediately before the first incompatible stabilized durable schema change, not earlier.
2. **Harness contract/conformance closure.** Resolve `OperationStatus.running`, abort signal/event binding order, and the Part 9 coverage matrix.
3. **Remote Session decision (decision only).** Resolve the false normative boundary early. If process-local wins, repair the docs. If raw RemoteSession wins, later create a dedicated protocol/client/server/worker package; do not fold it into telemetry or R12.
4. **Client watch/subscription staleness** and **repository lifecycle contract.** Small independent correctness packages; complete them before expanding server/worker lifecycle semantics. The lifecycle package must also address Memory's fail-fast repository close.
5. **JSONL snapshot compaction.** Implement the already-normative physical reclamation path and metrics.
6. **M11 durable frame volume.** Memory/SQLite measurement can start earlier; set final JSONL budgets only with compaction measured, and preserve all recovery boundaries.
7. **R12 session-wide watch.** Complete the only Harness method stub before building revisioned Transcript/session-wide remote observation.
8. **Telemetry, if retained:** reconcile schemas, then local instrumentation, then RPC propagation, then an optional exporter. RPC propagation follows the Remote Session/product-boundary decision.
9. **SQLite branch/fork/query performance hardening.** Keep separate from lease correctness and require benchmarks.
10. **S3 search.** Resolve its API/filter/cursor decisions, then implement catch-up and the standalone FTS projection.
11. **R11 migrations.** Activate immediately before the first incompatible stabilized durable schema change, not earlier.
## Stop conditions for roadmap accuracy

View file

@ -525,7 +525,7 @@ Ordinary assistant requests use the derived lane identity, structural requests k
**Tracked follow-up; not part of the M8/M10 public-drive gate.** A trivial mini coding-agent Session produced an approximately 300 KB JSONL file because live assistant streaming persists many `pi.pending.assistant_frame` list appends. Logical frame cleanup does not reclaim bytes already appended to the JSONL history, so short conversations can have disproportionate durable storage and replay cost.
M11 first adds a deterministic repository fixture and measurement script; the external approximately 300 KB mini Session is motivation, not a checked-in benchmark. It must measure frame count and encoded-byte growth across Memory, JSONL, and SQLite, then bound amplification without weakening the existing crash contract: an admitted assistant effect remains reconstructible, progress observation remains useful, and settlement still removes operation-owned pending-frame state. Generic JSONL current-state snapshot compaction is a separate missing §1.7 backend mechanism: it reclaims all dead write history after settlement, while M11 bounds frame progress during an open effect. Their metrics overlap, so Memory/SQLite M11 work may proceed independently but the final JSONL post-settlement budget must include snapshot compaction. Investigate coalesced durable checkpoints, bounded frame snapshots plus a short delta tail, and JSONL snapshot-compaction interaction. Do not solve this by dropping unknown-outcome recovery, persisting only the final response, or adding a second generic retention framework.
M11 must measure frame count and encoded-byte growth across Memory, JSONL, and SQLite, then bound amplification without weakening the existing crash contract: an admitted assistant effect remains reconstructible, progress observation remains useful, and settlement still removes operation-owned pending-frame state. Investigate coalesced durable checkpoints, bounded frame snapshots plus a short delta tail, and JSONL snapshot-compaction interaction. Do not solve this by dropping unknown-outcome recovery, persisting only the final response, or adding a generic retention framework.
Exit checks:

View file

@ -31,23 +31,23 @@ async function startServer(
const sessions = new MemorySessionRepo();
const host: ServerHost = {
sessions: {
list: () => sessions.list(),
async create({ id }) {
const session = await sessions.create({ id });
list: (context) => sessions.list(undefined, context),
async create({ id }, context) {
const session = await sessions.create({ id }, context);
try {
return session.metadata;
} finally {
await session.close();
await session.close(context);
}
},
},
async openSession(metadata) {
const session = await sessions.open(metadata);
async openSession(metadata, context) {
const session = await sessions.open(metadata, context);
try {
return await openRoutedSession(session);
} catch (error) {
try {
await session.close();
await session.close(context);
} catch (cleanupError) {
throw new AggregateError(
[error, cleanupError],