@gotgenes/pi-subagents 6.18.2 → 6.18.3
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,21 @@ 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
|
+
## [6.18.3](https://github.com/gotgenes/pi-packages/compare/pi-subagents-v6.18.2...pi-subagents-v6.18.3) (2026-05-24)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Performance Improvements
|
|
12
|
+
|
|
13
|
+
* reorder append-mode prompt for KV cache reuse ([#180](https://github.com/gotgenes/pi-packages/issues/180)) ([5f688bd](https://github.com/gotgenes/pi-packages/commit/5f688bd1d008e20987d28626c5f5d0df0f66b854))
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### Documentation
|
|
17
|
+
|
|
18
|
+
* plan reorder append-mode prompt for KV cache reuse ([#180](https://github.com/gotgenes/pi-packages/issues/180)) ([bb0ddec](https://github.com/gotgenes/pi-packages/commit/bb0ddec8a7beb37baace5698e4fa4d09e61497d6))
|
|
19
|
+
* **retro:** add planning stage notes for issue [#180](https://github.com/gotgenes/pi-packages/issues/180) ([3413158](https://github.com/gotgenes/pi-packages/commit/341315898baa09652df18731ad318c89861ec62c))
|
|
20
|
+
* **retro:** add retro notes for issue [#166](https://github.com/gotgenes/pi-packages/issues/166) ([fae30ce](https://github.com/gotgenes/pi-packages/commit/fae30cec3dd99bbac490a2764a8340aa12fc171c))
|
|
21
|
+
* **retro:** add TDD stage notes for issue [#180](https://github.com/gotgenes/pi-packages/issues/180) ([1560f2d](https://github.com/gotgenes/pi-packages/commit/1560f2d6f7029cbbe0cc7b1efe1aba2a243e8357))
|
|
22
|
+
|
|
8
23
|
## [6.18.2](https://github.com/gotgenes/pi-packages/compare/pi-subagents-v6.18.1...pi-subagents-v6.18.2) (2026-05-24)
|
|
9
24
|
|
|
10
25
|
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
---
|
|
2
|
+
issue: 180
|
|
3
|
+
issue_title: "perf(pi-subagents): reorder append-mode system prompt to enable KV cache reuse"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Reorder append-mode system prompt for KV cache reuse
|
|
7
|
+
|
|
8
|
+
## Problem Statement
|
|
9
|
+
|
|
10
|
+
In append mode, `buildAgentPrompt()` places varying, agent-specific content (the `<active_agent>` tag and env block) *before* the large shared inherited system prompt (~8k tokens).
|
|
11
|
+
LLM KV caching works on prefixes — the cache is only reusable when the beginning of the prompt matches.
|
|
12
|
+
Every subagent spawn reprocesses the entire inherited prompt from scratch because the prefix differs per agent.
|
|
13
|
+
|
|
14
|
+
## Goals
|
|
15
|
+
|
|
16
|
+
- Reorder the append-mode system prompt so shared/stable content comes first and varying content follows.
|
|
17
|
+
- Preserve the `<active_agent>` tag at any position — pi-permission-system's `ACTIVE_AGENT_TAG_REGEX.exec()` searches the full string.
|
|
18
|
+
- Keep replace-mode prompt ordering unchanged (it has no shared inherited content to cache).
|
|
19
|
+
- Update tests and JSDoc to reflect the new ordering.
|
|
20
|
+
|
|
21
|
+
## Non-Goals
|
|
22
|
+
|
|
23
|
+
- Changing replace-mode prompt assembly (no shared prefix to cache).
|
|
24
|
+
- Modifying pi-permission-system (its regex parsing is already position-independent).
|
|
25
|
+
- Changing the *content* of any prompt section — only reordering.
|
|
26
|
+
|
|
27
|
+
## Background
|
|
28
|
+
|
|
29
|
+
`buildAgentPrompt()` in `src/session/prompts.ts` assembles the system prompt for subagents.
|
|
30
|
+
In append mode, the current ordering is:
|
|
31
|
+
|
|
32
|
+
```text
|
|
33
|
+
1. <active_agent name="${name}"/> ← VARIES per agent
|
|
34
|
+
2. # Environment ... ← VARIES per runtime
|
|
35
|
+
3. <inherited_system_prompt> ← SHARED (~8k tokens)
|
|
36
|
+
4. <sub_agent_context> ← SHARED (static)
|
|
37
|
+
5. <agent_instructions> ← VARIES per agent
|
|
38
|
+
6. memory / skills ← VARIES
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
pi-permission-system's `getActiveAgentNameFromSystemPrompt()` in `src/active-agent.ts` uses `ACTIVE_AGENT_TAG_REGEX.exec(systemPrompt)` — a regex search that finds the tag at any position, confirmed by reading the source.
|
|
42
|
+
|
|
43
|
+
## Design Overview
|
|
44
|
+
|
|
45
|
+
Move shared/stable sections to the front of the append-mode prompt:
|
|
46
|
+
|
|
47
|
+
```text
|
|
48
|
+
1. <inherited_system_prompt> ← SHARED (~8k tokens, NOW CACHEABLE)
|
|
49
|
+
2. <sub_agent_context> ← SHARED (static)
|
|
50
|
+
3. <active_agent name="${name}"/> ← VARIES (after cached prefix)
|
|
51
|
+
4. # Environment ... ← VARIES
|
|
52
|
+
5. <agent_instructions> ← VARIES per agent
|
|
53
|
+
6. memory / skills ← VARIES
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
This is a pure reordering — no content changes.
|
|
57
|
+
The `<active_agent>` tag remains in the system prompt for pi-permission-system to find via regex.
|
|
58
|
+
The env block and agent instructions still provide context to the model; their position relative to the inherited prompt is not semantically significant.
|
|
59
|
+
|
|
60
|
+
## Module-Level Changes
|
|
61
|
+
|
|
62
|
+
### `src/session/prompts.ts`
|
|
63
|
+
|
|
64
|
+
1. Reorder the return statement in the `config.promptMode === "append"` branch to place `identity` (wrapped in `<inherited_system_prompt>`) and `bridge` before `activeAgentTag` and `envBlock`.
|
|
65
|
+
2. Update the JSDoc comment on `buildAgentPrompt()` — replace "Both modes prepend" language with a description that notes the tag is included (not necessarily prepended) in append mode.
|
|
66
|
+
|
|
67
|
+
### `test/session/prompts.test.ts`
|
|
68
|
+
|
|
69
|
+
1. Update "prepends `<active_agent>` tag in append mode" — change from asserting `prompt.startsWith()` to asserting the tag appears *after* the inherited system prompt.
|
|
70
|
+
2. Update "active_agent tag appears before envBlock in both modes" — the append-mode assertions change: the tag should still appear before the env block, but no longer at index 0.
|
|
71
|
+
The replace-mode assertions remain unchanged (`tagIdx === 0`).
|
|
72
|
+
|
|
73
|
+
## Test Impact Analysis
|
|
74
|
+
|
|
75
|
+
- Two existing tests assert `<active_agent>` is prepended (index 0) in append mode — these must change to assert the new ordering.
|
|
76
|
+
- All other prompt tests use `toContain()` and are position-independent — they pass without changes.
|
|
77
|
+
- No new test files or test surfaces are needed; the existing test suite covers the reordering adequately once the positional assertions are updated.
|
|
78
|
+
|
|
79
|
+
## TDD Order
|
|
80
|
+
|
|
81
|
+
1. **Red: update positional assertions for append mode.**
|
|
82
|
+
Change the two append-mode tests to assert the new ordering: `<inherited_system_prompt>` appears before `<active_agent>`, and the tag appears before the env block but not at index 0.
|
|
83
|
+
Commit: `test: assert cache-friendly prompt ordering in append mode (#180)`
|
|
84
|
+
|
|
85
|
+
2. **Green: reorder the append-mode return statement.**
|
|
86
|
+
Move `identity` + `<inherited_system_prompt>` wrapper and `bridge` before `activeAgentTag` + `envBlock` in the return expression.
|
|
87
|
+
Update the JSDoc on `buildAgentPrompt()`.
|
|
88
|
+
Commit: `perf: reorder append-mode prompt for KV cache reuse (#180)`
|
|
89
|
+
|
|
90
|
+
## Risks and Mitigations
|
|
91
|
+
|
|
92
|
+
| Risk | Mitigation |
|
|
93
|
+
| -------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
94
|
+
| pi-permission-system depends on tag position | Confirmed `ACTIVE_AGENT_TAG_REGEX.exec()` searches the full string — position-independent. |
|
|
95
|
+
| Model behavior changes with reordered prompt | The same content is present; only ordering changes. The inherited system prompt as the "base" followed by specialization is arguably more natural. |
|
|
96
|
+
| Replace mode accidentally affected | Replace mode has its own code path and is not touched by this change. |
|
|
97
|
+
|
|
98
|
+
## Open Questions
|
|
99
|
+
|
|
100
|
+
None — the design is straightforward and confirmed safe by code inspection.
|
|
@@ -37,3 +37,30 @@ Type check and lint both clean after all steps.
|
|
|
37
37
|
- `RunOptions` in `agent-runner.ts` needed a new import of `ParentSessionInfo` from `agent-manager.ts`; no circular dependency since `agent-runner.ts` already imports from `agent-manager.ts`.
|
|
38
38
|
- `agent-tool.ts` still imports `AgentSpawnConfig` (needed by `AgentToolManager` interface) — the new `ParentSessionInfo` import was added alongside it.
|
|
39
39
|
- All 5 commits are clean `refactor:` messages; architecture doc update is a separate `docs:` commit.
|
|
40
|
+
|
|
41
|
+
## Stage: Final Retrospective (2026-05-24T18:00:00Z)
|
|
42
|
+
|
|
43
|
+
### Session summary
|
|
44
|
+
|
|
45
|
+
Planning, TDD implementation (5 steps), shipping, and CI verification all completed in a single session.
|
|
46
|
+
Released as `pi-subagents-v6.18.2`.
|
|
47
|
+
Zero rework — every TDD step went green on first attempt.
|
|
48
|
+
|
|
49
|
+
### Observations
|
|
50
|
+
|
|
51
|
+
#### What went well
|
|
52
|
+
|
|
53
|
+
- The planning session's identification of the deep-merge trap in `background-spawner.test.ts`'s `makeParams` factory paid off — the TDD implementation handled it without friction because the risk was anticipated.
|
|
54
|
+
- The 5-step inside-out TDD order (manager → runner → background → foreground → agent-tool) was the right sequence.
|
|
55
|
+
Each step only introduced type errors in files that subsequent steps would fix, with no circular breakage.
|
|
56
|
+
- Clean mechanical execution — 805 tests before and after, zero rework commits, lint and type-check clean throughout.
|
|
57
|
+
|
|
58
|
+
#### What caused friction (agent side)
|
|
59
|
+
|
|
60
|
+
- `missing-context` — The plan repeated the issue body's stale "13 fields" count without verifying against the actual `AgentSpawnConfig` interface (which had 15 fields after `bypassQueue` was added in a prior issue).
|
|
61
|
+
The plan also inconsistently claimed the extraction would reduce the count to both "11" and "10" in different places.
|
|
62
|
+
Impact: required corrections in the architecture doc update, but no implementation rework.
|
|
63
|
+
|
|
64
|
+
#### What caused friction (user side)
|
|
65
|
+
|
|
66
|
+
- None observed — the user let the session run autonomously through all stages without intervention.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
issue: 180
|
|
3
|
+
issue_title: "perf(pi-subagents): reorder append-mode system prompt to enable KV cache reuse"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Retro: #180 — Reorder append-mode system prompt for KV cache reuse
|
|
7
|
+
|
|
8
|
+
## Stage: Planning (2026-05-24T20:00:00Z)
|
|
9
|
+
|
|
10
|
+
### Session summary
|
|
11
|
+
|
|
12
|
+
Produced a plan to reorder the append-mode system prompt in `buildAgentPrompt()` so the shared inherited content (~8k tokens) comes before the varying `<active_agent>` tag and env block, enabling LLM KV cache prefix reuse across subagent invocations.
|
|
13
|
+
|
|
14
|
+
### Observations
|
|
15
|
+
|
|
16
|
+
- Confirmed pi-permission-system's `ACTIVE_AGENT_TAG_REGEX.exec()` is position-independent — no changes needed in that package despite the `pkg:pi-permission-system` label on the issue.
|
|
17
|
+
- Only two tests assert positional ordering in append mode (`startsWith` and `tagIdx === 0`); all other prompt tests use `toContain()` and are unaffected.
|
|
18
|
+
- Replace mode is a separate code path and is not touched.
|
|
19
|
+
- The TDD cycle is minimal: one red step (update two positional assertions), one green step (reorder the return statement + update JSDoc).
|
|
20
|
+
|
|
21
|
+
## Stage: Implementation — TDD (2026-05-24T20:15:00Z)
|
|
22
|
+
|
|
23
|
+
### Session summary
|
|
24
|
+
|
|
25
|
+
Completed both TDD cycles in `buildAgentPrompt()` in `src/session/prompts.ts`.
|
|
26
|
+
Two positional assertions in `test/session/prompts.test.ts` were updated to expect the new ordering (red), then the append-mode return statement was reordered and the JSDoc updated (green).
|
|
27
|
+
Test count unchanged at 805 across 50 files.
|
|
28
|
+
|
|
29
|
+
### Observations
|
|
30
|
+
|
|
31
|
+
- The JSDoc bullet for append mode also described the old ordering ("env header + parent system prompt + ...") and was corrected as part of the green step.
|
|
32
|
+
- The `<active_agent>` tag is followed by a `\n\n`, so when it moves after `<sub_agent_context>`, a `\n\n` separator between the bridge and the tag was needed to maintain clean section boundaries.
|
|
33
|
+
- No deviations from the plan; both steps were exactly as described.
|
package/package.json
CHANGED
package/src/session/prompts.ts
CHANGED
|
@@ -17,12 +17,14 @@ export interface PromptExtras {
|
|
|
17
17
|
* Build the system prompt for an agent from its config.
|
|
18
18
|
*
|
|
19
19
|
* - "replace" mode: env header + config.systemPrompt (full control, no parent identity)
|
|
20
|
-
* - "append" mode:
|
|
20
|
+
* - "append" mode: parent system prompt + sub-agent context + env header + config.systemPrompt
|
|
21
21
|
* - "append" with empty systemPrompt: pure parent clone
|
|
22
22
|
*
|
|
23
|
-
* Both modes
|
|
23
|
+
* Both modes include an `<active_agent name="${config.name}"/>` tag so downstream
|
|
24
24
|
* extensions (e.g. `@gotgenes/pi-permission-system`) can resolve per-agent policy
|
|
25
25
|
* inside the child session by parsing the system prompt.
|
|
26
|
+
* In replace mode the tag is prepended; in append mode it follows the shared
|
|
27
|
+
* inherited content so the stable prefix is cacheable by the LLM's KV cache.
|
|
26
28
|
*
|
|
27
29
|
* @param parentSystemPrompt The parent agent's effective system prompt (for append mode).
|
|
28
30
|
* @param extras Optional extra sections to inject (memory, preloaded skills).
|
|
@@ -76,13 +78,17 @@ You are operating as a sub-agent invoked to handle a specific task.
|
|
|
76
78
|
? `\n\n<agent_instructions>\n${config.systemPrompt}\n</agent_instructions>`
|
|
77
79
|
: "";
|
|
78
80
|
|
|
81
|
+
// Place shared/stable content first so the LLM's KV cache can reuse the
|
|
82
|
+
// inherited prefix across all subagent invocations. The <active_agent> tag
|
|
83
|
+
// and env block vary per call and are placed after the cacheable prefix.
|
|
79
84
|
return (
|
|
80
|
-
|
|
81
|
-
envBlock +
|
|
82
|
-
"\n\n<inherited_system_prompt>\n" +
|
|
85
|
+
"<inherited_system_prompt>\n" +
|
|
83
86
|
identity +
|
|
84
87
|
"\n</inherited_system_prompt>\n\n" +
|
|
85
88
|
bridge +
|
|
89
|
+
"\n\n" +
|
|
90
|
+
activeAgentTag +
|
|
91
|
+
envBlock +
|
|
86
92
|
customSection +
|
|
87
93
|
extrasSuffix
|
|
88
94
|
);
|