@nklisch/pi-enhanced 0.4.3 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +1 -1
  3. package/node_modules/@nklisch/pi-astral-pocket/README.md +127 -93
  4. package/node_modules/@nklisch/pi-astral-pocket/package.json +2 -2
  5. package/node_modules/@nklisch/pi-astral-pocket/src/distiller.ts +196 -183
  6. package/node_modules/@nklisch/pi-astral-pocket/src/guidance.ts +26 -62
  7. package/node_modules/@nklisch/pi-astral-pocket/src/index.ts +8 -5
  8. package/node_modules/@nklisch/pi-astral-pocket/src/sessions.ts +10 -3
  9. package/node_modules/@nklisch/pi-astral-pocket/src/store.ts +439 -321
  10. package/node_modules/@nklisch/pi-astral-pocket/src/tools.ts +172 -66
  11. package/node_modules/@nklisch/pi-clearance/docs/CONFIGURATION.md +3 -3
  12. package/node_modules/@nklisch/pi-clearance/docs/DEVELOPER_GUIDE.md +11 -12
  13. package/node_modules/@nklisch/pi-clearance/docs/PACK_AUTHORING.md +5 -5
  14. package/node_modules/@nklisch/pi-clearance/docs/PRINCIPLES.md +1 -2
  15. package/node_modules/@nklisch/pi-clearance/docs/REFERENCE_PATTERNS.md +13 -19
  16. package/node_modules/@nklisch/pi-clearance/docs/SPEC.md +4 -4
  17. package/node_modules/@nklisch/pi-clearance/docs/USER_GUIDE.md +2 -3
  18. package/node_modules/@nklisch/pi-clearance/docs/VISION.md +1 -1
  19. package/node_modules/@nklisch/pi-clearance/native/clearance-core.win32-x64-msvc.node +0 -0
  20. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/README.md +2 -2
  21. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/VISION.md +2 -3
  22. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/architecture.md +105 -886
  23. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/decisions/0002-extensions-on-a-minimal-core.md +44 -78
  24. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/decisions/0003-publish-bundled-type-declarations.md +28 -57
  25. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/decisions/0004-reconsider-ui-direction.md +49 -261
  26. package/node_modules/@nklisch/pi-plugins/package.json +2 -2
  27. package/package.json +2 -2
  28. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/client-server-opportunities.md +0 -127
  29. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/history/phase-1-api-boundary.md +0 -8
  30. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/history/phase-10-structural-decomposition.md +0 -141
  31. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/history/phase-11-closure-to-class.md +0 -100
  32. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/history/phase-12-complexity-test-fixtures.md +0 -55
  33. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/history/phase-13-remaining-smells.md +0 -88
  34. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/history/phase-14-strip-policy.md +0 -49
  35. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/history/phase-15-domain-model-evolution.md +0 -73
  36. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/history/phase-16-invert-dependencies.md +0 -144
  37. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/history/phase-17-core-consolidation.md +0 -214
  38. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/history/phase-18-reconsider-ui.md +0 -166
  39. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/history/phase-19-implement-ui-decisions.md +0 -282
  40. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/history/phase-2-remove-scheduling.md +0 -9
  41. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/history/phase-3-remove-rpc-groupjoin.md +0 -11
  42. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/history/phase-4-implement-service.md +0 -8
  43. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/history/phase-5-decompose-index.md +0 -42
  44. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/history/phase-7-encapsulation.md +0 -173
  45. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/history/phase-8-testability.md +0 -103
  46. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/history/phase-9-observation-ctx.md +0 -122
  47. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/decisions/0001-deferred-patches.md +0 -80
