@zihanw/pi-forge 0.5.4 → 0.5.6

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 (237) hide show
  1. package/CHANGELOG.md +83 -0
  2. package/README.md +67 -103
  3. package/README.zh-CN.md +67 -95
  4. package/assets/pi-forge-header-concept-1.png +0 -0
  5. package/assets/readme/PROVENANCE.md +95 -0
  6. package/assets/readme/en/capability-tools.gif +0 -0
  7. package/assets/readme/en/context-composition.gif +0 -0
  8. package/assets/readme/en/context-toggle.gif +0 -0
  9. package/assets/readme/en/draft-diff.png +0 -0
  10. package/assets/readme/en/edit-draft-diff.gif +0 -0
  11. package/assets/readme/en/editor-overview-v3.png +0 -0
  12. package/assets/readme/en/editor-overview.png +0 -0
  13. package/assets/readme/en/mode-tools.gif +0 -0
  14. package/assets/readme/en/regex-transforms.gif +0 -0
  15. package/assets/readme/en/tool-selection.gif +0 -0
  16. package/assets/readme/tui-quickstart.gif +0 -0
  17. package/assets/readme/zh-CN/capability-tools.gif +0 -0
  18. package/assets/readme/zh-CN/context-composition.gif +0 -0
  19. package/assets/readme/zh-CN/context-toggle.gif +0 -0
  20. package/assets/readme/zh-CN/draft-diff.png +0 -0
  21. package/assets/readme/zh-CN/edit-draft-diff.gif +0 -0
  22. package/assets/readme/zh-CN/editor-overview-v3.png +0 -0
  23. package/assets/readme/zh-CN/editor-overview.png +0 -0
  24. package/assets/readme/zh-CN/mode-tools.gif +0 -0
  25. package/assets/readme/zh-CN/regex-transforms.gif +0 -0
  26. package/assets/readme/zh-CN/tool-selection.gif +0 -0
  27. package/dist/active-state.d.ts +148 -0
  28. package/dist/active-state.d.ts.map +1 -0
  29. package/dist/active-state.js +374 -0
  30. package/dist/active-state.js.map +1 -0
  31. package/dist/agent-profile.d.ts +1 -0
  32. package/dist/agent-profile.d.ts.map +1 -1
  33. package/dist/agent-profile.js +20 -14
  34. package/dist/agent-profile.js.map +1 -1
  35. package/dist/capabilities.d.ts +39 -0
  36. package/dist/capabilities.d.ts.map +1 -0
  37. package/dist/capabilities.js +160 -0
  38. package/dist/capabilities.js.map +1 -0
  39. package/dist/capability-anchors.d.ts +45 -0
  40. package/dist/capability-anchors.d.ts.map +1 -0
  41. package/dist/capability-anchors.js +263 -0
  42. package/dist/capability-anchors.js.map +1 -0
  43. package/dist/capability-command.d.ts +4 -0
  44. package/dist/capability-command.d.ts.map +1 -0
  45. package/dist/capability-command.js +164 -0
  46. package/dist/capability-command.js.map +1 -0
  47. package/dist/capability-events.d.ts +79 -0
  48. package/dist/capability-events.d.ts.map +1 -0
  49. package/dist/capability-events.js +478 -0
  50. package/dist/capability-events.js.map +1 -0
  51. package/dist/capability-projection.d.ts +22 -0
  52. package/dist/capability-projection.d.ts.map +1 -0
  53. package/dist/capability-projection.js +273 -0
  54. package/dist/capability-projection.js.map +1 -0
  55. package/dist/capability-protocol.d.ts +21 -0
  56. package/dist/capability-protocol.d.ts.map +1 -0
  57. package/dist/capability-protocol.js +15 -0
  58. package/dist/capability-protocol.js.map +1 -0
  59. package/dist/capability-state.d.ts +74 -0
  60. package/dist/capability-state.d.ts.map +1 -0
  61. package/dist/capability-state.js +43 -0
  62. package/dist/capability-state.js.map +1 -0
  63. package/dist/capability-tool.d.ts +11 -0
  64. package/dist/capability-tool.d.ts.map +1 -0
  65. package/dist/capability-tool.js +25 -0
  66. package/dist/capability-tool.js.map +1 -0
  67. package/dist/capability-web-host.d.ts +11 -0
  68. package/dist/capability-web-host.d.ts.map +1 -0
  69. package/dist/capability-web-host.js +105 -0
  70. package/dist/capability-web-host.js.map +1 -0
  71. package/dist/codecs/capability.d.ts +71 -0
  72. package/dist/codecs/capability.d.ts.map +1 -0
  73. package/dist/codecs/capability.js +363 -0
  74. package/dist/codecs/capability.js.map +1 -0
  75. package/dist/codecs/prompt-stack.d.ts +1 -1
  76. package/dist/codecs/prompt-stack.d.ts.map +1 -1
  77. package/dist/codecs/prompt-stack.js +140 -13
  78. package/dist/codecs/prompt-stack.js.map +1 -1
  79. package/dist/command-contribution/index.d.ts +21 -0
  80. package/dist/command-contribution/index.d.ts.map +1 -0
  81. package/dist/command-contribution/index.js +14 -0
  82. package/dist/command-contribution/index.js.map +1 -0
  83. package/dist/compile-cycle.d.ts +1 -0
  84. package/dist/compile-cycle.d.ts.map +1 -1
  85. package/dist/compile-cycle.js.map +1 -1
  86. package/dist/compiler.d.ts.map +1 -1
  87. package/dist/compiler.js +81 -17
  88. package/dist/compiler.js.map +1 -1
  89. package/dist/forge-command.d.ts +10 -0
  90. package/dist/forge-command.d.ts.map +1 -0
  91. package/dist/forge-command.js +106 -0
  92. package/dist/forge-command.js.map +1 -0
  93. package/dist/index.d.ts +2 -2
  94. package/dist/index.d.ts.map +1 -1
  95. package/dist/index.js +58 -5
  96. package/dist/index.js.map +1 -1
  97. package/dist/json-fingerprint.d.ts +11 -0
  98. package/dist/json-fingerprint.d.ts.map +1 -0
  99. package/dist/json-fingerprint.js +66 -0
  100. package/dist/json-fingerprint.js.map +1 -0
  101. package/dist/lifecycle.d.ts +14 -0
  102. package/dist/lifecycle.d.ts.map +1 -1
  103. package/dist/lifecycle.js +167 -67
  104. package/dist/lifecycle.js.map +1 -1
  105. package/dist/payload-command.d.ts +2 -2
  106. package/dist/payload-command.d.ts.map +1 -1
  107. package/dist/payload-command.js +80 -26
  108. package/dist/payload-command.js.map +1 -1
  109. package/dist/payload-state.d.ts +1 -0
  110. package/dist/payload-state.d.ts.map +1 -1
  111. package/dist/payload-state.js +1 -0
  112. package/dist/payload-state.js.map +1 -1
  113. package/dist/policy.d.ts +2 -1
  114. package/dist/policy.d.ts.map +1 -1
  115. package/dist/policy.js +3 -0
  116. package/dist/policy.js.map +1 -1
  117. package/dist/preset-command.d.ts +1 -0
  118. package/dist/preset-command.d.ts.map +1 -1
  119. package/dist/preset-command.js +94 -36
  120. package/dist/preset-command.js.map +1 -1
  121. package/dist/preview-text.d.ts +5 -0
  122. package/dist/preview-text.d.ts.map +1 -0
  123. package/dist/preview-text.js +27 -0
  124. package/dist/preview-text.js.map +1 -0
  125. package/dist/preview.d.ts +18 -1
  126. package/dist/preview.d.ts.map +1 -1
  127. package/dist/preview.js +132 -97
  128. package/dist/preview.js.map +1 -1
  129. package/dist/profile-command.js +68 -9
  130. package/dist/profile-command.js.map +1 -1
  131. package/dist/regex.d.ts.map +1 -1
  132. package/dist/regex.js +5 -0
  133. package/dist/regex.js.map +1 -1
  134. package/dist/render-helpers.d.ts.map +1 -1
  135. package/dist/render-helpers.js +2 -0
  136. package/dist/render-helpers.js.map +1 -1
  137. package/dist/repositories/capability.d.ts +53 -0
  138. package/dist/repositories/capability.d.ts.map +1 -0
  139. package/dist/repositories/capability.js +294 -0
  140. package/dist/repositories/capability.js.map +1 -0
  141. package/dist/runtime/capability-runtime.d.ts +93 -0
  142. package/dist/runtime/capability-runtime.d.ts.map +1 -0
  143. package/dist/runtime/capability-runtime.js +987 -0
  144. package/dist/runtime/capability-runtime.js.map +1 -0
  145. package/dist/runtime/profile-runtime.d.ts.map +1 -1
  146. package/dist/runtime/profile-runtime.js +10 -9
  147. package/dist/runtime/profile-runtime.js.map +1 -1
  148. package/dist/runtime/prompt-stack-runtime.d.ts +7 -4
  149. package/dist/runtime/prompt-stack-runtime.d.ts.map +1 -1
  150. package/dist/runtime/prompt-stack-runtime.js +47 -11
  151. package/dist/runtime/prompt-stack-runtime.js.map +1 -1
  152. package/dist/runtime/tool-policy-runtime.d.ts +10 -0
  153. package/dist/runtime/tool-policy-runtime.d.ts.map +1 -1
  154. package/dist/runtime/tool-policy-runtime.js +171 -30
  155. package/dist/runtime/tool-policy-runtime.js.map +1 -1
  156. package/dist/session-adapter.d.ts +13 -0
  157. package/dist/session-adapter.d.ts.map +1 -1
  158. package/dist/session-adapter.js +110 -0
  159. package/dist/session-adapter.js.map +1 -1
  160. package/dist/session-usage.d.ts +65 -0
  161. package/dist/session-usage.d.ts.map +1 -0
  162. package/dist/session-usage.js +134 -0
  163. package/dist/session-usage.js.map +1 -0
  164. package/dist/subagent/fingerprints.d.ts +3 -15
  165. package/dist/subagent/fingerprints.d.ts.map +1 -1
  166. package/dist/subagent/fingerprints.js +5 -69
  167. package/dist/subagent/fingerprints.js.map +1 -1
  168. package/dist/subagent/index.d.ts +2 -0
  169. package/dist/subagent/index.d.ts.map +1 -1
  170. package/dist/subagent/index.js +2 -0
  171. package/dist/subagent/index.js.map +1 -1
  172. package/dist/subagent-host.d.ts +2 -2
  173. package/dist/subagent-host.d.ts.map +1 -1
  174. package/dist/subagent-host.js +13 -1
  175. package/dist/subagent-host.js.map +1 -1
  176. package/dist/types.d.ts +6 -1
  177. package/dist/types.d.ts.map +1 -1
  178. package/dist/types.js.map +1 -1
  179. package/dist/web-editor/client-script.generated.d.ts.map +1 -1
  180. package/dist/web-editor/client-script.generated.js +1 -1
  181. package/dist/web-editor/client-script.generated.js.map +1 -1
  182. package/dist/web-editor/client-styles.generated.d.ts.map +1 -1
  183. package/dist/web-editor/client-styles.generated.js +1 -1
  184. package/dist/web-editor/client-styles.generated.js.map +1 -1
  185. package/dist/web-editor/server.d.ts.map +1 -1
  186. package/dist/web-editor/server.js +152 -4
  187. package/dist/web-editor/server.js.map +1 -1
  188. package/dist/web-editor/styles.d.ts.map +1 -1
  189. package/dist/web-editor/styles.js +573 -165
  190. package/dist/web-editor/styles.js.map +1 -1
  191. package/dist/web-editor/types.d.ts +81 -1
  192. package/dist/web-editor/types.d.ts.map +1 -1
  193. package/dist/web-host.d.ts +9 -0
  194. package/dist/web-host.d.ts.map +1 -1
  195. package/dist/web-host.js +210 -11
  196. package/dist/web-host.js.map +1 -1
  197. package/dist/workspace.d.ts +11 -0
  198. package/dist/workspace.d.ts.map +1 -1
  199. package/dist/workspace.js +63 -5
  200. package/dist/workspace.js.map +1 -1
  201. package/docs/README.md +4 -0
  202. package/docs/design/README.md +3 -1
  203. package/docs/design/architecture-0.5.md +22 -0
  204. package/docs/design/archive/2026-09-12-system-update-design.md +229 -0
  205. package/docs/design/pi-forge-system-update-design-notes.md +157 -229
  206. package/docs/development/release.md +20 -20
  207. package/docs/development/roadmap.md +21 -2
  208. package/docs/development/scoped-global-profiles-stacks.md +1 -1
  209. package/docs/development/setup.md +1 -1
  210. package/docs/getting-started.md +1 -1
  211. package/docs/guides/delegation.md +22 -20
  212. package/docs/guides/migrating-to-0.5.md +29 -0
  213. package/docs/guides/use-cases.md +6 -2
  214. package/docs/guides/web-editor.md +74 -5
  215. package/docs/reference/active-state.md +77 -0
  216. package/docs/reference/capabilities.md +259 -0
  217. package/docs/reference/commands.md +52 -24
  218. package/docs/reference/configuration.md +4 -2
  219. package/docs/reference/features.md +70 -4
  220. package/docs/reference/provider-support.md +67 -0
  221. package/docs/reference/public-api.md +49 -3
  222. package/docs/reference/session-cache.md +112 -0
  223. package/docs/reference/stack-schema.md +18 -4
  224. package/docs/reference/subagent-host-port.md +8 -0
  225. package/docs/zh-CN/README.md +3 -0
  226. package/docs/zh-CN/getting-started.md +1 -1
  227. package/docs/zh-CN/guides/delegation.md +22 -10
  228. package/docs/zh-CN/guides/migrating-to-0.5.md +29 -0
  229. package/docs/zh-CN/guides/web-editor.md +75 -7
  230. package/docs/zh-CN/reference/capabilities.md +259 -0
  231. package/docs/zh-CN/reference/commands.md +61 -33
  232. package/docs/zh-CN/reference/provider-support.md +67 -0
  233. package/docs/zh-CN/reference/session-cache.md +112 -0
  234. package/examples/capabilities/review.json +12 -0
  235. package/examples/capabilities/write-tools.json +15 -0
  236. package/examples/read-first-worker-prompt-stack.json +49 -0
  237. package/package.json +16 -9
