chore(vendor): import pi 0.85.1
Imported as a linear vendor commit so forge rebases do not replay the upstream root tree. git-subtree-dir: third_party/pi git-subtree-split: d981de1229ef899957bbe968bc8dcda02a21f477
This commit is contained in:
1 parent
5ebc7018c3
commit
4def357d09
1669 files changed
+397627
No files matched your search
+517
@@ -0,0 +1,517 @@
|
||||
# Work package 09 — LaneSnapshot settled-but-unplaced tools
|
||||
|
||||
## Status and baseline
|
||||
|
||||
- Repository: `earendil-works/pi`
|
||||
- Branch at handoff creation: `dev`
|
||||
- Baseline commit: `d14d6b22327d545d6a253f932165b63e48d7f9c8`
|
||||
- The user reported the worktree clean immediately before this handoff.
|
||||
- This document began as an implementation handoff after conversation compaction and now records the implemented design. It is not itself the normative harness specification; `packages/agent/docs/harness.md` remains normative.
|
||||
|
||||
## Goal
|
||||
|
||||
Keep every started or settled-but-unplaced tool call visible in `LaneSnapshot.operation.runningTools` until its immutable `toolResult` entry is placed in the transcript.
|
||||
|
||||
The intended projection is:
|
||||
|
||||
```text
|
||||
planned → not yet represented in runningTools
|
||||
effect_pending → runningTools(status: "running")
|
||||
outcome_ready → runningTools(status: "settled")
|
||||
completed → transcript toolResult entry
|
||||
```
|
||||
|
||||
For each call after it becomes presentation-active, `runningTools` and placed transcript entries must not have a gap or overlap. Placement is a source-prefix flush, not an all-tools barrier. Remove a call from `runningTools` on its own `entry_added`, never on `turn_end`.
|
||||
|
||||
## Original bug
|
||||
|
||||
A call disappeared between real-effect completion and source-ordered tree placement:
|
||||
|
||||
1. `packages/agent/src/harness/runtime/reducer.ts`: `tool_end` spliced the call out of `runningTools`.
|
||||
2. `packages/agent/src/harness/runtime/lane.ts`: `captureLaneSnapshot()`, `case "tools"`, projected only `effect_pending` calls and skipped `outcome_ready` calls.
|
||||
3. The finalized result was already durable at `pendingEntry(resultEntryId)`, but a fresh/reconnected snapshot could not display it.
|
||||
4. It reappeared only after `entry_added` placed the immutable `toolResult` entry.
|
||||
|
||||
For a parallel batch `[A, B, C]`, if B settles while A remains pending, B may stay `outcome_ready` until A is ready. If A is already placed, B can place without waiting for C. Therefore clearing everything at `turn_end` is wrong: early-placed results would temporarily exist in both `transcript` and `runningTools`.
|
||||
|
||||
## Confirmed current architecture
|
||||
|
||||
Mini does **not** replicate structural object deltas.
|
||||
|
||||
- `packages/coding-agent/src/experimental/mini/worker/lane-service.ts` sends one initial full snapshot and then forwards individual `HarnessEvent` objects.
|
||||
- `packages/coding-agent/src/experimental/mini/tui/session.ts` folds those events through `reduceLaneSnapshot()`.
|
||||
- Reconnect/rebase fetches another complete snapshot.
|
||||
- `tool_update` currently carries a complete replacement progress result, not a nested diff.
|
||||
|
||||
Implemented durable tool flow in `packages/agent/src/harness/runtime/drive/tools.ts`:
|
||||
|
||||
```text
|
||||
prepare
|
||||
→ before_tool
|
||||
→ intent commit (effect_pending + effective args), then tool_start
|
||||
→ execute/update/checkpoint
|
||||
→ after_tool
|
||||
→ finalize
|
||||
→ publishToolOutcome staging commit (pendingEntry + outcome_ready), then tool_end
|
||||
→ materializeReady prefix placement
|
||||
→ entry_added
|
||||
```
|
||||
|
||||
All real, immediate synthetic, cancellation, and recovery outcomes converge through `publishToolOutcome()`.
|
||||
|
||||
`Lane.settleOperation()` supports commit-bound events. It commits, publishes process-local state, constructs the event batch, and the public operation awaits delivery. In parallel execution, `materializeReady()` is scheduled only after the outcome-completion promise resolves. Consequently, `tool_end` is delivered after staging and before placement.
|
||||
|
||||
## Agreed event contract change
|
||||
|
||||
Do **not** add `tool_result_ready` or `tool_outcome_ready`.
|
||||
|
||||
Instead, redefine harness `tool_start`/`tool_end` as tool-call processing/result lifecycle events rather than exclusively real external-effect lifecycle events.
|
||||
|
||||
### Fresh executed call
|
||||
|
||||
```text
|
||||
intent commit
|
||||
→ tool_start
|
||||
→ tool_update*
|
||||
→ execute/finalize
|
||||
→ TX[pendingEntry + outcome_ready + cleanup]
|
||||
→ tool_end
|
||||
→ source-ordered placement
|
||||
→ entry_added
|
||||
```
|
||||
|
||||
### Fresh synthetic call
|
||||
|
||||
```text
|
||||
TX[pendingEntry + outcome_ready]
|
||||
→ tool_start
|
||||
→ tool_end
|
||||
→ source-ordered placement
|
||||
→ entry_added
|
||||
```
|
||||
|
||||
The staging transaction's post-commit event batch contains `tool_start` followed by `tool_end`, so a watcher cannot observe either lifecycle event without the authoritative staged state.
|
||||
|
||||
Fresh synthetic calls include:
|
||||
|
||||
- unknown tool;
|
||||
- argument preparation or validation failure;
|
||||
- `before_tool` denial or invalid replacement arguments;
|
||||
- genuine assistant `length`/truncated call handling;
|
||||
- cancellation while still `planned` or after intent but before effect admission.
|
||||
|
||||
### Recovery
|
||||
|
||||
Historical lifecycle events are not replayed.
|
||||
|
||||
- A restored `effect_pending` call is already represented by the initial snapshot.
|
||||
- Safe replay emits recovery-tagged `tool_start` from the checkpoint-clear commit and `tool_end` from the later outcome-staging commit.
|
||||
- Unsafe interruption synthesis may emit a recovery-tagged `tool_end` without a newly emitted `tool_start`; the initial snapshot supplied the running row.
|
||||
- A call already restored as `outcome_ready` appears as settled in the initial snapshot and needs no replayed end event before placement.
|
||||
|
||||
### Meaning of `tool_end`
|
||||
|
||||
After this change, `tool_end` means:
|
||||
|
||||
> The complete final tool result is durably staged and the call is `outcome_ready`.
|
||||
|
||||
It becomes the authoritative reducer transition from running to settled. It must be emitted **after** the staging commit, not before it.
|
||||
|
||||
The old distinction between actually executed and synthetic results was encoded by omitting lifecycle events. There is no in-repo runtime consumer requiring that distinction. If preserving it is desired, discuss adding an explicit field such as `execution: "executed" | "synthetic"`; this field was discussed but **not agreed**, so do not add it silently.
|
||||
|
||||
## LaneSnapshot type
|
||||
|
||||
Change `LaneSnapshot.operation.runningTools` in `packages/agent/src/harness/agent-harness.ts` to use one `result` field for both progress and final output. Do not retain a separate `partialResult` field in the snapshot.
|
||||
|
||||
Prefer a discriminated union so invalid combinations are unrepresentable:
|
||||
|
||||
```ts
|
||||
type SnapshotTool =
|
||||
| {
|
||||
status: "running";
|
||||
toolCallId: string;
|
||||
toolName: string;
|
||||
args: unknown;
|
||||
result?: AgentToolResult<unknown>; // latest complete progress snapshot
|
||||
}
|
||||
| {
|
||||
status: "settled";
|
||||
toolCallId: string;
|
||||
toolName: string;
|
||||
args: unknown;
|
||||
result: AgentToolResult<unknown>; // complete finalized result
|
||||
isError: boolean;
|
||||
};
|
||||
```
|
||||
|
||||
The user explicitly agreed to the discriminated union.
|
||||
|
||||
`tool_update.partialResult` may remain named `partialResult` in the event API; the reducer assigns it to the snapshot row's unified `result` field.
|
||||
|
||||
The current mini transport sends semantic events, not structural deltas, so `tool_end` still carries the complete final result even if it equals the latest update. Unifying the snapshot field is still the correct state model.
|
||||
|
||||
## Exact reducer behavior
|
||||
|
||||
File: `packages/agent/src/harness/runtime/reducer.ts`
|
||||
|
||||
### `tool_start`
|
||||
|
||||
- Resolve the operation with `matchingOperation(snapshot, event.runId)`.
|
||||
- Upsert by `toolCallId`; do not blindly push.
|
||||
- Set `status: "running"`, `toolName`, `args`.
|
||||
- Clear stale settled-only fields if replacing an existing row.
|
||||
- Preserve no stale final result. A newly started/replayed call may receive later `tool_update` values.
|
||||
|
||||
Upsert is required because a watch may capture durable `effect_pending` state before the buffered `tool_start` event is delivered.
|
||||
|
||||
### `tool_update`
|
||||
|
||||
- Use `matchingOperation(snapshot, event.runId)`, not `snapshot.operation` directly.
|
||||
- Find the matching row.
|
||||
- For a running row, replace `result` with `event.partialResult`.
|
||||
- Ignore wrong-operation or missing rows.
|
||||
|
||||
### `tool_end`
|
||||
|
||||
- Resolve with `matchingOperation(snapshot, event.runId)`.
|
||||
- Find the existing row by batch-local `toolCallId`; only one tool batch is presentation-active at a time.
|
||||
- Replace it with `status: "settled"`, preserving its arguments and using `event.result` and `event.isError`.
|
||||
- This naturally removes the provisional interpretation of the old `result`; there is no separate `partialResult` to delete.
|
||||
- The finalized result remains displayed until placement.
|
||||
|
||||
`tool_end` does not carry arguments and cannot create a row. Fresh synthetic `tool_start` and `tool_end` are emitted together after the staging commit, eliminating the old capture/event gap. Unsafe recovery relies on the initial snapshot's running row.
|
||||
|
||||
### `entry_added`
|
||||
|
||||
If `event.entry` is a message whose role is `toolResult`, remove the matching batch-local `toolCallId` from `snapshot.operation?.runningTools`, then apply the transcript update. Harness events are serialized, trusted, emitted exactly once, and not historically replayed, so neither duplicate-entry handling nor cross-batch identity is needed.
|
||||
|
||||
Do not clear tool rows on `turn_end`.
|
||||
|
||||
## Exact authoritative capture behavior
|
||||
|
||||
File: `packages/agent/src/harness/runtime/lane.ts`, `captureLaneSnapshot()`, `case "tools"`.
|
||||
|
||||
The assistant entry is already loaded once. For each batch call:
|
||||
|
||||
### `planned`
|
||||
|
||||
Skip. It has not become presentation-active yet.
|
||||
|
||||
### `completed`
|
||||
|
||||
Skip. Its `toolResult` entry must already be in the captured transcript.
|
||||
|
||||
### `effect_pending`
|
||||
|
||||
- Validate that `assistant.message.content[sourceIndex]` is the matching `toolCall` block.
|
||||
- Read `operationToolArgs(operationId, turnId, sourceIndex)`; it is required for effect-pending calls.
|
||||
- Read optional `pendingToolOutput(operationId, resultEntryId)`.
|
||||
- Project:
|
||||
|
||||
```ts
|
||||
{
|
||||
status: "running",
|
||||
toolCallId: block.id,
|
||||
toolName: block.name,
|
||||
args: persistedArgs,
|
||||
...(checkpoint === undefined ? {} : { result: checkpoint })
|
||||
}
|
||||
```
|
||||
|
||||
### `outcome_ready`
|
||||
|
||||
- Validate the source tool-call block.
|
||||
- Read `pendingEntry(call.resultEntryId)`.
|
||||
- Require a message payload with role `toolResult`.
|
||||
- Validate staged `toolCallId` and `toolName` against the source block.
|
||||
- Read `operationToolArgs(...)` when present.
|
||||
- Use `persistedArgs ?? block.arguments`. Immediate synthetic calls may never have written `operationToolArgs`, and this absence is legal only for the outcome-ready projection.
|
||||
- Reconstruct the canonical `AgentToolResult` from the staged `ToolResultMessage` and the durable call termination flag as needed.
|
||||
- Project `status: "settled"`, `result`, and `isError`.
|
||||
|
||||
The event and capture representations must normalize the final result identically so folding through `tool_end` equals a later authoritative snapshot. Pay attention to optional `details`, `usage`, `addedToolNames`, and `terminate`; do not rely on incidental object-property presence differences.
|
||||
|
||||
A missing or mismatched staged result for `outcome_ready` is presentation corruption and must fault snapshot capture.
|
||||
|
||||
## Runtime event production changes
|
||||
|
||||
Primary file: `packages/agent/src/harness/runtime/drive/tools.ts`
|
||||
|
||||
Related helpers: `packages/agent/src/harness/execution/tools.ts` and `packages/agent/src/harness/runtime/drive/tool-placement.ts`.
|
||||
|
||||
### Internal outcome shape
|
||||
|
||||
Current:
|
||||
|
||||
```ts
|
||||
type ToolOutcome = { message: ToolResultMessage<unknown>; terminate: boolean };
|
||||
```
|
||||
|
||||
Extend/refactor it so post-commit event production has the complete canonical final result and `isError`, without lossy reconstruction. It must retain enough data for:
|
||||
|
||||
- staged `ToolResultMessage`;
|
||||
- `tool_end.result`;
|
||||
- `tool_end.isError`;
|
||||
- durable/effective `terminate` after cancellation normalization.
|
||||
|
||||
Synthetic helpers currently return `ToolResultMessage` directly. Refactor carefully so synthetic outcomes also carry the canonical result data. Do not invent `details` in the transcript: existing unknown/invalid synthetic results deliberately omit message details.
|
||||
|
||||
### Commit-bound `tool_start`
|
||||
|
||||
For fresh execution, `publishToolIntent()` attaches `tool_start` to the commit that persists effective arguments and changes the call to `effect_pending`. The public operation awaits delivery before admitting `executeToolCall()`, preserving `tool_start → tool_update*` without requiring each update callback to await delivery.
|
||||
|
||||
For a fresh synthetic call that never writes effect intent, `publishToolOutcome()` attaches `tool_start` before `tool_end` in the outcome-staging commit's event batch. It reports the source block arguments.
|
||||
|
||||
For safe recovery, the checkpoint-clear commit emits recovery-tagged `tool_start` using persisted effective arguments. Do not emit a fresh start for an already-restored unsafe `effect_pending` call; its initial snapshot is the baseline.
|
||||
|
||||
### Post-commit `tool_end`
|
||||
|
||||
Remove the current pre-staging `tool_end` emission from `performToolInvocation()`.
|
||||
|
||||
`publishToolOutcome()` attaches `tool_end` to the same staging command's `events` callback. The event carries:
|
||||
|
||||
- `runId`, `turnId`, `toolCallId`, `toolName`;
|
||||
- canonical final `result`;
|
||||
- `isError`;
|
||||
- cancellation-normalized durable `terminate`;
|
||||
- `recovery: true` where applicable.
|
||||
|
||||
Arguments belong to `tool_start` and are not repeated on `tool_end`. Event data describes the state actually committed, especially cancellation forcing `terminate: false`.
|
||||
|
||||
Because `Lane.command()` awaits retained event delivery and `runParallel()` schedules materialization from the outcome-completion promise, the required order is:
|
||||
|
||||
```text
|
||||
staging commit
|
||||
→ tool_end delivery
|
||||
→ source-ready message lifecycle
|
||||
→ placement commit
|
||||
→ entry_added
|
||||
```
|
||||
|
||||
### Call sites to audit
|
||||
|
||||
Every `publishToolOutcome()` call must supply the source tool call and recovery context correctly:
|
||||
|
||||
- immediate outcome in `startToolInvocation()`;
|
||||
- cancellation after intent but before execution;
|
||||
- normal `performToolInvocation()` completion;
|
||||
- safe replay completion;
|
||||
- unsafe recovery interruption;
|
||||
- sequential cancellation of `planned`;
|
||||
- sequential cancellation of `effect_pending`.
|
||||
|
||||
Also audit the synchronous `AbortRequested` path inside `performToolInvocation()`: a call with durable intent must still have coherent start/end presentation even if effect admission fails immediately.
|
||||
|
||||
## Mini and other presentation consumers
|
||||
|
||||
### Mini
|
||||
|
||||
File: `packages/coding-agent/src/experimental/mini/tui/view.ts`, `MiniTui.apply()`.
|
||||
|
||||
For each `runningTools` row:
|
||||
|
||||
```text
|
||||
status running:
|
||||
markExecutionStarted()
|
||||
if result exists: updateResult({...result, isError:false}, true)
|
||||
|
||||
status settled:
|
||||
do not call markExecutionStarted()
|
||||
updateResult({...result, isError}, false)
|
||||
```
|
||||
|
||||
The final result remains visible while awaiting placement. After `entry_added`, transcript synchronization supplies the immutable `ToolResultMessage` and the row is no longer in `runningTools`.
|
||||
|
||||
### Other shared consumer
|
||||
|
||||
Apply equivalent handling in:
|
||||
|
||||
- `packages/coding-agent/src/experimental/client-tui-chat.ts`
|
||||
|
||||
Read `packages/coding-agent/src/modes/interactive/components/tool-execution.ts` before editing to confirm `updateResult(result, isPartial)` semantics.
|
||||
|
||||
## Tests
|
||||
|
||||
### Reducer tests
|
||||
|
||||
File: `packages/agent/test/harness/runtime/reducer.test.ts`
|
||||
|
||||
Add a parallel batch event-fold test with calls 0, 1, 2:
|
||||
|
||||
1. Establish all three as running.
|
||||
2. Call 2 settles before call 0.
|
||||
3. Call 0 settles and is placed while call 1 still runs.
|
||||
4. Call 1 settles.
|
||||
5. Placement flushes calls 1 and 2 in source order.
|
||||
6. After every settlement and placement event, assert each presentation-active call appears in exactly one of:
|
||||
- `operation.runningTools`; or
|
||||
- transcript `toolResult` entries.
|
||||
7. Assert call 2 remains present with `status:"settled"` and its final result while blocked by earlier calls.
|
||||
8. Assert each `entry_added` removes only its matching active row.
|
||||
|
||||
Add focused coverage for:
|
||||
|
||||
- `tool_update` from a stale/wrong `runId` does not mutate the current operation;
|
||||
- `tool_start` upserts rather than duplicates a row captured from durable intent;
|
||||
- `tool_end` settles the existing batch-local row.
|
||||
|
||||
### Capture/watch tests
|
||||
|
||||
File: `packages/agent/test/harness/runtime/watch.test.ts`
|
||||
|
||||
Construct a durable tools state containing:
|
||||
|
||||
- `planned` (omitted);
|
||||
- `effect_pending` with checkpoint (`status:"running"`, checkpoint exposed as `result`);
|
||||
- `effect_pending` without checkpoint;
|
||||
- real `outcome_ready` with persisted effective args;
|
||||
- synthetic `outcome_ready` without `operationToolArgs`, falling back to source block arguments;
|
||||
- completed call represented only by a transcript entry where practical.
|
||||
|
||||
Assert staged settled content, `isError`, arguments, and absence of duplicates. Add missing/mismatched `pendingEntry` corruption assertions.
|
||||
|
||||
### Runtime tool tests
|
||||
|
||||
File: `packages/agent/test/harness/runtime/drive-tools.test.ts`
|
||||
|
||||
Update/add ordering assertions proving:
|
||||
|
||||
- real: `intent commit < tool_start < tool_update* < staging commit < tool_end < entry_added`;
|
||||
- immediate synthetic: `staging commit < tool_start < tool_end < entry_added`, no tool effect and no `after_tool`;
|
||||
- planned cancellation gets coherent start/end;
|
||||
- unsafe recovery uses initial snapshot plus recovery-tagged end without replaying effects;
|
||||
- B can emit post-commit end and remain settled while A blocks placement;
|
||||
- source-order placement remains unchanged;
|
||||
- a crash after staging cannot replay the call.
|
||||
|
||||
The baseline normative tests/documentation required `tool_end` before staging; the implementation reverses those expectations deliberately.
|
||||
|
||||
### Type/event catalog tests
|
||||
|
||||
Audit:
|
||||
|
||||
- `packages/agent/test/harness/types.test.ts`
|
||||
- `packages/agent/src/harness/telemetry.ts`
|
||||
|
||||
No new event name is added. `tool_end` omits arguments and its semantics change.
|
||||
|
||||
### Mini regression
|
||||
|
||||
After unit tests, run the real mini abort smoke test used previously:
|
||||
|
||||
- execute exactly `sleep 20`;
|
||||
- send Escape after about two seconds;
|
||||
- assert `Command aborted` and elapsed time appear;
|
||||
- assert raw ANSI contains `toolErrorBg` (`48;2;60;40;40`);
|
||||
- verify the durable session contains an `isError:true` tool result and operation status `aborted`.
|
||||
|
||||
Also exercise a parallel batch where a later tool finishes first and verify its final result remains visible until in-order placement.
|
||||
|
||||
## Documentation changes
|
||||
|
||||
Read both documents completely before editing:
|
||||
|
||||
- `packages/agent/docs/harness.md` (normative)
|
||||
- `packages/agent/docs/tool-durability.md`
|
||||
|
||||
The implementation updates baseline statements that required:
|
||||
|
||||
- `tool_end` before staging;
|
||||
- `tool_start`/`tool_end` only for real effects;
|
||||
- synthetic outcomes emitting no lifecycle;
|
||||
- `outcome_ready` being omitted from `runningTools`;
|
||||
- snapshot field `partialResult`.
|
||||
|
||||
Important known locations from the baseline:
|
||||
|
||||
- `harness.md` §3.8 around lines 784–796;
|
||||
- `harness.md` §5.4 `LaneSnapshot` around lines 1101–1134;
|
||||
- `harness.md` §5.5 events around lines 1140–1158;
|
||||
- `harness.md` tool phases around lines 1214–1224;
|
||||
- `harness.md` conformance requirements around lines 1386–1400;
|
||||
- `tool-durability.md` finalization around lines 255–280;
|
||||
- `tool-durability.md` snapshots/events around lines 568–584;
|
||||
- `tool-durability.md` test requirements around lines 671–679.
|
||||
|
||||
The revised docs must state:
|
||||
|
||||
- `tool_end` is post-staging durability evidence for a final result;
|
||||
- fresh synthetic outcomes receive start/end lifecycle;
|
||||
- recovery events are not historically replayed;
|
||||
- `outcome_ready` remains projected as settled until placement;
|
||||
- `entry_added` moves settled presentation into transcript;
|
||||
- the unified snapshot `result` is provisional when running and final when settled.
|
||||
|
||||
Do not modify the separate `response.ts`/`tool-placement.ts` recovery `turn_end` discrepancy unless separately requested.
|
||||
|
||||
## Files to reread completely after compaction
|
||||
|
||||
Core/specification:
|
||||
|
||||
1. `packages/agent/docs/harness.md`
|
||||
2. `packages/agent/docs/tool-durability.md`
|
||||
3. `packages/agent/src/harness/agent-harness.ts`
|
||||
4. `packages/agent/src/harness/runtime/reducer.ts`
|
||||
5. `packages/agent/src/harness/runtime/lane.ts`
|
||||
6. `packages/agent/src/harness/runtime/drive/tools.ts`
|
||||
7. `packages/agent/src/harness/runtime/drive/tool-placement.ts`
|
||||
8. `packages/agent/src/harness/execution/tools.ts`
|
||||
9. `packages/agent/src/harness/runtime/types.ts`
|
||||
10. `packages/agent/src/harness/session/types.ts`
|
||||
11. `packages/agent/src/harness/events.ts`
|
||||
12. `packages/agent/src/harness/telemetry.ts`
|
||||
|
||||
Tests:
|
||||
|
||||
13. `packages/agent/test/harness/runtime/reducer.test.ts`
|
||||
14. `packages/agent/test/harness/runtime/watch.test.ts`
|
||||
15. `packages/agent/test/harness/runtime/drive-tools.test.ts`
|
||||
16. `packages/agent/test/harness/types.test.ts`
|
||||
17. Relevant test helpers imported by those files.
|
||||
|
||||
Mini/presentation:
|
||||
|
||||
18. `packages/coding-agent/src/experimental/mini/tui/session.ts`
|
||||
19. `packages/coding-agent/src/experimental/mini/worker/lane-service.ts`
|
||||
20. `packages/coding-agent/src/experimental/mini/shared/protocol.ts`
|
||||
21. `packages/coding-agent/src/experimental/mini/tui/view.ts`
|
||||
22. `packages/coding-agent/src/experimental/client-tui-chat.ts`
|
||||
23. `packages/coding-agent/src/modes/interactive/components/tool-execution.ts`
|
||||
|
||||
Before editing, run `git status --short` and inspect current diffs because other Pi sessions may share the worktree.
|
||||
|
||||
## Validation commands
|
||||
|
||||
From repository root, after changes:
|
||||
|
||||
```bash
|
||||
cd packages/agent
|
||||
node "$(git rev-parse --show-toplevel)/node_modules/vitest/dist/cli.js" --run test/harness/runtime/reducer.test.ts
|
||||
node "$(git rev-parse --show-toplevel)/node_modules/vitest/dist/cli.js" --run test/harness/runtime/watch.test.ts
|
||||
node "$(git rev-parse --show-toplevel)/node_modules/vitest/dist/cli.js" --run test/harness/runtime/drive-tools.test.ts
|
||||
node "$(git rev-parse --show-toplevel)/node_modules/vitest/dist/cli.js" --run test/harness/types.test.ts
|
||||
cd "$(git rev-parse --show-toplevel)"
|
||||
npm run check
|
||||
```
|
||||
|
||||
Do not run `npm test`, the full Vitest suite, or `npm run build` unless requested.
|
||||
|
||||
If a delegated review is used, repository policy requires:
|
||||
|
||||
```text
|
||||
--provider anthropic --model claude-fable-5
|
||||
```
|
||||
|
||||
Keep extensions enabled.
|
||||
|
||||
## Non-goals
|
||||
|
||||
- No generic structural-delta transport for mini.
|
||||
- No optimization to avoid the final result crossing the wire once in `tool_end` and again in `entry_added`.
|
||||
- No change to source-prefix placement semantics.
|
||||
- No clearing on `turn_end`.
|
||||
- No change to tool effect replay/durability rules.
|
||||
- No change to `after_tool`: it still runs only for actual fresh/safely replayed effects under its existing cancellation contract.
|
||||
- No work on the separate recovery `turn_end` discrepancy between `response.ts` and `tool-placement.ts`.
|
||||
- No backward-compatibility layer unless the user explicitly asks for one.
|
||||
- Do not commit unless the user asks.
|
||||
Reference in new issue
Block a user