@@ -1,166 +0,0 @@
1
- # Phase 18: Reconsider UI from first principles
2
-
3
- ## Summary
4
-
5
- Phase 18 disentangled the activity tier from the core and recorded a first-principles decision about the UI's direction and distribution.
6
- Steps 1–5 (the spine) removed the activity-tier entanglement: run state was consolidated onto `SubagentState`, `AgentActivityTracker` and `ui-observer` were deleted, and the widget was made a pure reactive consumer of lifecycle events.
7
- Steps 6–7 delivered independent hygiene: the public event contract was reconciled (breaking) and residual test clone families were consolidated.
8
- Step 8 captured the outcome as [ADR-0004] — a per-component UI decision recorded to gateway Phase 19.
9
-
10
- All eight steps are closed: [#420], [#421], [#422], [#423], [#424], [#425], [#426], [#427].
11
-
12
- ## Health metrics
13
-
14
- Baseline at the start of Phase 18 (end of Phase 17):
15
-
16
- | Metric | Phase 18 start | Phase 18 end |
17
- | ---------------------------------------- | ------------------------------------------------------------------ | ------------------------------------- |
18
- | Health score | 78/100 (B) | 78/100 (B) |
19
- | Source LOC | 7,751 (62 files) | 7,650 (61 files) |
20
- | Dead code | 0 files, 0 exports | 0 files, 0 exports |
21
- | Maintainability index | 90.9 (good) | 90.9 (good) |
22
- | Avg cyclomatic complexity | 1.4 | 1.4 |
23
- | P90 cyclomatic complexity | 2 | 2 |
24
- | Fallow refactoring targets | 0 | 0 |
25
- | Production duplication | 11 lines (1 internal clone group in `agent-config-editor.ts`) | 11 lines (1 internal clone group) |
26
- | Test duplication | 28 clone groups, 503 lines | 14 clone groups (below <15 target) |
27
- | Tests | 1,031 passing | 1,047 passing |
28
- | Activity-tier modules slated for removal | `ui-observer.ts` (61) + `agent-activity-tracker.ts` (84) = 145 LOC | Deleted in Step 3 |
29
-
30
- ## Findings
31
-
32
- Six findings told one story — the activity tier had metastasized out of the UI and into the core.
33
-
34
- 1. **UI state lives on the core runtime.**
35
- `SubagentRuntime.agentActivity: Map<string, AgentActivityTracker>` puts a UI streaming-state map on the core composition root.
36
- `SubagentRuntime` owns session-scoped lifecycle state; `AgentActivityTracker` (active tools, response text, turn count) is pure rendering state the core never reads.
37
- Category C (coupling).
38
- 2. **Core spawn tools wire UI streaming.**
39
- `foreground-runner.ts` and `background-spawner.ts` construct `AgentActivityTracker`, call `subscribeUIObserver` (a second session subscription parallel to the core's own `record-observer`), call `setSession`, and populate or delete the activity map and drive the widget (`ensureTimer`, `update`, `markFinished`).
40
- Their own doc comments list "AgentActivityTracker creation, UI observer subscription" as responsibilities.
41
- Category C (mixed responsibility, parameter relay).
42
- 3. **The LLM-facing tool depends on the widget.**
43
- `AgentTool` takes a 4-method `widget` dependency plus `runtime.agentActivity` and calls `this.widget.setUICtx(ctx.ui)`.
44
- Every `AgentTool` unit test must stub the widget and the activity map (`createToolDeps`), although the tool's real concern is dispatch — testability friction marking a domain seam.
45
- Category C/D.
46
- 4. **Two parallel observers split the run-metric domain.**
47
- Each child session gets two subscriptions: `record-observer` accumulates `SubagentState` (tool uses, usage, compactions) and `ui-observer` accumulates `AgentActivityTracker` (active tools, response text, turn count).
48
- `turnCount` is a genuine run metric that lives only in the UI tracker, so `notification.ts` and the foreground result text reach into the tracker to recover it.
49
- Category C (anemic split, duplication).
50
- 5. **A core observation concern reaches into UI state.**
51
- `NotificationManager` holds the activity map and reads `turnCount`/`maxTurns` from it to build notification details, and deletes entries from it.
52
- Category C (Law of Demeter).
53
- 6. **The public event contract is both vacant and incomplete.**
54
- `SUBAGENT_EVENTS.ACTIVITY = "subagents:activity"` is declared in the service surface and the lifecycle-events table but is never emitted anywhere — a vacant hook the "no vacant hooks" rule forbids.
55
- Meanwhile three emitted channels (`subagents:failed`, `subagents:compacted`, `subagents:created`) are absent from the constant map.
56
- Category A/E.
57
-
58
- ## Steps
59
-
60
- The spine (Steps 1–5) removes the activity-tier entanglement, leaving the core a pure orchestrator whose run state lives in one place and whose UI is a reactive consumer of broadcast events plus discrete queries.
61
- Steps 6–7 are independent hygiene.
62
- Step 8 is the user-driven UI reconsideration the disentangled core finally makes possible — a decision about the UI's distribution once it is substitutable, not optional.
63
-
64
- The deeper target in the [first-principles refinement] — metrics as a pure observer projection rather than mutable fields — is deliberately **not** forced here.
65
- Folding the live activity onto the record (the single owner of run state, consistent with Phase 17's `SubagentState`) removes the duplication without inventing the asynchronous-observation seam the `improvement-discovery` skill warns is essential, not structural.
66
-
67
- 1. **✅ Fold run metrics and live activity onto the core record (pure addition) — complete (v16.5.0).**
68
- ([#420]) Target: `lifecycle/subagent-state.ts`, `observation/record-observer.ts`, `lifecycle/subagent.ts`.
69
- Extend the single owned run-state value object with `turnCount`, active tools, and response text; have the already-subscribed `record-observer` handle `turn_end`, `tool_execution_start`, `message_start`, `message_update`; expose read-only `turnCount`/`maxTurns`/`activeTools`/`responseText` getters on `Subagent`.
70
- `AgentActivityTracker` still exists; nothing reads the new getters yet (tidy-first).
71
- Smell: Category C. Outcome: `Subagent` is the single home for all run state; getters available for migration.
72
- Landed: `SubagentState` owns `turnCount`/`activeTools`/`responseText` plus their transition methods; `record-observer` populates them on a single subscription; `Subagent` exposes the four read-only getters; +27 tests (1031 → 1058).
73
- 2. **✅ Migrate every activity reader to the record getters — complete.**
74
- ([#421]) Target: `ui/widget-renderer.ts`, `ui/conversation-viewer.ts`, `ui/agent-menu.ts`, `tools/foreground-runner.ts`, `observation/notification.ts`.
75
- Switch each reader from `AgentActivityTracker` to the record getters added in Step 1 (widget-renderer reads activity off `listAgents()`; viewer/menu drop the `activity` param; notification reads `turnCount`/`maxTurns` off the record).
76
- Smell: Category C (Law of Demeter).
77
- Outcome: no consumer references `AgentActivityTracker`.
78
- Landed: `WidgetAgent` folds the live-activity fields and a `contextPercent` projection; `AgentWidget` projects records; `ConversationViewer`, `AgentsMenuHandler`, `buildDetails`, and `buildNotificationDetails` read off the record; `NotificationSystem.cleanupCompleted` removed; `SubagentEventsObserver` returns early on consumed results; +8 tests (1058 → 1066).
79
- 3. **✅ Delete `AgentActivityTracker` and `ui-observer`; drop the activity map from the runtime and spawn tools — complete.**
80
- ([#422]) Target: `ui/agent-activity-tracker.ts` (delete), `ui/ui-observer.ts` (delete), `runtime.ts`, `tools/foreground-runner.ts`, `tools/background-spawner.ts`.
81
- The spawn tools stop constructing trackers, subscribing, and populating maps; `SubagentRuntime.agentActivity` is removed.
82
- Smell: Category A + C. Outcome: −145 LOC, one session subscription per child, runtime holds zero UI state.
83
- Landed: deleted `agent-activity-tracker.ts` (84) + `ui-observer.ts` (61) and their unit suites; dropped the `agentActivity` parameter from `runForeground`/`spawnBackground`, the `AgentActivityAccess` interface, and the `AgentToolRuntime`/`SubagentRuntime` activity-map fields; the foreground `observer.onSessionCreated` keeps `recordRef`/`fgId` binding and `widget.ensureTimer`; −34 tests (1066 → 1032).
84
- 4. **✅ Make the widget self-drive from lifecycle events — complete.**
85
- ([#423]) Target: `ui/agent-widget.ts`, `observation/composite-subagent-observer.ts` (new), `index.ts`.
86
- The widget starts/stops its timer in response to started/created/completed notifications instead of tool calls; spawn tools no longer call `ensureTimer`/`update`/`markFinished`.
87
- Smell: Category C (coupling direction).
88
- Outcome: the widget is a reactive consumer; no inbound calls from core spawn tools.
89
- Landed: `AgentWidget implements SubagentManagerObserver` (starts the 80 ms loop on `onSubagentStarted`/`onSubagentCreated`, re-renders on `onSubagentCompleted`/`onSubagentCompacted`); a new `CompositeSubagentObserver` fans the manager's single observer slot out to `[eventsObserver, widget]` (wired in `index.ts`, keeping `SubagentManager` unchanged); dropped the `widget` parameter and `ForegroundWidgetDeps`/`BackgroundWidgetDeps` interfaces from both spawners, deleted `AgentWidget.markFinished` (redundant with `seedFinishedAgents`), made `ensureTimer` private, and narrowed `AgentToolWidget` to `setUICtx`; +11 tests (1032 → 1043, then −4 with the dropped spawner widget-driving tests → 1039).
90
- 5. **✅ Drop the widget dependency from the `subagent` tool — complete.**
91
- ([#424]) Target: `tools/agent-tool.ts`, `test/helpers/make-deps.ts`.
92
- `AgentTool` loses its `widget` constructor param (UICtx capture stays in `ToolStartHandler`); `createToolDeps` sheds the widget stub.
93
- The activity-map (`agentActivity`) dependency this step originally named was already removed from the tool and runtime in Step 3 ([#422]), so only `widget` remained to drop.
94
- Smell: Category C/D.
95
- Outcome: the LLM tool depends only on manager/runtime/settings/registry; fixture drops 1 field.
96
- Landed: removed the `widget` constructor param and the redundant `this.widget.setUICtx(ctx.ui)` call from `AgentTool.execute`, deleted the `AgentToolWidget` interface and its `UICtx` import, updated the sole `index.ts` call site, and dropped the `widget` field/stub plus two now-obsolete tests (`agent-tool` UICtx capture, `make-deps` widget defaults) — UICtx capture is pinned by `handlers/tool-start.test.ts`; −2 tests (1039 → 1037).
97
- 6. **✅ Reconcile the public event contract — complete.**
98
- ([#425]) Target: `service/service.ts`, the lifecycle-events table in [architecture.md](../architecture.md).
99
- Remove the vacant `ACTIVITY` channel (or emit a real broadcast for it) and add the emitted `failed`/`compacted`/`created` channels so declared constants match emitted events.
100
- Smell: Category A/E.
101
- Outcome: declared channels equal emitted channels; no vacant hook.
102
- Landed: removed `SUBAGENT_EVENTS.ACTIVITY` (breaking) and added `FAILED`/`COMPACTED`/`CREATED`/`STEERED` — `subagents:steered` (from `steer-tool.ts`) was also emitted-but-undeclared, so all four emitted agent-lifecycle channels are now declared; corrected the stale `subagents:completed` payload in the lifecycle-events table to the real `buildEventData` shape; +1 test (1037 → 1038).
103
- 7. **✅ Consolidate residual test clone families — complete.**
104
- ([#426]) Target: `test/settings.test.ts` + `test/layered-settings.test.ts`, `test/lifecycle/create-subagent-session.test.ts`, `test/ui/agent-config-editor.test.ts`.
105
- Extract shared fixtures for the clone families fallow reports that the spine does not already rewrite.
106
- Smell: Category D. Outcome: test clone groups drop below 15.
107
- Landed: extracted `test/helpers/tmp-settings-dirs.ts` (global+project tmp-dir fixture) and `test/helpers/capture-warn.ts` (a `console.warn` capture helper), each with a paired self-test; table-drove the `create-subagent-session` post-bind membership cases and the `agent-config-editor` menu + confirm-remove cases into `it.each`; pi-subagents test clone groups dropped from 24 to 14 (below the <15 target); +9 tests (1038 → 1047).
108
- 8. **✅ Reconsider the UI direction (first-principles ADR) — complete.**
109
- ([#427]) Target: `docs/decisions/`, `ui/`.
110
- The spine already made the UI _substitutable_; this step decides its _distribution_, not whether the experiment is possible.
111
- The goal is **substitutable, not optional**: a human needs some surface, but the specific UI is replaceable — the way Pi ships a default TUI built on the same public API any extension targets.
112
- The disentangled core stays byte-for-byte identical whether or not a given UI consumer is installed (the composition test), so a replacement UI is a downstream concern even though _some_ UI is not.
113
- Unlike the worktrees provider seam (generative, rationed — one provider the core consults), the UI is an observational consumer (unlimited, the core never waits on it) reading the broadcast-plus-query surface, which is why packaging it is the secondary question and decoupling it was the real win.
114
- Two standing concerns are the evidence this decision weighs and the better boundaries the reconsideration is meant to surface:
115
- - **Truncated transcript.**
116
- The conversation viewer shows a truncated view, yet `Subagent.messages` already exposes the full history and the core already persists each child as a standard Pi session JSONL (`outputFile`) — the limit is the bespoke overlay's rendering, not data access.
117
- - **Foreground widget redundancy.**
118
- In foreground the tool's inline `onUpdate` stream already shows progress, so the above-editor widget duplicates it; the widget earns its keep only for background agents — a per-mode judgment the fused UI cannot vary.
119
- Candidate redesign to record: replace the bespoke overlay with "open the child session in the same viewer Pi uses for any session," following the recursive-Pi insight and the already-persisted session file.
120
- Judge the widget, conversation viewer, and `/agents` menu per component — keep, shrink, extract to `@gotgenes/pi-subagents-ui`, or remove — and capture the decision in an ADR that gateways Phase 19.
121
- Smell: Category E (organization / boundary).
122
- Outcome: a recorded per-component decision motivated by the two concerns; the inherited UI is substitutable and no longer preserved by default.
123
- Landed: [ADR-0004] records the per-component decision — (A) shrink the widget to background agents only; (B) remove the bespoke `ConversationViewer`, replacing it with native session navigation over the persisted child JSONL (`switchSession`/`loadEntriesFromFile`, mechanism gated on a Phase 19 spike); (C) dissolve the `/agents` command (remove the create wizard and the agent-types config editor, re-home running-agent visibility onto the widget + session navigation, extract settings to a focused `/subagents:settings` command); (D) keep the surviving UI in-core (substitutable, not extracted).
124
- The ADR gateways Phase 19, which implements these decisions under its own plan; no runtime code changed in this step.
125
-
126
- ## Step dependency diagram
127
-
128
- ```mermaid
129
- flowchart TB
130
- S1["1 — Fold metrics + activity onto record (#420) ✅"]
131
- S2["2 — Migrate readers to record getters (#421) ✅"]
132
- S3["3 — Delete tracker + ui-observer, drop activity map (#422) ✅"]
133
- S4["4 — Widget self-drives on events (#423) ✅"]
134
- S5["5 — Drop widget dep from subagent tool (#424) ✅"]
135
- S6["6 — Reconcile public event contract (#425) ✅"]
136
- S7["7 — Consolidate test clone families (#426) ✅"]
137
- S8["8 — Reconsider UI direction, ADR (#427) ✅"]
138
-
139
- S1 --> S2 --> S3 --> S4 --> S5 --> S8
140
- S6
141
- S7
142
- ```
143
-
144
- ## Parallel tracks
145
-
146
- - **Track A — Disentangle the activity tier (spine):** Steps 1, 2, 3.
147
- Strictly ordered; each is a safe lift-and-shift over the previous.
148
- - **Track B — Decouple widget and tool wiring:** Steps 4, 5.
149
- Begins once the activity map is gone (Step 3).
150
- - **Track C — Public-contract hygiene:** Step 6.
151
- Independent; can land any time.
152
- - **Track D — Test consolidation:** Step 7.
153
- Independent; can land any time.
154
- - **Track E — UI reconsideration:** Step 8.
155
- Gated on the spine and Track B (the UI must be a clean consumer first).
156
-
157
- [ADR-0004]: ../../decisions/0004-reconsider-ui-direction.md
158
- [first-principles refinement]: ../architecture.md#first-principles-refinement-and-the-deeper-target
159
- [#420]: https://github.com/gotgenes/pi-packages/issues/420
160
- [#421]: https://github.com/gotgenes/pi-packages/issues/421
161
- [#422]: https://github.com/gotgenes/pi-packages/issues/422
162
- [#423]: https://github.com/gotgenes/pi-packages/issues/423
163
- [#424]: https://github.com/gotgenes/pi-packages/issues/424
164
- [#425]: https://github.com/gotgenes/pi-packages/issues/425
165
- [#426]: https://github.com/gotgenes/pi-packages/issues/426
166
- [#427]: https://github.com/gotgenes/pi-packages/issues/427
@@ -1,282 +0,0 @@
1
- # Phase 19: Implement the ADR-0004 UI decisions
2
-
3
- ## Summary
4
-
5
- Phase 19 implements the per-component UI decisions recorded in [ADR-0004]: shrink the widget to background-only, replace the bespoke conversation viewer with native session navigation, dissolve the monolithic `/agents` menu, and keep the surviving UI in-core.
6
-
7
- The sequencing follows Kent Beck's "make the change easy, then make the easy change."
8
- The end state deletes `agent-menu.ts` — the god-command that bundles four unrelated jobs — and everything reachable only from it.
9
- Rather than surgically mutate that doomed module (and the #1 churn hotspot `index.ts`) once per option, Phase 19 first stood up the replacement surfaces additively, then removed the now-orphaned subtree in a single terminal cut.
10
- This kept every responsibility's old surface live until its replacement existed (ADR-0004's no-interim-regression invariant), turned the three replacement steps into genuinely parallel work (none touched `agent-menu.ts`), and reduced `index.ts` edits from four surgical removals to one deregistration.
11
-
12
- Seven numbered steps in three phases, plus two follow-ups (Steps 4a–4b) carved from the #445 slice:
13
-
14
- - **Phase A — stand up replacements (additive):** spike, settings command, background widget, native session navigation and its renderer/source follow-ups (Steps 1–4, 4a–4b).
15
- - **Phase B — dissolve `/agents` (terminal cut):** delete the orphaned subtree in two deletion commits, one per subtree (Steps 5–6).
16
- - **Phase C — test health:** consolidate the test clones that survive the cut (Step 7).
17
-
18
- All nine steps are closed: [#446], [#447], [#444], [#445], [#462], [#463], [#442], [#441], [#443].
19
- A follow-on issue, [#470] (README staleness — the terminal cut removed `/agents` but left the README describing it), was filed after Steps 5–6 shipped and closed independently; see "Follow-on issues" below.
20
-
21
- ## Health metrics
22
-
23
- | Metric | Phase 18 (start) | Phase 19 target | Phase 19 (delivered) |
24
- | ---------------------- | ------------------------ | -------------------- | ------------------------------------ |
25
- | Health score | 78/100 (B) | 83/100 (B+) | 78/100 (B) — unchanged |
26
- | Source LOC | 7,650 (61 files) | ~6,780 (~55 files) | 7,068 (57 files) |
27
- | Production duplication | 11 lines (1 group) | 0 lines | 0 lines ✅ |
28
- | Test clone groups | 16 | ≤ 10 | 9 ✅ |
29
- | Top churn hotspot | `index.ts` (103 commits) | `index.ts` (cooling) | `index.ts` (109 commits, cooling) ✅ |
30
-
31
- The health score held flat at 78/100 rather than reaching the 83/100 target — the score's `hotspots` and `unit size` deductions are dominated by long-lived test-suite characteristics (large test functions, `index.ts`'s cumulative churn history) that this phase's scope did not target.
32
- Every metric the phase's steps directly controlled — production duplication, test clone groups, and the churn trend on `index.ts` — hit or beat its target.
33
-
34
- ## Steps
35
-
36
- ### Step 1 — Spike: resolve ADR-0004 entry criteria ([#446])
37
-
38
- Smell: Category C (coupling boundary) — four open decisions block the session-navigation implementation.
39
- Target: `docs/decisions/0004-reconsider-ui-direction.md` addendum.
40
-
41
- The four entry criteria from ADR-0004:
42
-
43
- 1. **Root-continuity:** Does the root's in-flight turn survive `ctx.switchSession()` and a return gesture?
44
- 2. **View-only vs interactive:** `switchSession` (full interactive takeover) or `loadEntriesFromFile` (read-only transcript built from JSONL)?
45
- 3. **Parallel-agent navigation:** Operator gesture to select which of N background agents to view (from the widget, a command, or both).
46
- 4. **Settings command name:** `/subagents-settings`, `/agents-settings`, or another form consistent with sibling packages?
47
-
48
- Produce a minimal spike (observed test or PoC against a real session) that answers each question, then record the answers as an addendum to ADR-0004.
49
- No production source files change; the spike closes when the ADR addendum is merged.
50
-
51
- Outcome: ADR-0004 updated with all four entry-criteria answers; Step 4 unblocked.
52
-
53
- `Release: independent`
54
-
55
- ### Step 2 — Extract settings to a focused `/subagents-settings` command ([#447])
56
-
57
- Smell: Category E (naming/organization) — settings are buried inside the monolithic `/agents` command per ADR-0004 Decision C. This step is purely additive: it stands up the new surface without touching `agent-menu.ts`.
58
- Target files:
59
-
60
- - New `src/ui/subagents-settings.ts` — `SubagentsSettingsHandler` lifted from `AgentsMenuHandler.showSettings`, carrying its own narrow `SubagentsSettingsManager` interface (the three `apply*` methods and three readonly accessors only).
61
- - `src/index.ts` — register the new command (name confirmed by Step 1); pass `settings` directly.
62
- - New `test/ui/subagents-settings.test.ts` — unit tests for the extracted handler.
63
-
64
- `showSettings` depends only on `this.settings` (the self-contained `AgentMenuSettings` shape), so the extraction copies that logic into a new file with zero coupling to the wizard, editor, or viewer.
65
- The old in-menu Settings option keeps working until the terminal cut deletes `agent-menu.ts` wholesale — there is no surgical removal of `showSettings` or `AgentMenuSettings` from the doomed file.
66
-
67
- Outcome: new `subagents-settings.ts` (~80 LOC) and focused command registered; `agent-menu.ts` untouched.
68
-
69
- `Release: independent`
70
-
71
- ### Step 3 — Shrink widget to background agents only ([#444])
72
-
73
- Smell: Category C (coupling) — the widget shows all agents including foreground ones, duplicating the `subagent` tool's inline `onUpdate` stream for foreground runs.
74
- Target files:
75
-
76
- - `src/ui/agent-widget.ts` — funnel both `manager.listAgents()` call sites (`update()` and `renderWidget()`) through a single private accessor, then flip that accessor to background-only via `record.invocation?.runInBackground === true`.
77
- - `src/ui/widget-renderer.ts` — verify no foreground-specific rendering path survives.
78
- - `test/ui/agent-widget.test.ts` — add background-only filtering tests; update assertions.
79
-
80
- The widget calls `listAgents()` at two sites today — `update()` (feeding `seedFinishedAgents`, `assembleWidgetState`, and `clearWidget`) and `renderWidget()` (the tree map).
81
- Filtering at only one site leaves the other rendering foreground agents, so the enabling move is to route both through one accessor and apply the predicate once at the source.
82
- `Subagent.invocation.runInBackground` is the reliable signal: set by `spawn-config.ts` → `AgentInvocation.runInBackground` → stored on `Subagent.invocation`.
83
- ADR-0004 Decision A: foreground runs suppress the widget; the inline `onUpdate` stream is authoritative there.
84
-
85
- Outcome: widget shows only background agents; foreground/widget duplication eliminated; the background predicate lives at a single funnel.
86
-
87
- `Release: independent`
88
-
89
- ### Step 4 — Implement native session navigation ([#445])
90
-
91
- Smell: Category C (coupling) — the bespoke `ConversationViewer` re-implements session-transcript rendering when Pi's own machinery targets the already-persisted child session JSONL.
92
- This step adds the new surface alongside the existing viewer; it does not touch `agent-menu.ts`.
93
- Target files:
94
-
95
- - New `src/ui/session-navigator.ts` — a flat command that lists any subagent with a live record or a persisted session file (foreground included, never background-filtered), lets the operator pick one, and renders that child's transcript read-only.
96
- - New typed accessor on `Subagent`/`SubagentSession` returning `record.messages` as `AgentMessage[]` (the boundary currently widens it to `readonly unknown[]`).
97
- - `src/index.ts` — register the new command; the background widget ([#444]) is an optional secondary selection gesture, not a dependency.
98
-
99
- ADR-0004 Decision B: "Tell-Don't-Ask — hand Pi the session path; Pi owns the viewer."
100
- Mechanism (confirmed by the Step 1 spike and revised by [ADR-0004] Addendum 2): a **read-only** (non-interactive) transcript **dual-sourced by liveness**, rendered through Pi's own public entry components (no bespoke renderer).
101
-
102
- - **Tracked agent** (still in `manager.listAgents()`) — render live from the in-memory record: `record.messages` for history, `record.subscribeToUpdates()` to re-render on streaming updates, and `record.activeTools` / `record.responseText` for the running-agent streaming indicator.
103
- - **Evicted / untracked agent** — render from the file snapshot: `parseSessionEntries(readFileSync(record.outputFile, "utf8"))` → drop the `SessionHeader` → `buildSessionContext(...).messages`.
104
-
105
- Both sources yield `AgentMessage[]`, so one Pi-component renderer serves both: Pi's public entry components (`AssistantMessageComponent` / `ToolExecutionComponent` / …) or `serializeConversation` (see the [ADR-0004] addendum, Findings 0 and 1).
106
- Neither `switchSession` (a full takeover that invalidates the root's in-flight turn) nor `loadEntriesFromFile` (a test-only export the package's public barrel does not re-export, in both `0.79.1` and `0.79.8`) is used.
107
- `Subagent.outputFile` already exposes the persisted child session JSONL path via `subagentSession?.outputFile` — no new SDK dependency.
108
- The new surface stands up while the old `viewAgentConversation`/`ConversationViewer` path still works; the bespoke viewer is removed only by the terminal cut (Step 5).
109
-
110
- Outcome: operator views any subagent's session through Pi's native machinery — live for a running agent, a file snapshot for an evicted one; the new surface coexists with the old viewer until Step 5.
111
-
112
- Landed ([#445], sliced): #445 shipped the first releasable vertical slice — the `/subagent-sessions` command (`src/ui/session-navigator.ts`), the pure selection/sourcing/text-render core (`src/ui/session-navigation.ts`), and the typed `agentMessages` accessor (`SessionMessage` on `SubagentSession`/`Subagent`).
113
- It is **live-source only** behind a renderer-agnostic `TranscriptSource` seam, rendered via Pi's `serializeConversation` text.
114
- With the `manager.listAgents()`-only candidate set, no listed record is ever session-disposed (dispose-and-delete are atomic), so the file-snapshot branch has no reachable caller and was deferred to keep `fallow dead-code` clean.
115
- Step 4 (#445, the slice) is complete and released (`pi-subagents` v17.3.0); the remaining work is now tracked as two follow-up steps behind the same seam: Step 4a ([#462]) upgrades the renderer from `serializeConversation` text to Pi's per-entry TUI components (gates Step 5 for rendering parity); Step 4b ([#463]) broadens the candidate set to evicted agents and adds the file-snapshot source (`parseSessionEntries` → `buildSessionContext`, independent).
116
-
117
- `Release: independent` (spike-gated)
118
-
119
- ### Step 4a — Upgrade native-navigation renderer to Pi TUI components ([#462])
120
-
121
- Smell: Category C (coupling) — the #445 slice renders the transcript as `serializeConversation` plain text, while the bespoke `ConversationViewer` it replaces renders richer per-message formatting.
122
- Until the native renderer reaches parity, the terminal cut (Step 5) cannot delete the bespoke viewer without a fidelity regression.
123
- This step swaps the renderer behind the existing `TranscriptSource` seam (`src/ui/session-navigation.ts` / `session-navigator.ts`) for Pi's per-entry components (`AssistantMessageComponent` / `ToolExecutionComponent` / …); selection and sourcing are untouched.
124
-
125
- Gates Step 5: per [ADR-0004]'s no-interim-regression invariant, the native navigator must reach rendering parity with the bespoke viewer before Step 5 deletes it.
126
-
127
- Outcome: native session navigation renders at parity with the removed `ConversationViewer`; Step 5 can delete the bespoke viewer with no fidelity regression.
128
-
129
- Landed ([#462]): the renderer now mounts Pi's per-entry components (`AssistantMessageComponent` / `ToolExecutionComponent` / `BashExecutionComponent` / `UserMessageComponent` / `CompactionSummaryMessageComponent` / `BranchSummaryMessageComponent` / `SkillInvocationMessageComponent`) into a `Container`, mirroring Pi's own `renderSessionContext` mapping.
130
- The `TranscriptOverlay` caches that `Container` and rebuilds it on source change only (Pi's `rebuildChatFromMessages` path), keeping the lightweight `◍` streaming indicator.
131
- Tool calls render with their real `ToolDefinition`, resolved through a dependency-safe `getToolDefinition` read accessor on the record (mirroring `agentMessages`) surfaced on the `TranscriptSource` seam — no inbound call into the core.
132
- The pure `session-navigation.ts` sheds `renderTranscriptLines`/`serializeConversation`; rendering now lives in the SDK/TUI `session-navigator.ts`, which threads `cwd` from the command context.
133
- `custom`-role messages are skipped (the bespoke viewer never rendered them either).
134
- Selection and sourcing are untouched; native navigation now renders at parity, unblocking Step 5 for rendering fidelity.
135
-
136
- `Release: independent`
137
-
138
- ### Step 4b — File-snapshot source for evicted agents ([#463])
139
-
140
- Smell: Category C (coupling) — the #445 slice sources transcripts live from `manager.listAgents()` only; an agent evicted by the 10-minute cleanup sweep has a persisted session JSONL but no live record, so it is unreachable.
141
- This step adds the file-snapshot `TranscriptSource` branch (`parseSessionEntries(readFile(outputFile))` → drop the `SessionHeader` → `buildSessionContext(...).messages`) and broadens the candidate set to evicted agents, behind the same seam; the renderer is untouched.
142
-
143
- Independent: this is a new capability the bespoke viewer never had, so it gates nothing and is not a Step 5 prerequisite.
144
- Best sequenced after Step 4a (shared renderer), but carries no hard dependency.
145
-
146
- Outcome: the operator can view a fully-evicted agent's transcript from its persisted session file; the dual-source design recorded in [ADR-0004] Addendum 2 is fully realized.
147
-
148
- Landed ([#463]): `fileSnapshotSource(outputFile, readFile)` lands in the pure `session-navigation.ts` (`parseSessionEntries` → drop the `SessionHeader` → `buildSessionContext(...).messages`; a static no-subscribe, no-streaming source).
149
- The candidate set is broadened via **manager-retained descriptors**, not a directory scan: the persisted child session carries no subagent `type`/`description` (those live only on the in-memory record), so a scan would yield degraded labels and parse every file per open.
150
- Instead `SubagentManager.cleanup()` stashes a lightweight `EvictedSubagent` descriptor (label fields + `outputFile`, no messages) before disposing a record with a persisted file, exposed via `listEvicted()` and cleared by `clearCompleted()`/`dispose()`.
151
- `NavigationEntry` became a `live | evicted` discriminated union; the handler selects `liveSource` vs `fileSnapshotSource` by kind inside a `try/catch` (an unreadable file notifies and skips), and `index.ts` injects `readFileSync`.
152
- Evicted entries carry an `· evicted (snapshot)` label marker.
153
- Coverage is in-session evictions (the sweep's only targets); old-session orphan files — the ones a scan would surface with degraded labels — are out of scope.
154
-
155
- `Release: independent`
156
-
157
- ### Step 5 — Dissolve `/agents` and remove the conversation-viewer subtree ([#442])
158
-
159
- Smell: Category A (dead subsystem) plus Category B (oversized) — once Steps 2–4 re-home all four menu responsibilities, the `/agents` command and everything reachable only from `agent-menu.ts` is an unreferenced subtree.
160
- This is the first of two deletion commits (split by subtree).
161
- The hub `agent-menu.ts` is deleted here, not surgically narrowed, and deleting it is what orphans the leaf subtrees — so it must precede the definition-management deletion (Step 6), because `agent-menu.ts` statically imports the wizard, editor, and file-ops, and dynamically imports the viewer.
162
- Target files:
163
-
164
- - `src/index.ts` — remove the `registerCommand("agents", …)` block, the `AgentsMenuHandler` construction and import, and the `FsAgentFileOps` import/construction (its only use is wiring the menu).
165
- - Delete `src/ui/agent-menu.ts` (331 LOC) and `test/ui/agent-menu.test.ts` (185 LOC).
166
- - Delete `src/ui/conversation-viewer.ts` (241 LOC) and `test/conversation-viewer.test.ts` (239 LOC) — its only consumer is `agent-menu.ts`'s dynamic import, gone with the hub.
167
- - Delete `src/ui/message-formatters.ts` (195 LOC) and `test/message-formatters.test.ts` (388 LOC, the largest test function by LOC) — its only consumer is `ConversationViewer`.
168
-
169
- Running-agent visibility is now owned by the background widget (Step 3); session navigation replaces the bespoke overlay (Step 4); settings live in `/subagents-settings` (Step 2).
170
- Deleting the hub in one move avoids any surgical edit to the doomed file and leaves the definition-management leaves orphaned for Step 6.
171
-
172
- Actual approach (vs. original plan): a tidy-first preparatory commit first extracted `MenuUI` from `agent-menu.ts` into a new `src/ui/menu-ui.ts` module, breaking the bidirectional type cycle — the hub imported the wizard/editor classes while the leaves imported back the `MenuUI` type.
173
- Without the prep commit, deleting either subtree first would have left the other half referencing a deleted module.
174
- `index.ts` also shed the now-dead `join` (node:path) and `buildParentSnapshot` imports in addition to the two module imports.
175
- The `menu-ui.ts` module is transient and is removed with the wizard/editor in Step 6.
176
-
177
- Outcome: ✅ `/agents` dissolved; −767 LOC source (menu hub + viewer + formatters); −812 LOC test; largest test function eliminated; `index.ts` dewired.
178
-
179
- `Release: batch "dissolve-agents"`
180
-
181
- ### Step 6 — Remove the orphaned agent-definition management subtree ([#441])
182
-
183
- Smell: Category A (dead subsystem) — the creation wizard and config editor are removed per ADR-0004 Decision C; after Step 5 deletes their only importer (`agent-menu.ts`), they and their file-ops helpers are pure orphans.
184
- This is the second deletion commit (split by subtree).
185
- Target files:
186
-
187
- - Delete `src/ui/agent-creation-wizard.ts` (233 LOC) and `test/ui/agent-creation-wizard.test.ts` (296 LOC).
188
- - Delete `src/ui/agent-config-editor.ts` (199 LOC) and `test/ui/agent-config-editor.test.ts` (392 LOC) — eliminates the 11-line internal production clone in `disableAgent`/`ejectAgent`, the package's only remaining production duplication.
189
- - Delete `src/ui/agent-file-ops.ts` (59 LOC) and `test/ui/agent-file-ops.test.ts` (112 LOC) — only consumers were wizard + editor.
190
- - Delete `src/ui/agent-file-writer.ts` (55 LOC) and `test/ui/agent-file-writer.test.ts` (148 LOC) — only consumers were wizard + editor.
191
- - `test/helpers/ui-stubs.ts` — delete `makeFileOps`, `createTestSubagentConfig`, and `spawnAndWait` from `makeMenuManager` if no surviving consumer remains; delete the file outright once all consumers are gone.
192
-
193
- An operator generates a new agent `.md` by asking a Pi session directly (more capable than a fixed wizard) or by writing the file in an editor; viewing and editing definitions is served by opening the `.md` files in an editor or IDE.
194
- These files are orphaned by Step 5, so this is a pure `git rm` with no surviving references and no edit to any doomed file.
195
-
196
- Outcome: −546 LOC source (wizard + editor + file-ops + file-writer); −948 LOC test; production duplication → 0 lines; 1 production and 1 test clone group eliminated.
197
-
198
- Landed ([#441]): deleted `agent-creation-wizard.ts`, `agent-config-editor.ts`, `agent-file-ops.ts`, `agent-file-writer.ts`, and `menu-ui.ts` (orphaned transient) from `src/ui/`, plus their four test files.
199
- `test/helpers/ui-stubs.ts` pruned to `makeMenuUI` only (still consumed by `subagents-settings.test.ts`); `makeFileOps`, `makeMenuManager`, and `createTestSubagentConfig` removed with their `ui-stubs.test.ts` describe blocks.
200
- Production duplication: 0 lines (confirmed by `fallow dupes`); `fallow dead-code`: clean. 16 test clone groups remain — Step 7 consolidation target.
201
-
202
- `Release: batch "dissolve-agents"`
203
-
204
- ### Step 7 — Consolidate remaining test clone families ([#443])
205
-
206
- Smell: Category D (testability) — 16 clone groups at Phase 18 end; the terminal cut (Steps 5–6) removes ~4 groups; remaining groups are extraction targets.
207
- Run after the cut so no helper is extracted into a file the cut then deletes.
208
- Target files:
209
-
210
- - `test/lifecycle/subagent-manager.test.ts` — extract a shared assertion helper for 3 clone families (23 lines across groups at :92/:109, :282/:330, and :323 shared with `subagent.test.ts`).
211
- - `test/ui/agent-widget.test.ts` — merge the duplicate `makeWidget` helper defined twice across two `describe` blocks (14-line clone at :225/:284).
212
- - `test/session/session-config.test.ts` — extract a shared fixture for the 16-line internal clone (lines 131–146 / 151–166).
213
- - `test/lifecycle/concurrency-limiter.test.ts` — extract shared setup for the 10-line clone (lines 21–30 / 148–155).
214
- - `test/tools/spawn-config.test.ts` — extract a shared fixture for the 9-line clone (lines 22–30 / 35–43).
215
-
216
- Outcome (landed): test clone groups reduced from 16 to 9 (≤ 10 target met).
217
- Eight genuine arrange/fixture/helper families were extracted: `makeNavigable` (shared `test/helpers/make-navigable.ts`), `emitResumeUsageAndCompaction` (shared `test/helpers/mock-session.ts`), and local helpers for `makeWidget`, the captured-overlay render (`renderCapturedOverlay`), the `resultConsumed` observer (`seedResultConsumedObserver`), the ready subagent (`makeReadySubagent`), and the prepared bracket (`preparedBracket`).
218
- The nine residual families are the repeated system-under-test call (`resolveSpawnConfig`, `assembleSessionConfig`, `schedule`, `SessionNavigatorHandler.handle`, `spawnBg`+`await`, `agent.run()`, `execute`), left intact per the testing guardrail — the repeated act is the test subject, not duplication to remove.
219
- One family the plan pre-classified as captured-overlay boilerplate (`dup:ea0a1bce`) proved to be an act-clone once the boilerplate was extracted, so it joins the residual set rather than being wrapped.
220
-
221
- `Release: independent`
222
-
223
- ## Step dependency diagram
224
-
225
- ```mermaid
226
- flowchart LR
227
- S1["✅ Step 1 - Spike (#446)"]
228
- S2["✅ Step 2 - Settings command (#447)"]
229
- S3["✅ Step 3 - Background widget (#444)"]
230
- S4["✅ Step 4 - Native session nav slice (#445)"]
231
- S4a["✅ Step 4a - Renderer to TUI components (#462)"]
232
- S4b["✅ Step 4b - File-snapshot source (#463)"]
233
- S5["✅ Step 5 - Dissolve /agents + viewer (#442)"]
234
- S6["✅ Step 6 - Remove definition mgmt (#441)"]
235
- S7["✅ Step 7 - Test clones (#443)"]
236
-
237
- S1 --> S4
238
- S4 --> S4a
239
- S4 --> S4b
240
- S2 --> S5
241
- S3 --> S5
242
- S4a --> S5
243
- S5 --> S6
244
- S6 --> S7
245
- ```
246
-
247
- The terminal cut (Step 5) depends on all three replacements — settings (Step 2), widget (Step 3), and session navigation **at rendering parity** (Step 4a, which completes the #445 slice) — because each of the four `/agents` options must have its responsibility re-homed, and the viewer replacement at parity, before its branch can die.
248
- Step 4b (file-snapshot source) is a new capability and gates nothing.
249
- The old `S1 → S6 → S7` chain hid the widget dependency; this diagram makes it explicit.
250
-
251
- ## Parallel tracks
252
-
253
- - **Track A — Replacements (Steps 1–4):** the spike gates session navigation (Step 1 → Step 4); settings (Step 2) and the background widget (Step 3) are independent of the spike and of each other.
254
- None of these steps edits `agent-menu.ts`, so they carry no shared-file collision on the menu — genuinely parallelizable, unlike the prior plan's Steps 2/3/5, which all collided on `agent-menu.ts` and `index.ts`.
255
- Steps 2 and 4 each append a command registration to `index.ts` (additive, low-conflict).
256
- Steps 4a (renderer parity) and 4b (file-snapshot source) complete the #445 slice behind its `TranscriptSource` seam; Step 4a gates Step 5, Step 4b is independent.
257
- - **Track B — Dissolution (Steps 5 → 6):** the terminal cut, gated on all of Track A landing.
258
- Hub-first ordering is forced: Step 5 deletes `agent-menu.ts` (orphaning the leaves), then Step 6 `git rm`s the now-orphaned definition-management subtree.
259
- - **Track C — Test health (Step 7):** clone consolidation, run after the cut so no surviving helper is extracted into a doomed file.
260
-
261
- ## Release batches
262
-
263
- - **Batch "dissolve-agents":** Steps 5, 6 (ship together; tail = Step 6).
264
- Depends on Steps 2, 3, 4 already merged.
265
- - Independently releasable: Steps 1, 2, 3, 4, 4a, 4b, 7.
266
-
267
- ## Follow-on issues
268
-
269
- - [#470] — the terminal cut (Steps 5–6) removed `/agents`, the conversation viewer, and the creation wizard/config editor, but `README.md` was never updated and continued documenting the removed surface through the `pi-subagents-v18.0.0` release.
270
- Filed and closed independently after the phase's steps landed; the README now documents `/subagents:settings`, `/subagents:sessions`, and the background widget.
271
-
272
- [ADR-0004]: ../../decisions/0004-reconsider-ui-direction.md
273
- [#441]: https://github.com/gotgenes/pi-packages/issues/441
274
- [#442]: https://github.com/gotgenes/pi-packages/issues/442
275
- [#443]: https://github.com/gotgenes/pi-packages/issues/443
276
- [#444]: https://github.com/gotgenes/pi-packages/issues/444
277
- [#445]: https://github.com/gotgenes/pi-packages/issues/445
278
- [#446]: https://github.com/gotgenes/pi-packages/issues/446
279
- [#447]: https://github.com/gotgenes/pi-packages/issues/447
280
- [#462]: https://github.com/gotgenes/pi-packages/issues/462
281
- [#463]: https://github.com/gotgenes/pi-packages/issues/463
282
- [#470]: https://github.com/gotgenes/pi-packages/issues/470
@@ -1,9 +0,0 @@
1
- # Phase 2: Remove scheduling
2
-
3
- Deleted `schedule.ts`, `schedule-store.ts`, `ui/schedule-menu.ts`.
4
- Removed the `schedule` parameter from the `Agent` tool schema.
5
- Removed scheduler setup and lifecycle hooks from `index.ts`.
6
-
7
- ## Related issues
8
-
9
- - #52 — Remove scheduling
@@ -1,11 +0,0 @@
1
- # Phase 3: Remove group-join, ad-hoc RPC; replace output-file
2
-
3
- Deleted `group-join.ts`, `cross-extension-rpc.ts` (#49).
4
- Replaced `output-file.ts` with `SessionManager.create()` + `session-dir.ts` (#61).
5
- Simplified `index.ts` to use direct individual notifications.
6
- Lifecycle events emitted on `pi.events` for external consumers.
7
-
8
- ## Related issues
9
-
10
- - #49 — Remove group-join and ad-hoc RPC
11
- - #61 — Replace output-file with JSONL session transcripts
@@ -1,8 +0,0 @@
1
- # Phase 4: Implement and publish SubagentsService
2
-
3
- Wired `service-adapter.ts` to wrap `AgentManager` and call `publishSubagentsService()` at extension init.
4
- Model strings are resolved inside the adapter.
5
-
6
- ## Related issues
7
-
8
- - #48 — Implement and publish SubagentsService
@@ -1,42 +0,0 @@
1
- # Phase 5: Decompose index.ts
2
-
3
- Extracted tools, notifications, activity tracking, event handlers, and the `/agents` command into separate modules.
4
- Created `SubagentRuntime` factory to hold session-scoped state.
5
-
6
- ## index.ts decomposition
7
-
8
- The original monolithic `index.ts` has been decomposed into focused modules:
9
-
10
- ```text
11
- src/
12
- ├── index.ts - slimmed entry point: init, tool registration
13
- ├── runtime.ts - SubagentRuntime: session-scoped state + methods
14
- ├── tools/
15
- │ ├── agent-tool.ts - Agent tool definition, parameter validation, dispatch
16
- │ ├── foreground-runner.ts - foreground execution loop (spinner, streaming, result)
17
- │ ├── background-spawner.ts - background spawn (activity setup, notification wiring)
18
- │ ├── get-result-tool.ts - get_subagent_result tool
19
- │ ├── steer-tool.ts - steer_subagent tool
20
- │ └── helpers.ts - shared tool utilities (textResult, buildDetails, getStatusNote, ...)
21
- ├── handlers/
22
- │ ├── lifecycle.ts - session_start, session_before_switch, session_shutdown
23
- │ └── tool-start.ts - tool_execution_start handler
24
- ├── notification.ts - completion nudges, custom renderer
25
- ├── renderer.ts - notification TUI component
26
- ├── ui/agent-menu.ts - /agents slash command menu (orchestration, listing, settings)
27
- ├── ui/agent-config-editor.ts - agent detail view (edit/delete/eject/disable/enable)
28
- ├── ui/agent-creation-wizard.ts - agent creation (AI-generation and manual-form)
29
- ├── ui/agent-file-ops.ts - AgentFileOps interface + FsAgentFileOps implementation
30
- ├── service-adapter.ts - SubagentsService implementation wrapping AgentManager
31
- └── (existing domain modules unchanged)
32
- ```
33
-
34
- Each extracted module receives narrow constructor-injected dependencies rather than closing over module-level state.
35
- Handlers call methods on narrow runtime interfaces - no raw field writes, no `widget!` reach-throughs.
36
-
37
- ## Related issues
38
-
39
- - #54 — Decompose index.ts
40
- - #69 — SubagentRuntime factory
41
- - #70 — Handler extraction
42
- - #87 — Runtime methods