@zihanw/pi-forge 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (341) hide show
  1. package/CHANGELOG.md +49 -1
  2. package/README.md +11 -11
  3. package/README.zh-CN.md +4 -6
  4. package/SUBAGENT_ADAPTER_CONTRACT.md +3 -1
  5. package/dist/agent-profile.d.ts +21 -42
  6. package/dist/agent-profile.d.ts.map +1 -1
  7. package/dist/agent-profile.js +82 -194
  8. package/dist/agent-profile.js.map +1 -1
  9. package/dist/catalog.d.ts +27 -0
  10. package/dist/catalog.d.ts.map +1 -0
  11. package/dist/catalog.js +59 -0
  12. package/dist/catalog.js.map +1 -0
  13. package/dist/codecs/agent-profile.d.ts +53 -0
  14. package/dist/codecs/agent-profile.d.ts.map +1 -0
  15. package/dist/codecs/agent-profile.js +176 -0
  16. package/dist/codecs/agent-profile.js.map +1 -0
  17. package/dist/codecs/index.d.ts +5 -0
  18. package/dist/codecs/index.d.ts.map +1 -0
  19. package/dist/codecs/index.js +3 -0
  20. package/dist/codecs/index.js.map +1 -0
  21. package/dist/codecs/prompt-stack.d.ts +18 -0
  22. package/dist/codecs/prompt-stack.d.ts.map +1 -0
  23. package/dist/codecs/prompt-stack.js +479 -0
  24. package/dist/codecs/prompt-stack.js.map +1 -0
  25. package/dist/compile-cycle.d.ts +18 -0
  26. package/dist/compile-cycle.d.ts.map +1 -0
  27. package/dist/compile-cycle.js +13 -0
  28. package/dist/compile-cycle.js.map +1 -0
  29. package/dist/compiler.d.ts +10 -4
  30. package/dist/compiler.d.ts.map +1 -1
  31. package/dist/compiler.js +53 -19
  32. package/dist/compiler.js.map +1 -1
  33. package/dist/extension-registry.d.ts.map +1 -1
  34. package/dist/extension-registry.js +5 -2
  35. package/dist/extension-registry.js.map +1 -1
  36. package/dist/forge-config.d.ts +2 -81
  37. package/dist/forge-config.d.ts.map +1 -1
  38. package/dist/forge-config.js +5 -280
  39. package/dist/forge-config.js.map +1 -1
  40. package/dist/forge-v1/analyzer.d.ts +3 -0
  41. package/dist/forge-v1/analyzer.d.ts.map +1 -0
  42. package/dist/forge-v1/analyzer.js +50 -0
  43. package/dist/forge-v1/analyzer.js.map +1 -0
  44. package/dist/forge-v1/index.d.ts +6 -0
  45. package/dist/forge-v1/index.d.ts.map +1 -0
  46. package/dist/forge-v1/index.js +13 -0
  47. package/dist/forge-v1/index.js.map +1 -0
  48. package/dist/forge-v1/parser.d.ts +3 -0
  49. package/dist/forge-v1/parser.d.ts.map +1 -0
  50. package/dist/forge-v1/parser.js +186 -0
  51. package/dist/forge-v1/parser.js.map +1 -0
  52. package/dist/forge-v1/renderer.d.ts +9 -0
  53. package/dist/forge-v1/renderer.d.ts.map +1 -0
  54. package/dist/forge-v1/renderer.js +181 -0
  55. package/dist/forge-v1/renderer.js.map +1 -0
  56. package/dist/forge-v1/types.d.ts +87 -0
  57. package/dist/forge-v1/types.d.ts.map +1 -0
  58. package/dist/forge-v1/types.js +4 -0
  59. package/dist/forge-v1/types.js.map +1 -0
  60. package/dist/index.d.ts +12 -9
  61. package/dist/index.d.ts.map +1 -1
  62. package/dist/index.js +49 -59
  63. package/dist/index.js.map +1 -1
  64. package/dist/lifecycle.d.ts +7 -5
  65. package/dist/lifecycle.d.ts.map +1 -1
  66. package/dist/lifecycle.js +44 -110
  67. package/dist/lifecycle.js.map +1 -1
  68. package/dist/loader.d.ts +16 -3
  69. package/dist/loader.d.ts.map +1 -1
  70. package/dist/loader.js +42 -440
  71. package/dist/loader.js.map +1 -1
  72. package/dist/macro-engine.d.ts +9 -14
  73. package/dist/macro-engine.d.ts.map +1 -1
  74. package/dist/macro-engine.js +5 -238
  75. package/dist/macro-engine.js.map +1 -1
  76. package/dist/payload-command.d.ts +6 -6
  77. package/dist/payload-command.d.ts.map +1 -1
  78. package/dist/payload-command.js.map +1 -1
  79. package/dist/payload-state.d.ts +16 -0
  80. package/dist/payload-state.d.ts.map +1 -0
  81. package/dist/payload-state.js +14 -0
  82. package/dist/payload-state.js.map +1 -0
  83. package/dist/preset-command.d.ts +4 -4
  84. package/dist/preset-command.d.ts.map +1 -1
  85. package/dist/preset-command.js +55 -98
  86. package/dist/preset-command.js.map +1 -1
  87. package/dist/preview.d.ts +4 -4
  88. package/dist/preview.d.ts.map +1 -1
  89. package/dist/preview.js +17 -8
  90. package/dist/preview.js.map +1 -1
  91. package/dist/profile-command.d.ts +2 -2
  92. package/dist/profile-command.d.ts.map +1 -1
  93. package/dist/profile-command.js +52 -26
  94. package/dist/profile-command.js.map +1 -1
  95. package/dist/profile-service.d.ts +5 -2
  96. package/dist/profile-service.d.ts.map +1 -1
  97. package/dist/profile-service.js +63 -42
  98. package/dist/profile-service.js.map +1 -1
  99. package/dist/prompt-analysis.d.ts +24 -0
  100. package/dist/prompt-analysis.d.ts.map +1 -0
  101. package/dist/prompt-analysis.js +84 -0
  102. package/dist/prompt-analysis.js.map +1 -0
  103. package/dist/prompt-runtime.d.ts +19 -0
  104. package/dist/prompt-runtime.d.ts.map +1 -0
  105. package/dist/prompt-runtime.js +30 -0
  106. package/dist/prompt-runtime.js.map +1 -0
  107. package/dist/regex.js +6 -12
  108. package/dist/regex.js.map +1 -1
  109. package/dist/render-helpers.d.ts +2 -10
  110. package/dist/render-helpers.d.ts.map +1 -1
  111. package/dist/render-helpers.js +3 -53
  112. package/dist/render-helpers.js.map +1 -1
  113. package/dist/repositories/agent-profile.d.ts +36 -0
  114. package/dist/repositories/agent-profile.d.ts.map +1 -0
  115. package/dist/repositories/agent-profile.js +153 -0
  116. package/dist/repositories/agent-profile.js.map +1 -0
  117. package/dist/repositories/index.d.ts +3 -0
  118. package/dist/repositories/index.d.ts.map +1 -0
  119. package/dist/repositories/index.js +3 -0
  120. package/dist/repositories/index.js.map +1 -0
  121. package/dist/repositories/prompt-stack.d.ts +57 -0
  122. package/dist/repositories/prompt-stack.d.ts.map +1 -0
  123. package/dist/repositories/prompt-stack.js +175 -0
  124. package/dist/repositories/prompt-stack.js.map +1 -0
  125. package/dist/resource-identity.d.ts +33 -0
  126. package/dist/resource-identity.d.ts.map +1 -0
  127. package/dist/resource-identity.js +56 -0
  128. package/dist/resource-identity.js.map +1 -0
  129. package/dist/runtime/profile-runtime.d.ts +2 -2
  130. package/dist/runtime/profile-runtime.d.ts.map +1 -1
  131. package/dist/runtime/profile-runtime.js +18 -10
  132. package/dist/runtime/profile-runtime.js.map +1 -1
  133. package/dist/runtime/prompt-stack-runtime.d.ts +5 -4
  134. package/dist/runtime/prompt-stack-runtime.d.ts.map +1 -1
  135. package/dist/runtime/prompt-stack-runtime.js +47 -52
  136. package/dist/runtime/prompt-stack-runtime.js.map +1 -1
  137. package/dist/runtime/tool-policy-runtime.d.ts +2 -2
  138. package/dist/runtime/tool-policy-runtime.d.ts.map +1 -1
  139. package/dist/runtime/tool-policy-runtime.js +3 -3
  140. package/dist/runtime/tool-policy-runtime.js.map +1 -1
  141. package/dist/session-adapter.d.ts +17 -0
  142. package/dist/session-adapter.d.ts.map +1 -0
  143. package/dist/session-adapter.js +57 -0
  144. package/dist/session-adapter.js.map +1 -0
  145. package/dist/slot-renderers.d.ts +16 -3
  146. package/dist/slot-renderers.d.ts.map +1 -1
  147. package/dist/slot-renderers.js +15 -63
  148. package/dist/slot-renderers.js.map +1 -1
  149. package/dist/stack-migration.d.ts +6 -0
  150. package/dist/stack-migration.d.ts.map +1 -1
  151. package/dist/stack-migration.js +49 -52
  152. package/dist/stack-migration.js.map +1 -1
  153. package/dist/storage.d.ts +10 -0
  154. package/dist/storage.d.ts.map +1 -1
  155. package/dist/storage.js +45 -10
  156. package/dist/storage.js.map +1 -1
  157. package/dist/subagent/fingerprints.d.ts +24 -0
  158. package/dist/subagent/fingerprints.d.ts.map +1 -0
  159. package/dist/subagent/fingerprints.js +81 -0
  160. package/dist/subagent/fingerprints.js.map +1 -0
  161. package/dist/subagent/host-port.d.ts +296 -0
  162. package/dist/subagent/host-port.d.ts.map +1 -0
  163. package/dist/subagent/host-port.js +560 -0
  164. package/dist/subagent/host-port.js.map +1 -0
  165. package/dist/subagent/index.d.ts +10 -10
  166. package/dist/subagent/index.d.ts.map +1 -1
  167. package/dist/subagent/index.js +9 -10
  168. package/dist/subagent/index.js.map +1 -1
  169. package/dist/subagent-host.d.ts +99 -18
  170. package/dist/subagent-host.d.ts.map +1 -1
  171. package/dist/subagent-host.js +185 -162
  172. package/dist/subagent-host.js.map +1 -1
  173. package/dist/template-render.d.ts +18 -0
  174. package/dist/template-render.d.ts.map +1 -0
  175. package/dist/template-render.js +232 -0
  176. package/dist/template-render.js.map +1 -0
  177. package/dist/types.d.ts +43 -27
  178. package/dist/types.d.ts.map +1 -1
  179. package/dist/types.js.map +1 -1
  180. package/dist/web-editor/client-script.generated.d.ts.map +1 -1
  181. package/dist/web-editor/client-script.generated.js +1 -1
  182. package/dist/web-editor/client-script.generated.js.map +1 -1
  183. package/dist/web-editor/client-styles.generated.d.ts.map +1 -1
  184. package/dist/web-editor/client-styles.generated.js +1 -1
  185. package/dist/web-editor/client-styles.generated.js.map +1 -1
  186. package/dist/web-editor/server.d.ts.map +1 -1
  187. package/dist/web-editor/server.js +32 -72
  188. package/dist/web-editor/server.js.map +1 -1
  189. package/dist/web-editor/styles.d.ts.map +1 -1
  190. package/dist/web-editor/styles.js +13 -0
  191. package/dist/web-editor/styles.js.map +1 -1
  192. package/dist/web-editor/types.d.ts +10 -37
  193. package/dist/web-editor/types.d.ts.map +1 -1
  194. package/dist/web-host.d.ts +4 -2
  195. package/dist/web-host.d.ts.map +1 -1
  196. package/dist/web-host.js +110 -138
  197. package/dist/web-host.js.map +1 -1
  198. package/dist/workspace.d.ts +74 -0
  199. package/dist/workspace.d.ts.map +1 -0
  200. package/dist/workspace.js +351 -0
  201. package/dist/workspace.js.map +1 -0
  202. package/docs/README.md +6 -4
  203. package/docs/concepts/agent-profiles.md +2 -2
  204. package/docs/concepts/prompt-stacks.md +12 -7
  205. package/docs/design/README.md +21 -3
  206. package/docs/design/architecture-0.5.md +211 -0
  207. package/docs/design/archive/0.5-full-proposal/0.5-consumer-audit.md +62 -0
  208. package/docs/design/archive/0.5-full-proposal/0.5-inventory.md +208 -0
  209. package/docs/design/archive/0.5-full-proposal/0.5-phase0-decision-drafts.md +237 -0
  210. package/docs/design/archive/0.5-full-proposal/README.md +12 -0
  211. package/docs/design/archive/0.5-full-proposal/architecture-0.5.md +423 -0
  212. package/docs/design/archive/0.5-full-proposal/host-discovery-spike.md +103 -0
  213. package/docs/design/archive/0.5-full-proposal/template-language-spike.md +156 -0
  214. package/docs/design/context-diff-plan.md +72 -0
  215. package/docs/design/decision-template.md +33 -0
  216. package/docs/design/roadmap-0.4-archive.md +1 -1
  217. package/docs/design/subagents/interface-design.md +1 -1
  218. package/docs/development/architecture-rules.md +148 -0
  219. package/docs/development/roadmap.md +39 -13
  220. package/docs/development/scoped-global-profiles-stacks.md +325 -0
  221. package/docs/development/setup.md +6 -4
  222. package/docs/getting-started.md +9 -6
  223. package/docs/guides/custom-macros-and-slots.md +8 -7
  224. package/docs/guides/debugging.md +1 -1
  225. package/docs/guides/delegation.md +25 -21
  226. package/docs/guides/migrating-to-0.5.md +107 -0
  227. package/docs/guides/use-cases.md +7 -11
  228. package/docs/guides/web-editor.md +7 -11
  229. package/docs/reference/commands.md +4 -3
  230. package/docs/reference/configuration.md +18 -17
  231. package/docs/reference/features.md +34 -79
  232. package/docs/reference/macros-and-slots.md +70 -49
  233. package/docs/reference/public-api.md +64 -17
  234. package/docs/reference/stack-schema.md +14 -9
  235. package/docs/reference/subagent-host-port.md +49 -0
  236. package/docs/zh-CN/README.md +3 -3
  237. package/docs/zh-CN/concepts/agent-profiles.md +4 -2
  238. package/docs/zh-CN/concepts/prompt-stacks.md +9 -7
  239. package/docs/zh-CN/getting-started.md +10 -7
  240. package/docs/zh-CN/guides/delegation.md +11 -13
  241. package/docs/zh-CN/guides/migrating-to-0.5.md +92 -0
  242. package/docs/zh-CN/guides/web-editor.md +7 -7
  243. package/docs/zh-CN/reference/commands.md +6 -3
  244. package/examples/custom-system-status-extension/README.md +3 -3
  245. package/examples/custom-system-status-extension/index.ts +2 -1
  246. package/examples/custom-system-status-extension/prompt-stack.json +4 -3
  247. package/examples/default-prompt-stack.json +9 -4
  248. package/examples/image-reader-prompt-stack.json +16 -26
  249. package/examples/reviewer-prompt-stack.json +13 -24
  250. package/package.json +101 -120
  251. package/dist/runtime/subagent-runtime.d.ts +0 -45
  252. package/dist/runtime/subagent-runtime.d.ts.map +0 -1
  253. package/dist/runtime/subagent-runtime.js +0 -335
  254. package/dist/runtime/subagent-runtime.js.map +0 -1
  255. package/dist/runtime-state.d.ts +0 -30
  256. package/dist/runtime-state.d.ts.map +0 -1
  257. package/dist/runtime-state.js +0 -17
  258. package/dist/runtime-state.js.map +0 -1
  259. package/dist/sillytavern-importer/items.d.ts +0 -3
  260. package/dist/sillytavern-importer/items.d.ts.map +0 -1
  261. package/dist/sillytavern-importer/items.js +0 -88
  262. package/dist/sillytavern-importer/items.js.map +0 -1
  263. package/dist/sillytavern-importer/macros.d.ts +0 -15
  264. package/dist/sillytavern-importer/macros.d.ts.map +0 -1
  265. package/dist/sillytavern-importer/macros.js +0 -141
  266. package/dist/sillytavern-importer/macros.js.map +0 -1
  267. package/dist/sillytavern-importer/prompt-order.d.ts +0 -6
  268. package/dist/sillytavern-importer/prompt-order.d.ts.map +0 -1
  269. package/dist/sillytavern-importer/prompt-order.js +0 -38
  270. package/dist/sillytavern-importer/prompt-order.js.map +0 -1
  271. package/dist/sillytavern-importer/regex.d.ts +0 -3
  272. package/dist/sillytavern-importer/regex.d.ts.map +0 -1
  273. package/dist/sillytavern-importer/regex.js +0 -275
  274. package/dist/sillytavern-importer/regex.js.map +0 -1
  275. package/dist/sillytavern-importer/report.d.ts +0 -21
  276. package/dist/sillytavern-importer/report.d.ts.map +0 -1
  277. package/dist/sillytavern-importer/report.js +0 -166
  278. package/dist/sillytavern-importer/report.js.map +0 -1
  279. package/dist/sillytavern-importer/types.d.ts +0 -106
  280. package/dist/sillytavern-importer/types.d.ts.map +0 -1
  281. package/dist/sillytavern-importer/types.js +0 -2
  282. package/dist/sillytavern-importer/types.js.map +0 -1
  283. package/dist/sillytavern-importer.d.ts +0 -5
  284. package/dist/sillytavern-importer.d.ts.map +0 -1
  285. package/dist/sillytavern-importer.js +0 -117
  286. package/dist/sillytavern-importer.js.map +0 -1
  287. package/dist/subagent/canonical.d.ts +0 -22
  288. package/dist/subagent/canonical.d.ts.map +0 -1
  289. package/dist/subagent/canonical.js +0 -24
  290. package/dist/subagent/canonical.js.map +0 -1
  291. package/dist/subagent/context.d.ts +0 -8
  292. package/dist/subagent/context.d.ts.map +0 -1
  293. package/dist/subagent/context.js +0 -125
  294. package/dist/subagent/context.js.map +0 -1
  295. package/dist/subagent/contract.d.ts +0 -10
  296. package/dist/subagent/contract.d.ts.map +0 -1
  297. package/dist/subagent/contract.js +0 -10
  298. package/dist/subagent/contract.js.map +0 -1
  299. package/dist/subagent/plan.d.ts +0 -18
  300. package/dist/subagent/plan.d.ts.map +0 -1
  301. package/dist/subagent/plan.js +0 -157
  302. package/dist/subagent/plan.js.map +0 -1
  303. package/dist/subagent/preflight.d.ts +0 -4
  304. package/dist/subagent/preflight.d.ts.map +0 -1
  305. package/dist/subagent/preflight.js +0 -108
  306. package/dist/subagent/preflight.js.map +0 -1
  307. package/dist/subagent/request.d.ts +0 -4
  308. package/dist/subagent/request.d.ts.map +0 -1
  309. package/dist/subagent/request.js +0 -122
  310. package/dist/subagent/request.js.map +0 -1
  311. package/dist/subagent/response.d.ts +0 -8
  312. package/dist/subagent/response.d.ts.map +0 -1
  313. package/dist/subagent/response.js +0 -155
  314. package/dist/subagent/response.js.map +0 -1
  315. package/dist/subagent/tools.d.ts +0 -4
  316. package/dist/subagent/tools.d.ts.map +0 -1
  317. package/dist/subagent/tools.js +0 -42
  318. package/dist/subagent/tools.js.map +0 -1
  319. package/dist/subagent/types.d.ts +0 -268
  320. package/dist/subagent/types.d.ts.map +0 -1
  321. package/dist/subagent/types.js +0 -3
  322. package/dist/subagent/types.js.map +0 -1
  323. package/dist/subagent/validation.d.ts +0 -35
  324. package/dist/subagent/validation.d.ts.map +0 -1
  325. package/dist/subagent/validation.js +0 -314
  326. package/dist/subagent/validation.js.map +0 -1
  327. package/dist/subagent-command.d.ts +0 -4
  328. package/dist/subagent-command.d.ts.map +0 -1
  329. package/dist/subagent-command.js +0 -246
  330. package/dist/subagent-command.js.map +0 -1
  331. package/dist/subagent-profile-tool.d.ts +0 -49
  332. package/dist/subagent-profile-tool.d.ts.map +0 -1
  333. package/dist/subagent-profile-tool.js +0 -124
  334. package/dist/subagent-profile-tool.js.map +0 -1
  335. package/dist/subagent-tool.d.ts +0 -53
  336. package/dist/subagent-tool.d.ts.map +0 -1
  337. package/dist/subagent-tool.js +0 -456
  338. package/dist/subagent-tool.js.map +0 -1
  339. package/docs/guides/sillytavern-import.md +0 -47
  340. package/docs/reference/subagent-adapter.md +0 -204
  341. package/examples/sillytavern-dm-writer-prompt-stack.json +0 -190
