@gotgenes/pi-subagents 5.4.0 → 5.4.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 CHANGED
@@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [5.4.1](https://github.com/gotgenes/pi-packages/compare/pi-subagents-v5.4.0...pi-subagents-v5.4.1) (2026-05-20)
9
+
10
+
11
+ ### Documentation
12
+
13
+ * plan inject cwd into AgentManager constructor ([#76](https://github.com/gotgenes/pi-packages/issues/76)) ([7d3d50a](https://github.com/gotgenes/pi-packages/commit/7d3d50a7b7b96ef15cf5ffd7f609ed0baa46d6b9))
14
+ * **retro:** add retro notes for issue [#80](https://github.com/gotgenes/pi-packages/issues/80) ([ac38a72](https://github.com/gotgenes/pi-packages/commit/ac38a7209788c7725c7307491a18fb5a8e83962d))
15
+
8
16
  ## [5.4.0](https://github.com/gotgenes/pi-packages/compare/pi-subagents-v5.3.0...pi-subagents-v5.4.0) (2026-05-20)
9
17
 
10
18
 
@@ -0,0 +1,102 @@
1
+ ---
2
+ issue: 76
3
+ issue_title: "refactor: inject cwd into AgentManager constructor instead of reading process.cwd() in dispose()"
4
+ ---
5
+
6
+ # Inject cwd into AgentManager constructor
7
+
8
+ ## Problem Statement
9
+
10
+ `AgentManager.dispose()` calls `pruneWorktrees(process.cwd())` directly — the only place in the class that reads a process global instead of accepting `cwd` from the caller.
11
+ Every other code path that needs a working directory receives it via the per-spawn invocation context (`ctx.cwd`).
12
+ This implicit dependency makes the class harder to test and inconsistent with its own conventions.
13
+
14
+ ## Goals
15
+
16
+ - Add `cwd: string` as the first parameter of the `AgentManager` constructor and store it as a private field.
17
+ - Replace `pruneWorktrees(process.cwd())` in `dispose()` with `pruneWorktrees(this.cwd)`.
18
+ - Update the single production call site in `index.ts` to pass `process.cwd()`.
19
+ - Update all 18 test-file constructor calls to pass a test directory string.
20
+
21
+ ## Non-Goals
22
+
23
+ - Removing other `process.cwd()` calls elsewhere in the extension (e.g., `loadCustomAgents` in `index.ts`).
24
+ - Changing how per-spawn `ctx.cwd` flows through `agent-runner.ts`.
25
+ - Refactoring the constructor's callback-heavy signature into an options object (potential follow-up).
26
+
27
+ ## Background
28
+
29
+ ### Relevant modules
30
+
31
+ | Module | Role |
32
+ | -------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
33
+ | `agent-manager.ts` | Owns `AgentManager` class; constructor at line 83, `dispose()` at line 479 with the `process.cwd()` call. |
34
+ | `index.ts` | Extension entry point; constructs `AgentManager` at line 64. Already calls `process.cwd()` at line 43 for `loadCustomAgents`. |
35
+ | `worktree.ts` | Exports `pruneWorktrees(cwd: string)` consumed by `dispose()`. |
36
+ | `service-adapter.ts` | Depends on `AgentManagerLike` interface, which does not expose the constructor — unaffected. |
37
+
38
+ ### Constraints
39
+
40
+ From AGENTS.md / code-style skill:
41
+
42
+ > Do not read `process.env`, `process.cwd()`, or `process.platform` inside library/utility functions — accept the value as a parameter.
43
+
44
+ This refactoring directly enforces that rule.
45
+
46
+ `AgentManager` is internal — the public API surface (`exports` in `package.json`) is `service.ts` only, so this is a non-breaking change for consumers.
47
+
48
+ ## Design Overview
49
+
50
+ The change is mechanical:
51
+
52
+ 1. Prepend `cwd: string` to the constructor parameter list.
53
+ 2. Store it as `private readonly cwd: string`.
54
+ 3. Replace `process.cwd()` in `dispose()` with `this.cwd`.
55
+ 4. At the call site in `index.ts`, pass `process.cwd()` as the first argument.
56
+ 5. In tests, pass a fixed string like `"/test-cwd"` to every `new AgentManager(...)` call.
57
+
58
+ No new types, no interface changes, no export changes.
59
+
60
+ ## Module-Level Changes
61
+
62
+ ### `src/agent-manager.ts`
63
+
64
+ - Add `private readonly cwd: string` field.
65
+ - Constructor: add `cwd: string` as the first parameter, assign `this.cwd = cwd`.
66
+ - `dispose()`: change `pruneWorktrees(process.cwd())` → `pruneWorktrees(this.cwd)`.
67
+ - Remove the `process` global dependency (no more `process.cwd()` import needed in this file).
68
+
69
+ ### `src/index.ts`
70
+
71
+ - Pass `process.cwd()` as the first argument to `new AgentManager(...)`.
72
+
73
+ ### `test/agent-manager.test.ts`
74
+
75
+ - All 18 `new AgentManager(...)` calls gain `"/test-cwd"` as the first argument.
76
+ - No other test logic changes — `pruneWorktrees` is already mocked.
77
+
78
+ ## Test Impact Analysis
79
+
80
+ 1. No new unit tests are needed — the existing `dispose()` test already exercises `pruneWorktrees` via the mock; it will now verify the injected `cwd` is forwarded instead of the process global.
81
+ 2. No existing tests become redundant.
82
+ 3. All 18 constructor calls must be updated with the new first argument, but the test assertions remain valid.
83
+
84
+ ## TDD Order
85
+
86
+ 1. **Red → Green: update constructor and dispose** — change the `AgentManager` constructor to accept `cwd` as the first parameter, store it, and use `this.cwd` in `dispose()`.
87
+ Update all 18 test constructor calls to pass `"/test-cwd"`.
88
+ Update `index.ts` call site to pass `process.cwd()`.
89
+ Commit message: `refactor: inject cwd into AgentManager constructor (#76)`
90
+
91
+ This is a single-step refactoring — splitting it further would leave the codebase in a broken intermediate state since the constructor signature change must be applied atomically across production code and tests.
92
+
93
+ ## Risks and Mitigations
94
+
95
+ | Risk | Mitigation |
96
+ | ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
97
+ | Missing a constructor call site | `grep 'new AgentManager'` across the entire repo confirms only `index.ts` (1 call) and `agent-manager.test.ts` (18 calls). |
98
+ | Accidentally changing behavior | `pruneWorktrees` is already mocked in tests; production call site passes `process.cwd()` which is the same value `dispose()` read before. |
99
+
100
+ ## Open Questions
101
+
102
+ None — the issue's proposed change section is unambiguous and the refactoring is mechanical.
@@ -0,0 +1,35 @@
1
+ ---
2
+ issue: 80
3
+ issue_title: "refactor: consolidate getConfig / getAgentConfig into a single resolution path"
4
+ ---
5
+
6
+ # Retro: #80 — consolidate getConfig / getAgentConfig
7
+
8
+ ## Final Retrospective (2026-05-20T00:35:00Z)
9
+
10
+ ### Session summary
11
+
12
+ Consolidated two overlapping agent config lookup functions (`getConfig` and `getAgentConfig`) into a single `resolveAgentConfig(type): AgentConfig` with a guaranteed-non-null return and internal fallback chain.
13
+ Migrated all 6 source callers and 5 test files across 6 TDD commits, then shipped as `pi-subagents-v5.4.0`.
14
+
15
+ ### Observations
16
+
17
+ #### What went well
18
+
19
+ - The lift-and-shift migration strategy (add new function → migrate callers incrementally → remove old functions) kept every commit green.
20
+ No intermediate step broke the test suite.
21
+ - The planning phase correctly identified an under-documented scope question (callers beyond the two mentioned in the issue) and used `ask-user` to resolve it before writing the plan.
22
+ - The `test/prompts.test.ts` caller, missed by the plan, was caught cleanly during the final grep sweep in step 6 — no rework needed, just an additional edit in the same commit.
23
+
24
+ #### What caused friction (agent side)
25
+
26
+ - `missing-context` — The plan specified that `resolveAgentConfig` should fall back for disabled types (matching `getConfig`'s semantics), but didn't trace what `agent-menu.ts` actually reads from disabled configs.
27
+ `agent-menu.ts` iterates `getAllTypes()` (including disabled agents) and needs the real config to render `✕` indicators, source badges, and `(disabled)` descriptions.
28
+ With fallback-for-disabled semantics, disabled agents would silently display as general-purpose.
29
+ Caught during step 4 while editing `agent-menu.ts`, before any wrong test assertions ran.
30
+ Impact: required changing `resolveAgentConfig` semantics (only fall back for unknown types, not disabled) and updating the step 1 test — a ~5 minute fix folded into the step 4 commit.
31
+
32
+ #### What caused friction (user side)
33
+
34
+ - Nothing notable.
35
+ The user's `ask-user` response during planning ("remove both, migrate all callers") was clear and included a useful directional note about computing values earlier.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gotgenes/pi-subagents",
3
- "version": "5.4.0",
3
+ "version": "5.4.1",
4
4
  "exports": {
5
5
  ".": "./src/service.ts"
6
6
  },
@@ -72,6 +72,7 @@ export class AgentManager {
72
72
  private onComplete?: OnAgentComplete;
73
73
  private onStart?: OnAgentStart;
74
74
  private onCompact?: OnAgentCompact;
75
+ private readonly cwd: string;
75
76
  private maxConcurrent: number;
76
77
  private getRunConfig?: () => RunConfig;
77
78
 
@@ -81,12 +82,14 @@ export class AgentManager {
81
82
  private runningBackground = 0;
82
83
 
83
84
  constructor(
85
+ cwd: string,
84
86
  onComplete?: OnAgentComplete,
85
87
  maxConcurrent = DEFAULT_MAX_CONCURRENT,
86
88
  onStart?: OnAgentStart,
87
89
  onCompact?: OnAgentCompact,
88
90
  getRunConfig?: () => RunConfig,
89
91
  ) {
92
+ this.cwd = cwd;
90
93
  this.onComplete = onComplete;
91
94
  this.onStart = onStart;
92
95
  this.onCompact = onCompact;
@@ -485,6 +488,6 @@ export class AgentManager {
485
488
  }
486
489
  this.agents.clear();
487
490
  // Prune any orphaned git worktrees (crash recovery)
488
- try { pruneWorktrees(process.cwd()); } catch (err) { debugLog("pruneWorktrees on dispose", err); }
491
+ try { pruneWorktrees(this.cwd); } catch (err) { debugLog("pruneWorktrees on dispose", err); }
489
492
  }
490
493
  }
package/src/index.ts CHANGED
@@ -61,7 +61,7 @@ export default function (pi: ExtensionAPI) {
61
61
  });
62
62
 
63
63
  // Background completion: emit lifecycle event and delegate to notification system
64
- const manager = new AgentManager((record) => {
64
+ const manager = new AgentManager(process.cwd(), (record) => {
65
65
  // Emit lifecycle event based on terminal status
66
66
  const isError = record.status === "error" || record.status === "stopped" || record.status === "aborted";
67
67
  const eventData = buildEventData(record);