@zihanw/pi-forge 0.4.0-beta.1 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (227) hide show
  1. package/CHANGELOG.md +45 -1
  2. package/PUBLIC_API.md +3 -26
  3. package/README.md +90 -601
  4. package/README.zh-CN.md +86 -585
  5. package/SUBAGENT_ADAPTER_CONTRACT.md +3 -197
  6. package/dist/agent-profile.d.ts +24 -1
  7. package/dist/agent-profile.d.ts.map +1 -1
  8. package/dist/agent-profile.js +146 -36
  9. package/dist/agent-profile.js.map +1 -1
  10. package/dist/catalog.d.ts +27 -0
  11. package/dist/catalog.d.ts.map +1 -0
  12. package/dist/catalog.js +59 -0
  13. package/dist/catalog.js.map +1 -0
  14. package/dist/forge-config.d.ts +106 -0
  15. package/dist/forge-config.d.ts.map +1 -1
  16. package/dist/forge-config.js +305 -18
  17. package/dist/forge-config.js.map +1 -1
  18. package/dist/index.d.ts +5 -5
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +55 -8
  21. package/dist/index.js.map +1 -1
  22. package/dist/lifecycle.d.ts +2 -1
  23. package/dist/lifecycle.d.ts.map +1 -1
  24. package/dist/lifecycle.js +7 -4
  25. package/dist/lifecycle.js.map +1 -1
  26. package/dist/loader.d.ts +17 -1
  27. package/dist/loader.d.ts.map +1 -1
  28. package/dist/loader.js +84 -25
  29. package/dist/loader.js.map +1 -1
  30. package/dist/preset-command.d.ts +1 -1
  31. package/dist/preset-command.d.ts.map +1 -1
  32. package/dist/preset-command.js +38 -10
  33. package/dist/preset-command.js.map +1 -1
  34. package/dist/profile-command.d.ts.map +1 -1
  35. package/dist/profile-command.js +46 -21
  36. package/dist/profile-command.js.map +1 -1
  37. package/dist/profile-service.d.ts +6 -3
  38. package/dist/profile-service.d.ts.map +1 -1
  39. package/dist/profile-service.js +55 -13
  40. package/dist/profile-service.js.map +1 -1
  41. package/dist/resource-identity.d.ts +33 -0
  42. package/dist/resource-identity.d.ts.map +1 -0
  43. package/dist/resource-identity.js +56 -0
  44. package/dist/resource-identity.js.map +1 -0
  45. package/dist/runtime/profile-runtime.d.ts.map +1 -1
  46. package/dist/runtime/profile-runtime.js +7 -2
  47. package/dist/runtime/profile-runtime.js.map +1 -1
  48. package/dist/runtime/prompt-stack-runtime.d.ts +1 -1
  49. package/dist/runtime/prompt-stack-runtime.d.ts.map +1 -1
  50. package/dist/runtime/prompt-stack-runtime.js +22 -12
  51. package/dist/runtime/prompt-stack-runtime.js.map +1 -1
  52. package/dist/runtime/subagent-runtime.d.ts +23 -8
  53. package/dist/runtime/subagent-runtime.d.ts.map +1 -1
  54. package/dist/runtime/subagent-runtime.js +296 -67
  55. package/dist/runtime/subagent-runtime.js.map +1 -1
  56. package/dist/storage.d.ts +11 -0
  57. package/dist/storage.d.ts.map +1 -1
  58. package/dist/storage.js +51 -2
  59. package/dist/storage.js.map +1 -1
  60. package/dist/subagent/canonical.d.ts +19 -7
  61. package/dist/subagent/canonical.d.ts.map +1 -1
  62. package/dist/subagent/canonical.js +19 -47
  63. package/dist/subagent/canonical.js.map +1 -1
  64. package/dist/subagent/contract.d.ts +1 -2
  65. package/dist/subagent/contract.d.ts.map +1 -1
  66. package/dist/subagent/contract.js +1 -2
  67. package/dist/subagent/contract.js.map +1 -1
  68. package/dist/subagent/index.d.ts +4 -3
  69. package/dist/subagent/index.d.ts.map +1 -1
  70. package/dist/subagent/index.js +4 -3
  71. package/dist/subagent/index.js.map +1 -1
  72. package/dist/subagent/plan.d.ts +5 -1
  73. package/dist/subagent/plan.d.ts.map +1 -1
  74. package/dist/subagent/plan.js +29 -32
  75. package/dist/subagent/plan.js.map +1 -1
  76. package/dist/subagent/request.d.ts.map +1 -1
  77. package/dist/subagent/request.js +36 -4
  78. package/dist/subagent/request.js.map +1 -1
  79. package/dist/subagent/types.d.ts +66 -178
  80. package/dist/subagent/types.d.ts.map +1 -1
  81. package/dist/subagent/types.js +1 -1
  82. package/dist/subagent/types.js.map +1 -1
  83. package/dist/subagent/validation.d.ts +14 -14
  84. package/dist/subagent/validation.d.ts.map +1 -1
  85. package/dist/subagent/validation.js +52 -238
  86. package/dist/subagent/validation.js.map +1 -1
  87. package/dist/subagent-command.d.ts +2 -1
  88. package/dist/subagent-command.d.ts.map +1 -1
  89. package/dist/subagent-command.js +115 -19
  90. package/dist/subagent-command.js.map +1 -1
  91. package/dist/subagent-host.d.ts.map +1 -1
  92. package/dist/subagent-host.js +43 -16
  93. package/dist/subagent-host.js.map +1 -1
  94. package/dist/subagent-profile-tool.d.ts +25 -2
  95. package/dist/subagent-profile-tool.d.ts.map +1 -1
  96. package/dist/subagent-profile-tool.js +41 -9
  97. package/dist/subagent-profile-tool.js.map +1 -1
  98. package/dist/subagent-tool.d.ts +31 -4
  99. package/dist/subagent-tool.d.ts.map +1 -1
  100. package/dist/subagent-tool.js +311 -137
  101. package/dist/subagent-tool.js.map +1 -1
  102. package/dist/types.d.ts +3 -0
  103. package/dist/types.d.ts.map +1 -1
  104. package/dist/types.js.map +1 -1
  105. package/dist/web-editor/client-script.generated.d.ts +1 -1
  106. package/dist/web-editor/client-script.generated.d.ts.map +1 -1
  107. package/dist/web-editor/client-script.generated.js +1 -1
  108. package/dist/web-editor/client-script.generated.js.map +1 -1
  109. package/dist/web-editor/client-styles.d.ts +2 -0
  110. package/dist/web-editor/client-styles.d.ts.map +1 -0
  111. package/dist/web-editor/client-styles.generated.d.ts +2 -0
  112. package/dist/web-editor/client-styles.generated.d.ts.map +1 -0
  113. package/dist/web-editor/client-styles.generated.js +3 -0
  114. package/dist/web-editor/client-styles.generated.js.map +1 -0
  115. package/dist/web-editor/client-styles.js +2 -0
  116. package/dist/web-editor/client-styles.js.map +1 -0
  117. package/dist/web-editor/page.d.ts +2 -0
  118. package/dist/web-editor/page.d.ts.map +1 -1
  119. package/dist/web-editor/page.js +11 -73
  120. package/dist/web-editor/page.js.map +1 -1
  121. package/dist/web-editor/server.d.ts.map +1 -1
  122. package/dist/web-editor/server.js +176 -1
  123. package/dist/web-editor/server.js.map +1 -1
  124. package/dist/web-editor/styles.d.ts.map +1 -1
  125. package/dist/web-editor/styles.js +60 -3
  126. package/dist/web-editor/styles.js.map +1 -1
  127. package/dist/web-editor/types.d.ts +87 -0
  128. package/dist/web-editor/types.d.ts.map +1 -1
  129. package/dist/web-host.d.ts +13 -2
  130. package/dist/web-host.d.ts.map +1 -1
  131. package/dist/web-host.js +371 -27
  132. package/dist/web-host.js.map +1 -1
  133. package/docs/README.md +41 -0
  134. package/docs/concepts/agent-profiles.md +60 -0
  135. package/docs/concepts/prompt-stacks.md +95 -0
  136. package/docs/design/README.md +17 -0
  137. package/docs/design/roadmap-0.4-archive.md +216 -0
  138. package/docs/design/subagents/design-review.md +220 -0
  139. package/docs/design/subagents/interface-design.md +274 -0
  140. package/docs/design/subagents/sdk-spike-findings.md +117 -0
  141. package/docs/development/complexity-review.md +86 -0
  142. package/docs/development/release.md +31 -0
  143. package/docs/development/roadmap.md +36 -0
  144. package/docs/development/scoped-global-profiles-stacks.md +325 -0
  145. package/docs/development/setup.md +75 -0
  146. package/docs/getting-started.md +95 -0
  147. package/docs/guides/custom-macros-and-slots.md +68 -0
  148. package/docs/guides/debugging.md +39 -0
  149. package/docs/guides/delegation.md +107 -0
  150. package/docs/guides/sillytavern-import.md +47 -0
  151. package/docs/guides/use-cases.md +65 -0
  152. package/docs/guides/web-editor.md +75 -0
  153. package/docs/reference/commands.md +60 -0
  154. package/docs/reference/configuration.md +66 -0
  155. package/docs/reference/features.md +280 -0
  156. package/docs/reference/macros-and-slots.md +82 -0
  157. package/docs/reference/public-api.md +28 -0
  158. package/docs/reference/stack-schema.md +167 -0
  159. package/docs/reference/subagent-adapter.md +204 -0
  160. package/docs/zh-CN/README.md +37 -0
  161. package/docs/zh-CN/concepts/agent-profiles.md +46 -0
  162. package/docs/zh-CN/concepts/prompt-stacks.md +42 -0
  163. package/docs/zh-CN/getting-started.md +81 -0
  164. package/docs/zh-CN/guides/delegation.md +66 -0
  165. package/docs/zh-CN/guides/web-editor.md +45 -0
  166. package/docs/zh-CN/reference/commands.md +60 -0
  167. package/package.json +29 -15
  168. package/dist/subagent/backend-registry.d.ts +0 -75
  169. package/dist/subagent/backend-registry.d.ts.map +0 -1
  170. package/dist/subagent/backend-registry.js +0 -463
  171. package/dist/subagent/backend-registry.js.map +0 -1
  172. package/dist/subagent/diagnostics.d.ts +0 -3
  173. package/dist/subagent/diagnostics.d.ts.map +0 -1
  174. package/dist/subagent/diagnostics.js +0 -5
  175. package/dist/subagent/diagnostics.js.map +0 -1
  176. package/dist/subagent/pi-model-runtime.d.ts +0 -8
  177. package/dist/subagent/pi-model-runtime.d.ts.map +0 -1
  178. package/dist/subagent/pi-model-runtime.js +0 -22
  179. package/dist/subagent/pi-model-runtime.js.map +0 -1
  180. package/dist/subagent/pi-sdk-backend.d.ts +0 -23
  181. package/dist/subagent/pi-sdk-backend.d.ts.map +0 -1
  182. package/dist/subagent/pi-sdk-backend.js +0 -383
  183. package/dist/subagent/pi-sdk-backend.js.map +0 -1
  184. package/dist/subagent/pi-subprocess-backend.d.ts +0 -72
  185. package/dist/subagent/pi-subprocess-backend.d.ts.map +0 -1
  186. package/dist/subagent/pi-subprocess-backend.js +0 -756
  187. package/dist/subagent/pi-subprocess-backend.js.map +0 -1
  188. package/dist/subagent/subprocess-bridge.d.ts +0 -21
  189. package/dist/subagent/subprocess-bridge.d.ts.map +0 -1
  190. package/dist/subagent/subprocess-bridge.js +0 -87
  191. package/dist/subagent/subprocess-bridge.js.map +0 -1
  192. package/dist/subagent/subprocess-report.d.ts +0 -4
  193. package/dist/subagent/subprocess-report.d.ts.map +0 -1
  194. package/dist/subagent/subprocess-report.js +0 -55
  195. package/dist/subagent/subprocess-report.js.map +0 -1
  196. package/dist/subagent-contract.d.ts +0 -8
  197. package/dist/subagent-contract.d.ts.map +0 -1
  198. package/dist/subagent-contract.js +0 -8
  199. package/dist/subagent-contract.js.map +0 -1
  200. package/dist/web-editor/client/api.d.ts +0 -9
  201. package/dist/web-editor/client/api.d.ts.map +0 -1
  202. package/dist/web-editor/client/api.js +0 -26
  203. package/dist/web-editor/client/api.js.map +0 -1
  204. package/dist/web-editor/client/dom.d.ts +0 -13
  205. package/dist/web-editor/client/dom.d.ts.map +0 -1
  206. package/dist/web-editor/client/dom.js +0 -30
  207. package/dist/web-editor/client/dom.js.map +0 -1
  208. package/dist/web-editor/client/inspector.d.ts +0 -22
  209. package/dist/web-editor/client/inspector.d.ts.map +0 -1
  210. package/dist/web-editor/client/inspector.js +0 -226
  211. package/dist/web-editor/client/inspector.js.map +0 -1
  212. package/dist/web-editor/client/main.d.ts +0 -2
  213. package/dist/web-editor/client/main.d.ts.map +0 -1
  214. package/dist/web-editor/client/main.js +0 -1468
  215. package/dist/web-editor/client/main.js.map +0 -1
  216. package/dist/web-editor/client/policy-editor.d.ts +0 -16
  217. package/dist/web-editor/client/policy-editor.d.ts.map +0 -1
  218. package/dist/web-editor/client/policy-editor.js +0 -330
  219. package/dist/web-editor/client/policy-editor.js.map +0 -1
  220. package/dist/web-editor/client/regex-editor.d.ts +0 -19
  221. package/dist/web-editor/client/regex-editor.d.ts.map +0 -1
  222. package/dist/web-editor/client/regex-editor.js +0 -281
  223. package/dist/web-editor/client/regex-editor.js.map +0 -1
  224. package/dist/web-editor/client/types.d.ts +0 -60
  225. package/dist/web-editor/client/types.d.ts.map +0 -1
  226. package/dist/web-editor/client/types.js +0 -2
  227. package/dist/web-editor/client/types.js.map +0 -1
