@gotgenes/pi-subagents 17.5.0 → 18.0.1
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.
- package/CHANGELOG.md +20 -0
- package/README.md +22 -31
- package/docs/architecture/architecture.md +24 -19
- package/docs/decisions/0004-reconsider-ui-direction.md +17 -0
- package/docs/plans/0441-remove-agent-definition-management-subtree.md +180 -0
- package/docs/plans/0442-dissolve-agents-conversation-viewer.md +195 -0
- package/docs/plans/0443-consolidate-remaining-test-clone-families.md +268 -0
- package/docs/plans/0470-refresh-readme-command-surface.md +159 -0
- package/docs/retro/0441-remove-agent-definition-management-subtree.md +97 -0
- package/docs/retro/0442-dissolve-agents-conversation-viewer.md +108 -0
- package/docs/retro/0443-consolidate-remaining-test-clone-families.md +28 -0
- package/docs/retro/0463-file-snapshot-source-evicted-agents.md +54 -0
- package/docs/retro/0470-refresh-readme-command-surface.md +40 -0
- package/package.json +1 -1
- package/src/index.ts +4 -31
- package/src/ui/session-navigation.ts +1 -1
- package/src/ui/session-navigator.ts +3 -3
- package/src/ui/subagents-settings.ts +2 -2
- package/src/ui/agent-config-editor.ts +0 -199
- package/src/ui/agent-creation-wizard.ts +0 -233
- package/src/ui/agent-file-ops.ts +0 -59
- package/src/ui/agent-file-writer.ts +0 -55
- package/src/ui/agent-menu.ts +0 -331
- package/src/ui/conversation-viewer.ts +0 -241
- package/src/ui/message-formatters.ts +0 -195
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
---
|
|
2
|
+
issue: 442
|
|
3
|
+
issue_title: "pi-subagents: dissolve /agents and remove the conversation-viewer subtree"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Dissolve `/agents` and remove the conversation-viewer subtree
|
|
7
|
+
|
|
8
|
+
## Release Recommendation
|
|
9
|
+
|
|
10
|
+
**Release:** mid-batch — defer (batch "dissolve-agents"); confirm at ship time
|
|
11
|
+
|
|
12
|
+
This is Phase 19 Step 5, the first of the two deletion commits in release batch "dissolve-agents" (Steps 5–6).
|
|
13
|
+
The batch tail is Step 6 ([#441]); per the architecture roadmap's `Release batches` subsection the two ship together, and the operator has confirmed: do not release until both [#442] and [#441] have landed on `main`.
|
|
14
|
+
Hold the release-please PR open after this issue merges; the release is cut when [#441] (the tail) lands.
|
|
15
|
+
|
|
16
|
+
## Problem Statement
|
|
17
|
+
|
|
18
|
+
Phase 19 Steps 2–4 re-homed all four `/agents` menu responsibilities: settings moved to the `/subagents:settings` command, running-agent visibility moved to the background widget, and session viewing moved to native session navigation (`/subagents:sessions`).
|
|
19
|
+
With those replacements live, the `/agents` command and everything reachable only from `agent-menu.ts` is an orphaned subtree.
|
|
20
|
+
This issue performs the first of two terminal-cut deletions: dissolve the `/agents` command and delete the conversation-viewer subtree (`agent-menu.ts`, `conversation-viewer.ts`, `message-formatters.ts`, and their tests).
|
|
21
|
+
Deleting the hub `agent-menu.ts` wholesale — rather than surgically narrowing it once per option — is what orphans the definition-management leaves, so the hub must go first (it statically imports the wizard, editor, and file-ops, and dynamically imports the viewer).
|
|
22
|
+
|
|
23
|
+
## Goals
|
|
24
|
+
|
|
25
|
+
- Remove the `/agents` slash command and its menu hub (`agent-menu.ts`).
|
|
26
|
+
- Delete the conversation-viewer subtree: `conversation-viewer.ts` (the bespoke session overlay) and `message-formatters.ts` (its only consumer), plus all three tests.
|
|
27
|
+
- Dewire `index.ts`: drop the `registerCommand("agents", …)` block, the `AgentsMenuHandler` and `FsAgentFileOps` imports/construction, and the now-dead `join` and `buildParentSnapshot` imports.
|
|
28
|
+
- Keep `pnpm run check`, `pnpm run lint`, `pnpm run test`, and `pnpm fallow dead-code` green at every commit by breaking the hub↔leaf type cycle first (see Design Overview).
|
|
29
|
+
- Leave the agent-definition-management leaves (`agent-creation-wizard.ts`, `agent-config-editor.ts`, `agent-file-ops.ts`, `agent-file-writer.ts`) orphaned but compiling, for [#441] to `git rm`.
|
|
30
|
+
|
|
31
|
+
This change is **breaking**: removing the `/agents` command alters observable behavior on upgrade with no user edit.
|
|
32
|
+
The deletion commit uses `feat(pi-subagents)!:` with a `BREAKING CHANGE:` footer naming the replacements (`/subagents:settings`, `/subagents:sessions`, the background widget).
|
|
33
|
+
|
|
34
|
+
## Non-Goals
|
|
35
|
+
|
|
36
|
+
- Deleting the agent-definition-management subtree (`agent-creation-wizard.ts`, `agent-config-editor.ts`, `agent-file-ops.ts`, `agent-file-writer.ts`) and the transient `menu-ui.ts` — that is [#441] (Step 6), the batch tail.
|
|
37
|
+
- Consolidating residual test clone families — that is [#443] (Step 7), which runs after the cut.
|
|
38
|
+
- Cleaning up `test/helpers/ui-stubs.ts` (`makeFileOps`, `makeMenuManager`, `createTestSubagentConfig`) — its helpers still have surviving consumers (the wizard/editor tests) until [#441].
|
|
39
|
+
- The holistic architecture-doc refresh (health-metrics final numbers, the domain Mermaid diagram, the complexity tables, migrating Phase 19 to `docs/architecture/history/`) — deferred to the batch tail [#441] to avoid editing the same analytical tables twice, since they also reference files [#441] deletes.
|
|
40
|
+
|
|
41
|
+
## Background
|
|
42
|
+
|
|
43
|
+
Relevant modules and their current coupling:
|
|
44
|
+
|
|
45
|
+
- `src/ui/agent-menu.ts` (331 LOC) — the `AgentsMenuHandler` god-command; statically imports `AgentConfigEditor` and `AgentCreationWizard` (constructs them), and dynamically imports `ConversationViewer` in `viewAgentConversation`.
|
|
46
|
+
Defines three exported interfaces: `AgentMenuManager`, `AgentMenuSettings`, and `MenuUI`.
|
|
47
|
+
- `src/ui/conversation-viewer.ts` (241 LOC) — the bespoke scrollable session overlay; its only consumer is `agent-menu.ts`'s dynamic `import("./conversation-viewer")`.
|
|
48
|
+
- `src/ui/message-formatters.ts` (195 LOC) — pure per-message-type formatters; its only consumer is `ConversationViewer`.
|
|
49
|
+
- `src/index.ts` — registers the `/agents` command, constructs `AgentsMenuHandler` (wiring in `FsAgentFileOps` and the two agents dirs), and uses `join` + `buildParentSnapshot` only inside that block.
|
|
50
|
+
|
|
51
|
+
The hub↔leaf type cycle (the key constraint):
|
|
52
|
+
|
|
53
|
+
- `agent-menu.ts` value-imports the wizard and editor classes.
|
|
54
|
+
- `agent-creation-wizard.ts` and `agent-config-editor.ts` each `import type { MenuUI } from "#src/ui/agent-menu"` and use `MenuUI` as a parameter type throughout.
|
|
55
|
+
|
|
56
|
+
This is a bidirectional cycle: the hub imports the leaf classes; the leaves import the hub's `MenuUI` type.
|
|
57
|
+
Deleting either subtree first leaves the other half referencing a deleted module, so `tsc --noEmit` (which type-checks all of `src` + `test`) fails.
|
|
58
|
+
The issue's premise that the leaves become "pure orphans" once the hub is gone holds for *runtime* reachability but not at the *type* level — the `MenuUI` back-import keeps them coupled.
|
|
59
|
+
|
|
60
|
+
Constraints from AGENTS.md / package skill:
|
|
61
|
+
|
|
62
|
+
- Each commit must leave the repo in a valid state (`pnpm run check` green).
|
|
63
|
+
- This package builds public `.d.ts` bundles; none of the deleted modules are part of the public surface (`service.ts`, `layered-settings.ts`), so no `verify:public-types` impact.
|
|
64
|
+
- `MenuUI`, `AgentMenuManager`, `AgentMenuSettings` are internal — not exported from any package subpath.
|
|
65
|
+
|
|
66
|
+
## Design Overview
|
|
67
|
+
|
|
68
|
+
Resolve the cycle with a **tidy-first** preparatory move (per the operator's decision and the `code-design` skill's "preparatory refactoring"): relocate the `MenuUI` interface to its own surviving module before deleting the hub.
|
|
69
|
+
|
|
70
|
+
Only `MenuUI` needs to survive the cut — `AgentMenuManager` and `AgentMenuSettings` have no consumers outside the hub (verified) and die with it.
|
|
71
|
+
`MenuUI` is self-contained (its members reference only SDK-shaped primitives), so the extracted module carries no upstream-dependency baggage and introduces no Tell-Don't-Ask or output-argument smell.
|
|
72
|
+
|
|
73
|
+
New module `src/ui/menu-ui.ts`:
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
/** Narrow UI interface — only the ctx.ui methods menu handlers actually call. */
|
|
77
|
+
export interface MenuUI {
|
|
78
|
+
select(title: string, options: string[]): Promise<string | undefined>;
|
|
79
|
+
confirm(title: string, message: string): Promise<boolean>;
|
|
80
|
+
input(title: string, defaultValue?: string): Promise<string | undefined>;
|
|
81
|
+
notify(message: string, level: "info" | "warning" | "error"): void;
|
|
82
|
+
editor(title: string, content: string): Promise<string | undefined>;
|
|
83
|
+
custom<R>(component: any, options?: any): Promise<R>;
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Consumer call sites after the move (the leaves import the relocated type unchanged):
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
// agent-creation-wizard.ts / agent-config-editor.ts
|
|
91
|
+
import type { MenuUI } from "#src/ui/menu-ui";
|
|
92
|
+
async showCreateWizard(ui: MenuUI, parentSnapshot: ParentSnapshot): Promise<void> { … }
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
`menu-ui.ts` is **transient**: after this issue it is imported only by the wizard and editor (both alive until [#441]), so it has live consumers and stays off the fallow dead-code list.
|
|
96
|
+
[#441] deletes the wizard, editor, and `menu-ui.ts` together, so the transient module never outlives its consumers.
|
|
97
|
+
|
|
98
|
+
Two-commit sequence within this issue:
|
|
99
|
+
|
|
100
|
+
1. `refactor(pi-subagents): extract MenuUI to its own module` — pure move; repoints the hub, wizard, and editor imports.
|
|
101
|
+
Green.
|
|
102
|
+
2. `feat(pi-subagents)!: dissolve /agents and remove the conversation-viewer subtree` — delete the three source files + three tests, dewire `index.ts`, update docs.
|
|
103
|
+
Green (wizard/editor now import `MenuUI` from the surviving `menu-ui.ts`; the hub is gone).
|
|
104
|
+
|
|
105
|
+
Edge cases / verifications already confirmed:
|
|
106
|
+
|
|
107
|
+
- `subagents-settings.ts` defines its own `SubagentsSettingsUI` interface — it does **not** import `MenuUI`, so the relocation does not touch the surviving settings command.
|
|
108
|
+
- `test/helpers/ui-stubs.ts`'s `makeMenuUI` is structurally typed and does **not** import the `MenuUI` type, so no test-helper repointing is needed.
|
|
109
|
+
- After dewiring, `join` (node:path) and `buildParentSnapshot` are used nowhere else in `index.ts` (verified) and their imports are removed; `getAgentDir`, `process.cwd`, `registry`, `settings`, and `manager` retain other live uses and stay.
|
|
110
|
+
- `FsAgentFileOps` becomes production-unused after the `index.ts` construction is removed, but `test/ui/agent-file-ops.test.ts` still imports it, so fallow (syntactic import analysis) keeps it off the dead-code list until [#441].
|
|
111
|
+
- Deleting the consumers does not orphan any local export: `formatDuration`/`getDisplayName`/`getModelLabelFromConfig` retain other consumers, and `wrapTextWithAnsi` is an external `@earendil-works/pi-tui` import.
|
|
112
|
+
|
|
113
|
+
## Module-Level Changes
|
|
114
|
+
|
|
115
|
+
Commit 1 — extract `MenuUI` (refactor):
|
|
116
|
+
|
|
117
|
+
- Add `src/ui/menu-ui.ts` — the `MenuUI` interface (moved verbatim from `agent-menu.ts`).
|
|
118
|
+
- `src/ui/agent-menu.ts` — remove the `MenuUI` interface definition; import `MenuUI` from `#src/ui/menu-ui`.
|
|
119
|
+
- `src/ui/agent-creation-wizard.ts` — change `import type { MenuUI } from "#src/ui/agent-menu"` to `from "#src/ui/menu-ui"`.
|
|
120
|
+
- `src/ui/agent-config-editor.ts` — same import repoint.
|
|
121
|
+
|
|
122
|
+
Commit 2 — dissolve `/agents` and delete the viewer subtree (feat!):
|
|
123
|
+
|
|
124
|
+
- Delete `src/ui/agent-menu.ts`, `src/ui/conversation-viewer.ts`, `src/ui/message-formatters.ts`.
|
|
125
|
+
- Delete `test/ui/agent-menu.test.ts`, `test/conversation-viewer.test.ts`, `test/message-formatters.test.ts`.
|
|
126
|
+
- `src/index.ts`:
|
|
127
|
+
- Remove the `import { FsAgentFileOps } from "#src/ui/agent-file-ops"` and `import { AgentsMenuHandler } from "#src/ui/agent-menu"` lines.
|
|
128
|
+
- Remove the now-dead `import { join } from "node:path"` and `import { buildParentSnapshot } from "#src/lifecycle/parent-snapshot"` lines.
|
|
129
|
+
- Remove the `// ---- /agents interactive menu ----` comment, the `agentsMenu` construction, and the `registerCommand("agents", …)` block.
|
|
130
|
+
- Remove the `/agents — Interactive agent management menu` line from the top-of-file `Commands:` doc comment.
|
|
131
|
+
- `packages/pi-subagents/docs/architecture/architecture.md` — update the current-state `ui/` file tree (remove the `agent-menu.ts`, `conversation-viewer.ts`, `message-formatters.ts` entries; add a `menu-ui.ts` entry), and annotate the Step 5 roadmap entry's `Outcome:` to record the actual approach (the `MenuUI` relocation prep; `index.ts` import-removal also drops `join`/`buildParentSnapshot`).
|
|
132
|
+
The structural-analysis tables, domain Mermaid diagram, and health-metrics numbers are deferred to the batch tail [#441] (see Non-Goals).
|
|
133
|
+
- `.pi/skills/package-pi-subagents/SKILL.md` — update the UI domain row: count `13` → `11`, and drop "conversation viewer, /agents menu" from the responsibility description (keep "creation wizard, config editor" — those survive until [#441]).
|
|
134
|
+
|
|
135
|
+
The Step 5 `Outcome:` line in `architecture.md` currently asserts "no edit to doomed files" and "`index.ts` edited once."
|
|
136
|
+
Both are now slightly inaccurate: the tidy-first prep repoints the doomed wizard/editor `MenuUI` import (one line each), and `index.ts` also sheds two now-dead imports.
|
|
137
|
+
The annotation should reflect this, not leave the stale claim.
|
|
138
|
+
|
|
139
|
+
## Test Impact Analysis
|
|
140
|
+
|
|
141
|
+
This is a deletion, not an extraction-for-testability, so no new unit tests are enabled.
|
|
142
|
+
|
|
143
|
+
1. New tests enabled: none.
|
|
144
|
+
2. Tests that become redundant / removed: `test/ui/agent-menu.test.ts`, `test/conversation-viewer.test.ts`, `test/message-formatters.test.ts` (the largest test function by LOC) — they exercise deleted production code and are deleted with it.
|
|
145
|
+
3. Tests that must stay as-is: the wizard/editor tests (`test/ui/agent-creation-wizard.test.ts`, `test/ui/agent-config-editor.test.ts`) keep compiling against the relocated `MenuUI` and survive until [#441]; `test/ui/subagents-settings.test.ts`, the session-navigation tests, and `test/ui/agent-widget.test.ts` pin the replacement surfaces and must stay green (see Invariants at risk).
|
|
146
|
+
|
|
147
|
+
## Invariants at risk
|
|
148
|
+
|
|
149
|
+
The cut removes surfaces whose responsibilities Steps 2–4 already re-homed.
|
|
150
|
+
Each replacement's invariant must remain green after this deletion:
|
|
151
|
+
|
|
152
|
+
- Settings management (Step 2, [#447]) → pinned by `test/ui/subagents-settings.test.ts`.
|
|
153
|
+
The `/subagents:settings` command and `SubagentsSettingsHandler` are untouched here.
|
|
154
|
+
- Running-agent visibility (Step 3, [#444]) → pinned by `test/ui/agent-widget.test.ts`.
|
|
155
|
+
The background widget is untouched.
|
|
156
|
+
- Session viewing (Step 4 / 4a, [#445]) → pinned by the session-navigation / session-navigator tests.
|
|
157
|
+
The `/subagents:sessions` command is untouched.
|
|
158
|
+
|
|
159
|
+
The deletion touches none of those files, so the full suite (minus the three deleted tests) staying green is the verification that no replacement regressed.
|
|
160
|
+
|
|
161
|
+
## Implementation Order
|
|
162
|
+
|
|
163
|
+
This issue has no red→green test cycles (a pure interface move plus deletions verified by the existing suite), so it is a build-style change — the next step is `/build-plan`, not `/tdd-plan`.
|
|
164
|
+
|
|
165
|
+
1. `refactor(pi-subagents): extract MenuUI to its own module`
|
|
166
|
+
- Add `src/ui/menu-ui.ts`; remove the interface from `agent-menu.ts` and import it; repoint the wizard and editor imports.
|
|
167
|
+
- Verify: `pnpm run check`, `pnpm run lint`, `pnpm run test`, `pnpm fallow dead-code` all green.
|
|
168
|
+
2. `feat(pi-subagents)!: dissolve /agents and remove the conversation-viewer subtree`
|
|
169
|
+
- Delete the three source files and three tests; dewire `index.ts`; update `architecture.md` file tree + Step 5 `Outcome:`; update `SKILL.md` UI row.
|
|
170
|
+
- `BREAKING CHANGE:` footer: the `/agents` command is removed; its responsibilities are served by `/subagents:settings` (configure concurrency/turn limits), `/subagents:sessions` (read-only transcript viewing), and the always-on background widget (running-agent visibility).
|
|
171
|
+
- Verify: `pnpm run check`, `pnpm run lint`, `pnpm run test`, `pnpm fallow dead-code` green; confirm `/agents` no longer registers and `menu-ui.ts` retains its wizard/editor consumers.
|
|
172
|
+
|
|
173
|
+
## Risks and Mitigations
|
|
174
|
+
|
|
175
|
+
- Risk: deleting the hub before the leaves breaks `tsc` via the `MenuUI` back-import.
|
|
176
|
+
Mitigation: the tidy-first Commit 1 relocates `MenuUI` to a surviving module so Commit 2 compiles; verified that only the wizard and editor consume `MenuUI` and that `subagents-settings.ts` and `ui-stubs.ts` do not.
|
|
177
|
+
- Risk: `FsAgentFileOps` becomes production-unused and trips `fallow dead-code`.
|
|
178
|
+
Mitigation: verified `test/ui/agent-file-ops.test.ts` still imports it; fallow's syntactic import analysis keeps it live until [#441].
|
|
179
|
+
Run `pnpm fallow dead-code` after Commit 2 to confirm.
|
|
180
|
+
- Risk: the transient `menu-ui.ts` looks like speculative indirection.
|
|
181
|
+
Mitigation: it is short-lived by design (one issue), has two live consumers immediately, and is deleted by the batch tail [#441]; the alternative (inlining a throwaway type into doomed files, or merging [#441] into [#442]) was considered and rejected via the operator decision.
|
|
182
|
+
- Risk: stale architecture docs mid-batch (the domain diagram and tables still show the deleted modules between [#442] and [#441]).
|
|
183
|
+
Mitigation: accepted deliberately — the analytical-table refresh is batched into the tail [#441] to avoid double-editing tables that [#441] also touches; the current-state file tree and SKILL.md count are kept accurate at each commit.
|
|
184
|
+
|
|
185
|
+
## Open Questions
|
|
186
|
+
|
|
187
|
+
None.
|
|
188
|
+
The hub↔leaf type-cycle resolution (relocate `MenuUI`, keep two commits) and the release-timing (defer until [#441] lands) were settled with the operator during planning.
|
|
189
|
+
|
|
190
|
+
[#441]: https://github.com/gotgenes/pi-packages/issues/441
|
|
191
|
+
[#442]: https://github.com/gotgenes/pi-packages/issues/442
|
|
192
|
+
[#443]: https://github.com/gotgenes/pi-packages/issues/443
|
|
193
|
+
[#444]: https://github.com/gotgenes/pi-packages/issues/444
|
|
194
|
+
[#445]: https://github.com/gotgenes/pi-packages/issues/445
|
|
195
|
+
[#447]: https://github.com/gotgenes/pi-packages/issues/447
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
---
|
|
2
|
+
issue: 443
|
|
3
|
+
issue_title: "pi-subagents: consolidate remaining test clone families"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Consolidate remaining test clone families
|
|
7
|
+
|
|
8
|
+
## Release Recommendation
|
|
9
|
+
|
|
10
|
+
**Release:** ship independently
|
|
11
|
+
|
|
12
|
+
This is Phase 19 Step 7 (Track C — test health), tagged `Release: independent` in the architecture roadmap.
|
|
13
|
+
It depends only on the terminal cut (Steps 5–6, [#441] / [#442], both closed) having landed, which it has.
|
|
14
|
+
No other roadmap step is gated on it, so it ships on its own.
|
|
15
|
+
|
|
16
|
+
## Problem Statement
|
|
17
|
+
|
|
18
|
+
`fallow dupes` reports test clone families in `pi-subagents`.
|
|
19
|
+
The issue (written at the Phase 18 end) named five files and a "≤ 10 clone groups (from 16)" target, on the premise that each clone is an extractable shared fixture.
|
|
20
|
+
|
|
21
|
+
Re-running fallow against current `main` (after the terminal cut shifted line numbers and the Phase-19 UI surfaces added new test files) shows the live picture differs from the issue's snapshot.
|
|
22
|
+
There are **16** `pi-subagents` test clone families today, but they split into two kinds:
|
|
23
|
+
|
|
24
|
+
1. Genuine *arrange / fixture / helper* duplication — safe to extract.
|
|
25
|
+
2. The repeated *system-under-test call* (`resolveSpawnConfig`, `assembleSessionConfig`, `schedule`) — which the `testing` skill explicitly says **not** to wrap in a helper just to clear a duplication metric, because the repeated act *is* the test subject.
|
|
26
|
+
|
|
27
|
+
Several of the issue's five named targets fall into category 2.
|
|
28
|
+
The operator confirmed (planning `ask_user`) a **guardrail-first** approach over the **full live set** of clones: extract only genuine fixtures, leave act-clones in place and documented, and address the new Phase-19 UI clones the issue never anticipated.
|
|
29
|
+
|
|
30
|
+
## Goals
|
|
31
|
+
|
|
32
|
+
- Extract genuine (non-act) test duplication into shared or hoisted helpers, following the package's `test/helpers/*.ts` convention.
|
|
33
|
+
- Clear the clone families that are legitimately arrange/fixture/result-extraction boilerplate.
|
|
34
|
+
- Keep the full suite green at every step — the existing tests are the safety net for their own refactor.
|
|
35
|
+
- Reach the issue's `≤ 10` clone-group target *honestly*, without wrapping any system-under-test call.
|
|
36
|
+
- Document the residual act-clones as intentional in the plan, so a future fallow pass does not re-flag them as oversight.
|
|
37
|
+
|
|
38
|
+
## Non-Goals
|
|
39
|
+
|
|
40
|
+
- Do **not** wrap or extract the repeated system-under-test call to clear a clone metric (the `testing`-skill guardrail).
|
|
41
|
+
These act-clones are left in place by design:
|
|
42
|
+
- `test/tools/spawn-config.test.ts` — repeated `resolveSpawnConfig(...)` calls (`dup:9b42a569`, `dup:ef875c08`).
|
|
43
|
+
- `test/session/session-config.test.ts` — repeated `assembleSessionConfig(...)` calls (`dup:539a8ca2`).
|
|
44
|
+
- `test/lifecycle/concurrency-limiter.test.ts` — repeated `schedule(...)` sequences (`dup:ff841f05`).
|
|
45
|
+
- `test/lifecycle/subagent-manager.test.ts` — `spawnBg` + `await promise` act blocks (`dup:29158516`, `dup:082c007e`).
|
|
46
|
+
- `test/lifecycle/subagent.test.ts` — `agent.run()` act block (`dup:a3814745`).
|
|
47
|
+
- `test/tools/get-result-tool.test.ts` — `execute(...)` act block (`dup:230828a8`, 5 lines, marginal).
|
|
48
|
+
- No production-source changes — this is test-only.
|
|
49
|
+
- No change to test *assertions* or behavior coverage; only the arrange/setup ceremony is consolidated.
|
|
50
|
+
- No new fallow rule or config change.
|
|
51
|
+
|
|
52
|
+
## Background
|
|
53
|
+
|
|
54
|
+
- Phase 19 Step 7 in `packages/pi-subagents/docs/architecture/architecture.md` ([#443]) — the roadmap entry, `Release: independent`.
|
|
55
|
+
- The terminal cut ([#441], [#442]) removed `agent-menu.ts`, the conversation viewer, and the definition-management subtree, deleting ~4 of the Phase-18 clone groups automatically and shifting the line numbers in the issue's target list.
|
|
56
|
+
- The Phase-19 replacement surfaces added new test files the issue could not have named: `test/ui/session-navigation.test.ts` and `test/ui/session-navigator.test.ts` ([#445], [#462], [#463]), which carry the largest genuine clone (an identical `makeNavigable` factory duplicated across both files).
|
|
57
|
+
- Shared-fixture convention: `test/helpers/<name>.ts` exporting named helpers, imported via the `#test/helpers/<name>` path alias, each with a companion `<name>.test.ts` (e.g. `make-subagent.ts` + `make-subagent.test.ts`).
|
|
58
|
+
- The `testing` skill rule that drives the guardrail: "Do not wrap the system-under-test call in a helper to eliminate a duplication-metric clone — the repeated act is the test subject, not duplication to remove."
|
|
59
|
+
|
|
60
|
+
## Design Overview
|
|
61
|
+
|
|
62
|
+
### Clone classification (live fallow output vs. issue)
|
|
63
|
+
|
|
64
|
+
| Fingerprint | Location | Kind | Disposition |
|
|
65
|
+
| -------------- | ----------------------------------------------------------------------------- | ---------------------------------------------- | --------------------------- |
|
|
66
|
+
| `dup:1d5dc276` | `ui/agent-widget.test.ts` :229 / :292 | duplicated `makeWidget` helper | **Extract** (hoist) |
|
|
67
|
+
| `dup:e29e4749` | `ui/session-navigation.test.ts` :23 / `ui/session-navigator.test.ts` :47 | duplicated `makeNavigable` factory (identical) | **Extract** (shared helper) |
|
|
68
|
+
| `dup:6268a42f` | `ui/session-navigator.test.ts` :201 / :229 | captured-overlay invocation boilerplate | **Extract** (local helper) |
|
|
69
|
+
| `dup:ea0a1bce` | `ui/session-navigator.test.ts` :220 / :243 | captured-overlay invocation boilerplate | **Extract** (local helper) |
|
|
70
|
+
| `dup:b0d55079` | `lifecycle/subagent-manager.test.ts` :92 / :109 | `resultConsumed`-observer arrange | **Extract** (local helper) |
|
|
71
|
+
| `dup:080c5017` | `lifecycle/subagent.test.ts` :257 / :273 | "ready subagent" arrange | **Extract** (local helper) |
|
|
72
|
+
| `dup:5d8dbd48` | `lifecycle/subagent-manager.test.ts` :376 / `lifecycle/subagent.test.ts` :717 | resume-events mock body (cross-file) | **Extract** (shared helper) |
|
|
73
|
+
| `dup:f4c08c00` | `lifecycle/workspace-bracket.test.ts` :90 / :97 | prepared-bracket arrange | **Extract** (local helper) |
|
|
74
|
+
| `dup:9b42a569` | `tools/spawn-config.test.ts` :43 / :56 | `resolveSpawnConfig` act | Leave (Non-Goal) |
|
|
75
|
+
| `dup:ef875c08` | `tools/spawn-config.test.ts` :81 / :95 | `resolveSpawnConfig` act | Leave (Non-Goal) |
|
|
76
|
+
| `dup:539a8ca2` | `session/session-config.test.ts` :131 / :151 | `assembleSessionConfig` act | Leave (Non-Goal) |
|
|
77
|
+
| `dup:ff841f05` | `lifecycle/concurrency-limiter.test.ts` :21 / :148 | `schedule` act | Leave (Non-Goal) |
|
|
78
|
+
| `dup:29158516` | `lifecycle/subagent-manager.test.ts` :335 / :383 | `spawnBg` + await act | Leave (Non-Goal) |
|
|
79
|
+
| `dup:082c007e` | `lifecycle/subagent-manager.test.ts` :410 / :422 | `spawnBg` + await act | Leave (Non-Goal) |
|
|
80
|
+
| `dup:a3814745` | `lifecycle/subagent.test.ts` :504 / :533 | `agent.run()` act | Leave (Non-Goal) |
|
|
81
|
+
| `dup:230828a8` | `tools/get-result-tool.test.ts` :81 / :89 | `execute` act (5 lines) | Leave (Non-Goal) |
|
|
82
|
+
|
|
83
|
+
Extracting the eight **Extract** families clears those fingerprints and drops the count from 16 to **8** — below the issue's `≤ 10` target — with no act-clone wrapped. (The four primary UI/lifecycle extractions alone reach 10; the cross-file and workspace-bracket arrange extractions take it to 8.)
|
|
84
|
+
|
|
85
|
+
### Shared-helper extractions (cross-file → `test/helpers/`)
|
|
86
|
+
|
|
87
|
+
Two clones span two files each, so their helpers must live in `test/helpers/` (the package convention for shared fixtures, with a companion test):
|
|
88
|
+
|
|
89
|
+
`test/helpers/make-navigable.ts`:
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
import type { NavigableSubagent } from "#src/ui/session-navigation";
|
|
93
|
+
|
|
94
|
+
export function makeNavigable(overrides: Partial<NavigableSubagent> = {}): NavigableSubagent {
|
|
95
|
+
return {
|
|
96
|
+
id: "agent-1",
|
|
97
|
+
type: "general-purpose",
|
|
98
|
+
description: "Test task",
|
|
99
|
+
status: "completed",
|
|
100
|
+
startedAt: 1000,
|
|
101
|
+
completedAt: 4000,
|
|
102
|
+
toolUses: 2,
|
|
103
|
+
activeTools: new Map(),
|
|
104
|
+
responseText: "",
|
|
105
|
+
agentMessages: [],
|
|
106
|
+
isSessionReady: () => true,
|
|
107
|
+
subscribeToUpdates: vi.fn(() => () => {}),
|
|
108
|
+
getToolDefinition: vi.fn(() => undefined),
|
|
109
|
+
...overrides,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
The two source copies are byte-identical (verified with `diff`), so this is a pure lift with no reconciliation.
|
|
115
|
+
Both call sites import it: `import { makeNavigable } from "#test/helpers/make-navigable";`.
|
|
116
|
+
|
|
117
|
+
`test/helpers/mock-session.ts` (extend the existing helper) — add a resume-events emitter for `dup:5d8dbd48`:
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
export function emitResumeUsageAndCompaction(session: MockSession): void {
|
|
121
|
+
session.emit({ type: "message_end", message: { role: "assistant", usage: { input: 70, output: 30, cacheWrite: 5 } } });
|
|
122
|
+
session.emit({ type: "compaction_end", aborted: false, result: { tokensBefore: 999 }, reason: "overflow" });
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Both `subagent-manager.test.ts` and `subagent.test.ts` set this inside a `mockImplementation(async () => { …; return "second"; })`, so the helper emits the events and each call site keeps its own `mockImplementation` wrapper and `return`. (Adding to the already-shared `mock-session.ts` avoids a one-function new module; its companion `mock-session.test.ts` gains a case.)
|
|
127
|
+
|
|
128
|
+
### Local-helper extractions (single-file)
|
|
129
|
+
|
|
130
|
+
These stay file-local (the convention reserves `test/helpers/` for cross-file sharing); each is a `function` declared once at the top of its `describe`/module and called from each test, with the **act left explicit** in every test:
|
|
131
|
+
|
|
132
|
+
- `ui/agent-widget.test.ts` — the `makeWidget(agents)` helper is currently declared *twice* (one per `describe`).
|
|
133
|
+
Hoist a single copy to module scope (above the first `describe`) and delete the second.
|
|
134
|
+
The second `describe` uses `vi.useFakeTimers()` in `beforeEach`, but `makeWidget` does not touch timers, so a module-scope definition serves both.
|
|
135
|
+
- `ui/session-navigator.test.ts` — extract a `renderCapturedOverlay(ui): string[]` helper that performs the repeated `const factory = ui.custom.mock.calls[0][0] as (…) => Component; return factory(mockTui(), ansiTheme(), undefined, vi.fn()).render(80);`.
|
|
136
|
+
This is *result extraction* (reading what the SUT produced), not the act (`new SessionNavigatorHandler().handle(…)` stays explicit in each test).
|
|
137
|
+
The `#423` reactive-consumer invariant assertion (`expect(record.getToolDefinition).not.toHaveBeenCalled()`) lives in the test body, untouched by the helper.
|
|
138
|
+
- `lifecycle/subagent-manager.test.ts` — extract a local `seedResultConsumedObserver()` returning `{ manager, record, seenConsumed: () => boolean | undefined }` for the two Bug-1 tests; the act (`markConsumed()` before/after `await record.promise`) stays in each test.
|
|
139
|
+
- `lifecycle/subagent.test.ts` — extract a local `makeReadySubagent()` returning `{ agent }` (build `makeSubagent()`, push a message onto a `createMockSession()`, wire `createSubagentSessionStub`/`toSubagentSession`); the act (reading `agent.messages` vs `agent.agentMessages`) stays in each test.
|
|
140
|
+
- `lifecycle/workspace-bracket.test.ts` — extract a local `preparedBracket(addendum?)` async helper that builds the workspace, constructs the `WorkspaceBracket`, and awaits `prepare(ctx)`, returning the bracket; the act (`bracket.dispose(outcome)`) stays in each test.
|
|
141
|
+
|
|
142
|
+
### Guardrail rationale (why the act-clones stay)
|
|
143
|
+
|
|
144
|
+
`spawn-config.test.ts` already extracts its arrange (`makeModelInfo`, `testRegistry`, `defaultSettings`); the only remaining duplication is the four-argument `resolveSpawnConfig(...)` call — the SUT.
|
|
145
|
+
`session-config.test.ts`'s clone is the six-argument `assembleSessionConfig(...)` SUT call.
|
|
146
|
+
`concurrency-limiter.test.ts`'s clone is the `schedule(...)` act sequence.
|
|
147
|
+
Wrapping any of these would hide the test subject behind a helper, exactly the anti-pattern the `testing` skill names.
|
|
148
|
+
They are recorded in Non-Goals so a later fallow pass reads them as deliberate.
|
|
149
|
+
|
|
150
|
+
### Design-review check
|
|
151
|
+
|
|
152
|
+
The `design-review` checklist (dependency width, Law of Demeter, output arguments, shared-interface changes) targets production wiring.
|
|
153
|
+
This change touches only test arrange code and introduces no production collaborator or shared-interface change, so the checklist finds nothing applicable.
|
|
154
|
+
The new `makeNavigable` helper follows ISP — it returns a full `NavigableSubagent` because both consumers (`listNavigableAgents` fixtures and `SessionNavigatorHandler` records) need the whole shape; there is no unused-field smell.
|
|
155
|
+
|
|
156
|
+
## Module-Level Changes
|
|
157
|
+
|
|
158
|
+
New files:
|
|
159
|
+
|
|
160
|
+
- `packages/pi-subagents/test/helpers/make-navigable.ts` — shared `makeNavigable` factory.
|
|
161
|
+
- `packages/pi-subagents/test/helpers/make-navigable.test.ts` — companion test (per convention).
|
|
162
|
+
|
|
163
|
+
Changed files:
|
|
164
|
+
|
|
165
|
+
- `packages/pi-subagents/test/helpers/mock-session.ts` — add `emitResumeUsageAndCompaction(session)`.
|
|
166
|
+
- `packages/pi-subagents/test/helpers/mock-session.test.ts` — add a case for the new emitter.
|
|
167
|
+
- `packages/pi-subagents/test/ui/session-navigation.test.ts` — delete local `makeNavigable`, import the shared one.
|
|
168
|
+
- `packages/pi-subagents/test/ui/session-navigator.test.ts` — delete local `makeNavigable`, import the shared one; add `renderCapturedOverlay` local helper and migrate its two clone sites.
|
|
169
|
+
- `packages/pi-subagents/test/ui/agent-widget.test.ts` — hoist `makeWidget` to a single module-scope definition; delete the duplicate.
|
|
170
|
+
- `packages/pi-subagents/test/lifecycle/subagent-manager.test.ts` — add `seedResultConsumedObserver` local helper (migrate `:92`/`:109`); migrate the `dup:5d8dbd48` resume-mock site to `emitResumeUsageAndCompaction`.
|
|
171
|
+
- `packages/pi-subagents/test/lifecycle/subagent.test.ts` — add `makeReadySubagent` local helper (migrate `:257`/`:273`); migrate the `dup:5d8dbd48` resume-mock site to `emitResumeUsageAndCompaction`.
|
|
172
|
+
- `packages/pi-subagents/test/lifecycle/workspace-bracket.test.ts` — add `preparedBracket` local helper; migrate the four construct-and-prepare sites.
|
|
173
|
+
|
|
174
|
+
Documentation:
|
|
175
|
+
|
|
176
|
+
- `packages/pi-subagents/docs/architecture/architecture.md` — Phase 19 Step 7 currently states "Outcome: test clone groups ≤ 10 (from 16); `subagent-manager.test.ts` uses shared factory helpers."
|
|
177
|
+
Update the Outcome to record the achieved count (8) and that the residual six families are intentional act-clones (left per the `testing` guardrail), so the roadmap and fallow stay reconciled.
|
|
178
|
+
No layout/complexity table references these test files, so no other architecture edit is needed.
|
|
179
|
+
- No `package-pi-subagents` SKILL.md reference to these helpers or counts — grep confirms no doc symbol to update beyond the architecture Outcome line.
|
|
180
|
+
|
|
181
|
+
## Test Impact Analysis
|
|
182
|
+
|
|
183
|
+
1. **New lower-level tests enabled.**
|
|
184
|
+
`make-navigable.test.ts` and the new `mock-session.test.ts` case pin the shared helpers' default shapes directly — previously each consumer test re-encoded the defaults inline.
|
|
185
|
+
These are the only genuinely new tests; the rest is arrange consolidation.
|
|
186
|
+
2. **Tests made redundant.**
|
|
187
|
+
None are removed.
|
|
188
|
+
The behavior assertions in every migrated test stay exactly as-is; only their arrange/setup lines collapse into a helper call.
|
|
189
|
+
The local copies of `makeNavigable`/`makeWidget` are deleted (duplication removed), not their tests.
|
|
190
|
+
3. **Tests that must stay as-is.**
|
|
191
|
+
All act-clone tests (Non-Goals list) keep their explicit SUT call.
|
|
192
|
+
The `session-navigator.test.ts` `#423` reactive-consumer assertions stay in the test body; `renderCapturedOverlay` only factors out the overlay-rendering boilerplate, not the assertions.
|
|
193
|
+
|
|
194
|
+
## Invariants at risk
|
|
195
|
+
|
|
196
|
+
- **`#423` reactive-consumer invariant** (`SessionNavigatorHandler` sources the transcript and never reads tool definitions off the record): pinned by `expect(record.getToolDefinition).not.toHaveBeenCalled()` in `session-navigator.test.ts`.
|
|
197
|
+
The `renderCapturedOverlay` extraction must leave that assertion in the test body, not absorb it.
|
|
198
|
+
- **Resume usage/compaction accumulation** (`#420`/`#421`/Phase 17 observer lifecycle): pinned by the resume tests in both `subagent-manager.test.ts` and `subagent.test.ts`.
|
|
199
|
+
`emitResumeUsageAndCompaction` must emit the identical event payloads (`input:70 output:30 cacheWrite:5`, `tokensBefore:999`, `reason:"overflow"`); the migrated tests assert on these exact numbers, so a value drift would surface as a red test in the same step.
|
|
200
|
+
- **Widget background-only filter** (`#444`/`#423`): the hoisted `makeWidget` must keep the `runInBackground: true` default merge (`{ invocation: { runInBackground: true }, ...a }`) — both `describe` copies already share it, so the hoist preserves it verbatim.
|
|
201
|
+
|
|
202
|
+
Each invariant is already covered by an existing assertion; no new pinning test is required beyond the helper companion tests.
|
|
203
|
+
|
|
204
|
+
## TDD Order
|
|
205
|
+
|
|
206
|
+
This is a test-only refactor: there is no new product behavior, so the "green" gate at each step is the **existing suite staying green** after the arrange is consolidated.
|
|
207
|
+
Each step is independently committable and leaves the suite green.
|
|
208
|
+
Run the affected file(s) with `pnpm --filter @gotgenes/pi-subagents exec vitest run <path>` and the full suite before the final commit (shared `test/helpers` changes touch multiple files).
|
|
209
|
+
|
|
210
|
+
1. **Shared `makeNavigable` fixture.**
|
|
211
|
+
Add `test/helpers/make-navigable.ts` and `make-navigable.test.ts` (companion: assert default shape + an override).
|
|
212
|
+
Delete the two local copies in `session-navigation.test.ts` / `session-navigator.test.ts` and import from `#test/helpers/make-navigable`.
|
|
213
|
+
Run both UI files green.
|
|
214
|
+
Commit: `test(pi-subagents): extract shared makeNavigable test fixture`.
|
|
215
|
+
2. **`agent-widget` makeWidget hoist.**
|
|
216
|
+
Hoist one `makeWidget` to module scope; delete the duplicate in the second `describe`.
|
|
217
|
+
Run `agent-widget.test.ts` green.
|
|
218
|
+
Commit: `test(pi-subagents): hoist duplicated makeWidget helper`.
|
|
219
|
+
3. **`session-navigator` captured-overlay helper.**
|
|
220
|
+
Add `renderCapturedOverlay(ui)` and migrate the two clone sites (`dup:6268a42f`, `dup:ea0a1bce`), keeping the `#423` assertions inline.
|
|
221
|
+
Run `session-navigator.test.ts` green.
|
|
222
|
+
Commit: `test(pi-subagents): extract captured-overlay render helper`.
|
|
223
|
+
4. **`subagent-manager` resultConsumed arrange + resume-events emitter.**
|
|
224
|
+
Add `emitResumeUsageAndCompaction` to `mock-session.ts` (+ companion case).
|
|
225
|
+
Add local `seedResultConsumedObserver` and migrate `:92`/`:109`.
|
|
226
|
+
Migrate the resume-mock site (`dup:5d8dbd48` manager half) to the emitter.
|
|
227
|
+
Run `subagent-manager.test.ts` + `mock-session.test.ts` green.
|
|
228
|
+
Commit: `test(pi-subagents): consolidate subagent-manager arrange helpers`.
|
|
229
|
+
5. **`subagent` ready-subagent arrange + resume-events emitter.**
|
|
230
|
+
Add local `makeReadySubagent` and migrate `:257`/`:273`.
|
|
231
|
+
Migrate the resume-mock site (`dup:5d8dbd48` subagent half) to `emitResumeUsageAndCompaction`.
|
|
232
|
+
Run `subagent.test.ts` green (this clears the cross-file `dup:5d8dbd48` once both halves use the emitter).
|
|
233
|
+
Commit: `test(pi-subagents): consolidate subagent ready-state arrange`.
|
|
234
|
+
6. **`workspace-bracket` prepared-bracket arrange.**
|
|
235
|
+
Add local `preparedBracket(addendum?)` and migrate the four construct-and-prepare sites.
|
|
236
|
+
Run `workspace-bracket.test.ts` green.
|
|
237
|
+
Commit: `test(pi-subagents): extract preparedBracket setup helper`.
|
|
238
|
+
7. **Verify + document.**
|
|
239
|
+
Run the full suite, `pnpm run check`, `pnpm run lint`, and `pnpm fallow dupes --workspace @gotgenes/pi-subagents` to confirm the eight target fingerprints are gone and the count is ≤ 10.
|
|
240
|
+
Update the Phase 19 Step 7 Outcome line in `architecture.md` to the achieved count and the intentional-residual note.
|
|
241
|
+
Commit: `docs(pi-subagents): reconcile Phase 19 Step 7 outcome with achieved clone count`.
|
|
242
|
+
|
|
243
|
+
## Risks and Mitigations
|
|
244
|
+
|
|
245
|
+
- **Risk: hoisting `makeWidget` past the fake-timers `beforeEach` changes timing.**
|
|
246
|
+
Mitigation: `makeWidget` constructs objects only (no timer calls); the `vi.useFakeTimers()` lives in the second `describe`'s `beforeEach`, unaffected by where the helper is declared.
|
|
247
|
+
Step 2 runs the file green to confirm.
|
|
248
|
+
- **Risk: the resume-events emitter drifts from one of the two call sites' expected numbers.**
|
|
249
|
+
Mitigation: both sites currently use identical payloads (verified); the migrated tests assert the exact numbers, so any drift fails red in steps 4–5.
|
|
250
|
+
- **Risk: a `test/helpers` change silently breaks an unrelated importer.**
|
|
251
|
+
Mitigation: `mock-session.ts` is widely imported; the change is purely additive (new export), and step 4 runs the full suite.
|
|
252
|
+
- **Risk: orphaned imports after deleting local helpers (Biome `noUnusedImports` is warning-level).**
|
|
253
|
+
Mitigation: after each deletion, re-check the file's imports (e.g. `vi` may still be used elsewhere; `NavigableSubagent` import in the UI files is type-only and still referenced).
|
|
254
|
+
The step 7 `pnpm run lint` is the backstop.
|
|
255
|
+
- **Risk: fallow re-flags the intentional act-clones in a future audit.**
|
|
256
|
+
Mitigation: the Non-Goals list and the architecture Outcome note record them as deliberate.
|
|
257
|
+
|
|
258
|
+
## Open Questions
|
|
259
|
+
|
|
260
|
+
- None.
|
|
261
|
+
The guardrail-first / full-live-set scope was settled via the planning `ask_user`; no follow-up issue is warranted because the residual act-clones are intentional, not deferred work.
|
|
262
|
+
|
|
263
|
+
[#441]: https://github.com/gotgenes/pi-packages/issues/441
|
|
264
|
+
[#442]: https://github.com/gotgenes/pi-packages/issues/442
|
|
265
|
+
[#443]: https://github.com/gotgenes/pi-packages/issues/443
|
|
266
|
+
[#445]: https://github.com/gotgenes/pi-packages/issues/445
|
|
267
|
+
[#462]: https://github.com/gotgenes/pi-packages/issues/462
|
|
268
|
+
[#463]: https://github.com/gotgenes/pi-packages/issues/463
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
---
|
|
2
|
+
issue: 470
|
|
3
|
+
issue_title: "pi-subagents: README still documents the removed /agents command and omits /subagents:settings and /subagents:sessions"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Refresh pi-subagents README to the post-Phase-19 command surface
|
|
7
|
+
|
|
8
|
+
## Release Recommendation
|
|
9
|
+
|
|
10
|
+
**Release:** ship independently
|
|
11
|
+
|
|
12
|
+
This is a standalone documentation fix.
|
|
13
|
+
It is not a member of any architecture-roadmap step or `Release: batch` — the `dissolve-agents` batch (Steps 5–6, [#442]/[#441]) already shipped as `pi-subagents-v18.0.0`, and this issue corrects README staleness that batch left behind.
|
|
14
|
+
There is no code change and nothing to batch with, so it ships on its own.
|
|
15
|
+
|
|
16
|
+
## Problem Statement
|
|
17
|
+
|
|
18
|
+
The Phase 19 terminal cut ([#442], [#441]) removed the `/agents` command, the bespoke conversation viewer, and the agent creation wizard / config editor, replacing them with `/subagents:settings`, `/subagents:sessions`, and the always-on background widget.
|
|
19
|
+
`packages/pi-subagents/README.md` was never updated and still documents the deleted surface as if it were live.
|
|
20
|
+
This shipped to npm with `pi-subagents-v18.0.0`, so the published package's README actively misleads users toward commands and menu actions that no longer exist.
|
|
21
|
+
|
|
22
|
+
## Goals
|
|
23
|
+
|
|
24
|
+
- Replace every reference to the removed `/agents` interactive menu with the current focused commands `/subagents:settings` and `/subagents:sessions`.
|
|
25
|
+
- Remove the **Conversation viewer** feature bullet — the live-scrolling overlay was deleted; transcript viewing is now served by `/subagents:sessions`.
|
|
26
|
+
- Remove the **eject** customization story from the Default Agent Types section — the eject/disable/enable/edit/delete menu is gone; customization is now "override by creating `.pi/agents/<name>.md`" and disabling stays `enabled: false` frontmatter (per ADR-0004 Decision C).
|
|
27
|
+
- Rewrite the **Commands** section to document the two real commands instead of the deleted `/agents` menu tree.
|
|
28
|
+
- Correct the **Persistent Settings** section's `/agents` → Settings references to `/subagents:settings`.
|
|
29
|
+
- Correct the **Events** table's `subagents:settings_changed` description (currently "`/agents` → Settings mutation").
|
|
30
|
+
- Add a feature bullet (or amend an existing one) so the read-only session navigation surface (`/subagents:sessions`) is discoverable in the Features list, since the deleted Conversation viewer bullet was its only nearby mention.
|
|
31
|
+
|
|
32
|
+
## Non-Goals
|
|
33
|
+
|
|
34
|
+
- No source, test, or behavior changes — this is a pure documentation edit.
|
|
35
|
+
`src/`, `test/`, the architecture doc, and the ADRs are already accurate (architecture.md lines 405/559 already describe the Phase 19 outcome) and are not touched.
|
|
36
|
+
- No rewrite of accurate sections (Quick Start, UI widget render examples, Default Agent Types table, Custom Agents, Tools, Graceful Max Turns, Concurrency, Worktree Isolation, migration notes, For Extension Authors).
|
|
37
|
+
- No new screenshots or media.
|
|
38
|
+
The widget render examples in the **UI** section already describe the background-only widget accurately and stay as-is.
|
|
39
|
+
- No change to the `subagents.json` settings-file layering description (global `~/.pi/agent/subagents.json` + project `.pi/subagents.json`) — that mechanism is unchanged; only the command name that writes the project file changed.
|
|
40
|
+
|
|
41
|
+
## Background
|
|
42
|
+
|
|
43
|
+
Relevant current surface (verified against `src/index.ts`):
|
|
44
|
+
|
|
45
|
+
- `pi.registerCommand("subagents:settings", …)` → `SubagentsSettingsHandler.handle({ ui })` — interactive list to set max concurrency, default max turns, and grace turns at runtime (`src/ui/subagents-settings.ts`).
|
|
46
|
+
This is the re-homed Settings job from the old `/agents` menu; it still persists to the same `subagents.json` files.
|
|
47
|
+
- `pi.registerCommand("subagents:sessions", …)` → `SessionNavigatorHandler.handle({ … agents, evicted, registry, cwd, readFile })` — read-only transcript navigation over `manager.listAgents()` and `manager.listEvicted()`, so any subagent (live or evicted) is navigable (`src/ui/session-navigation.ts`, `session-navigator.ts`).
|
|
48
|
+
|
|
49
|
+
ADR-0004 Decision C (`docs/decisions/0004-reconsider-ui-direction.md`) is the authority for the customization story the README must now tell:
|
|
50
|
+
|
|
51
|
+
- Create-new-agent wizard → removed.
|
|
52
|
+
An operator generates a new agent `.md` by asking a Pi session directly or by writing the file in an editor.
|
|
53
|
+
- Agent-types list + config editor → removed.
|
|
54
|
+
Viewing/editing definitions is done by opening the `.md` files in an editor/IDE.
|
|
55
|
+
- The eject convenience no longer exists; overriding a default agent is done by creating `.pi/agents/<name>.md` with the same name, and disabling stays `enabled: false` frontmatter.
|
|
56
|
+
|
|
57
|
+
AGENTS.md constraint that applies: this is a single-package README change, so it lives in `packages/pi-subagents/docs/plans/`.
|
|
58
|
+
The README documents commands, not module filenames, which is exactly why the Phase 19 module-name doc-staleness check missed it (the issue's own root-cause note, Refs [#442]/[#441]).
|
|
59
|
+
|
|
60
|
+
## Design Overview
|
|
61
|
+
|
|
62
|
+
Pure prose edit, no decision model or data shapes.
|
|
63
|
+
The README is restructured section-by-section to describe the live surface.
|
|
64
|
+
The one structural choice is how to present the two commands in the **Commands** section: keep the existing two-column command table (`| Command | Description |`) with two rows, then a short subsection per command describing what it opens, instead of the old single-command-plus-menu-tree layout.
|
|
65
|
+
|
|
66
|
+
### Commands section — target shape (illustrative)
|
|
67
|
+
|
|
68
|
+
```markdown
|
|
69
|
+
## Commands
|
|
70
|
+
|
|
71
|
+
| Command | Description |
|
|
72
|
+
| --------------------- | ------------------------------------------------------ |
|
|
73
|
+
| `/subagents:settings` | Configure subagent settings (concurrency, turn limits) |
|
|
74
|
+
| `/subagents:sessions` | View a subagent's session transcript (read-only) |
|
|
75
|
+
|
|
76
|
+
### `/subagents:settings`
|
|
77
|
+
|
|
78
|
+
Interactive list to tune runtime settings — max concurrency, default max turns, and grace turns.
|
|
79
|
+
Changes persist across pi restarts (see Persistent Settings).
|
|
80
|
+
|
|
81
|
+
### `/subagents:sessions`
|
|
82
|
+
|
|
83
|
+
Pick any subagent — running or already evicted — and read its full session transcript in pi's native per-entry viewer.
|
|
84
|
+
Read-only: no steering, no session takeover (steering lives in the `steer_subagent` tool).
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
The command descriptions in the table are copied verbatim from the `registerCommand` calls in `src/index.ts` so the README matches what `/help` shows.
|
|
88
|
+
|
|
89
|
+
### Customization story — Default Agent Types section
|
|
90
|
+
|
|
91
|
+
Replace the eject sentence (line 119) with two retained mechanisms only:
|
|
92
|
+
|
|
93
|
+
```markdown
|
|
94
|
+
Default agents can be **overridden** by creating a `.md` file with the same name (e.g. `.pi/agents/general-purpose.md`), or **disabled** per-project with `enabled: false` frontmatter.
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
(The "ejected … to export them as `.md` files" clause is dropped entirely — there is no eject UI to produce the export.)
|
|
98
|
+
|
|
99
|
+
## Module-Level Changes
|
|
100
|
+
|
|
101
|
+
Single file: `packages/pi-subagents/README.md`.
|
|
102
|
+
Line numbers are against the current README (from the issue's "Affected lines"); each is a prose edit, not a code change.
|
|
103
|
+
|
|
104
|
+
1. **Line 21 — Features list, Conversation viewer bullet.**
|
|
105
|
+
Remove the `**Conversation viewer**` bullet (it describes selecting an agent in `/agents` to open a live overlay).
|
|
106
|
+
In its place, add a bullet for read-only session navigation, e.g. `**Session transcripts** — open any subagent's full session transcript (running or evicted) in a read-only viewer via /subagents:sessions`.
|
|
107
|
+
2. **Line 119 — Default Agent Types, eject sentence.**
|
|
108
|
+
Reword to drop eject; keep override + disable (see Design Overview snippet).
|
|
109
|
+
3. **Lines ~226–303 — Commands + Persistent Settings sections.**
|
|
110
|
+
- Rewrite the **Commands** section (table row `/agents` and the entire interactive-menu code block + bullet list, lines ~228–252) to document `/subagents:settings` and `/subagents:sessions` per the target shape above.
|
|
111
|
+
- In **Persistent Settings**, replace each `/agents` → Settings reference (lines 277, 281, 283, 301) with `/subagents:settings`, and "the `/agents` menu never writes here" (line 281) with "the `/subagents:settings` command never writes here", and "without ever touching the menu" (line 300) with "without ever touching the command".
|
|
112
|
+
- Line 303 failure-behavior sentence: change "the `/agents` toast" to "the `/subagents:settings` toast".
|
|
113
|
+
4. **Line 318 — Events table, `subagents:settings_changed` row.**
|
|
114
|
+
Change the "When" cell from "`/agents` → Settings mutation was applied" to "`/subagents:settings` mutation was applied".
|
|
115
|
+
|
|
116
|
+
Doc-staleness cross-checks performed (per plan-issue checklist):
|
|
117
|
+
|
|
118
|
+
- Grepped the README for every removed term (`/agents`, `eject`/`Eject`, `conversation viewer`, `wizard`, `Create new agent`, `interactive menu`, `menu`) — all occurrences are enumerated in the steps above (lines 21, 119, 228, 230, 235, 241–248, 277, 281, 283, 300, 301, 303, 318).
|
|
119
|
+
- Confirmed no other `packages/pi-subagents/docs/` file or `.pi/skills/package-pi-subagents/SKILL.md` references `/agents` as a live command needing update (architecture.md already describes the Phase 19 removal as past tense; the SKILL.md describes `/subagents:settings`/`/subagents:sessions` already).
|
|
120
|
+
- The **UI** widget-render examples and the **Default Agent Types** table are accurate post-Phase-19 and are left unchanged — verify they are not contradicted by the edits.
|
|
121
|
+
|
|
122
|
+
## Test Impact Analysis
|
|
123
|
+
|
|
124
|
+
Not applicable — documentation-only change with no test surface.
|
|
125
|
+
There is no executable behavior to cover; correctness is verified by `pnpm run lint` (rumdl markdown rules) and visual review against `src/index.ts`'s registered commands.
|
|
126
|
+
|
|
127
|
+
## Invariants at risk
|
|
128
|
+
|
|
129
|
+
None.
|
|
130
|
+
This change touches no code surface a prior phase step refactored; the Phase 19 spine invariants ([#422]–[#425]) are pinned by existing source/observer/event-contract suites and are untouched by a README edit.
|
|
131
|
+
|
|
132
|
+
## Build Order
|
|
133
|
+
|
|
134
|
+
This is a `/build-plan` (docs-only) change, executed as a single reviewable commit — no red→green cycles.
|
|
135
|
+
|
|
136
|
+
1. Edit `packages/pi-subagents/README.md` per all four Module-Level Changes steps in one pass.
|
|
137
|
+
Apply one-sentence-per-line formatting (markdown-conventions skill) to all rewritten prose.
|
|
138
|
+
Suggested commit message: `docs(pi-subagents): refresh README for /subagents:settings and /subagents:sessions (#470)`.
|
|
139
|
+
2. Verify: run `pnpm --filter @gotgenes/pi-subagents run lint` (or `pnpm run lint` at root) to confirm rumdl passes, and re-grep the README for `/agents`, `eject`, `wizard`, `conversation viewer` to confirm zero stale references remain.
|
|
140
|
+
Cross-check the two command descriptions against `src/index.ts` `registerCommand` strings.
|
|
141
|
+
|
|
142
|
+
## Risks and Mitigations
|
|
143
|
+
|
|
144
|
+
- **Risk: missing a stale reference.**
|
|
145
|
+
Mitigation: the grep in Module-Level Changes enumerated every occurrence; the build step re-greps after editing to confirm none survive.
|
|
146
|
+
- **Risk: command description drift from the actual `/help` text.**
|
|
147
|
+
Mitigation: copy the table descriptions verbatim from the `registerCommand` calls in `src/index.ts`.
|
|
148
|
+
- **Risk: markdown lint failure on the rewritten Commands table or code fences.**
|
|
149
|
+
Mitigation: follow markdown-conventions (compact table style, fenced-block languages, sequential numbering) and run `pnpm run lint` before committing.
|
|
150
|
+
|
|
151
|
+
## Open Questions
|
|
152
|
+
|
|
153
|
+
None.
|
|
154
|
+
The issue is the operator's own, the surface is verified against source, and no follow-up work is named.
|
|
155
|
+
|
|
156
|
+
[#441]: https://github.com/gotgenes/pi-packages/issues/441
|
|
157
|
+
[#442]: https://github.com/gotgenes/pi-packages/issues/442
|
|
158
|
+
[#422]: https://github.com/gotgenes/pi-packages/issues/422
|
|
159
|
+
[#425]: https://github.com/gotgenes/pi-packages/issues/425
|