@@ -0,0 +1,237 @@
1
+ # 0.5.0 Phase-0 decision drafts
2
+
3
+ [Design index](README.md) · [Architecture decision template](../../decision-template.md) · [Migration inventory](0.5-inventory.md)
4
+
5
+ Status: proposed drafts; requires maintainer acceptance
6
+
7
+ Date: 2026-08-17
8
+
9
+ This document packages the remaining Phase-0 choices for review. It does not
10
+ authorize code, schema, package, or persistence changes. Each accepted section
11
+ may become a focused architecture decision or an amendment to the 0.5 plan.
12
+
13
+ ## D1: Pi compatibility and release matrix
14
+
15
+ ### Candidate decision
16
+
17
+ Support Pi 0.83.0 as the initial documented minimum, because it is the checked
18
+ development fixture and supplies the extension/event APIs used by pi-forge.
19
+ Treat compatibility as a rolling list of explicitly tested Pi versions, not a
20
+ semver range inferred from wildcard peers. Test 0.83.0 and npm `latest` (0.84.2
21
+ when this draft was written) for every 0.5 release candidate, including packed
22
+ main-only and main-plus-optional-subagent installs. Keep Pi packages as wildcard
23
+ optional peers so Pi supplies one coherent SDK instance.
24
+
25
+ ### Alternatives
26
+
27
+ - Claim every Pi version through a semver range: reject, because wildcard peers
28
+ and Pi's frequent 0.x releases do not prove behavioral compatibility.
29
+ - Pin Pi dependencies inside pi-forge: reject, because it risks duplicate Pi
30
+ runtimes and conflicts with Pi package loading.
31
+
32
+ ### Acceptance evidence
33
+
34
+ Document exact tested versions, Node version, packed-install commands, and
35
+ main-only/optional-package results in release notes. Run a scheduled latest-Pi
36
+ probe that reports compatibility but does not silently widen the supported list.
37
+
38
+ ## D2: Pi session custom-entry versioning
39
+
40
+ ### Candidate decision
41
+
42
+ Keep the existing prompt-stack and profile custom entry types, but make every
43
+ newly written payload an envelope with `schemaVersion: 1`. Read unversioned 0.4
44
+ entries through explicit legacy decoders only; do not rewrite historical Pi JSONL
45
+ entries. Ignore unknown versions and malformed entries with a bounded diagnostic.
46
+
47
+ The latest valid entry in the active branch remains authoritative. Restoring a
48
+ selector or provenance must never apply a profile or mutate Pi runtime state.
49
+ `pi-forge-variable-state` is never restored or written in 0.5; its presence
50
+ produces one migration diagnostic per restoration, not a variable store.
51
+
52
+ ### Alternatives
53
+
54
+ - Rename all custom entry types: reject unless a real collision requires it;
55
+ existing type names are useful migration anchors.
56
+ - Continue unversioned free-form payloads: reject; it violates the state rules.
57
+ - Automatically append replacement entries while restoring: reject; opening a
58
+ historical session must not mutate it.
59
+
60
+ ### Acceptance evidence
61
+
62
+ Characterization tests cover legacy/current/unknown/malformed entries, branch
63
+ selection, compaction/tree navigation, missing resources, and no variable-state
64
+ resurrection.
65
+
66
+ ## D3: configuration ownership after subagent extraction
67
+
68
+ ### Candidate decision
69
+
70
+ The main package owns `webEditor.*` in `.pi/forge/config.json` and its global
71
+ equivalent. The optional package owns all subagent configuration, parsing,
72
+ validation, mutation, and diagnostics in dedicated
73
+ `.pi/forge/subagents.json` and `~/.pi/forge/subagents.json` files. Main pi-forge
74
+ does not read, write, validate, or surface subagent policy when the optional
75
+ package is absent.
76
+
77
+ The optional package may read the 0.4 `config.json.subagents` section only in a
78
+ one-time migration mode. It writes no automatic migration, preserves the legacy
79
+ section, and reports conflicts rather than merging silently.
80
+
81
+ ### Alternatives
82
+
83
+ - Keep a shared `config.json` namespaced section: lower migration cost, but
84
+ creates shared-file coordination and leaves main-package ownership ambiguous.
85
+ - Preserve main-package parsing of `subagents.*`: reject; it contradicts the
86
+ optional package boundary.
87
+
88
+ ### Acceptance evidence
89
+
90
+ Test absent optional package, untrusted project, project/global precedence,
91
+ legacy-config migration, conflict reporting, and deletion/config cleanup.
92
+
93
+ ## D4: resource repositories and workspace snapshots
94
+
95
+ ### Candidate decision
96
+
97
+ Repositories own all stack/profile discovery and mutation. A codec is the only
98
+ source of parse, normalize, validate, serialize, and content fingerprint logic.
99
+ Every write/delete receives an expected fingerprint when replacing an existing
100
+ resource; mismatch returns a typed conflict without writing.
101
+
102
+ `ForgeWorkspace` serializes reloads and publishes an immutable complete
103
+ snapshot with a monotonic revision. There is no filesystem watcher in 0.5:
104
+ explicit reload and existing lifecycle-driven reload are the only refresh paths.
105
+ Invalid/missing resources appear as diagnostics in the published snapshot, while
106
+ resolution and activation fail closed. A selected active resource that becomes
107
+ invalid or disappears is not active until a later complete reload resolves it.
108
+
109
+ Filesystem repositories use temp-file-plus-rename replacement where supported,
110
+ validate containment before every mutation, and clean failed temporary files.
111
+
112
+ ### Alternatives
113
+
114
+ - Keep synchronous adapter writes: reject; it preserves duplicate persistence
115
+ workflows and bypasses consistent conflict handling.
116
+ - Publish each catalog independently: reject; profiles could resolve against a
117
+ different stack generation.
118
+ - Add file watching during the refactor: defer; it is a new state/lifecycle
119
+ feature outside 0.5 scope.
120
+
121
+ ### Acceptance evidence
122
+
123
+ Test external edit conflicts, atomic-write failures, reload serialization,
124
+ mixed valid/invalid catalogs, scoped shadowing, active deletion, and consumers
125
+ never observing half a stack/profile graph.
126
+
127
+ ## D5: profile-application transaction semantics
128
+
129
+ ### Candidate decision
130
+
131
+ `AgentProfileService` resolves and validates model, authentication, thinking,
132
+ stack, and tool policy before any Pi mutation. It delegates mutations to a
133
+ runtime-controller port in this order: model, thinking level, active stack/tool
134
+ policy. It records provenance only after all three succeed.
135
+
136
+ On failure, the service compensates in reverse order using the captured prior
137
+ state and reports every failed compensation. This is a best-effort transaction,
138
+ not an atomic Pi-host transaction; an unset prior model that Pi cannot restore
139
+ is an explicit residual failure. Adapters render the typed result but do not
140
+ attempt their own rollback.
141
+
142
+ ### Alternatives
143
+
144
+ - Call Pi setters directly from commands/web handlers: reject; it duplicates
145
+ transaction behavior.
146
+ - Describe this as atomic: reject; Pi setters have externally visible effects
147
+ and no common rollback primitive.
148
+
149
+ ### Acceptance evidence
150
+
151
+ Integration tests cover each failure point, unexpected thinking-level clamp,
152
+ missing stack after preflight, rollback failure, provenance write timing, and
153
+ browser/command equivalence.
154
+
155
+ ## D6: regex and v1-to-v2 migration
156
+
157
+ ### Candidate decision
158
+
159
+ Retain deterministic outgoing `history` and `compiled` regex transforms in v2,
160
+ after schema characterization. Remove `display`/`both` as unsupported 0.4
161
+ configuration and remove destructive `finalize` transforms: they alter stored
162
+ assistant transcript after streaming and sit outside deterministic compilation.
163
+
164
+ Provide one explicit v1-to-v2 migration utility with dry-run default, per-file
165
+ diagnostics, no overwrite unless requested, backup/copy before replacement, and
166
+ no source deletion. It mechanically converts only documented safe fields and
167
+ emits error-level diagnostics for mutable variables, custom macros/slots,
168
+ removed regex effects, and unsupported template constructs. Users run the final
169
+ 0.4 storage migration before the v2 utility; 0.5 does not retain the legacy
170
+ storage migration command.
171
+
172
+ ### Alternatives
173
+
174
+ - Retain `finalize`: requires a separate persistent-transcript ownership and
175
+ previewability decision; defer rather than retain incidentally.
176
+ - Silently drop unsupported fields: reject; migration must make behavior loss
177
+ visible.
178
+ - Keep both legacy storage and v2 migration commands indefinitely: reject;
179
+ conflicts with the breaking-cleanup policy.
180
+
181
+ ### Acceptance evidence
182
+
183
+ Fixture coverage proves dry runs do not write, conflicts/backups are explicit,
184
+ repeated runs are idempotent, and every removed field is reported. The final
185
+ 0.4→0.5 user guide documents exact ordering and recovery.
186
+
187
+ ## D7: physical package topology
188
+
189
+ ### Candidate decision
190
+
191
+ Do not publish `pi-forge-core` in 0.5. Establish its boundaries as enforced
192
+ internal modules first. Publish only `@zihanw/pi-forge` and the optional
193
+ `pi-forge-subagents` package in Phase 5. The optional package uses documented
194
+ `@zihanw/pi-forge/subagent` host-port messages and Pi wildcard peers; it has no
195
+ dependency on core internals, web-editor modules, or a private copy of runtime
196
+ state. Extract core as a third package only after 0.5 if a named consumer proves
197
+ that package boundary necessary.
198
+
199
+ ### Alternatives
200
+
201
+ - Introduce a workspace and three published packages immediately: reject; it
202
+ adds package/version/build complexity before interfaces are characterized.
203
+ - Let optional subagents import internal core modules: reject; it defeats the
204
+ host-port boundary.
205
+
206
+ ### Acceptance evidence
207
+
208
+ Packed installs prove main pi-forge works with no subagent runtime/package, and
209
+ the optional package works only through the versioned host protocol.
210
+
211
+ ## D8: final public surface
212
+
213
+ ### Candidate decision
214
+
215
+ Use the public-surface register in the migration inventory as the Phase-6
216
+ allowlist. The root default extension remains stable. `/subagent` is the sole
217
+ versioned experimental host port. `src/*` aliases and root subagent re-exports
218
+ are removed. Resource/catalog/loader/profile helpers become internal unless the
219
+ consumer audit names a consumer and an intentional domain/service entry is
220
+ accepted. Macro/slot registration remains provisional pending the immutable
221
+ template/slot-port decision. Retain the two root documentation pointer files as
222
+ offline redirects in the 0.5 package unless the package documentation layout
223
+ otherwise provides a stable equivalent.
224
+
225
+ ### Acceptance evidence
226
+
227
+ Update package exports, `files`, package checks, public-API tests, reference
228
+ docs, changelog, and migration guide in one Phase-6 change. Test rejection of
229
+ all removed subpaths from a packed install.
230
+
231
+ ## Maintainer choices required
232
+
233
+ 1. Accept, amend, or reject the host-RPC and `forge-v1` template spike
234
+ candidates.
235
+ 2. Choose D3 dedicated subagent files versus a namespaced shared config file.
236
+ 3. Choose D6 removal versus separately designed retention of `finalize` regex.
237
+ 4. Accept/amend D1, D2, D4, D5, D7, and D8 before their affected phases.
@@ -0,0 +1,12 @@
1
+ # 0.5.0 full architecture proposal (archive)
2
+
3
+ Status: archived 2026-08-18 as the long-term target.
4
+
5
+ The active, executable 0.5.0 scope is now the [lean 0.5.0 architecture plan](../../architecture-0.5.md). The documents here were the original Phase-0 proposal and evidence base. They remain authoritative for the long-term target architecture, not for current 0.5.0 lane sequencing.
6
+
7
+ - [Full 0.5 architecture plan](architecture-0.5.md) — original six-phase target and release gates.
8
+ - [Migration inventory](0.5-inventory.md) — 0.4 surface characterization.
9
+ - [Public-consumer audit](0.5-consumer-audit.md) — known external consumer evidence.
10
+ - [Phase-0 decision drafts](0.5-phase0-decision-drafts.md) — original open decisions D1-D8.
11
+ - [Template-language spike](template-language-spike.md) — evidence behind `forge-v1`.
12
+ - [Pi host-discovery spike](host-discovery-spike.md) — evidence behind the event-bus host port.
@@ -0,0 +1,423 @@
1
+ # pi-forge 0.5.0 architecture plan
2
+
3
+ [Documentation](../../../README.md) · [Development rules](../../../development/architecture-rules.md) · [Roadmap](../../../development/roadmap.md)
4
+
5
+ Status: proposed
6
+
7
+ Date: 2026-08-17
8
+
9
+ 0.5 is a deliberately breaking stabilization release. Its purpose is to make the extension understandable and evolvable before adding more features. Compatibility is preserved only where it has a demonstrated consumer and does not compromise the target boundaries.
10
+
11
+ ## Problem statement
12
+
13
+ The 0.4 implementation is well tested, but feature throughput has outpaced architectural consolidation. Prompt stacks, profiles, web editing, mutable variables, imports, payload debugging, and subagents share state and orchestration paths. Several adapters perform application or persistence work directly, and internal file-shaped exports constrain reorganization.
14
+
15
+ The problem is not primarily file size. It is unclear ownership and too many ways to load, validate, mutate, compile, or present the same resources.
16
+
17
+ ## Release goals
18
+
19
+ 0.5 will:
20
+
21
+ - establish a one-directional architecture with explicit domain, application, port, infrastructure, and adapter layers;
22
+ - make a `ForgeWorkspace` the owner of coherent prompt-stack/profile resource state;
23
+ - unify stack/profile persistence behind scoped repositories and codecs while keeping their domain models separate;
24
+ - make prompt compilation deterministic over a normalized immutable environment;
25
+ - remove mutable turn/session variables and render-time variable mutation;
26
+ - replace the macro implementation only through an explicit template-engine contract, preserving a legacy reader only when migration requires it;
27
+ - extract optional subagent integration from the main extension through a versioned host port;
28
+ - remove or sharply reduce SillyTavern-specific functionality;
29
+ - replace wildcard internal exports with intentional package entry points;
30
+ - simplify commands and the web editor into adapters over shared application services.
31
+
32
+ ## Non-goals
33
+
34
+ 0.5 will not add orchestration, background agents, pipelines, retries, queues, new regex modes, richer imports, or new editor product surfaces. Sandbox and staged-write work remains deferred until the package and host boundaries are stable.
35
+
36
+ The refactor does not merge profiles, stacks, and compilation into one domain object. They share infrastructure and an application facade, but retain distinct responsibilities.
37
+
38
+ ## Accepted architectural decisions
39
+
40
+ ### Breaking cleanup is preferred to indefinite compatibility
41
+
42
+ 0.5 may change JSON schema, public TypeScript APIs, commands, package exports, and internal storage coordination. Every user-visible break must have an explicit migration note; not every 0.4 feature requires a compatibility implementation.
43
+
44
+ ### Mutable variables are removed
45
+
46
+ The following 0.4 behavior is removed from the 0.5 core design:
47
+
48
+ - turn and session variable stores;
49
+ - `setvar`, `setturnvar`, `setsessionvar`, and clear-variable macros;
50
+ - variable persistence in Pi session entries;
51
+ - the `variables` slot;
52
+ - render-time mutation through custom macro/slot contexts.
53
+
54
+ Templates receive an immutable context containing built-in runtime values. Static reusable values are retained as an immutable `parameters` object in stack schema v2; the v1 `stack.variables` string/JSON inconsistency is resolved by the v2 codec.
55
+
56
+ ### SillyTavern is not a core architecture driver
57
+
58
+ The current fidelity-oriented importer, regex translation, report surface, command, guide, and dedicated example are removed from the core 0.5 scope.
59
+
60
+ Decision: **complete removal**. 0.4 is documented as the last supported conversion path. A richer converter can later live in a separate package without shaping the prompt compiler.
61
+
62
+ ### Subagents become optional integration
63
+
64
+ The main extension retains profile/stack resolution and prompt preparation. A separate `pi-forge-subagents` extension owns delegation configuration, tools, commands, approval/progress UI, execution adaptation, and its dependency on `@zihanw/pi-subagent-runtime`.
65
+
66
+ The extraction must use a versioned Forge host port. It may not import internal runtime state, duplicate the active resource workspace, or make ordinary stack/profile usage depend on a subagent package.
67
+
68
+ Confirmed decisions:
69
+
70
+ - `@zihanw/pi-forge/subagent` remains a main-package entry point, but is cleaned into a versioned host port / host-neutral contract rather than re-exporting internal host preparation modules.
71
+ - The main package removes the hard dependency on `@zihanw/pi-subagent-runtime`; that dependency moves to `pi-forge-subagents` or becomes an optional peer dependency.
72
+ - The optional package may depend on the main package only through documented public ports.
73
+
74
+ ### Schemas and public APIs restart deliberately
75
+
76
+ Prompt-stack schema v2 describes the cleaned compiler and template model. Agent-profile v2 is introduced only if its stored shape must change. The package no longer exports implementation modules through `src/*`; public surfaces are explicit entry points with documented stability.
77
+
78
+ ## Confirmed 0.5.0 planning decisions
79
+
80
+ The following decisions were confirmed while this plan was in proposed status. Items still open are marked explicitly.
81
+
82
+ ### Architecture direction
83
+
84
+ - A1: Target diagrams use port dependencies: `PromptStackService` / `AgentProfileService` depend on repository/host ports; `StackRepo` / `ProfileRepo` implement those ports.
85
+ - A2: Add an automatic dependency-direction check (`check:architecture`) during Phase 1/2.
86
+ - A3: When `src/*` exports are removed, update `scripts/check-package.mjs`, `docs/reference/public-api.md`, and public-API tests in the same change.
87
+ - A4: The release is referred to consistently as 0.5.0.
88
+
89
+ ### Component ownership
90
+
91
+ - B1: `@zihanw/pi-forge/subagent` remains in the main package as a versioned host port / host-neutral contract, but its internal implementation surface is cleaned.
92
+ - B2: Remove the main package hard dependency on `@zihanw/pi-subagent-runtime`.
93
+ - B3: Forge extension loading/unloading and registry coordination are owned by `ForgeWorkspace`.
94
+ - B4: Tool-policy synchronization is defined as a port (`ToolPolicyPort`), called by `PromptStackService`; Pi adapter implements it.
95
+ - B5: Debug/payload/browser presentation state is a separate state slice, not part of the `ForgeWorkspace` resource snapshot.
96
+
97
+ ### Schema and feature decisions
98
+
99
+ - B6: SillyTavern is removed completely from 0.5.0 core; 0.4 is the last supported conversion path.
100
+ - B7: Template language is still open; it will be decided after a spike.
101
+ - B8: Static reusable values are retained as immutable `parameters` in stack schema v2; the v1 `variables` codec inconsistency is fixed in v2.
102
+ - B9: Cross-extension host discovery will be decided after a focused spike; no final mechanism is assumed yet.
103
+
104
+ ### Process decisions
105
+
106
+ - C1: Phase 0 produces an explicit inventory deliverable (for example `docs/design/0.5-inventory.md` or a comparable checklist).
107
+ - C2: Chinese documentation is updated for user-facing breaking changes; internal architecture documentation is not required to be fully synchronized.
108
+ - C3: No formal owner field is used; maintainer and agents together drive and review decisions.
109
+
110
+ ## Current 0.4 architecture
111
+
112
+ ```mermaid
113
+ flowchart TB
114
+ Pi["Pi host"] --> Entry["index.ts composition root"]
115
+ Entry --> Lifecycle["Lifecycle"]
116
+ Entry --> StackRuntime["Stack runtime"]
117
+ Entry --> ProfileRuntime["Profile runtime"]
118
+ Entry --> PolicyRuntime["Policy runtime"]
119
+ Entry --> WebRuntime["Web-editor runtime"]
120
+ Entry --> SubRuntime["Subagent runtime"]
121
+
122
+ State[("Shared PiForgeRuntimeState")]
123
+ Lifecycle --> State
124
+ StackRuntime --> State
125
+ ProfileRuntime --> State
126
+ PolicyRuntime --> State
127
+ WebRuntime --> State
128
+ SubRuntime --> State
129
+
130
+ StackRuntime --> StackLoader["Stack loader + validation"]
131
+ ProfileRuntime --> ProfileLoader["Profile loader + resolution"]
132
+ ProfileRuntime --> StackRuntime
133
+ StackRuntime --> ProfileRuntime
134
+
135
+ Lifecycle --> Compiler["Compiler"]
136
+ Compiler --> Macros["Stateful macros + variables"]
137
+ Compiler --> Slots["Slot registry"]
138
+ Compiler --> Regex["Regex transforms"]
139
+
140
+ WebRuntime --> WebHost["Web host"]
141
+ WebHost --> DirectIO["Direct stack filesystem mutations"]
142
+ WebHost --> ProfileService["Profile service"]
143
+ WebHost --> SubRuntime
144
+
145
+ SubRuntime --> SubHost["Forge host preparation"]
146
+ SubHost --> Compiler
147
+ SubRuntime --> ExternalRuntime["pi-subagent-runtime"]
148
+ ```
149
+
150
+ The high-risk connections are shared state ownership, circular stack/profile coordination, direct persistence in adapters, and optional subagent concerns reaching the core editor and composition root.
151
+
152
+ ## Target package and component architecture
153
+
154
+ ```mermaid
155
+ flowchart TB
156
+ subgraph Main["@zihanw/pi-forge"]
157
+ PiAdapters["Pi lifecycle + command adapters"]
158
+ WebAdapters["HTTP + browser adapters"]
159
+ Workspace["ForgeWorkspace"]
160
+ StackService["PromptStackService"]
161
+ ProfileService["AgentProfileService"]
162
+ PiPorts["Pi runtime/environment adapters"]
163
+
164
+ PiAdapters --> Workspace
165
+ WebAdapters --> Workspace
166
+ Workspace --> StackService
167
+ Workspace --> ProfileService
168
+ ProfileService --> StackService
169
+ end
170
+
171
+ subgraph Core["@zihanw/pi-forge-core"]
172
+ ResourceCore["Scoped resources + catalogs"]
173
+ StackDomain["Prompt-stack schema + codec"]
174
+ ProfileDomain["Agent-profile schema + codec"]
175
+ Compiler["PromptCompiler"]
176
+ Templates["TemplateEngine registry"]
177
+ Diagnostics["Common diagnostics"]
178
+ Ports["Repository + host ports"]
179
+
180
+ Compiler --> StackDomain
181
+ Compiler --> Templates
182
+ StackDomain --> ResourceCore
183
+ ProfileDomain --> ResourceCore
184
+ end
185
+
186
+ subgraph Infra["Main extension infrastructure"]
187
+ StackRepo["PromptStackRepository"]
188
+ ProfileRepo["AgentProfileRepository"]
189
+ AtomicFiles["Atomic scoped file store"]
190
+
191
+ StackRepo --> AtomicFiles
192
+ ProfileRepo --> AtomicFiles
193
+ end
194
+
195
+ StackService --> StackDomain
196
+ StackService --> Compiler
197
+ StackService --> Ports
198
+ ProfileService --> ProfileDomain
199
+ ProfileService --> Ports
200
+ PiPorts --> Ports
201
+ StackRepo -.->|implements| Ports
202
+ ProfileRepo -.->|implements| Ports
203
+
204
+ subgraph Optional["pi-forge-subagents"]
205
+ SubAdapters["Commands + tools + approval UI"]
206
+ SubHost["ForgeHostPort client"]
207
+ SubRuntime["pi-subagent-runtime"]
208
+
209
+ SubAdapters --> SubHost
210
+ SubAdapters --> SubRuntime
211
+ end
212
+
213
+ Workspace -. "versioned host capability" .-> SubHost
214
+ ```
215
+
216
+ `pi-forge-core` is host-neutral: it does not import the Pi extension API, HTTP, browser, TUI, or subagent runtime. If physical package extraction would delay boundary work, the same structure may land first as enforced internal modules and become a package before the subagent split.
217
+
218
+ ## Target responsibilities
219
+
220
+ ### ForgeWorkspace
221
+
222
+ - Own one immutable workspace snapshot containing scoped stack/profile catalogs and active selection/provenance references.
223
+ - Own Forge extension loading/unloading and registry coordination; coordinate resource reload and snapshot publication without circular runtime callbacks.
224
+ - Expose application services and resource-change subscriptions to adapters.
225
+ - Keep payload debugging and browser presentation state outside the resource snapshot.
226
+
227
+ ### PromptStackService
228
+
229
+ - List, resolve, validate, create, update, fork, delete, activate, preview, and compile stacks.
230
+ - Own auto-activation selection and active-stack state transitions.
231
+ - Coordinate tool-policy changes through a `ToolPolicyPort` rather than calling UI, Pi API, or persistence code directly.
232
+
233
+ ### AgentProfileService
234
+
235
+ - List, resolve, validate, create, update, delete, preflight, apply, and report provenance/drift.
236
+ - Apply model, thinking, and stack transactionally through a runtime-controller port.
237
+ - Resolve stack references through the workspace catalog, not through a separate loader.
238
+
239
+ ### Repositories and codecs
240
+
241
+ - Repositories implement scoped discovery and safe mutation.
242
+ - Codecs are the only schema parsing, normalization, validation, serialization, and fingerprint source.
243
+ - Updates/deletes carry expected fingerprints to prevent overwriting unseen external changes.
244
+ - Filesystem writes use atomic replacement where the platform permits it.
245
+
246
+ ### PromptCompiler and TemplateEngine
247
+
248
+ - Consume a normalized immutable `PromptEnvironment`, not a live Pi context.
249
+ - Return system prompt, prepared messages, sources, diagnostics, template dependencies, and an explicit variable/parameter receipt if parameters are retained.
250
+ - Keep history placement, structured runtime slots, tool/skill selection, and outgoing deterministic transforms as separate compiler stages.
251
+ - Use an engine contract with parse, analyze, and render operations. A restricted Jinja-like engine is a candidate, not yet an accepted dependency.
252
+
253
+ ### Adapters
254
+
255
+ - Parse external input and render typed service results.
256
+ - Contain no resource persistence or duplicated schema validation.
257
+ - Browser view models and HTTP status mapping remain outside application/domain state.
258
+
259
+ ## Proposed source layout
260
+
261
+ The exact filenames may evolve, but ownership should converge on:
262
+
263
+ ```text
264
+ packages/
265
+ core/
266
+ src/resources/
267
+ src/prompt-stacks/
268
+ src/profiles/
269
+ src/compiler/
270
+ src/templates/
271
+ src/ports/
272
+ pi-forge/
273
+ src/application/
274
+ src/infrastructure/
275
+ src/adapters/pi/
276
+ src/adapters/commands/
277
+ src/adapters/web/
278
+ pi-forge-subagents/
279
+ src/host/
280
+ src/runtime/
281
+ src/adapters/commands/
282
+ src/adapters/tools/
283
+ ```
284
+
285
+ Moving to a workspace is an implementation choice, not permission to move files before their interfaces and ownership are characterized.
286
+
287
+ ## Feature disposition
288
+
289
+ | 0.4 capability | 0.5 disposition |
290
+ |---|---|
291
+ | Ordered prompt blocks and runtime slots | Keep and move into the v2 compiler |
292
+ | Scoped global/project resources | Keep behind common repositories/catalogs |
293
+ | Tool policy and model-visible skill filtering | Keep stack-owned |
294
+ | One-shot profiles, transactional apply, provenance, drift | Keep in `AgentProfileService` |
295
+ | Web stack/profile editor | Keep as adapters over services; simplify during migration |
296
+ | Prompt preview and redacted payload debugging | Keep; isolate debugging state |
297
+ | Turn/session variables and mutation macros | Remove |
298
+ | Static stack variables | Keep as immutable `parameters` in schema v2; fix the v1 string/JSON codec inconsistency |
299
+ | Current custom macro API | Break and replace with the template/slot extension contract |
300
+ | SillyTavern fidelity importer and regex emulation | Remove completely; 0.4 is the last supported conversion path |
301
+ | Regex history/compiled transforms | Keep initially; no new modes during 0.5 |
302
+ | Destructive finalized-transcript regex | Audit separately before schema v2 is frozen |
303
+ | Foreground subagent integration | Move to optional `pi-forge-subagents`; `@zihanw/pi-forge/subagent` remains as a versioned host port/contract |
304
+ | `src/*` package exports | Remove; update `check-package.mjs`, public API docs/tests in the same change |
305
+ | Legacy prompt-stack storage migration command | Remove after documenting the required pre-0.5 migration path |
306
+
307
+ ## Implementation phases
308
+
309
+ ### Phase 0: freeze and characterize
310
+
311
+ - Announce the 0.5 feature freeze in repository guidance and roadmap.
312
+ - Produce an explicit inventory deliverable covering public exports, persisted entries, commands, schemas, examples, and real internal consumers.
313
+ - Add characterization tests around any behavior that will move before changing ownership.
314
+ - Run the template-language spike and cross-extension host-discovery spike; record their findings before the affected phases start.
315
+ - Decide the remaining implementation gates listed under open decisions.
316
+
317
+ Exit: the removal/migration inventory is reviewed, and no unplanned feature work is in flight.
318
+
319
+ ### Phase 1: resource core and repositories
320
+
321
+ - Introduce common diagnostic and loaded-resource envelopes.
322
+ - Extract stack/profile codecs.
323
+ - Implement repository ports and guarded filesystem repositories.
324
+ - Add the automatic dependency-direction check (`check:architecture`) so adapter/domain boundaries are enforced from this phase onward.
325
+ - Move all stack mutations out of `web-host.ts` and import commands.
326
+
327
+ Exit: every domain resource mutation uses a repository and has consistent stale-write/path-safety behavior.
328
+
329
+ ### Phase 2: application services and workspace
330
+
331
+ - Consolidate stack operations into `PromptStackService`.
332
+ - Consolidate profile operations into `AgentProfileService`.
333
+ - Introduce `ForgeWorkspace` and publish coherent reload snapshots.
334
+ - Split debug/browser state away from resource state into a separate state slice.
335
+ - Replace circular stack/profile runtime wiring with workspace-owned services and ports.
336
+
337
+ Exit: commands, lifecycle, and web host use services; `PiForgeRuntimeState` is removed or reduced to adapter-owned state with no domain ownership.
338
+
339
+ ### Phase 3: compiler and schema v2
340
+
341
+ - Define normalized `PromptEnvironment`, compiler result, and template-engine contracts.
342
+ - Remove mutable variables and session variable persistence.
343
+ - Select and implement the v2 template syntax.
344
+ - Make template dependency analysis authoritative.
345
+ - Decide the retained regex surface and freeze prompt-stack schema v2.
346
+
347
+ Exit: compilation is deterministic over immutable inputs, previews and runtime use the same entry point, and v1-to-v2 migration behavior is documented and tested.
348
+
349
+ ### Phase 4: adapter cleanup
350
+
351
+ - Reduce Pi lifecycle modules to event adaptation.
352
+ - Reduce commands and HTTP handlers to parsing/result rendering.
353
+ - Split web view-model construction from application workflows.
354
+ - Remove SillyTavern surfaces from commands, web editor, docs, examples, and tests; update Chinese user docs for user-facing breaking changes.
355
+
356
+ Exit: dependency checks show adapters pointing inward with no direct resource persistence.
357
+
358
+ ### Phase 5: subagent extraction and packages
359
+
360
+ - Validate cross-extension capability discovery with a focused spike.
361
+ - Publish the versioned Forge host port and clean `@zihanw/pi-forge/subagent` into that stable surface.
362
+ - Remove the main package hard dependency on `@zihanw/pi-subagent-runtime`.
363
+ - Move subagent configuration, commands, tools, UI, and runtime adaptation into `pi-forge-subagents`.
364
+ - Ensure main pi-forge installs and runs without subagent dependencies.
365
+ - Remove subagent UI/configuration from the core web editor unless an explicit contribution port is accepted.
366
+
367
+ Exit: ordinary stacks/profiles have no dependency on the optional package, and the optional extension consumes only documented public ports.
368
+
369
+ ### Phase 6: public surface and release
370
+
371
+ - Replace root re-export sprawl with explicit package entry points.
372
+ - Remove `src/*` aliases and 0.4 compatibility barrels; update `check-package.mjs`, public API docs, and public API tests in the same change.
373
+ - Complete migration guide, changelog, package checks, and documentation rewrite; use 0.5.0 naming consistently.
374
+ - Run packed-install tests against supported Pi versions with and without `pi-forge-subagents`.
375
+
376
+ Exit: all release gates below pass.
377
+
378
+ ## Open implementation-gate decisions
379
+
380
+ These are the remaining decisions that must be resolved before their affected implementation phases begin:
381
+
382
+ 1. **Template language (spike completed; decision pending):** the Phase-0 [template-language spike](template-language-spike.md) rejects a broad Jinja-like engine and recommends a closed `forge-v1` AST grammar. Accept the exact grammar, environment schema, filter/condition set, extension-port disposition, schema representation, and migration behavior before Phase 3.
383
+ 2. **Static parameters (decided):** retain a JSON-compatible immutable `parameters` object in stack schema v2; do not remove static reusable values.
384
+ 3. **SillyTavern migration (decided):** complete removal; 0.4 is the last supported conversion path. No converter is retained in 0.5.0 core.
385
+ 4. **Cross-extension host discovery (spike completed; decision pending):** the Phase-0 [Pi host-discovery spike](host-discovery-spike.md) validated Pi's shared in-process event bus across both extension load orders. It recommends a versioned, session-scoped event-bus RPC port with explicit duplicate-host detection and disposal; accept the protocol, operation catalogue, and package versioning before Phase 5.
386
+ 5. **Pi session custom-entry versioning (open):** define explicit version, restoration, branch-navigation, malformed-entry, and migration semantics for prompt-stack selection and profile provenance entries. Define how removed variable entries are handled without recreating mutable state. Resolve before Phase 2/3 changes session restoration.
387
+ 6. **Configuration ownership after subagent extraction (open):** `webEditor.*` remains owned by the main package. Decide whether `subagents.*`, which must be owned and written only by `pi-forge-subagents`, remains a namespaced section of `.pi/forge/config.json` or moves to dedicated optional-package configuration files; include migration and behavior when the optional package is absent. Resolve before Phase 4/5 changes configuration adapters.
388
+ 7. **Final public-surface classification (open):** before Phase 6, use the Phase-0 inventory to classify every root and subpath surface as stable, experimental, internal, or removed; record named consumers, target entry points, and migration notices. Phase 6 must implement this accepted register rather than decide exports during removal.
389
+ 8. **Pi compatibility policy (open):** define the minimum supported Pi version and rolling tested-version release matrix separately from wildcard host peers. Include packed main-only and main-plus-optional-package tests, plus a release-time npm `latest` probe. Resolve before Phase 1 establishes the supported CI matrix.
390
+
391
+ ## Migration policy
392
+
393
+ - Provide a v1-to-v2 stack migration command or standalone script for mechanically convertible fields.
394
+ - Mutable variable behavior that cannot be preserved becomes an explicit migration diagnostic, not a silent approximation.
395
+ - Recommend running the final 0.4 release to convert legacy `.pi/prompt-stacks` storage before upgrading if 0.5 removes that migration command.
396
+ - Agent profiles retain IDs and scoped stack references where possible; migration rewrites only schema fields that actually change.
397
+ - SillyTavern users must convert with 0.4 before upgrading; 0.5.0 core does not retain a converter.
398
+ - No compatibility shim is accepted without a named consumer, test, warning/removal version, and owner.
399
+
400
+ ## Release gates
401
+
402
+ 0.5 is ready only when:
403
+
404
+ - dependency direction is checked automatically;
405
+ - all resource persistence is repository-owned;
406
+ - workspace reload and profile application have transactional/integration coverage;
407
+ - runtime and preview compilation share one compiler entry point;
408
+ - mutable variables and their persisted entries are removed or explicitly migrated;
409
+ - schema v2 and public entry points are documented without `src/*` exports;
410
+ - main pi-forge passes verification without installing the subagent extension/runtime;
411
+ - the optional subagent package passes host-version, preparation, approval, cancellation, and packed-install tests;
412
+ - current and target architecture diagrams match the implementation;
413
+ - English user documentation is updated and Chinese user-facing documentation is updated for breaking changes (internal architecture docs are not required to be fully synchronized);
414
+ - `npm run verify` and packed-install smoke tests pass on the documented Pi compatibility range.
415
+
416
+ ## Deferred until after 0.5
417
+
418
+ - New prompt composition features.
419
+ - New import formats or high-fidelity external-preset emulation.
420
+ - Sandbox and staged subagent writes.
421
+ - Background/resumable agents, chains, queues, or orchestration.
422
+ - New web-editor surfaces unrelated to the migration.
423
+ - Additional regex or transcript-rewriting behavior.