@@ -1,229 +1,157 @@
1
- # pi-forge `system_update` Design Notes
2
-
3
- **Status:** Current plan (revised 2026-09-12). Supersedes the 2026-09-10
4
- exploration draft, which assumed pi-forge would implement the full
5
- persistence/projection/transport stack itself. Upstream Pi has since started
6
- building the primitive natively, so pi-forge's scope shrinks to the
7
- workflow layer.
8
-
9
- **Target:** 0.5.5+, blocked on an upstream Pi redo (see §2).
10
-
11
- ---
12
-
13
- ## 1. TL;DR — Current Plan
14
-
15
- `system_update` is a **session-timeline event**, not a mutation of the
16
- top-level system prompt. That core decision from the original draft survives.
17
- What changed is who builds what:
18
-
19
- - **Upstream Pi is building the primitive**: a first-class `SystemMessage`
20
- (`role: "system"`) appended to the transcript, rendered natively on models
21
- that support mid-conversation system messages and as a tagged user turn
22
- elsewhere. Persistence, resume, compaction, and provider rendering are all
23
- owned by the harness.
24
- - **pi-forge builds only the workflow layer**: an append-only event log, a
25
- reducer over it, the `/system-update` command family, preset-declared
26
- dormant instruction blocks, and a permission-gated agent tool.
27
- - **Integration is declarative**: pi-forge renders its active update set into
28
- `systemPromptOptions.sections` and lets the harness diff engine emit the
29
- deltas. pi-forge no longer returns a fully-compiled replacement string for
30
- this path.
31
-
32
- Discarded from the original draft: the custom-entry + self-written projector
33
- design, the `custom_message` transport, the provider transport matrix, and
34
- the six-phase rollout. See §5 for why.
35
-
36
- ---
37
-
38
- ## 2. Upstream Landscape (snapshot 2026-09-12)
39
-
40
- ### 2.1 The PRs
41
-
42
- - **PR #9116** (`system-role` branch, pi-ai layer): adds `SystemMessage` to
43
- the `Message` union. Appended to the transcript, never folded into
44
- `Context.systemPrompt`. Persisted as ordinary message entries; compaction
45
- cut points and summaries understand them (rendered as `[System]:` in
46
- summaries); interactive mode hides them.
47
- - **PR #9117** (`system-tool-deltas` branch, stacked, coding-agent layer):
48
- the first rendered prompt of a session becomes a stored **baseline**;
49
- anything that changes afterwards is appended as a provider-neutral system
50
- message delta. On resume/tree navigation the stored baseline is reinstated
51
- so a resumed session sends byte-identical cached prefixes. After
52
- compaction, the effective prompt folds into a fresh baseline at no extra
53
- cost.
54
-
55
- **Both PRs were closed by the author on 2026-09-11 with "I will redo this."**
56
- Direction is alive; implementation is being redone; timeline unknown.
57
- Community testing (13-scenario harness, all green) flagged two design
58
- issues likely motivating the redo: ~10 KB per-prompt-entry session bloat
59
- from storing rendered baselines, and silent tool disappearance on
60
- non-supporting models across resume.
61
-
62
- ### 2.2 Verified behavior of the PR branch (local clone: `~/programming/pi-pr9117`)
63
-
64
- Measured against the actual `system-tool-deltas` build:
65
-
66
- - `sections: Record<string, string>` on `systemPromptOptions` renders as
67
- XML-wrapped blocks (`<name>\n...\n</name>`), diff-keyed as `section:name`.
68
- - `diffSystemPrompts` behavior matrix:
69
- - identical pieces → `unchanged` (no cost)
70
- - section added → update delta: "The following `<name>` system guidance
71
- now applies: ..."
72
- - section removed → retraction: "The previous `<name>` system guidance no
73
- longer applies."
74
- - section content changed → "The `<name>` system guidance has changed. The
75
- following supersedes..."
76
- - literals changed or `forceSystemPrompt` changed → `replace`
77
- (deliberate full cache miss)
78
- - **`forceSystemPrompt` short-circuits everything**: when set, pieces are
79
- only the forced prompt; sections are not rendered at all. Any extension
80
- returning a full replacement string from `before_agent_start` gets this
81
- path, and every content change is a full prefix miss.
82
- - **`customPrompt` is a value piece** (keyed `customPrompt`, diff-friendly)
83
- and does NOT short-circuit sections. This is pi-forge's integration point
84
- for `mode = replace` stacks.
85
- - Mid-run timing: the diff runs before every LLM request
86
- (`agent-loop.ts`), including mid-tool-loop, so an agent tool that mutates
87
- sections gets its delta delivered after the tool batch and before the next
88
- inference. The tool-call adjacency problem from the original draft is
89
- handled by the harness.
90
- - Fallback rendering for unsupported providers:
91
- `<system_update>\n{text}\n</system_update>` as a user-role message
92
- (`pi-ai/utils/system-messages.ts`); Gemini confirmed user-role.
93
- - Native support matrix (upstream compat flags): Anthropic Opus 4.8/5,
94
- Fable 5/5.1, Mythos 5/5.1 get real system messages (Anthropic requires a
95
- system message to directly precede an assistant turn; pending messages are
96
- held). OpenAI transports get `developer`/`system` items. Everything else
97
- gets the tagged user turn.
98
- - `BeforeAgentStartEventResult.message` only accepts `CustomMessage`
99
- (customType/content/display/details) — there is **no imperative
100
- append-SystemMessage extension API** in the PR as written. The declarative
101
- sections path is the intended extension surface.
102
- - The PR branch itself had two TypeScript errors (`openrouter.ts`,
103
- `xai.ts`) when we built it; dist artifacts were still produced.
104
-
105
- ### 2.3 Trigger to resume this work
106
-
107
- When the redone PR appears: verify the sections/diff semantics survived the
108
- redo (re-run the §2.2 matrix), then wire pi-forge's workflow layer to it.
109
- If the redo removes the declarative sections surface, reassess; the escape
110
- hatch is splicing `SystemMessage` in the context hook (see §5).
111
-
112
- ---
113
-
114
- ## 3. pi-forge Design (workflow layer)
115
-
116
- These decisions survive from the original draft and remain the plan.
117
-
118
- ### 3.1 Event model
119
-
120
- - Updates are **append-only custom session entries**
121
- (`pi-forge-system-update`, schemaVersion 1), written via the existing
122
- `session-adapter.ts` pattern (`pi.appendEntry` / `getCurrentBranchEntries`).
123
- Branch semantics come for free.
124
- - Entry payload: `{ updateId, op: "apply" | "revoke" | "reset", source,
125
- presetId?, contentSnapshot, createdAt }`.
126
- - **Snapshot content, not file paths**: file-backed presets are rendered at
127
- activation time and the rendered text is persisted. Editing a preset file
128
- tomorrow must not alter yesterday's session.
129
- - Logical state is a **reducer view** over the branch's events, never
130
- canonical mutable state. Powers `/system-update status`, badges, and
131
- section rendering.
132
- - Revoke/reset are new events, never history rewrites. In practice the
133
- harness retraction wording ("no longer applies") is generated for us once
134
- the section disappears; the event log only records intent.
135
-
136
- ### 3.2 Rendering (the declarative bridge)
137
-
138
- - The reducer's active set is rendered into
139
- `systemPromptOptions.sections["pi-forge-update-<id>"]` during
140
- `before_agent_start` (and picked up mid-run by the harness's per-request
141
- diff).
142
- - pi-forge's stack compilation moves off the legacy "return one big string"
143
- path: `mode = replace` stacks go into `systemPromptOptions.customPrompt`,
144
- additive content into keyed `sections`. This is a prerequisite refactor,
145
- and it upgrades cache behavior for the whole stack system, not just
146
- updates.
147
- - Transport is not pi-forge's concern: native vs fallback rendering is the
148
- harness's compatibility layer.
149
-
150
- ### 3.3 Commands
151
-
152
- - `/system-update <text>` — apply a freeform update (auto-id `update-N`).
153
- - `/system-update status` — reducer view of active updates.
154
- - `/system-update reset` — deactivate all (new event, append-only).
155
- - 0.5.5+ with presets: `/system-update list|use <id>|off <id>`.
156
- - No command deletes history. None of these trigger an agent turn.
157
-
158
- ### 3.4 Presets and the agent tool
159
-
160
- - Presets declare dormant runtime blocks:
161
- `{ "systemUpdates": [{ "id", "name", "description", "modelCallable",
162
- "content" | "file" }] }`.
163
- - The base system prompt carries only a compact inventory; full blocks load
164
- on activation (lazy privileged prompt loading).
165
- - Agent-facing tool `forge_system_update({action, id})` references declared
166
- preset IDs only. **No arbitrary file elevation, no arbitrary agent-provided
167
- privileged text.** Repository content is untrusted; elevation requires an
168
- explicit preset declaration.
169
- - Source-aware deactivation: the agent may only deactivate agent-activated
170
- modes; the user may deactivate anything.
171
- - Mid-turn activation rides the harness's per-request diff — no
172
- pending-commit machinery on our side.
173
-
174
- ### 3.5 Compaction, resume, branching
175
-
176
- All owned by the harness under the new architecture: update sections are part
177
- of the effective prompt, folded into the post-compaction baseline; stored
178
- baseline is reinstated on resume; events live on the branch. pi-forge's only
179
- job is to re-derive the active set from the branch's event log on session
180
- start/branch switch (same restore pattern as the active-stack state today).
181
-
182
- ---
183
-
184
- ## 4. Version Plan
185
-
186
- - **0.5.4 (done, pushed):** web editor fixes and visual work; prompt-cache
187
- features — cache-impact warning on `/preset use` / `/profile use`
188
- (common-prefix estimate + last-request cacheRead), and compile-time
189
- diagnostics for cache-sensitive content (`{{time}}`, date slots with
190
- `includeTime`, `{{date}}` info).
191
- - **0.5.5:** system update workflow layer per §3, gated on the upstream redo
192
- landing in a released Pi. Build the upstream-touching code behind a small
193
- isolated module so a redo API change rewrites one file, not the feature.
194
-
195
- ---
196
-
197
- ## 5. Discarded Designs (recorded so we don't re-litigate)
198
-
199
- - **Custom entry + self-written projector** (original draft's main design):
200
- required replicating Pi's session-entry→context translation rules
201
- (compaction truncation, deferred-message filtering) to compute splice
202
- positions, plus a compaction checkpoint synthesizer. Real maintenance
203
- coupling to Pi internals. Killed by the upstream `SystemMessage`.
204
- - **`pi.sendMessage` custom_message transport**: zero projection code, but
205
- `custom_message` entries evaporate at compaction (the compaction path
206
- doesn't recognize them) and render only as user-role. Viable fallback if
207
- the upstream redo dies entirely; otherwise obsolete.
208
- - **Provider transport matrix / native lowering in pi-forge**: the wire role
209
- is the harness's compatibility layer. pi-forge stores semantics
210
- (`op`, `presetId`) so a future transport change needs no data migration.
211
- - **Context-hook SystemMessage splicing**: possible once upstream keeps
212
- `role: "system"` messages, but brings back per-request projection, position
213
- mapping, and Anthropic placement-rule handling. Escape hatch only.
214
-
215
- ---
216
-
217
- ## 6. Open Questions for the Redo
218
-
219
- 1. Did sections survive the redo, and did their diff semantics change?
220
- 2. Is there an imperative append path for extensions after all, or is
221
- declarative sections still the only surface?
222
- 3. How does the redo store baselines (the session-bloat feedback)?
223
- 4. Does `customPrompt` remain a non-short-circuiting value piece?
224
- 5. Timing: which Pi release carries it, and what's our minimum-version
225
- dependency story for the feature?
226
-
227
- Community posture: when the redo PR opens, comment as a downstream consumer
228
- with the runtime-instruction-modes use case (do not file a new issue;
229
- feature-request issues get auto-closed while a PR is in flight).
1
+ # Capabilities — accepted 0.5.5 design
2
+
3
+ [Documentation](../README.md) · [Lean architecture](architecture-0.5.md) · [Roadmap](../development/roadmap.md)
4
+
5
+ **Status:** implementation authorized, 2026-09-20; accepted 9/21 amendment incorporated. Functional source is delivered across all planned lanes: foundation codecs, human CLI core (`/capability`), plain metadata anchor projection, Web Session capabilities activity panel, live Preset bindings (`capabilities`) in dedicated peer Capability bindings tab with finite overrides and opt-in `modelCallable: true`, restricted model-callable Agent control (`forge_capability`), Web Capabilities surface CRUD with SDK-grouped tool picker and `sourceRevision` stale-save protection, custom default tools policy (`tools.initial`), guarded human Web activation picker (`GET /api/capability-state/available`, `POST /api/capability-state/enable`), and Pi 0.87 transcript/projection migration. Parent safeguards enforce raw source/revision coherence, external new-bindings stale-save protection, and lifecycle/re-entry fences (`disposed`, `lifecycleRevision`, `sameContext`). [Current reference](../reference/capabilities.md) states operational boundaries. Capabilities support `add`/`remove` only; candidate `only`/allowlist is not implemented. Parent build and full verification passed on Pi 0.87.0 (773 Node / 37 browser); development package version remains 0.5.4; release version bump decision pending between 0.5.5 or 0.6; repo dev SDK is pinned to `0.87.0` with peer range `>=0.87.0 <0.88.0` (no dual 0.86 support claim).
6
+
7
+ This supersedes the [September 12 upstream-blocked proposal](archive/2026-09-12-system-update-design.md). Historical spike notes below reflect dated 0.86 exploration; current production architecture builds directly on Pi 0.87 APIs.
8
+
9
+ ## Ownership and bounded scope
10
+
11
+ **Definitions are reusable; authorization belongs to Presets; active state belongs to Sessions.** Capabilities contain continuing collaboration/output guidance and optional tool selection changes. Skills remain the place for procedures, scripts and reference material.
12
+
13
+ - Forge owns semantic events, activation snapshots, derived delivery anchors and request-only capability projection.
14
+ - Pi owns ordinary transcript storage/branching, message protocols, provider encoding and actual tool execution. No fork or private `AgentSession` patches.
15
+ - `ForgeWorkspace` remains the single resource-state owner. Existing codecs/repositories/catalogs are reused. The capability reducer is a pure view, not a second mutable workspace.
16
+ - `tool-policy-runtime` remains the only Forge owner of executable tool selection. Text saying a tool is disabled is not enforcement.
17
+ - CLI, restricted Agent tool and Web UI share one application service. No dynamic control-tool schema, new registry/framework/package entry point, arbitrary JSON Patch, inheritance chain, capability dependencies, automatic resource bundling, or general undo/redo.
18
+
19
+ ## Evidence behind the architecture
20
+
21
+ An isolated Pi 0.86 `AgentSession`/extension-runner spike used fake models/tools and intercepted adapter payload assembly; no provider HTTP was sent by that harness. Nineteen assertions and a separate smoke passed, including assertions that intentionally reproduce integration failures. They are not nineteen production features passing.
22
+
23
+ 1. Keeping and mutating `before_agent_start.systemPromptOptions.sections` across a tool loop did not reliably synchronize later changes: the expected text sequence off/on/off became off/on/on while tools restored correctly. The command options getter was not a live-run setter.
24
+ 2. Returning Forge's current full `systemPrompt` invokes Pi's forced request projection after context hooks; it suppresses later native system updates. `customPrompt` is not an exact replacement because the cwd contribution remains.
25
+ 3. A Forge-owned marker/context projector worked in the sampled repeated toggle, native/user/native switch, branch/JSON reconstruction and manual-compaction scenarios. Those samples do not establish production crash recovery, automatic compaction, concurrency, old-Preset compatibility or tool-baseline recovery.
26
+ 4. `systemPromptOptions.sections` is a prompt-building input; `SystemMessage.sections` is still useful as a native request representation. Failure of the tested thin bridge does not prove every upstream integration impossible.
27
+ 5. `sendMessage` steering with explicit `triggerTurn:false` did not enter the next request in the tested live loop. Omitting it worked while streaming and did not start inference in the tested idle command. Context-hook exceptions alone are swallowed; explicit abort behavior must be accounted for.
28
+
29
+ The implemented request-base bridge preserves compiled replacement strings while retaining foreign named sections and tool declarations. Built-in base text and selected-tool macros refresh when the executable set changes.
30
+
31
+ **Production architecture:** management completely avoids transcript `sendMessage` and `custom_message` carriers, preventing dialogue contamination and spurious model turns. Under Pi 0.87, standard `context` hooks intentionally exclude System messages; Forge moves the entire compiler, base prompt replacement, and capability projection pipeline to `context_with_system` without an internal two-phase split. Delivery is anchored using plain `custom` session entries under the same delivery type (`pi-forge-capability-delivery`) carrying strictly cursor-only metadata (`{ schemaVersion: 1, throughEventId: string }`).
32
+
33
+ - **Anchor persistence points:**
34
+ - **Idle:** persisted immediately upon `/capability` execution or synchronization.
35
+ - **Running session:** safely deferred while a tool loop is busy; anchors are never inserted between an in-flight tool call and its matching result.
36
+ - **On `agent_end`:** uncommitted pending anchors are committed after the assistant's final response when no Forge context failure or incomplete batch remains, before the next user turn.
37
+ - **Cycle reset on `agent_settled`:** while `agent_end` commits anchors, compile cycles and the busy fence reset only on `agent_settled`. This ensures `agent_before_settle` continuations preserve compiled Preset inputs and active capabilities across low-level runs.
38
+ - **Context assembly via canonical projection:**
39
+ - Runtime, Preview, and anchor helpers build against Pi 0.87's `buildSessionProjection` (handling `context_edit` omissions, replacements, and `sourceEntry`). Raw session history on disk is never modified.
40
+ - `prepareCapabilityMessages` materializes before Preset compilation plain metadata anchors into ephemeral in-memory markers at their exact ordinal positions, verifying a unique ordered alignment against the canonical session projection.
41
+ - Incoming SDK leading System prompts always remain first; Forge's own prefix plain metadata anchors are inserted after it.
42
+ - `projectCapabilityMessages` then projects active capability deltas into native request-only `SystemMessage.sections` or fallback attributed timeline user messages.
43
+ - **Decoupled UI notification:** UI status notifications (`ctx.ui.setStatus` and Web activity panel) are completely independent and never enqueue turns to the model.
44
+
45
+ Preceding extension message rewrites (modifying messages in context hooks) are a legal and valid Pi SDK capability. However, Forge's anchor materialization requires a unique ordered alignment with canonical session entries. Content/protocol rewrites, inserted messages, non-custom omissions and ambiguous custom-message omissions fail closed. Prior full-System context extensions must move to `context_with_system`; `before_agent_start` forced System prompt injection continues to execute later in Pi's lifecycle; and final request arbitrary preceding rewrites still fail closed. Users may adjust conflicting extension order or extension behavior, but this is an operational suggestion only; Forge does not guarantee post-extension rewrite safety, nor can it guarantee generic plugin compatibility, prompt cache retention, warming, or automatic overflow handling. Upstream Pi metadata chunking and semantic-cut defects are NOT patched and remain unfixed upstream; legacy session carriers remain untouched, and Oh My Pi (OMP) is not supported or promised.
46
+
47
+ The SDK queue exception is explicit: persisted custom messages can be absent from the current tool follow-up and have different live/persisted envelope timestamps. Compare full content/protocol fields, ignore only the regenerated custom timestamp, and permit custom-message omissions only when earliest/latest ordered alignments agree. Identical ambiguous omissions fail closed. Never rebuild/overwrite incoming context or reinsert omitted peer messages.
48
+
49
+ ## Resource and binding contract
50
+
51
+ Discovered directories:
52
+
53
+ - `.pi/forge/capabilities/*.json`
54
+ - `~/.pi/forge/capabilities/*.json`
55
+
56
+ ```json
57
+ {
58
+ "schemaVersion": 1,
59
+ "type": "pi-forge.capability",
60
+ "id": "review",
61
+ "name": "Review",
62
+ "description": "Report findings and evidence before editing.",
63
+ "content": "List findings, evidence and risks. Do not directly edit files.",
64
+ "tools": {
65
+ "add": ["grep", "find", "ls"],
66
+ "remove": ["bash", "powershell", "write", "edit"]
67
+ }
68
+ }
69
+ ```
70
+
71
+ The definition has no Agent authorization. Content is literal text, not an executable template or file path. `name`/`description` are optional; omitted tool arrays normalize to empty arrays. At least non-whitespace text or one tool effect is required. Content is bounded to 100,000 characters, name to 1,000, each tool array to 256 names and each exact tool name to 128 characters. Tool names cannot contain whitespace, controls, `*` or `?`. Capabilities support `add` and `remove` only; candidate `only` or capability-level allowlists are not implemented. Unknown and malformed fields fail closed.
72
+
73
+ Preset binding field:
74
+
75
+ ```json
76
+ {
77
+ "capabilities": [{
78
+ "ref": "global:review",
79
+ "id": "review",
80
+ "modelCallable": true,
81
+ "overrides": {
82
+ "appendContent": "Also inspect backwards compatibility.",
83
+ "tools": { "add": ["grep", "find"] }
84
+ }
85
+ }]
86
+ }
87
+ ```
88
+
89
+ The `capabilities` field is live in the Preset schema and validated by codecs and editors.
90
+
91
+ ### Accepted 9/21 amendment: Tool selection and UX refinements
92
+
93
+ - **Preset initial tools (`tools.initial?: string[]`):** Configures initial active tools for a preset using concrete valid tool names (no wildcards allowed). When omitted, legacy behavior is preserved (selective allow selects matching registered tools; unrestricted/deny retains or filters the session baseline). When set to `[]`, zero tools are active initially. The `allow`/`deny` ceiling remains authoritative and exclusive; tools blocked by policy produce validation errors. Extensions and mods register allowed inactive tools: if `initial` is set, dynamically registered tools remain inactive unless listed or added by an active capability. Configured defaults serve as the active base throughout preset activation (not a one-time reset per turn): disabling a capability or calling disable/reset restores these defaults plus remaining capabilities; disabling the preset restores the reconciled session baseline (including preserved external changes).
94
+ - **Capability grouped picker:** The tool picker organizes tools using SDK `sourceInfo` (Pi built-in tools, packages, or top-level entry points). It saves exact concrete tool names: no package references are persisted, no packages are auto-installed, and newly added package tools are not auto-added. Inactive registered tools are visible in the picker; unloaded tools are unavailable in the session, but manual saved references are preserved.
95
+ - **Preset bindings tab:** Preset bindings are relocated from Preset metadata to a dedicated peer **Capability bindings** tab (`bindings`). Overrides (content, tools add/remove) and source-effective preview are collapsed under an advanced toggle (`showAdvanced` / `hideAdvanced`).
96
+ - **Default tools editor:** An opt-in, searchable, collapsible grouped picker in the Policy tab allows choosing default tools, while retaining advanced literal and wildcard allow/deny policy.
97
+ - **Save execution behavior:** Saving a Capability in the Capabilities surface updates its library definition only and never activates it. Saving an inactive Preset updates disk bytes without selecting or activating it. Crucially, saving the currently active Preset reloads and syncs its live tool and capability authorization policy immediately in the session without replacing frozen active capability snapshots (UI docs accurately reflect this; never promise that all saves leave execution untouched).
98
+ - **Compatibility and versioning:** Stacks using `tools.initial` require new Forge (older Forge ignores `initial`, not downgrade-compatible). Development remains in the 0.5.4 tree with release version bump pending (0.5.5 or maybe 0.6); host requirement remains Pi `>=0.87.0 <0.88.0` unchanged.
99
+ - **Prompt caching:** On compatible Codex transports, first-time additions can preserve request prefixes if retained history contains no removals/redeclarations; this is not a cache-hit guarantee. Removals/re-additions use the full-current-tool fallback. No permission bypass or caching guarantees.
100
+
101
+ - Direct library selection of a bare ID uses project-over-global. Invalid or duplicate local definitions do not fall back to global.
102
+ - A bare Preset reference resolves in its owner's scope. A project Preset must explicitly write `global:<id>` to use a global capability; a global Preset cannot use project capabilities.
103
+ - UI writes qualified references. Binding ID defaults to the referenced ID; duplicate effective binding IDs are rejected, including same-name cross-scope references unless explicitly disambiguated. At most 256 bindings per Preset.
104
+ - Only `modelCallable: true` grants eligibility for the Agent control path; omission defaults to `false`. Current tool policy and registration still apply on every call.
105
+ - Overrides allow `content` (replace) **or** `appendContent` (paragraph append with two newlines), never both. Each specified `tools.add`/`tools.remove` array replaces that entire field; the other field is preserved. Identity, name, authorization, and arbitrary fields cannot be overridden.
106
+ - Base resources must validate before applying overrides; an override cannot repair an invalid source silently. Effective results are defensive snapshots.
107
+
108
+ ## Semantic events and snapshots
109
+
110
+ The internal schema is persisted through existing `session-adapter`/Pi custom entries, not a new persistence backend. Semantic entries carry validated snapshots; delivery messages carry only a versioned event cursor. Baseline records belong to the existing tool-policy owner.
111
+
112
+ Common event fields: `schemaVersion: 1`, `eventId`, `op`, `actor`, `createdAt` (finite nonnegative milliseconds). Branch order, not timestamps, determines reduction. Opaque event/activation IDs are at most 128 characters. Resource/Preset/binding IDs keep the existing grammar.
113
+
114
+ - **activate:** actor `user` or `agent`, with an immutable `snapshot` containing `activationId`, `source`, optional name, content, normalized tool patch, and content fingerprint.
115
+ - **deactivate:** targets an `activationId`; actor `user`, `agent` or `lifecycle`.
116
+ - **reset:** user only. Clears current activity, not historical events.
117
+ - Source is `{ kind: "manual" }` or `{ kind: "capability", key: { scope, id }, binding?: { preset: { scope, id }, id } }`.
118
+ - Agent activation requires an authorized bound capability (`modelCallable: true`). Agent deactivation cannot close user-owned activations. Lifecycle deactivation is restricted to bound capabilities; it cannot clear manual or unbound user rules.
119
+ - Unknown/repeated off is a no-op. Activation IDs cannot be reused within one branch even after reset/off. Repeated identical event IDs are no-ops without moving the latest event marker backwards; conflicting reuse fails closed.
120
+ - Repeated `enable` is deduplicated and idempotent; it never performs an automatic owner takeover between user and agent. Takeover requires explicit deactivation and reactivation.
121
+ - Malformed owned event data fails reduction with an index/error, never a partially restored active set. Unrelated Pi entries are filtered by the adapter, not fed as fake capability events.
122
+ - Fingerprints use Forge's canonical `sha256:v1` algorithm. The payload is domain-tagged effective source/name/content/tools, excluding activation ID. It represents content identity, not a cryptographic signature.
123
+
124
+ Snapshot content never drifts with source edits. Switching Presets appends deactivations for old bound activations while retaining manual and unbound user rules; reloading the same Preset retains immutable active snapshots. Revoked authorization does not retroactively erase active snapshots; human recovery via CLI or Web disable/reset is the recovery path.
125
+
126
+ ## Delivery, recovery, tools, and parent safeguards
127
+
128
+ Derived plain `custom` metadata entries anchor delivery; they do not independently own active state, duplicate authoritative snapshot payloads, or pollute conversation dialogue. One semantic history supports both presentations:
129
+
130
+ - Native: request-only `SystemMessage.sections` keyed by activation identity; off uses a null patch and Pi's existing removal wording, without an extra duplicate user notice.
131
+ - Unsupported models: an attributed timeline user update/stop notice. Do not silently fold Forge capability updates into the leading prompt. Genuine user/tool content is never promoted to system authority.
132
+ - Transform only clearly owned Forge rule content, never an entire mixed system message. Preserve unrelated content/sections and `toolsAdded`/`toolsRemoved` for Pi's adapters.
133
+ - Compaction requires an owned current-state checkpoint derived from semantic events; suppress pre-checkpoint anchors, including retained-tail copies, then replay later deltas. Request-only sections are not automatically saved by Pi's raw transcript checkpoint. Checkpoint placement remains unchanged (precedes summary, follows leading system prompt); the upstream Pi metadata chunking bug is an independent issue and remains unfixed.
134
+ - Compaction input characterization: in real SDK compaction, summarizers receive no metadata anchors and no Forge rule bodies (projection is request-only), while user, assistant, and peer dialogue are preserved. Simulated responses in test harnesses characterize request plumbing and harness shape, not remote LLM semantic compaction fidelity or summarizer compliance.
135
+ - **Breaking pre-release rename boundary:** no legacy aliases or readers are provided for the former instruction-mode schema, directories, or capability state. Existing development configuration must be converted and continuing old sessions are unsupported; Forge does not rewrite old JSONL or historical summaries, so converted configurations require a new session.
136
+ - Immediate tool synchronization vs. next-request prompt projection: admission validates text/reference/authorization/tool effects before commit. Executable tool policy synchronizes *immediately* (`sync()` / `setActiveTools()`), whereas prompt text and native sections or user updates take effect at the *next model request* boundary. Running tool batches are not interrupted.
137
+ - Tool policy calculation: tools are computed from a recoverable baseline plus all remaining additions minus all remaining removals, subject to top-level Preset deny policy; removal wins globally across active capabilities. Additions must be registered and permitted by the active Preset.
138
+ - Read-only resource discovery and Preview: inspecting capabilities, calling `GET /api/capability-state/available`, or inspecting the Preview dock never mutates tool policies, commits session events, or marks pending capabilities prepared.
139
+ - Parent safeguards:
140
+ - Raw source and revision coherence: GET operations couple editable data and `sourceRevision` from the same raw file bytes.
141
+ - External new bindings stale save detection: Preset saves enforce `sourceRevision` checks whenever bindings are present or modified, rejecting stale overwrites (409 Conflict) if the file changed on disk (including externally added bindings).
142
+ - Lifecycle and re-entry fences: explicit `disposed` flag, `lifecycleRevision` increment, and `sameContext` verification prevent cross-session pollution or operations after session disposal.
143
+ - Provider-managed cache warning: prompt caching, tool transport, and KV cache hits are downstream provider-managed. Stable prefixes may help caching, but schema changes, removals, fallback, base recompilation, model switches, and compaction alter cache boundaries; pi-forge provides no guarantees of zero KV invalidation or exact cache hits.
144
+ - Human recovery: human CLI (`/capability disable`, `/capability reset`) and Web panel controls remain available; an Agent-owned capability cannot disable its own control path without a safe recovery policy.
145
+
146
+ ## Staged implementation and release gates
147
+
148
+ 1. **Foundation (verified):** JSON codec, finite overrides, scoped resolution, immutable snapshots, and strict event reduction.
149
+ 2. **Human CLI core and metadata anchor projection (implemented):** Pi 0.87 dependency upgrade, `context_with_system` full pipeline, `buildSessionProjection` canonical alignment, request-base bridge, scoped discovery, session event persistence, plain `custom` cursor-only metadata anchors (replacing transcript carriers), ordinal materialization, compaction checkpoints, and executable tool-policy coordination. Real SDK tests cover same-run toggles, native/fallback switches, fake tool execution, disk reopens, branches, crash-window baseline recovery, and legitimate preceding extension rewrite fail-closed safety.
150
+ 3. **Session activity UI and compaction characterization (implemented):** read/control view derived from the existing runtime, never a second state owner. Human disable/reset carries an exact session/leaf/revision guard with runtime-instance fencing; Web requires trust, pure reads never synchronize or infer, and stale pages cannot retry writes automatically. Real-SDK compaction-input characterization confirms Forge metadata and request-only rules are absent from summarizer history while user, assistant, and peer dialogue remain intact; fake test responses are plumbing characterization, not remote semantic validation.
151
+ 4. **Preset authorization and restricted Agent control (implemented):** live Preset binding schema (`capabilities`), opt-in `modelCallable: true`, and restricted fixed-schema `forge_capability` (list, status, enable, disable, ID ≤ 128 chars). Per-call trust, binding identity, authorization, and tool policy checks prevent privilege escalation. CLI additions `/capability bindings` and `/capability enable-bound <id>` provide human parity. Management operations do not initiate paid inference.
152
+ 5. **Capabilities library CRUD, binding editor, and guarded human Web activation picker (delivered in functional source):** dedicated **Capabilities** surface for project/global capability CRUD with `sourceRevision` stale-save guards; Preset metadata bindings editor with finite overrides and live source-effective preview; guarded human Web activation picker (`GET /api/capability-state/available`, `POST /api/capability-state/enable`) with pre-activation preview and session/leaf/revision plus content fingerprint validation. Parent safeguards enforce raw source/revision coherence, external new bindings stale-save detection, and lifecycle/re-entry fences.
153
+ 6. **Release closeout (pending release review and user authorization):** Pi 0.87 migration and accepted tool-selection/UX amendment passed parent build and full verification (773 Node / 37 browser). Development package version remains 0.5.4; release version bump decision pending between 0.5.5 or 0.6; repo dev SDK is pinned to `0.87.0` with peer range `>=0.87.0 <0.88.0` (no dual 0.86 support claim); release, git push, and host reload (`/reload`) are separate user-authorized actions.
154
+
155
+ Acceptance includes old Presets, regex/history filtering, repeated same-run toggles, native/user/native transitions, request abort/retry/concurrency, explicit and automatic compaction, disk resume/branches/crash boundaries, baseline recovery, real tool-call rejection, external tool changes, warming, and payload/usage association.
156
+
157
+ No universal native support, obedience, zero-KV-invalidation, or guaranteed cache-hit claims. No automatic legacy migration, no old summary rewrites, and no Pi split patch. Publishing, host upgrades, reloads, and deployment remain separate user-authorized actions.
@@ -2,36 +2,36 @@
2
2
 
3
3
  [Documentation](../README.md)
4
4
 
5
- ## Before release
6
-
7
- 1. Confirm the changelog and user documentation describe the intended version and experimental surfaces accurately.
8
- 2. Publish and smoke-test any required `@zihanw/pi-subagent-runtime` version first.
9
- 3. Install dependencies from the lockfile and run `npm run verify`; require the
10
- Ubuntu, macOS, and Windows GitHub Actions jobs to pass for the release commit.
11
- 4. Test a packed installation against the documented minimum and current Pi versions.
12
- 5. Exercise ordinary stack/profile use independently of delegation.
13
- 6. Exercise both configured foreground backends and confirm unsupported host capabilities fail closed before provider transport.
14
- 7. Inspect `npm pack --dry-run` for package size and unexpected or missing files.
15
-
16
- The macOS and Windows jobs run the same complete verification surface as Linux,
17
- including the real-browser editor suite against the hosted runner's system
18
- Chrome. Compatibility-version and scheduled latest-Pi probes remain Linux-only;
19
- they test dependency drift rather than operating-system behavior.
5
+ ## Independent packages
6
+
7
+ The main `@zihanw/pi-forge` package has **no** dependency on `@zihanw/pi-forge-subagents` or `@zihanw/pi-subagent-runtime`. It can release independently; unfinished optional features do not block ordinary Forge use or a main-package release.
8
+
9
+ The optional package is tested against the released Forge host before its own publication. Any required runtime version must be published and smoke-tested before publishing the optional package that depends on it. Backend, continuation, background-task, and nested-usage producer acceptance belong to that companion release, not to the main package.
10
+
11
+ ## Before main-package release
12
+
13
+ 1. Confirm the intended version in the manifest, lockfile, changelog, and current user documentation. Preserve historical release records and document breaking configuration/session boundaries.
14
+ 2. Install dependencies from the lockfile with `npm ci`, build, and run the complete `npm run verify` chain: Node tests, browser tests, types, generated client, docs, distribution, package contents, and packed installation.
15
+ 3. Require the Ubuntu, macOS, Windows, and configured Pi compatibility GitHub Actions jobs to pass for the **exact release commit**, not an earlier source revision.
16
+ 4. Test a packed main-package installation against both the documented minimum and current tested Pi versions; exercise ordinary Preset/Profile/Capability behavior independently of optional delegation.
17
+ 5. Inspect `npm pack --dry-run` for package size and unexpected or missing files. Publish the verified artifact, not an unreviewed working tree.
18
+
19
+ The macOS and Windows jobs run the same complete verification surface as Linux, including the real-browser editor suite. Compatibility-version and scheduled latest-Pi probes remain Linux-only; they test dependency drift rather than operating-system behavior.
20
20
 
21
21
  ## Dependency policy
22
22
 
23
- Published manifests use wildcard peer dependencies for Pi-host-provided SDK packages. Exact versions belong in development dependencies and the lockfile so tests are reproducible without restricting compatible host releases.
23
+ The four Pi SDK packages remain host-provided optional peers, never private runtime dependencies. Forge 0.5.6 requires Pi `>=0.87.0 <0.88.0`, with development fixtures pinned to `0.87.0`; `typebox` remains a wildcard optional peer. Pi 0.86 and future minor versions are not implicitly supported. Exact tested versions belong in development dependencies and the lockfile, not exact host-version requirements.
24
24
 
25
- `pi-subagent-runtime` remains a normal exact dependency until its compatibility policy says otherwise. Its own host-facing Pi dependencies must follow the same host-provided peer model.
25
+ Published `@zihanw/pi-forge-subagents` 0.5.3 does not understand `tools.initial`. The upcoming optional package needs the matching fix and a Forge dependency floor of `^0.5.5` for the new command-contribution entry. This is a companion compatibility gate, not a requirement to publish the packages simultaneously. See the [host-port compatibility note](../reference/subagent-host-port.md#tool-selection-compatibility).
26
26
 
27
27
  ## Package contents
28
28
 
29
- The tarball must include compiled `dist/`, examples, the English and Chinese landing pages, changelog, license, and user/reference documentation. It must not include physical `src/` files. Both the default extension entry and experimental subagent entry must resolve to compiled output.
29
+ The tarball must include compiled `dist/`, examples, the English and Chinese landing pages, changelog, license, and user/reference documentation. It must not include physical `src/` files. The root, `/subagent`, `/ui-contribution`, and `/command-contribution` entries must resolve to compiled output.
30
30
 
31
31
  The root `PUBLIC_API.md` and `SUBAGENT_ADAPTER_CONTRACT.md` files are compatibility pointers; authoritative content lives under `docs/reference/`.
32
32
 
33
33
  ## Publish and verify
34
34
 
35
- Publish the intended version/tag, then install it through Pi in a clean project. Verify `/preset`, `/profile`, `/preset ui`, and—when deliberately enabled—delegation. Restart Pi after installation to avoid testing a stale extension instance.
35
+ With release authorization, publish the intended version using the intended tag (`latest` for a stable main-package release). Verify registry version, tag, and tarball integrity, then install the published package through Pi in a clean project and smoke-test the main commands and resource workflow without model inference.
36
36
 
37
- For a stable release, ensure npm `latest` points to the new version and any prerelease channel no longer leaves users on an incompatible older build.
37
+ Do not silently move unrelated legacy or prerelease tags. Publishing is not a host upgrade: restart or reload a user's existing host only with that user's authorization, and start a new session when the release's migration notes require it. Keep release evidence separate from static documentation; a version bump or changelog entry alone is not proof of successful publication.
@@ -4,7 +4,26 @@
4
4
 
5
5
  This file contains forward-looking product work only. Completed capability belongs in the [feature inventory](../reference/features.md), release history in the root [changelog](../../CHANGELOG.md), and completed investigation in the [design archive](../design/README.md).
6
6
 
7
- ## 0.5.0 breaking cleanup (lean)
7
+ ## Active 0.5.6: regression and UI closeout
8
+
9
+ The patch preserves the leading SDK System header, protects Preset/Profile edits, preflights Capability conflicts before Preset changes, and corrects auto-profile diagnostics. The user accepted whole-row disabled styling and browser-local resizing of the Presets/Stack items panes. Focused browser regressions and the exact-commit full CI/packed-install gates in the [release process](release.md) close out this patch. No schema change, new history semantics, optional-package publication or installed-host upgrade is implied.
10
+
11
+ ## 0.5.5 capability baseline (completed)
12
+
13
+ Implementation is authorized under the [accepted capability design](../design/pi-forge-system-update-design-notes.md) and [lean-plan amendment](../design/architecture-0.5.md#accepted-055-amendment-session-capabilities). Pi 0.86 is released; the old upstream-blocked thin-sections proposal is superseded.
14
+
15
+ One active lane at a time:
16
+
17
+ 1. **Foundation (verified):** strict capability/override codec, scoped binding resolution, immutable snapshots, and branch event reducer.
18
+ 2. **Human CLI core & metadata anchor projection (implemented):** Pi 0.87 dependency upgrade, request-base replacement, `context_with_system` full pipeline, `buildSessionProjection` canonical alignment, native/user projection, semantic events and plain `custom` cursor-only metadata anchors, durable tool baselines, repositories/ForgeWorkspace discovery, and `/capability` add/list/bindings/enable/enable-bound/disable/status/reset. See [current reference](../reference/capabilities.md).
19
+ 3. **Session observability & activity panel (implemented):** derived multi-capability state, actual selected tools, delivery status (`none`, `pending`, `prepared`), presentation indicators, and guarded human disable/reset; real SDK summarizer-input characterization.
20
+ 4. **Preset authorization & restricted Agent control (implemented):** live Preset binding schema (`capabilities`), opt-in `modelCallable: true`, and model-callable `forge_capability` tool with fixed list/status/enable/disable schema; per-call trust, binding identity, authorization, and tool policy checks; strict user-vs-agent ownership.
21
+ 5. **Capabilities library CRUD, Preset binding editor, and guarded human Web activation picker (delivered in functional source):** dedicated **Capabilities** surface for project/global capability CRUD with `sourceRevision` stale-save guards; dedicated peer Capability bindings editor with finite overrides and live source-effective preview; guarded human Web activation picker (`GET /api/capability-state/available`, `POST /api/capability-state/enable`) with pre-activation preview and session guard plus content fingerprint validation. Parent safeguards enforce raw source/revision coherence, external new bindings stale-save detection, and lifecycle/re-entry fences (`disposed`, `lifecycleRevision`, `sameContext`).
22
+ 6. **Main-package 0.5.5 release closeout:** The accepted UI and local full verification closed out on 2026-09-24 (`89c6ba2`); bilingual README B and reviewed continuous media are adopted. UI scope is frozen except for regressions/release blockers. The main package 0.5.5 was published; subsequent patches retain the exact-commit CI and packed-install gates in the [release process](release.md). No paid provider matrix is implied. The optional package and runtime have independent unfinished release work and are not a main-package gate. Repo dev SDK remains pinned to 0.87.0 with peer `>=0.87.0 <0.88.0` (no dual 0.86 support claim).
23
+
24
+ Existing README and optional Pet active-state changes are preserved. No host upgrade, reload or publication follows implicitly from local feature development. Foundation tests are not proof of live 0.5.5 behavior.
25
+
26
+ ## 0.5.0 breaking cleanup (lean history)
8
27
 
9
28
  0.5.0 is a deliberately breaking cleanup release plus the minimum foundation for 0.5.x. Net-new feature work is frozen.
10
29
 
@@ -78,7 +97,7 @@ Candidate history controls need concrete use cases and dangling tool-pair tests.
78
97
  - Skill filtering is model-visible prompt filtering, not an invocation or security boundary.
79
98
  - Delegation remains opt-in, foreground, clean-context, and fail-closed on missing capabilities, and lives in the optional package.
80
99
  - Do not report shared-user read-only policy as an OS sandbox.
81
- - New editor product workflows are frozen; migration changes retain real-browser coverage.
100
+ - New editor workflows remain frozen except the explicitly accepted capability surfaces above; migration and new workflows retain real-browser coverage.
82
101
  - Run the full verification and package checks before release.
83
102
 
84
103
  The detailed completed 0.4 plan is retained in the [historical roadmap](../design/roadmap-0.4-archive.md).
@@ -158,7 +158,7 @@ For compatibility:
158
158
 
159
159
  - Read legacy branch entries containing only `activeStackId` using effective lookup.
160
160
  - Write new entries with a scoped active-stack reference.
161
- - Preserve the explicit `none`/`off` selection as a scope-independent opt-out.
161
+ - Preserve the explicit `none`/`disable` selection as a scope-independent opt-out.
162
162
  - Profile provenance should add the profile scope/key while continuing to accept older provenance that has only `profileId` and `sourcePath`.
163
163
  - Drift snapshots should store the resolved scoped stack reference so status can distinguish definition changes from a scope change.
164
164
 
@@ -55,7 +55,7 @@ Set `CHROME_PATH` when Chrome/Chromium is outside a standard location. CI runs t
55
55
 
56
56
  ## Pi compatibility
57
57
 
58
- Published pi-forge treats Pi-owned SDK packages (`pi-agent-core`, `pi-ai`, `pi-coding-agent`, `pi-tui`, and `typebox`) as host-provided wildcard peers. The running Pi host supplies one coherent SDK instance, avoiding duplicate packages and avoiding an install-time lock to Pi's frequent release cadence.
58
+ Pi-forge treats Pi-owned SDK packages (`pi-agent-core`, `pi-ai`, `pi-coding-agent`, `pi-tui`, and `typebox`) as host-provided optional peers, not private runtime dependencies. The repository dev SDK is pinned to `0.87.0` and the peer requirement is `>=0.87.0 <0.88.0` for the four Pi SDK peers; `typebox` remains `*`. There is no claim of dual 0.86 runtime support. The running host supplies one coherent SDK instance, avoiding duplicate packages and exact-version locks while expressing the actual API requirement.
59
59
 
60
60
  The repository keeps exact SDK versions as development/test fixtures for reproducibility. Exact fixtures do not constrain which Pi version may load the published extension.
61
61
 
@@ -25,7 +25,7 @@ mkdir -p .pi/forge/prompt-stacks
25
25
  cp examples/default-prompt-stack.json .pi/forge/prompt-stacks/default.json
26
26
  ```
27
27
 
28
- When installed from npm, open `/preset ui` and create a stack; new stacks start from the same mirror layout.
28
+ Open `/forge ui` to create a preset without copying a file. In Forge 0.5.5, you can choose the default Pi mirror layout, an empty preset (where Pi retains its base prompt and history), or a minimal worker template (`bash` and `edit` only).
29
29
 
30
30
  Reload and activate it:
31
31