@@ -0,0 +1,86 @@
1
+ # Complexity review
2
+
3
+ > **Historical snapshot:** This review records the repository structure at the end of the 0.4 implementation cycle. File counts and hotspot rankings may age; use it as refactoring context, not current user guidance.
4
+
5
+ Date: 2026-07-18
6
+
7
+ ## Executive Summary
8
+
9
+ The structural refactor recommended by the original 2026-07-12 review is complete:
10
+
11
+ - The browser editor is authored as typed modules and bundled only for distribution.
12
+ - The subagent contract is split into focused modules behind compatibility barrels.
13
+ - `src/index.ts` is a small composition root over dedicated runtime services.
14
+ - Package contents and stable, experimental, and compatibility exports are explicitly classified.
15
+
16
+ pi-forge is still a reasonable size for its feature set. The main engineering risk has moved from a few monolithic files to the safety and lifecycle seams of the experimental subagent backend. The narrow parent-agent integration is now complete; the next iteration should harden the shared-user boundary and evaluate an optional sandbox without adding orchestration breadth.
17
+
18
+ ## Current Size
19
+
20
+ Measured from the current `feature/0.4-subagents-prep` working tree:
21
+
22
+ | Area | Files | Lines of TypeScript |
23
+ |---|---:|---:|
24
+ | Production source (`src`) | 72 | 16,355 |
25
+ | Core tests and helpers (`tests`) | 23 | 7,271 |
26
+ | Browser tests (`tests-browser`) | 1 | 139 |
27
+ | Internal TypeScript scripts (`scripts`) | 2 | 628 |
28
+
29
+ Additional observations:
30
+
31
+ - `dist/` is generated output and is about 2.1 MB; verification rejects stale generated files.
32
+ - Runtime dependency count remains low.
33
+ - The implementation checkpoint passes 184 core tests, one browser test, TypeScript typecheck, generated-client and `dist` consistency, and npm package-layout checks.
34
+ - The npm package resolves both entry points to compiled output and contains no physical `src/` files.
35
+
36
+ ## Completed Structural Work
37
+
38
+ ### Typed browser client
39
+
40
+ The previous 2,253-line embedded browser script is now a generated one-line compatibility wrapper. Typed source modules under `src/web-editor/client/` own API transport, DOM access, policy editing, regex editing, inspection, and orchestration. `src/web-editor/client/main.ts` is still large, but it is type-checked and can be split incrementally as profile UI introduces clear component boundaries.
41
+
42
+ ### Modular subagent contract
43
+
44
+ The previous 1,373-line `src/subagent-contract.ts` implementation is now a seven-line compatibility barrel. Types, canonicalization, request validation, preflight, tools, context, plans, response handling, and validation live in focused `src/subagent/` modules with import-surface tests preserving the experimental API.
45
+
46
+ ### Small composition root
47
+
48
+ `src/index.ts` remains a small composition root and primarily wires prompt-stack, profile, tool-policy, web-editor, lifecycle, subagent runtime, command, and tool registration. Operational behavior lives in dedicated modules.
49
+
50
+ ### Package and API boundaries
51
+
52
+ The [public API policy](../reference/public-api.md) classifies stable, experimental, and compatibility surfaces. `@zihanw/pi-forge/subagent` is the preferred experimental integration entry point, while legacy `src/*` aliases resolve to compiled modules without publishing source files.
53
+
54
+ ## Current Complexity Hotspots
55
+
56
+ | File | Lines | Current assessment |
57
+ |---|---:|---|
58
+ | `src/web-editor/client/main.ts` | 1,491 | Largest remaining orchestration module; split along profile UI boundaries when that work begins |
59
+ | `src/web-editor/styles.ts` | 995 | Large but mostly presentation logic |
60
+ | `src/compiler.ts` | 578 | Mature core compiler; change cautiously |
61
+ | `src/subagent/backend-registry.ts` | 575 | Highest semantic risk: dispatch, cancellation, timeout, binding, and trace routing |
62
+ | `src/subagent/pi-subprocess-backend.ts` | 773 | Foreground child lifecycle, exact bridge inputs, sanitized report transport, cancellation, and cleanup |
63
+ | `src/subagent-tool.ts` | 453 | Approval UX, bounded model projection, and expandable human report rendering |
64
+ | `src/loader.ts` | 518 | Broad input normalization and validation surface |
65
+ | `src/regex.ts` | 500 | Mature transformation engine with focused tests |
66
+ | `src/subagent/pi-sdk-backend.ts` | 450 | Experimental provider/session lifecycle boundary |
67
+
68
+ The registry, subprocess backend, and approval tool are not concerning solely by line count, but they carry the strongest correctness and egress guarantees. Prefer focused helpers and end-to-end lifecycle tests over broad rewrites.
69
+
70
+ ## Near-Term Priorities
71
+
72
+ 1. Keep provider egress fail-closed in interactive, non-UI, cancelled, and timed-out paths.
73
+ 2. Dogfood the model-callable foreground path without creating a second runner or allowing a tool call to grant its own egress consent.
74
+ 3. Preserve read-only defaults, bounded result projection, no automatic parent-history export, and honest shared-user receipts while evaluating bubblewrap-style isolation.
75
+ 4. Add profile UI by reusing the existing profile repository/application services and splitting browser orchestration only where the new UI creates stable boundaries.
76
+ 5. Re-run the complete verification suite for every release candidate and keep generated output synchronized.
77
+
78
+ ## Guardrails
79
+
80
+ Do not remove strict validation, immutable preparation binding, task preservation, access/limit receipts, rollback, provenance, or drift reporting merely to reduce line count. These mechanisms make the experimental runtime's behavior inspectable and enforceable.
81
+
82
+ Avoid building retries, queues, chains, background execution, direct write/shell access, media routing, or artifact/trace storage into the 0.4 foreground path. Evaluate sandbox and external orchestration packages behind the existing backend contract before expanding pi-forge into a general runner.
83
+
84
+ ## Final Assessment
85
+
86
+ The original concentration problems and narrow parent-agent integration are addressed. Future complexity control should be incremental: isolate lifecycle-sensitive backend logic, split the browser client along real product boundaries, and resist turning pi-forge into a general orchestration framework without demonstrated need.
@@ -0,0 +1,31 @@
1
+ # Release process
2
+
3
+ [Documentation](../README.md)
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`.
10
+ 4. Test a packed installation against the documented minimum and current Pi versions.
11
+ 5. Exercise ordinary stack/profile use independently of delegation.
12
+ 6. Exercise both configured foreground backends and confirm unsupported host capabilities fail closed before provider transport.
13
+ 7. Inspect `npm pack --dry-run` for package size and unexpected or missing files.
14
+
15
+ ## Dependency policy
16
+
17
+ 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.
18
+
19
+ `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.
20
+
21
+ ## Package contents
22
+
23
+ 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.
24
+
25
+ The root `PUBLIC_API.md` and `SUBAGENT_ADAPTER_CONTRACT.md` files are compatibility pointers; authoritative content lives under `docs/reference/`.
26
+
27
+ ## Publish and verify
28
+
29
+ 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.
30
+
31
+ 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.
@@ -0,0 +1,36 @@
1
+ # Roadmap
2
+
3
+ [Documentation](../README.md)
4
+
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
+
7
+ ## 0.4 baseline
8
+
9
+ The profile UI, foreground-delegation dogfooding, dependency compatibility work, and documentation reorganization are complete and merged to `main`. Runtime beta.2 is published, and the packed 0.4.0 extension passes the full verification surface against the documented Pi versions.
10
+
11
+ The 0.4.1 release adds scoped global profiles and prompt stacks with project-over-global shadowing, exact `project:<id>`/`global:<id>` selectors, scoped delegation authorization, untrusted-project global browsing, web-editor global create/fork/import, and zh-CN documentation. The accepted resolution model is archived in [scoped global profiles and prompt stacks](scoped-global-profiles-stacks.md).
12
+
13
+ Stable 0.4 does not imply that the subagent adapter or runtime has become stable. Prompt stacks and ordinary profile use remain independent of delegation.
14
+
15
+ ## Near-term candidates
16
+
17
+ ### Sandbox and staged writes
18
+
19
+ Evaluate an optional backend that can honestly enforce roots, process behavior, symlink containment, and requested network policy. Keep shared-user as an explicit compatibility boundary. Design writes as a separately approved staged patch/change set; do not add write/edit/shell tools directly to the shared-user child.
20
+
21
+ ### Import, history, and prompt diagnostics
22
+
23
+ Add SillyTavern fidelity only from real unsupported fixtures. Candidate history controls need concrete use cases and dangling tool-pair tests. Provider-payload rewriting and display-only streaming regex remain deferred until a stable, previewable lifecycle hook exists.
24
+
25
+ ## Product guardrails
26
+
27
+ - Prompt-stack JSON stays declarative; executable customization stays in trusted extensions/packages.
28
+ - Profiles remain one-shot presets, not continuous runtime owners.
29
+ - Tool and skill policy stays in prompt stacks, not profiles.
30
+ - Skill filtering is model-visible prompt filtering, not an invocation or security boundary.
31
+ - Delegation remains opt-in, foreground, clean-context, and fail-closed on missing capabilities.
32
+ - Do not report shared-user read-only policy as an OS sandbox.
33
+ - New editor workflows require real-browser coverage.
34
+ - Run the full verification and package checks before release.
35
+
36
+ The detailed completed 0.4 plan is retained in the [historical roadmap](../design/roadmap-0.4-archive.md).
@@ -0,0 +1,325 @@
1
+ # Scoped global profiles and prompt stacks
2
+
3
+ [Documentation](../README.md) · [Roadmap](roadmap.md)
4
+
5
+ Status: accepted design; implementation complete for 0.4.1 (identity, catalogs, scoped stacks/profiles, persistence, auto-activation, delegation, zh-CN docs, and web-editor global create/fork/import with explicit scope).
6
+
7
+ ## Confirmed design decisions
8
+
9
+ Recorded before implementation started; these resolve the options left open by the analysis above.
10
+
11
+ - **D1** Unified resource ID grammar: `/^[A-Za-z0-9][A-Za-z0-9._-]*$/` for both profiles and stacks. `:` is reserved for scope qualification and rejected in JSON IDs (with a diagnostic, not a load failure).
12
+ - **D2** When capturing/saving a profile, `promptStack` is serialized relative to the target profile scope: same scope writes a bare ID, a different scope writes a qualified selector (`global:<id>`), and a global profile is never allowed to reference a project stack (the save is rejected).
13
+ - **D3** Global profiles/stacks are loaded and can be browsed/previewed in untrusted projects, but applying a profile or stack still requires project trust.
14
+ - **D4** Subagent delegation remains entirely disabled in untrusted projects, including for global profiles.
15
+ - **D5** `default.json` has no special auto-activation role anymore. Only `autoActivate: true` participates in standalone stack activation. A `default.json` without an explicit `autoActivate` field receives a one-time migration warning; `autoActivate: false` remains an explicit opt-out. Multiple `autoActivate: true` stacks in the same scope fail closed.
16
+ - **D6** Legacy provenance records without a scope field are interpreted as project-scoped.
17
+ - **D7** `forge_subagent` accepts a bare `profileId` through effective lookup (project first) and `global:<id>` for exact global access; tool descriptions and `forge_subagent_profiles` explain the canonical selectors.
18
+ - **D8** New session entries and provenance persist the string selector form (`project:<id>` / `global:<id>`); `none` stays a scope-independent bare opt-out.
19
+ - **D9** Runtime state keeps flat `Loaded*[]` arrays whose entries carry `scope`/`key`; a shared catalog module owns `all`/`effective`/exact resolution.
20
+ - **D10** Web editor API routes encode scope as a single path segment (`scope:id`, e.g. `/api/stacks/global:reviewer`).
21
+ - **D11** A new `PI_FORGE_GLOBAL_DIR` environment override replaces the real `~/.pi/forge` for tests and embedders; loaders accept an explicit global Forge directory, and `globalForgeDir()` is only the default.
22
+ - **D12** Slice 5 is split into 5a (forge-config data model, scoped authorization, and unit tests) and 5b (discovery, tool descriptions, approval display, commands, docs, and browser verification).
23
+ - **D13** The web editor may edit/delete global resources when the route uses an explicit scope; unqualified routes remain project-only.
24
+
25
+
26
+ This note defines the resource identity, lookup, activation, persistence, and delegation model for adding user-global agent profiles and prompt stacks without weakening project shadowing or authorization boundaries.
27
+
28
+ ## Goals
29
+
30
+ - Reuse profiles and prompt stacks across projects.
31
+ - Keep common commands concise through project-over-global shadowing.
32
+ - Preserve an explicit way to address either scope when IDs collide.
33
+ - Make stored profile dependencies deterministic rather than dependent on later shadowing.
34
+ - Keep global and project delegation authorization separate.
35
+ - Preserve existing project-only files and unqualified commands where no collision exists.
36
+
37
+ ## Non-goals
38
+
39
+ - Do not add inheritance or merging between two profile or stack definitions.
40
+ - Do not make profiles continuously own runtime state.
41
+ - Do not move tool or skill policy from prompt stacks into profiles.
42
+ - Do not let a global profile depend on project-controlled prompt content.
43
+ - Do not add writable subagents, compaction settings, or a concurrency cap as part of this feature.
44
+
45
+ ## Storage and identity
46
+
47
+ Global resources use the existing user-owned Forge root:
48
+
49
+ ```text
50
+ ~/.pi/forge/prompt-stacks/*.json
51
+ ~/.pi/forge/agent-profiles/*.json
52
+ ```
53
+
54
+ Project resources keep their current locations:
55
+
56
+ ```text
57
+ <project>/.pi/forge/prompt-stacks/*.json
58
+ <project>/.pi/forge/agent-profiles/*.json
59
+ ```
60
+
61
+ The JSON `id` remains an unqualified value such as `reviewer`. Scope comes from the storage location and must not be duplicated as an editable field in the file.
62
+
63
+ Every loaded resource must carry a first-class scoped identity:
64
+
65
+ ```ts
66
+ type ResourceScope = "global" | "project";
67
+
68
+ interface ResourceKey {
69
+ scope: ResourceScope;
70
+ id: string;
71
+ }
72
+ ```
73
+
74
+ Do not repeatedly infer scope from `filePath`. Loaded profiles and stacks should expose their scope/key directly, and runtime state should compare keys rather than bare IDs.
75
+
76
+ Duplicate IDs are errors only within one scope. A project and global resource with the same ID form a valid shadow pair.
77
+
78
+ ## Selector syntax
79
+
80
+ Commands, completion candidates, profile stack references, persisted diagnostics, and delegation discovery use one selector grammar:
81
+
82
+ ```text
83
+ reviewer
84
+ project:reviewer
85
+ global:reviewer
86
+ ```
87
+
88
+ Existing resource IDs cannot contain `:`, so qualification is unambiguous. Reject unknown scope prefixes, empty IDs, and malformed selectors with a specific diagnostic.
89
+
90
+ The canonical formatter should return:
91
+
92
+ - `reviewer` only when presenting the effective unqualified resource;
93
+ - `project:reviewer` or `global:reviewer` when exact identity matters;
94
+ - qualified selectors for both resources when a collision must be shown.
95
+
96
+ Internally, parse selectors into `{ scope?: ResourceScope; id: string }` and resolve them to a required `ResourceKey` before mutation, application, persistence, or delegation.
97
+
98
+ ## Two lookup modes
99
+
100
+ Unqualified interactive selection and unqualified profile dependencies deliberately use different lookup rules.
101
+
102
+ ### Effective lookup
103
+
104
+ Commands such as `/preset use` and `/profile use` use effective lookup:
105
+
106
+ 1. A qualified selector resolves only the named scope.
107
+ 2. An unqualified selector resolves the project resource when present.
108
+ 3. Otherwise it resolves the global resource.
109
+ 4. A project definition shadows the same-ID global definition even when the project definition is invalid. The invalid shadow fails closed; it must not silently fall back to the global resource.
110
+
111
+ Examples:
112
+
113
+ ```text
114
+ /profile use reviewer # project first, otherwise global
115
+ /profile use global:reviewer # exact global profile
116
+ /preset use project:reviewer # exact project stack
117
+ ```
118
+
119
+ Both colliding resources remain inspectable and explicitly selectable. Shadowing is an ergonomic default, not deletion of the global definition.
120
+
121
+ ### Profile dependency lookup
122
+
123
+ A profile's `promptStack` is a stored dependency and must remain stable when unrelated files are later added. Its unqualified reference therefore resolves relative to the profile's own scope rather than through effective lookup.
124
+
125
+ | Profile scope | `"reviewer"` | `"project:reviewer"` | `"global:reviewer"` |
126
+ |---|---|---|---|
127
+ | Project | project stack | project stack | global stack |
128
+ | Global | global stack | rejected | global stack |
129
+
130
+ Consequences:
131
+
132
+ - A project profile may use either a project stack or an explicitly qualified global stack.
133
+ - A project profile with `"promptStack": "reviewer"` does not fall back to a global stack when the project stack is missing. The diagnostic should suggest `global:reviewer` when that global stack exists.
134
+ - A global profile may use only global stacks. `project:*` is rejected even if the project is trusted.
135
+ - Adding a project stack later cannot silently change the dependency of a project profile that explicitly uses `global:reviewer`.
136
+ - A project cannot replace the prompt or tool policy of a user-authorized global profile.
137
+
138
+ The string form remains sufficient for profile schema v1 because qualification expands the accepted reference syntax without adding a new field or object shape. Existing project profiles keep resolving their unqualified stack IDs to project stacks.
139
+
140
+ ## Loading and catalogs
141
+
142
+ Global definitions are user-owned and may load independently of project trust. Project definitions load only when the project is trusted.
143
+
144
+ Pure loaders and tests must not accidentally read the developer's real home directory. Prefer an explicit catalog/repository input for the global Forge directory over relying on a process-wide environment variable. Existing project-only public loader functions may remain as compatibility wrappers while the extension runtime adopts scoped catalog loaders.
145
+
146
+ Maintain both views:
147
+
148
+ - `all`: every loaded scoped definition, including shadowed resources;
149
+ - `effective`: one resource per unqualified ID after project-over-global shadowing.
150
+
151
+ Centralize resolution helpers instead of continuing to use bare `array.find(candidate.id === id)` calls. Application, preview, mutation, auto-activation, subagent preparation, and the editor must resolve through the same catalog semantics.
152
+
153
+ ## Selection and persistence
154
+
155
+ New session entries must persist the exact scoped key, not just the bare ID. This prevents a restored global selection from changing to a newly created project shadow after reload or tree navigation.
156
+
157
+ For compatibility:
158
+
159
+ - Read legacy branch entries containing only `activeStackId` using effective lookup.
160
+ - Write new entries with a scoped active-stack reference.
161
+ - Preserve the explicit `none`/`off` selection as a scope-independent opt-out.
162
+ - Profile provenance should add the profile scope/key while continuing to accept older provenance that has only `profileId` and `sourcePath`.
163
+ - Drift snapshots should store the resolved scoped stack reference so status can distinguish definition changes from a scope change.
164
+
165
+ Profile application remains transactional and one-shot. Later manual model/thinking changes remain respected; the selected stack continues enforcing its existing policy exactly as it does now.
166
+
167
+ ## Auto-activation
168
+
169
+ Restored branch state and explicit opt-out continue to take precedence over all fresh-session defaults.
170
+
171
+ For agent profiles:
172
+
173
+ 1. Inspect project `autoActivate: true` candidates first.
174
+ 2. If any project candidate exists, do not fall back to a global candidate.
175
+ 3. Exactly one usable project candidate applies; an invalid or ambiguous project selection fails closed.
176
+ 4. If no project candidate exists, apply the same rules to global candidates.
177
+ 5. A project and global auto-activation candidate are not a conflict because project scope has explicit precedence.
178
+
179
+ For standalone prompt-stack activation, apply the same scope precedence after profile auto-activation has declined to select a profile:
180
+
181
+ 1. Only stacks with `autoActivate: true` participate; `default.json` has no filename-based activation role (D5).
182
+ 2. Resolve project candidates before global candidates.
183
+ 3. A same-ID project stack shadows the global stack, including an invalid shadow or `autoActivate: false` opt-out.
184
+ 4. Exactly one usable candidate applies; multiple `autoActivate: true` stacks in the same scope fail closed.
185
+ 5. Do not silently activate the global same-ID stack through an invalid or opted-out project shadow.
186
+ 6. Preserve the existing rule that agent-profile auto-activation takes precedence over standalone stack activation, including profiles whose `promptStack` is `null`.
187
+
188
+ ## Commands and editor behavior
189
+
190
+ Unqualified commands use effective lookup. Qualified commands address exact scope.
191
+
192
+ Recommended command behavior:
193
+
194
+ ```text
195
+ /preset use reviewer
196
+ /preset use global:reviewer
197
+ /profile use project:reviewer
198
+ /profile preview global:reviewer
199
+ /profile save reviewer # project by default
200
+ /profile save global:reviewer # explicit global mutation
201
+ ```
202
+
203
+ Mutations must resolve the target scope before computing a path. Existing overwrite, changed-file, containment, and symbolic-link protections apply independently to each storage root. Global mutation must always be explicit; an unqualified save/fork/import continues to target project storage.
204
+
205
+ The web editor should:
206
+
207
+ - show global/project badges on profiles and stacks;
208
+ - show `shadows global:<id>` and `shadowed by project:<id>` states;
209
+ - retain both resources in navigation when IDs collide;
210
+ - require explicit scope for create, fork, import, save-as, and delete targets;
211
+ - prevent editing a shadowed global resource through an unqualified project route;
212
+ - keep the current token, trust, idle-state, overwrite, and browser-test protections for mutations.
213
+
214
+ Completions may prefer concise unqualified effective selectors, but must also offer qualified selectors when a collision exists or when the user has begun typing a scope prefix.
215
+
216
+ ## Delegation boundary
217
+
218
+ Delegation authorization follows the profile's scope, not the effective unqualified ID:
219
+
220
+ - `~/.pi/forge/config.json` `subagents.profiles.<id>` authorizes only `global:<id>`.
221
+ - `<project>/.pi/forge/config.json` `subagents.profiles.<id>` authorizes only `project:<id>`.
222
+ - Same-ID global and project profiles never inherit enablement, backend, or timeout policy from one another.
223
+ - General backend, timeout, and summary defaults retain their current global-then-project layering.
224
+ - Deleting a profile clears delegation policy only from the matching scope's config.
225
+ - A global profile remains bound to global prompt content even when a project profile or stack shadows the same ID.
226
+
227
+ `forge_subagent_profiles` should return canonical callable selectors. When both scopes expose the same ID, the project profile may use the concise effective selector and the global profile must remain callable as `global:<id>`. The `forge_subagent` parameter, `/forge-agent` commands, embedded description summary, preparation lookup, approval display, fingerprints, and reports must retain exact scope.
228
+
229
+ Global profiles are user-owned, but ordinary delegation safety does not change: profiles remain disabled unless authorized in the matching config, unattended invocation remains a separate trusted-project decision, and read-only still does not imply an OS sandbox.
230
+
231
+ ## Compatibility and migration
232
+
233
+ - No files move automatically.
234
+ - Existing `.pi/forge` and legacy `.pi/prompt-stacks` resources remain project-scoped.
235
+ - Existing project profile `promptStack` strings remain project-relative.
236
+ - Existing unqualified commands behave the same when no global collision exists.
237
+ - Legacy bare-ID session entries restore through effective lookup; all new entries record scope.
238
+ - Same-ID cross-scope definitions are valid and must not receive duplicate-ID errors.
239
+ - Duplicate IDs within one scope keep the current fail-closed diagnostics.
240
+ - Global `subagents.profiles` entries, which currently warn and are ignored, become scoped authorization for global profiles only. Document this behavior change prominently.
241
+ - Public loaded-resource types may add scope/key metadata without removing existing fields; compatibility helpers should continue accepting legacy bare IDs where persisted data requires them.
242
+
243
+ ## Implementation slices
244
+
245
+ Each slice should land with focused tests and leave the full verification surface green.
246
+
247
+ ### Slice 1: scoped identity and storage
248
+
249
+ - Add `ResourceScope`, `ResourceKey`, selector parsing/formatting, and exact/effective resolution primitives.
250
+ - Add global profile/stack directory and safe mutation-path helpers.
251
+ - Add scope/key metadata to loaded resources.
252
+ - Keep JSON IDs unqualified and validate selector syntax separately from ID syntax.
253
+ - Add table-driven parser, formatter, storage-containment, and same-ID-key tests.
254
+
255
+ Exit criterion: scoped resources can be represented and addressed without changing runtime loading behavior.
256
+
257
+ ### Slice 2: scoped stack catalog and persistence
258
+
259
+ - Load global stacks plus trusted project/legacy stacks into `all` and `effective` views.
260
+ - Implement project shadowing, exact qualified selection, and invalid-shadow fail-closed behavior.
261
+ - Replace bare-ID runtime lookups with catalog resolution.
262
+ - Persist scoped active-stack references and restore legacy bare-ID entries.
263
+ - Apply scoped standalone stack auto-activation and explicit opt-out rules.
264
+
265
+ Exit criterion: `/preset` runtime behavior, branch restoration, tool policy, preview, and stack diagnostics operate correctly across both scopes before profiles are migrated.
266
+
267
+ ### Slice 3: scoped profiles and dependency resolution
268
+
269
+ - Load global and trusted-project profiles with duplicate and auto-activation diagnostics scoped correctly.
270
+ - Implement the profile-to-stack resolution matrix.
271
+ - Extend preview, application, rollback, provenance, drift, save, delete, and reload with exact scoped keys.
272
+ - Preserve profile auto-activation precedence over standalone stacks.
273
+ - Extend host/subagent profile snapshots and fingerprints with resolved scope where required without changing legacy provenance fingerprint interpretation.
274
+
275
+ Exit criterion: global and project profiles apply deterministically, including explicit project-to-global stack reuse and rejection of global-to-project references.
276
+
277
+ ### Slice 4: commands and web editor
278
+
279
+ - Add qualified parsing and completions to `/preset`, `/profile`, and editor APIs.
280
+ - Make unqualified mutations project-scoped and global mutations explicit.
281
+ - Show scope, collisions, shadow relationships, exact dependencies, and scoped drift in human surfaces.
282
+ - Add real-browser coverage for browsing, applying, editing, forking, deleting, collision handling, and failed scoped preflight.
283
+
284
+ Exit criterion: users can understand and manage both scopes without an unqualified action mutating a global resource.
285
+
286
+ ### Slice 5: scoped delegation, documentation, and release verification
287
+
288
+ - Accept global profile authorization from global config and project profile authorization from project config.
289
+ - Update discovery, embedded summaries, callable selectors, `/forge-agent`, preparation, approval, reports, and policy cleanup.
290
+ - Test same-ID profiles with independent enablement/backend/timeout settings and no authority inheritance.
291
+ - Update English and Chinese concepts, guides, commands, configuration, schema/reference, feature inventory, changelog, and roadmap.
292
+ - Regenerate tracked browser assets and `dist`, then run `npm run verify` and a packed-install smoke test.
293
+
294
+ Exit criterion: scoped ordinary use and scoped delegation are documented, fail closed, package-clean, and verified end to end.
295
+
296
+ ## Required scenario coverage
297
+
298
+ At minimum, automated tests should cover:
299
+
300
+ - Global-only, project-only, and same-ID collision lookup.
301
+ - Exact global access while shadowed.
302
+ - Invalid project shadow without global fallback.
303
+ - Global profile to global stack.
304
+ - Project profile to unqualified project stack.
305
+ - Project profile to explicitly qualified global stack.
306
+ - Missing project stack with a same-ID global suggestion but no fallback.
307
+ - Rejected global profile to project stack.
308
+ - Project auto-activation precedence, global fallback, ambiguity, invalid candidate, restored branch, and explicit opt-out.
309
+ - `default.json` no longer auto-activates by filename; missing `autoActivate` yields a migration warning (D5).
310
+ - Scoped session restoration after a new shadow appears.
311
+ - Scoped provenance and drift after source edits or scope changes.
312
+ - Independent global/project delegation authorization for the same ID.
313
+ - Deletion clearing only matching-scope delegation policy.
314
+ - Untrusted projects loading global resources but not project resources.
315
+ - Web-editor collision navigation and explicit-scope mutation safeguards.
316
+
317
+ ## Architectural guardrails
318
+
319
+ - Keep resolution in shared catalog/services; do not duplicate shadow rules across commands, the editor, and subagent code.
320
+ - Never use project-over-global effective lookup for a stored global profile dependency.
321
+ - Never infer delegation authority from a bare ID after profile resolution.
322
+ - Never persist a new active selection or provenance record without exact scope.
323
+ - Never silently fall back across scopes after an explicit selector or an invalid shadow.
324
+ - Keep profile application transactional and tool/skill policy owned by the resolved prompt stack.
325
+ - Require the complete unit, browser, type, generated-output, documentation, and package verification surface for the final slice.
@@ -0,0 +1,75 @@
1
+ # Development setup
2
+
3
+ [Documentation](../README.md)
4
+
5
+ ## Build from source
6
+
7
+ ```bash
8
+ git clone https://github.com/MacroSony/pi-forge.git
9
+ cd pi-forge
10
+ npm install
11
+ npm run build
12
+ pi
13
+ ```
14
+
15
+ Trust the project in Pi and use `/reload` when needed.
16
+
17
+ The npm package loads compiled `dist/index.js` and intentionally omits physical `src/` files. Clone or fork the repository to inspect or modify source; do not edit generated files in `node_modules`.
18
+
19
+ ## Load the extension
20
+
21
+ For release-like local testing, register the cloned package directory in Pi settings:
22
+
23
+ ```json
24
+ {
25
+ "packages": ["../pi-forge"]
26
+ }
27
+ ```
28
+
29
+ For live source development, remove that package entry and load the TypeScript extension directly:
30
+
31
+ ```json
32
+ {
33
+ "extensions": ["../pi-forge/src/index.ts"]
34
+ }
35
+ ```
36
+
37
+ You can also run `pi -e ../pi-forge/src/index.ts` for a one-off smoke test. Never load both package and source entries simultaneously; pi-forge would initialize twice.
38
+
39
+ Browser-client source changes require `npm run build:client` because the editor serves a generated embedded bundle.
40
+
41
+ ## Verification
42
+
43
+ ```bash
44
+ npm test # core Node test suite
45
+ npm run test:browser # real-browser editor characterization
46
+ npm run typecheck # TypeScript and Vue
47
+ npm run build # client bundle and dist output
48
+ npm run verify # all tests plus generated/package consistency
49
+ npm pack --dry-run # inspect the publishable tarball
50
+ ```
51
+
52
+ Set `CHROME_PATH` when Chrome/Chromium is outside a standard location. CI runs the full verification. When source changes generated output, commit matching generated client and `dist` files.
53
+
54
+ ## Pi compatibility
55
+
56
+ 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.
57
+
58
+ 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.
59
+
60
+ Release validation should test:
61
+
62
+ - the documented minimum supported Pi version;
63
+ - the current Pi version at release time;
64
+ - an automated or scheduled probe of npm `latest`.
65
+
66
+ Document the tested range separately from peer constraints. Pi-coupled experimental subagent capabilities must preflight against the actual host and fail closed with a precise compatibility diagnostic when required APIs are unavailable; ordinary stacks and profiles should remain usable.
67
+
68
+ ## Package boundaries
69
+
70
+ - `@zihanw/pi-forge` is the Pi extension and stable macro/slot registration surface.
71
+ - `@zihanw/pi-forge/subagent` is the preferred experimental host-contract entry point.
72
+ - `@zihanw/pi-subagent-runtime` owns execution lifecycle and fresh-process backends.
73
+ - Legacy `@zihanw/pi-forge/src/*` aliases resolve to compiled compatibility modules and are not a promise that internals are public.
74
+
75
+ See the [public API policy](../reference/public-api.md).
@@ -0,0 +1,95 @@
1
+ # Getting started
2
+
3
+ [Documentation](README.md) · [中文](zh-CN/getting-started.md)
4
+
5
+ ## Requirements and installation
6
+
7
+ pi-forge requires Node.js 22.19 or newer and runs as a Pi extension.
8
+
9
+ ```bash
10
+ pi install npm:@zihanw/pi-forge
11
+ ```
12
+
13
+ Restart Pi after installing or updating. The running Pi host supplies its SDK packages; see [Pi compatibility](development/setup.md#pi-compatibility) for the tested-version policy.
14
+
15
+ Project stacks, profiles, and configuration are loaded only after Pi trusts the project.
16
+
17
+ ## Create your first stack
18
+
19
+ Prompt stacks live in `.pi/forge/prompt-stacks/*.json`. The quickest baseline is [the default Pi mirror](../examples/default-prompt-stack.json), which preserves normal Pi behavior while splitting its prompt into movable sections.
20
+
21
+ In a repository clone:
22
+
23
+ ```bash
24
+ mkdir -p .pi/forge/prompt-stacks
25
+ cp examples/default-prompt-stack.json .pi/forge/prompt-stacks/default.json
26
+ ```
27
+
28
+ When installed from npm, open `/preset ui` and create a stack; new stacks start from the same mirror layout.
29
+
30
+ Reload and activate it:
31
+
32
+ ```text
33
+ /preset reload
34
+ /preset use default
35
+ ```
36
+
37
+ If no restored session selection or explicit opt-out takes precedence, `default.json` auto-activates. Set `"autoActivate": false` to prevent that behavior.
38
+
39
+ ## Edit and inspect
40
+
41
+ ```text
42
+ /preset ui
43
+ ```
44
+
45
+ The editor opens on a token-protected `127.0.0.1` URL. It supports structured and raw JSON editing, drag-and-drop ordering, validation, exact preview, policy selection, regex rules, import/export, fork, and profile management. See the [web-editor guide](guides/web-editor.md).
46
+
47
+ To inspect without opening a browser:
48
+
49
+ ```text
50
+ /preset validate default
51
+ /preset preview default
52
+ /preset diagnostics
53
+ ```
54
+
55
+ ## Create a profile
56
+
57
+ Select the model, thinking level, and prompt stack you want in Pi, then save them:
58
+
59
+ ```text
60
+ /profile save reviewer
61
+ /profile preview reviewer
62
+ /profile use reviewer
63
+ ```
64
+
65
+ Profiles live in `.pi/forge/agent-profiles/*.json` by default; `/profile save global:<id>` writes to `~/.pi/forge/agent-profiles`. Applying one is a preflighted, one-shot operation: later manual model/thinking changes remain until you apply the profile again. Read [agent-profile concepts](concepts/agent-profiles.md) for validation, auto-activation, and drift semantics.
66
+
67
+ ## Storage and migration
68
+
69
+ | Location | Purpose |
70
+ |---|---|
71
+ | `.pi/forge/prompt-stacks/` | Project prompt stacks |
72
+ | `.pi/forge/agent-profiles/` | Project agent profiles |
73
+ | `.pi/forge/config.json` | Trusted project configuration and `project:<id>` delegation authorization |
74
+ | `.pi/forge/extensions/` | Trusted project macro/slot registration code |
75
+ | `~/.pi/forge/prompt-stacks/` | User-global prompt stacks |
76
+ | `~/.pi/forge/agent-profiles/` | User-global agent profiles |
77
+ | `~/.pi/forge/config.json` | User defaults and `global:<id>` delegation authorization |
78
+ | `~/.pi/forge/extensions/` | Trusted user macro/slot registration code |
79
+
80
+ Legacy `.pi/prompt-stacks/*.json` files remain readable. Command-created stacks go to `.pi/forge/prompt-stacks`; use the web editor's `global` scope selector to create stacks in `~/.pi/forge/prompt-stacks`. Same-named new-location files shadow legacy ones. Migrate safely with:
81
+
82
+ ```text
83
+ /preset migrate-stacks --dry-run
84
+ /preset migrate-stacks
85
+ ```
86
+
87
+ Add `--overwrite` only when target replacement is intended. Add `--delete-legacy` only after checking the copied files.
88
+
89
+ ## Where to go next
90
+
91
+ - Learn the [prompt-stack model](concepts/prompt-stacks.md).
92
+ - Fork a [focused reviewer](../examples/reviewer-prompt-stack.json) or [DM writer](../examples/sillytavern-dm-writer-prompt-stack.json).
93
+ - Use the [SillyTavern importer](guides/sillytavern-import.md).
94
+ - Learn [macros and slots](reference/macros-and-slots.md).
95
+ - Inspect the [complete commands](reference/commands.md) and [stack schema](reference/stack-schema.md).