@entelligentsia/forgecli 0.10.1 → 0.11.2

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 (161) hide show
  1. package/CHANGELOG.md +78 -0
  2. package/README.md +21 -3
  3. package/dist/CHANGELOG-forge-plugin.md +22 -0
  4. package/dist/extensions/forgecli/add-pipeline.d.ts +19 -0
  5. package/dist/extensions/forgecli/add-pipeline.js +143 -0
  6. package/dist/extensions/forgecli/add-pipeline.js.map +1 -0
  7. package/dist/extensions/forgecli/add-task.d.ts +20 -0
  8. package/dist/extensions/forgecli/add-task.js +154 -0
  9. package/dist/extensions/forgecli/add-task.js.map +1 -0
  10. package/dist/extensions/forgecli/calibrate.d.ts +61 -0
  11. package/dist/extensions/forgecli/calibrate.js +488 -0
  12. package/dist/extensions/forgecli/calibrate.js.map +1 -0
  13. package/dist/extensions/forgecli/fix-bug.d.ts +9 -1
  14. package/dist/extensions/forgecli/fix-bug.js +70 -8
  15. package/dist/extensions/forgecli/fix-bug.js.map +1 -1
  16. package/dist/extensions/forgecli/forge-commands.js +15 -22
  17. package/dist/extensions/forgecli/forge-commands.js.map +1 -1
  18. package/dist/extensions/forgecli/forge-subagent.js +34 -7
  19. package/dist/extensions/forgecli/forge-subagent.js.map +1 -1
  20. package/dist/extensions/forgecli/forge-update-command.d.ts +9 -0
  21. package/dist/extensions/forgecli/forge-update-command.js +106 -7
  22. package/dist/extensions/forgecli/forge-update-command.js.map +1 -1
  23. package/dist/extensions/forgecli/health-check.d.ts +22 -1
  24. package/dist/extensions/forgecli/health-check.js +177 -4
  25. package/dist/extensions/forgecli/health-check.js.map +1 -1
  26. package/dist/extensions/forgecli/hook-dispatcher.d.ts +25 -1
  27. package/dist/extensions/forgecli/hook-dispatcher.js +104 -9
  28. package/dist/extensions/forgecli/hook-dispatcher.js.map +1 -1
  29. package/dist/extensions/forgecli/hooks/check-update.d.ts +81 -0
  30. package/dist/extensions/forgecli/hooks/check-update.js +308 -0
  31. package/dist/extensions/forgecli/hooks/check-update.js.map +1 -0
  32. package/dist/extensions/forgecli/hooks/forge-permissions.d.ts +32 -0
  33. package/dist/extensions/forgecli/hooks/forge-permissions.js +119 -0
  34. package/dist/extensions/forgecli/hooks/forge-permissions.js.map +1 -0
  35. package/dist/extensions/forgecli/hooks/triage-error.d.ts +23 -0
  36. package/dist/extensions/forgecli/hooks/triage-error.js +62 -0
  37. package/dist/extensions/forgecli/hooks/triage-error.js.map +1 -0
  38. package/dist/extensions/forgecli/hooks/write-guard.d.ts +28 -0
  39. package/dist/extensions/forgecli/hooks/write-guard.js +225 -0
  40. package/dist/extensions/forgecli/hooks/write-guard.js.map +1 -0
  41. package/dist/extensions/forgecli/index.js +60 -0
  42. package/dist/extensions/forgecli/index.js.map +1 -1
  43. package/dist/extensions/forgecli/init-context.d.ts +1 -1
  44. package/dist/extensions/forgecli/init-context.js +21 -6
  45. package/dist/extensions/forgecli/init-context.js.map +1 -1
  46. package/dist/extensions/forgecli/materialize.d.ts +16 -0
  47. package/dist/extensions/forgecli/materialize.js +195 -0
  48. package/dist/extensions/forgecli/materialize.js.map +1 -0
  49. package/dist/extensions/forgecli/migrate.d.ts +19 -0
  50. package/dist/extensions/forgecli/migrate.js +258 -0
  51. package/dist/extensions/forgecli/migrate.js.map +1 -0
  52. package/dist/extensions/forgecli/migration-engine.d.ts +111 -0
  53. package/dist/extensions/forgecli/migration-engine.js +533 -0
  54. package/dist/extensions/forgecli/migration-engine.js.map +1 -0
  55. package/dist/extensions/forgecli/quiz-agent.d.ts +17 -0
  56. package/dist/extensions/forgecli/quiz-agent.js +98 -0
  57. package/dist/extensions/forgecli/quiz-agent.js.map +1 -0
  58. package/dist/extensions/forgecli/remove-command.d.ts +17 -0
  59. package/dist/extensions/forgecli/remove-command.js +124 -0
  60. package/dist/extensions/forgecli/remove-command.js.map +1 -0
  61. package/dist/extensions/forgecli/report-bug.d.ts +25 -0
  62. package/dist/extensions/forgecli/report-bug.js +159 -0
  63. package/dist/extensions/forgecli/report-bug.js.map +1 -0
  64. package/dist/extensions/forgecli/retrospective.d.ts +19 -0
  65. package/dist/extensions/forgecli/retrospective.js +156 -0
  66. package/dist/extensions/forgecli/retrospective.js.map +1 -0
  67. package/dist/extensions/forgecli/run-sprint.js +34 -0
  68. package/dist/extensions/forgecli/run-sprint.js.map +1 -1
  69. package/dist/extensions/forgecli/run-task.d.ts +9 -1
  70. package/dist/extensions/forgecli/run-task.js +64 -10
  71. package/dist/extensions/forgecli/run-task.js.map +1 -1
  72. package/dist/extensions/forgecli/session-registry.d.ts +27 -2
  73. package/dist/extensions/forgecli/session-registry.js +52 -1
  74. package/dist/extensions/forgecli/session-registry.js.map +1 -1
  75. package/dist/extensions/forgecli/status-command.d.ts +19 -0
  76. package/dist/extensions/forgecli/status-command.js +140 -0
  77. package/dist/extensions/forgecli/status-command.js.map +1 -0
  78. package/dist/extensions/forgecli/store-query.d.ts +22 -0
  79. package/dist/extensions/forgecli/store-query.js +107 -0
  80. package/dist/extensions/forgecli/store-query.js.map +1 -0
  81. package/dist/extensions/forgecli/store-repair.d.ts +17 -0
  82. package/dist/extensions/forgecli/store-repair.js +123 -0
  83. package/dist/extensions/forgecli/store-repair.js.map +1 -0
  84. package/dist/extensions/forgecli/thread-switcher.js +213 -28
  85. package/dist/extensions/forgecli/thread-switcher.js.map +1 -1
  86. package/dist/extensions/forgecli/update-tools.d.ts +23 -0
  87. package/dist/extensions/forgecli/update-tools.js +136 -0
  88. package/dist/extensions/forgecli/update-tools.js.map +1 -0
  89. package/dist/extensions/forgecli/viewport-theme.js +4 -0
  90. package/dist/extensions/forgecli/viewport-theme.js.map +1 -1
  91. package/dist/forge-payload/.claude-plugin/plugin.json +1 -1
  92. package/dist/forge-payload/.schemas/config.schema.json +83 -0
  93. package/dist/forge-payload/.schemas/migrations.json +2049 -0
  94. package/dist/forge-payload/commands/regenerate.md +17 -1
  95. package/dist/forge-payload/meta/personas/README.md +16 -0
  96. package/dist/forge-payload/meta/personas/meta-architect.md +70 -0
  97. package/dist/forge-payload/meta/personas/meta-bug-fixer.md +73 -0
  98. package/dist/forge-payload/meta/personas/meta-collator.md +72 -0
  99. package/dist/forge-payload/meta/personas/meta-engineer.md +70 -0
  100. package/dist/forge-payload/meta/personas/meta-orchestrator.md +71 -0
  101. package/dist/forge-payload/meta/personas/meta-product-manager.md +82 -0
  102. package/dist/forge-payload/meta/personas/meta-qa-engineer.md +91 -0
  103. package/dist/forge-payload/meta/personas/meta-supervisor.md +92 -0
  104. package/dist/forge-payload/meta/skill-recommendations.md +154 -0
  105. package/dist/forge-payload/meta/skills/meta-architect-skills.md +43 -0
  106. package/dist/forge-payload/meta/skills/meta-bug-fixer-skills.md +43 -0
  107. package/dist/forge-payload/meta/skills/meta-collator-skills.md +41 -0
  108. package/dist/forge-payload/meta/skills/meta-engineer-skills.md +43 -0
  109. package/dist/forge-payload/meta/skills/meta-generic-skills.md +58 -0
  110. package/dist/forge-payload/meta/skills/meta-qa-engineer-skills.md +46 -0
  111. package/dist/forge-payload/meta/skills/meta-supervisor-skills.md +43 -0
  112. package/dist/forge-payload/meta/store-schema/bug.schema.md +71 -0
  113. package/dist/forge-payload/meta/store-schema/event.schema.md +76 -0
  114. package/dist/forge-payload/meta/store-schema/feature.schema.md +65 -0
  115. package/dist/forge-payload/meta/store-schema/sprint.schema.md +64 -0
  116. package/dist/forge-payload/meta/store-schema/task.schema.md +78 -0
  117. package/dist/forge-payload/meta/templates/meta-code-review.md +26 -0
  118. package/dist/forge-payload/meta/templates/meta-plan-review.md +28 -0
  119. package/dist/forge-payload/meta/templates/meta-plan.md +28 -0
  120. package/dist/forge-payload/meta/templates/meta-progress.md +25 -0
  121. package/dist/forge-payload/meta/templates/meta-retrospective.md +28 -0
  122. package/dist/forge-payload/meta/templates/meta-sprint-manifest.md +26 -0
  123. package/dist/forge-payload/meta/templates/meta-sprint-requirements.md +91 -0
  124. package/dist/forge-payload/meta/templates/meta-task-prompt.md +26 -0
  125. package/dist/forge-payload/meta/tool-specs/collate.spec.md +88 -0
  126. package/dist/forge-payload/meta/tool-specs/generation-manifest.spec.md +139 -0
  127. package/dist/forge-payload/meta/tool-specs/manage-config.spec.md +143 -0
  128. package/dist/forge-payload/meta/tool-specs/seed-store.spec.md +91 -0
  129. package/dist/forge-payload/meta/tool-specs/store-cli.spec.md +328 -0
  130. package/dist/forge-payload/meta/tool-specs/validate-store.spec.md +191 -0
  131. package/dist/forge-payload/meta/workflows/_fragments/context-injection.md +75 -0
  132. package/dist/forge-payload/meta/workflows/_fragments/event-emission-schema.md +73 -0
  133. package/dist/forge-payload/meta/workflows/_fragments/finalize.md +13 -0
  134. package/dist/forge-payload/meta/workflows/_fragments/friction-emit.md +73 -0
  135. package/dist/forge-payload/meta/workflows/_fragments/progress-reporting.md +38 -0
  136. package/dist/forge-payload/meta/workflows/_fragments/store-cli-verbs.md +39 -0
  137. package/dist/forge-payload/meta/workflows/meta-approve.md +119 -0
  138. package/dist/forge-payload/meta/workflows/meta-collate.md +89 -0
  139. package/dist/forge-payload/meta/workflows/meta-commit.md +93 -0
  140. package/dist/forge-payload/meta/workflows/meta-enhance.md +286 -0
  141. package/dist/forge-payload/meta/workflows/meta-fix-bug.md +501 -0
  142. package/dist/forge-payload/meta/workflows/meta-implement.md +132 -0
  143. package/dist/forge-payload/meta/workflows/meta-migrate.md +455 -0
  144. package/dist/forge-payload/meta/workflows/meta-orchestrate.md +993 -0
  145. package/dist/forge-payload/meta/workflows/meta-plan-task.md +133 -0
  146. package/dist/forge-payload/meta/workflows/meta-quiz-agent.md +135 -0
  147. package/dist/forge-payload/meta/workflows/meta-retrospective.md +65 -0
  148. package/dist/forge-payload/meta/workflows/meta-review-implementation.md +119 -0
  149. package/dist/forge-payload/meta/workflows/meta-review-plan.md +108 -0
  150. package/dist/forge-payload/meta/workflows/meta-review-sprint-completion.md +65 -0
  151. package/dist/forge-payload/meta/workflows/meta-sprint-intake.md +76 -0
  152. package/dist/forge-payload/meta/workflows/meta-sprint-plan.md +147 -0
  153. package/dist/forge-payload/meta/workflows/meta-update-implementation.md +76 -0
  154. package/dist/forge-payload/meta/workflows/meta-update-plan.md +76 -0
  155. package/dist/forge-payload/meta/workflows/meta-validate.md +111 -0
  156. package/dist/forge-payload/tools/check-structure.cjs +344 -0
  157. package/dist/forge-payload/tools/list-skills.js +76 -0
  158. package/dist/forge-payload/tools/store-cli.cjs +27 -1
  159. package/dist/forge-payload/tools/substitute-placeholders.cjs +60 -8
  160. package/dist/forge-payload/tools/verify-integrity.cjs +86 -0
  161. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -7,6 +7,84 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.11.2] — 2026-05-20
11
+
12
+ ### Fixed
13
+
14
+ - **`package.json.bundledVersion` actually advanced to `0.44.6`.** The 0.11.1 CHANGELOG entry claimed bundled 0.44.6 but the manifest still read 0.44.5; downstream `/forge:update` heuristics that key off `bundledVersion` were stale.
15
+ - **`thread-switcher.ts` — hide viewport footer when no orchestrator session is active.** `ViewportFooterComponent.render()` previously kept the row visible across sessions; now returns `[]` unless at least one session is `running` or `cancelling`, removing a permanent blank line in the editor area between sessions.
16
+
17
+ ---
18
+
19
+ ## [0.11.1] — 2026-05-20
20
+
21
+ ### Fixed
22
+
23
+ **P1 bug-fix batch (forge-cli#25 — defects A and B) — payload packaging gaps.**
24
+
25
+ - **Defect A — meta/ directory missing from bundled payload.** `scripts/build-payload.cjs` now copies `forge/forge/meta/` (personas + skills source-of-truth) into `dist/forge-payload/meta/`. Without this directory, `build-persona-pack.cjs` hashed an empty input tree and produced SHA `e3b0c4...` for every install, causing `/forge:health` to permanently flag "persona pack stale" on fresh installs.
26
+
27
+ - **Defect B — three health-check tools missing from bundled payload.** `check-structure.cjs`, `list-skills.js`, and `verify-integrity.cjs` are now included in `TOOLS_TO_COPY` in `build-payload.cjs`. Previously these tools were absent from `dist/forge-payload/tools/`, causing `/forge:health` to silently skip 3 of its 14 checks on every install (reported as "(skipped — `<tool>` not available in this Forge version)").
28
+
29
+ **Bundled plugin version**: 0.44.6 (defects C, D, E fixes included).
30
+
31
+ ---
32
+
33
+ ## [0.11.0] — 2026-05-20
34
+
35
+ ### Added
36
+
37
+ **FORGE-S23: Full /forge:\* surface port + migration runner + thread cancellation**
38
+
39
+ - **Migration runner (`/forge:update`)** (FORGE-S23-T01): `runMigrations()` deterministic engine. Executes pending migrations in version order, idempotent, integrated with the `/forge:update` upgrade flow. Migrations are defined in `forge-cli/dist/forge-payload/.schemas/migrations.json` and applied automatically on `forge update`.
40
+
41
+ - **Validate-write hook** (FORGE-S23-T02): Port of `forge/forge/hooks/validate-write.js` as a pi `PostToolUse` hook. Full FS-level schema guard — rejects JSON writes to forge-owned paths (`.forge/store/**`, `.forge/config.json`) that violate their schema. Schema errors are surfaced in the pi notification strip.
42
+
43
+ - **Triage-error hook** (FORGE-S23-T03): Port of `forge/forge/hooks/triage-error.js`. When a Bash tool call exits non-zero and matches Forge-related patterns (11 regexes), emits a `FORGE_ERROR_TRIAGE` notify suggesting `/forge:report-bug`. Non-Forge commands and successful exits are silent.
44
+
45
+ - **Forge-permissions hook** (FORGE-S23-T04): Port of `forge/forge/hooks/forge-permissions.js`. Pattern-match auto-allow for forge-owned tool invocations; surfaces a permission prompt for unknown patterns.
46
+
47
+ - **Check-update hook** (FORGE-S23-T05): Port of `forge/forge/hooks/check-update.js`. Full parity (5 functions): version fetch, stale-check, banner injection, changelog delta, and auto-dismiss on upgrade.
48
+
49
+ - **`/forge:retrospective`** (FORGE-S23-T06): Kickoff shim. Reads the retrospective workflow and injects into the LLM conversation with the sprint context.
50
+
51
+ - **`/forge:health` programmatic checks** (FORGE-S23-T07): 3 new checks added: schema integrity scan (validates `.forge/schemas/` JSON Schemas), store referential integrity (detects orphaned task/bug references), forgeRef drift detection (compares `paths.forgeRef` vs bundled plugin version). Health output now includes structured check results with pass/fail/warning states.
52
+
53
+ - **`/forge:calibrate`** (FORGE-S23-T08): Orchestrator handler. Drift detection + patch proposal: reads `.forge/config.json`, compares against expected schema, proposes a patch for stale or missing fields. Allows one-shot config repair from within pi.
54
+
55
+ - **`/forge:materialize` + `/forge:migrate`** (FORGE-S23-T09): Two new atomic handlers. `materialize` regenerates `.forge/` from the bundled plugin source (calls `forge:regenerate` logic). `migrate` applies pending schema migrations to the active `.forge/store/`.
56
+
57
+ - **`/forge:update-tools`, `/forge:store-query`, `/forge:status`** (FORGE-S23-T10): Three new atomic handlers. `update-tools` refreshes `.forge/schemas/` from the bundled plugin. `store-query` exposes store inspection (list sprints, tasks, bugs with filters). `status` renders a sprint-status widget in the main viewport.
58
+
59
+ - **6 kickoff-shim commands** (FORGE-S23-T11): `/forge:add-task`, `/forge:add-pipeline`, `/forge:quiz-agent`, `/forge:remove`, `/forge:report-bug`, `/forge:store-repair` — all now have real handlers (previously advisory stubs that fell back to the Claude Code plugin).
60
+
61
+ - **Thread cancellation** (`feat/thread-cancellation`): User can cancel an in-progress orchestrator run (`/forge:run-task`, `/forge:run-sprint`, `/forge:fix-bug`) from the session-monitor strip UI. Between-phase cancellation gate in `run-task.ts` and `fix-bug.ts`. State file preserved on cancellation so runs are resumable (ADR-S21-01). Cancellation status tracked in bug state (`status: "cancelled"` vs `"halted"`).
62
+
63
+ - **Structured transcript paths**: Subagent transcripts now land in `.forge/transcripts/<entityId>/<entityId>__<phase>.json` (previously `forge-subagent-<timestamp>__<persona>__<tag>.json`). Deterministic, overwrite-on-rerun, gitignored via the existing `.forge/` entry in `.gitignore`.
64
+
65
+ ### Changed
66
+
67
+ - **`forge.bundledVersion` updated to `0.44.5`**: New installs via `/forge:init` materialize at Forge plugin 0.44.5 (was 0.44.3 since v0.10.0).
68
+
69
+ ### Notes
70
+
71
+ - All 36 `/forge:*` commands now have real handlers. Zero advisory stubs remain.
72
+ - Smoke matrix gate (113/113 structural checks) passes on all T06–T12 handlers for both `openai-compatible` and `anthropic` model classes (FORGE-S23-T14).
73
+ - Sprint parity audit (FORGE-S23-T12) documents command coverage against the plugin's workflow surface.
74
+ - Versions 0.10.4–0.10.11 were internal pre-release version bumps during sprint development; they were never published to npm. This release (0.11.0) supersedes all of them.
75
+
76
+ ## [0.10.3] — 2026-05-20
77
+
78
+ ### Added
79
+ - **Triage-error hook — post-Bash-failure context injection** (FORGE-S23-T03).
80
+ When a Bash tool call exits non-zero and the command matches Forge-related patterns
81
+ (`FORGE_PATTERNS` — 11 regexes ported verbatim from `triage-error.js:10-20`),
82
+ `hook-dispatcher.ts` now calls `ctx.ui.notify` with a `FORGE_ERROR_TRIAGE` message
83
+ suggesting the user run `/forge:report-bug`. Non-Forge commands and successful exits
84
+ are silent. Port of `forge/forge/hooks/triage-error.js` for the pi extension context.
85
+
86
+ ## [0.10.2] — 2026-05-20
87
+
10
88
  ## [0.10.1] — 2026-05-19
11
89
 
12
90
  ### Fixed
package/README.md CHANGED
@@ -8,7 +8,7 @@
8
8
  [![npm](https://img.shields.io/npm/v/@entelligentsia/forgecli?style=flat-square&color=000&label=npm)](https://www.npmjs.com/package/@entelligentsia/forgecli)
9
9
  [![node](https://img.shields.io/badge/node-%E2%89%A520-000?style=flat-square)](#)
10
10
  [![license](https://img.shields.io/badge/license-MIT-000?style=flat-square)](#)
11
- [![forge plugin](https://img.shields.io/badge/forge--plugin-v0.43.16-000?style=flat-square&labelColor=fafafa)](https://github.com/Entelligentsia/forge)
11
+ [![forge plugin](https://img.shields.io/badge/forge--plugin-v0.44.5-000?style=flat-square&labelColor=fafafa)](https://github.com/Entelligentsia/forge)
12
12
  [![pi runtime](https://img.shields.io/badge/runtime-pi--coding--agent-000?style=flat-square)](https://www.npmjs.com/package/@earendil-works/pi-coding-agent)
13
13
 
14
14
  </div>
@@ -77,12 +77,20 @@ Idempotent and resumable. Re-running picks up at the last checkpoint via `.forge
77
77
  ```
78
78
  SETUP /forge:init Bootstrap Forge SDLC into the project
79
79
  /forge:regenerate Refresh generated workflows + KB
80
+ /forge:materialize Fill in stub artifacts after fast-mode init
81
+ /forge:migrate Schema + structural migration of legacy stores
80
82
  /forge:update Check for + apply forge-cli updates
83
+ /forge:update-tools Refresh .forge/schemas/ to bundled version
84
+ /forge:add-pipeline Add or customize a pipeline interactively
81
85
  /forge:remove Tear down the Forge install
82
86
 
83
87
  RUN /forge:run-task Execute one task pipeline end-to-end
84
88
  /forge:run-sprint Orchestrate every task in a sprint
85
89
  /forge:fix-bug Triage + fix flow
90
+ /forge:sprint-intake Elicit sprint requirements
91
+ /forge:sprint-plan Decompose a sprint into tasks
92
+ /forge:add-task Add a task to an existing sprint mid-flight
93
+ /forge:retrospective Produce a sprint retrospective document
86
94
 
87
95
  CHAIN /forge:plan plan
88
96
  /forge:implement implement
@@ -96,6 +104,11 @@ ASK /forge:health KB freshness + store integrity
96
104
  /forge:status Sprint + task status
97
105
  /forge:ask <q> Ask the Tomoshibi concierge
98
106
  /forge:config Set up AI models for your workflow
107
+ /forge:store-query Query the JSON store by NLP or flags
108
+ /forge:store-repair Diagnose + repair corrupted store records
109
+ /forge:quiz-agent Verify an agent has loaded the KB
110
+ /forge:calibrate Detect KB↔agent drift, propose patches
111
+ /forge:report-bug File a Forge bug as a GitHub issue
99
112
  ```
100
113
 
101
114
  → [Full reference](docs/cli-reference.md) · [Non-interactive mode](docs/non-interactive.md) · [Hook safety net](docs/hook-safety-net.md) · [Custom tools](docs/custom-tools.md) · [Publishing](docs/publishing.md)
@@ -309,6 +322,8 @@ before forge-cli's extension hook runs.
309
322
 
310
323
  | Up next | Status |
311
324
  |----------------------------------------------------|---------------------|
325
+ | Full `/forge:*` surface + 4 hooks + migration runner | Shipped (0.11.0) |
326
+ | Pi-aligned data layout under `~/.pi/forge-cli/` | Shipped (0.10.0) |
312
327
  | Per-persona model routing + tiered config TUI | Shipped (0.9.0) |
313
328
  | 4ge brand wordmark in CLI banner + 3 themes | Shipped (0.7.7) |
314
329
  | Slim README + docs/ split | Shipped (0.7.7) |
@@ -316,7 +331,6 @@ before forge-cli's extension hook runs.
316
331
  | Bundled plugin command markdowns | Shipped (0.7.6) |
317
332
  | `/forge:run-task`, `run-sprint`, `fix-bug` | Shipped (0.7.5) |
318
333
  | Atomic chain shims (`/forge:plan` … `commit`) ×6 | Shipped (0.7.5) |
319
- | Port admin commands (`migrate`, `calibrate`, …) | Roadmap |
320
334
 
321
335
  → Full roadmap + history: [CHANGELOG.md](CHANGELOG.md)
322
336
 
@@ -348,6 +362,10 @@ MIT © Entelligentsia
348
362
  0.5.0 · 0.5.1 · 0.5.2 · 0.5.3 · 0.5.4 · 0.5.5 · 0.5.6 · 0.5.7 ·
349
363
  0.6.1 · 0.6.2 · 0.6.3 · 0.6.4 · 0.6.5 · 0.6.6 ·
350
364
  0.7.0 · 0.7.1 · 0.7.2 · 0.7.3 · 0.7.4 · 0.7.5 · 0.7.6 · 0.7.7 ·
351
- 0.8.0 · 0.8.1 · 0.8.2 · 0.8.3 · 0.8.4 · 0.9.0
365
+ 0.7.8 · 0.7.9 · 0.7.10 · 0.7.11 ·
366
+ 0.8.0 · 0.8.1 · 0.8.2 · 0.8.3 · 0.8.4 ·
367
+ 0.9.0 · 0.9.1 · 0.9.2 · 0.9.3 · 0.9.4 ·
368
+ 0.10.0 · 0.10.1 · 0.10.2 · 0.10.3 ·
369
+ 0.11.0
352
370
  -->
353
371
 
@@ -5,6 +5,28 @@ Format: newest first. Breaking changes are marked **△ Breaking**.
5
5
 
6
6
  ---
7
7
 
8
+ ## [0.44.6] — 2026-05-20
9
+
10
+ **P1 bug-fix batch (forge-cli#25 — defects C, D, E).** Three tool fixes to address defects discovered in the forge-cli 0.11.0 dogfooding session.
11
+
12
+ **C — substitute-placeholders.cjs base-pack path stale.** Tool now probes `.base-pack/` (bundled install layout) before `init/base-pack` (source layout) when no `--base-pack` flag is supplied. `--help`/`-h` now short-circuits before any path resolution so the usage text is always accessible.
13
+
14
+ **D — store-cli list event.** The `list` subcommand previously exited 1 with "Unknown entity type: event" despite `event` being in the documented entity set. Fixed by adding an `event` case to `listEntities()` that traverses all sub-directories under `.forge/store/events/` (`bugs/`, `enhancement/`, and per-sprint `<sprintId>/` dirs) and returns the union. Sidecar files (`_`-prefixed) are skipped.
15
+
16
+ **E — substitute-placeholders.cjs --category flag.** New `--category <name[,name]>` flag limits materialisation to the specified subdirectory names (e.g. `--category personas` writes only `.forge/personas/` and skips workflows, skills, templates, and commands). `commands/regenerate.md` documents the scope-enforcement rule for callers that invoke the tool directly during per-category regeneration.
17
+
18
+ **Regenerate:** tools:substitute-placeholders, tools:store-cli, commands:regenerate
19
+
20
+ ---
21
+
22
+ ## [0.44.5] — 2026-05-20
23
+
24
+ **Migration apply path + config schema.** Two FORGE-S23 contributions to the plugin distribution. First, `migrations.json` gains the `0.44.4→0.44.5` entry consumed by forge-cli's new `runMigrations()` deterministic engine: semver-range traversal `[from, to)` on keys, per-category resolver covering 84 unique category strings, idempotency ledger at `.forge/applied-migrations.json`, always-on schema refresh post-pass, fileOps forward-compat, and path-traversal defense. The `/forge:update` flow in forge-cli prompts to apply pending migrations after upgrade (`FORGE_NON_INTERACTIVE=1` auto-applies); the `update_plan` and `plan_task` workflows reference the new application steps. Second, `forge/schemas/config.schema.json` is added so the validate-write hook (also ported to forge-cli in this sprint) can enforce `.forge/config.json` structure at write time. No tool or persona changes — the plugin's role is to ship the migration entry and the new schema; the engine lives in forge-cli (v0.11.0).
25
+
26
+ **Regenerate:** workflows:update_plan, workflows:plan_task
27
+
28
+ ---
29
+
8
30
  ## [0.44.4] — 2026-05-19
9
31
 
10
32
  **Supervisor persona forbids FSM writes from review phases.** `meta-supervisor.md` gains a top-level Iron Law: "The Supervisor NEVER writes entity status — the workflow orchestrator owns all FSM transitions. Do not call `store-cli update-status` from a review phase. The verdict signal travels through the SUMMARY's `verdict` field, not `entity.status`." The workflow-level guard at `meta-review-plan.md:76` and `meta-review-implementation.md:82` ("Bug mode — NO status write") already existed; this is the persona-level reinforcement so the model never attempts the write in the first place. Surfaced during FORGE-BUG-003 re-run testing of the forge-cli stale-ctx fix: a supervisor subagent called `update-status bug FORGE-BUG-003 status plan-approved` against a bug already in terminal `fixed` state. `store-cli` correctly rejected the illegal transition and the run completed (the rails held), but the persona now discourages the attempt.
@@ -0,0 +1,19 @@
1
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
+ export type AddPipelineMode = "add" | "edit" | "view" | "remove";
3
+ export interface ParsedAddPipelineArgs {
4
+ mode: AddPipelineMode;
5
+ pipelineName: string | null;
6
+ seed: string;
7
+ sourceLabel: string;
8
+ }
9
+ export declare function parseAddPipelineArgs(rawArgs: string, cwd: string): ParsedAddPipelineArgs;
10
+ export interface ComposeAddPipelineKickoffOpts {
11
+ commandMd: string;
12
+ parsed: ParsedAddPipelineArgs;
13
+ }
14
+ export declare function composeAddPipelineKickoff(opts: ComposeAddPipelineKickoffOpts): string;
15
+ export interface RegisterAddPipelineOptions {
16
+ forgeRoot: string | null;
17
+ cwd?: string;
18
+ }
19
+ export declare function registerAddPipeline(pi: ExtensionAPI, options: RegisterAddPipelineOptions): void;
@@ -0,0 +1,143 @@
1
+ // forge:add-pipeline — native kickoff handler (FORGE-S23-T11).
2
+ //
3
+ // Replaces the auto-generated stub previously installed by
4
+ // registerAllForgeCommands (forge-commands.ts). Kickoff Shim archetype
5
+ // (Pack-04 + Pack-06): single LLM handoff in current context, no fork.
6
+ //
7
+ // Parses --add/--edit/--view/--remove/--list/--name flags and a plain
8
+ // pipeline name before dispatching. Resolved mode is prepended to the
9
+ // kickoff so the LLM starts in the correct mode without prompting.
10
+ //
11
+ // Workflow source: <forgeRoot>/commands/add-pipeline.md (command file).
12
+ // File-existence check only — command files lack Pack-06 workflow markers.
13
+ //
14
+ // Iron Laws:
15
+ // IL1 — code only under forge-cli/src/extensions/forgecli/.
16
+ // IL4 — no JSON.stringify-into-subagent dispatch.
17
+ // IL6 — no shell-string interpolation; no spawn calls here.
18
+ // IL7 — every failure path emits ctx.ui.notify and returns; no silent
19
+ // continuation.
20
+ import * as fs from "node:fs";
21
+ import * as path from "node:path";
22
+ import { sendKickoff } from "./kickoff.js";
23
+ export function parseAddPipelineArgs(rawArgs, cwd) {
24
+ const trimmed = (rawArgs ?? "").trim();
25
+ const result = {
26
+ mode: "add",
27
+ pipelineName: null,
28
+ seed: "",
29
+ sourceLabel: "",
30
+ };
31
+ if (!trimmed) {
32
+ result.sourceLabel = "(no args — LLM will ask intent)";
33
+ return result;
34
+ }
35
+ const tokens = trimmed.split(/\s+/);
36
+ const remaining = [];
37
+ for (let i = 0; i < tokens.length; i++) {
38
+ const tok = tokens[i];
39
+ if (tok === "--add") {
40
+ result.mode = "add";
41
+ }
42
+ else if (tok === "--edit") {
43
+ result.mode = "edit";
44
+ }
45
+ else if (tok === "--view" || tok === "--list") {
46
+ result.mode = "view";
47
+ }
48
+ else if (tok === "--remove") {
49
+ result.mode = "remove";
50
+ }
51
+ else if (tok === "--name" && i + 1 < tokens.length) {
52
+ result.pipelineName = tokens[++i];
53
+ }
54
+ else {
55
+ remaining.push(tok);
56
+ }
57
+ }
58
+ const tail = remaining.join(" ").trim();
59
+ if (tail.startsWith("@")) {
60
+ const ref = tail.slice(1).trim();
61
+ const filePath = path.isAbsolute(ref) ? ref : path.resolve(cwd, ref);
62
+ result.seed = fs.readFileSync(filePath, "utf8");
63
+ result.sourceLabel = `(seed from file: ${ref})`;
64
+ }
65
+ else if (tail) {
66
+ // A bare word with no mode flag = pipeline name, default mode "add"
67
+ if (!result.pipelineName && !/^--/.test(tail)) {
68
+ result.pipelineName = tail;
69
+ }
70
+ else {
71
+ result.seed = tail;
72
+ }
73
+ result.sourceLabel = "(from inline text)";
74
+ }
75
+ return result;
76
+ }
77
+ // ── Kickoff composition ───────────────────────────────────────────────────
78
+ const MODE_LABELS = {
79
+ add: "Add a new pipeline",
80
+ edit: "Customize an existing pipeline",
81
+ view: "View configured pipelines",
82
+ remove: "Remove a pipeline",
83
+ };
84
+ export function composeAddPipelineKickoff(opts) {
85
+ const { commandMd, parsed } = opts;
86
+ const sections = ["# /forge:add-pipeline", ""];
87
+ sections.push("## Dispatch", "");
88
+ sections.push(`Start in **Mode: ${MODE_LABELS[parsed.mode]}**.`);
89
+ if (parsed.pipelineName) {
90
+ sections.push(`Pipeline name: \`${parsed.pipelineName}\``);
91
+ }
92
+ sections.push("");
93
+ sections.push("Run the pipeline manager command below. Use `forge_store` for all config reads and writes. " +
94
+ "Read `.forge/config.json` directly when you need the pipelines section.");
95
+ sections.push("", "---", "", "## Command", "", commandMd.trim(), "", "---");
96
+ if (parsed.seed) {
97
+ sections.push("", `## Additional Input — ${parsed.sourceLabel}`, "", parsed.seed.trim());
98
+ }
99
+ return sections.join("\n");
100
+ }
101
+ // ── Registration ──────────────────────────────────────────────────────────
102
+ const COMMAND_NAME = "add-pipeline";
103
+ export function registerAddPipeline(pi, options) {
104
+ pi.registerCommand("forge:add-pipeline", {
105
+ description: "Conversational pipeline manager — add, customize, view, or remove Forge pipelines. " +
106
+ "Usage: /forge:add-pipeline [--add|--edit|--view|--remove] [--name <name>] [<pipeline-name>]",
107
+ async handler(args, ctx) {
108
+ const { forgeRoot } = options;
109
+ const cwd = options.cwd ?? process.cwd();
110
+ if (!forgeRoot) {
111
+ ctx.ui.notify("× forge:add-pipeline — no Forge project at cwd; run /forge:init to bootstrap", "warning");
112
+ return;
113
+ }
114
+ const commandPath = path.join(forgeRoot, "commands", `${COMMAND_NAME}.md`);
115
+ let commandMd;
116
+ try {
117
+ commandMd = fs.readFileSync(commandPath, "utf8");
118
+ }
119
+ catch (err) {
120
+ const e = err;
121
+ if (e.code === "ENOENT") {
122
+ ctx.ui.notify(`× forge:add-pipeline — command file not found at commands/${COMMAND_NAME}.md; run /forge:init or /forge:regenerate first.`, "error");
123
+ }
124
+ else {
125
+ ctx.ui.notify(`× forge:add-pipeline — failed to read command file: ${e.message ?? "unknown error"}`, "error");
126
+ }
127
+ return;
128
+ }
129
+ let parsed;
130
+ try {
131
+ parsed = parseAddPipelineArgs(args, cwd);
132
+ }
133
+ catch (err) {
134
+ const e = err;
135
+ ctx.ui.notify(`× forge:add-pipeline — failed to parse args: ${e.message ?? "unknown"}`, "error");
136
+ return;
137
+ }
138
+ const kickoff = composeAddPipelineKickoff({ commandMd, parsed });
139
+ sendKickoff(pi, kickoff);
140
+ },
141
+ });
142
+ }
143
+ //# sourceMappingURL=add-pipeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add-pipeline.js","sourceRoot":"","sources":["../../../src/extensions/forgecli/add-pipeline.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
+ export interface ParsedAddTaskArgs {
3
+ sprintId: string | null;
4
+ title: string | null;
5
+ estimate: string | null;
6
+ pipeline: string | null;
7
+ seed: string;
8
+ sourceLabel: string;
9
+ }
10
+ export declare function parseAddTaskArgs(rawArgs: string, cwd: string): ParsedAddTaskArgs;
11
+ export interface ComposeAddTaskKickoffOpts {
12
+ commandMd: string;
13
+ parsed: ParsedAddTaskArgs;
14
+ }
15
+ export declare function composeAddTaskKickoff(opts: ComposeAddTaskKickoffOpts): string;
16
+ export interface RegisterAddTaskOptions {
17
+ forgeRoot: string | null;
18
+ cwd?: string;
19
+ }
20
+ export declare function registerAddTask(pi: ExtensionAPI, options: RegisterAddTaskOptions): void;
@@ -0,0 +1,154 @@
1
+ // forge:add-task — native kickoff handler (FORGE-S23-T11).
2
+ //
3
+ // Replaces the auto-generated stub previously installed by
4
+ // registerAllForgeCommands (forge-commands.ts). Kickoff Shim archetype
5
+ // (Pack-04 + Pack-06): single LLM handoff in current context, no fork.
6
+ //
7
+ // This handler reads commands/add-task.md from the bundled forge payload,
8
+ // forwards any provided argv shortcuts (--sprint, --title, --estimate,
9
+ // --pipeline) in the kickoff body so the LLM skips those interview steps,
10
+ // and dispatches via pi.sendUserMessage with { deliverAs: "steer" }.
11
+ //
12
+ // Note: The task prompt mentions "store-cli --next-id pre-flight", but
13
+ // store-cli has no next-id subcommand. The ID is computed by the LLM
14
+ // from the sprint record (per Step 3 in the command file). The handler
15
+ // only forwards shortcuts to reduce LLM round-trips.
16
+ //
17
+ // Workflow source: <forgeRoot>/commands/add-task.md (command file).
18
+ // File-existence check only (not Pack-06 4-marker check) — command files
19
+ // are simpler than full workflow files and lack the required markers.
20
+ //
21
+ // Iron Laws:
22
+ // IL1 — code only under forge-cli/src/extensions/forgecli/.
23
+ // IL4 — no JSON.stringify-into-subagent dispatch.
24
+ // IL6 — no shell-string interpolation; no spawn calls here.
25
+ // IL7 — every failure path emits ctx.ui.notify and returns; no silent
26
+ // continuation.
27
+ import * as fs from "node:fs";
28
+ import * as path from "node:path";
29
+ import { sendKickoff } from "./kickoff.js";
30
+ export function parseAddTaskArgs(rawArgs, cwd) {
31
+ const trimmed = (rawArgs ?? "").trim();
32
+ const result = {
33
+ sprintId: null,
34
+ title: null,
35
+ estimate: null,
36
+ pipeline: null,
37
+ seed: "",
38
+ sourceLabel: "",
39
+ };
40
+ if (!trimmed) {
41
+ result.sourceLabel = "(no args — LLM will conduct full interview)";
42
+ return result;
43
+ }
44
+ // Parse known flags
45
+ const tokens = trimmed.split(/\s+/);
46
+ const remaining = [];
47
+ for (let i = 0; i < tokens.length; i++) {
48
+ const tok = tokens[i];
49
+ if (tok === "--sprint" && i + 1 < tokens.length) {
50
+ result.sprintId = tokens[++i];
51
+ }
52
+ else if (tok === "--title" && i + 1 < tokens.length) {
53
+ result.title = tokens[++i];
54
+ }
55
+ else if (tok === "--estimate" && i + 1 < tokens.length) {
56
+ result.estimate = tokens[++i];
57
+ }
58
+ else if (tok === "--pipeline" && i + 1 < tokens.length) {
59
+ result.pipeline = tokens[++i];
60
+ }
61
+ else {
62
+ remaining.push(tok);
63
+ }
64
+ }
65
+ // Remaining tokens: @<file> or free-form text
66
+ const tail = remaining.join(" ").trim();
67
+ if (tail.startsWith("@")) {
68
+ const ref = tail.slice(1).trim();
69
+ const filePath = path.isAbsolute(ref) ? ref : path.resolve(cwd, ref);
70
+ result.seed = fs.readFileSync(filePath, "utf8");
71
+ result.sourceLabel = `(seed from file: ${ref})`;
72
+ }
73
+ else if (tail) {
74
+ result.seed = tail;
75
+ result.sourceLabel = "(seed from inline text)";
76
+ }
77
+ else {
78
+ result.sourceLabel = "(shortcuts provided)";
79
+ }
80
+ return result;
81
+ }
82
+ export function composeAddTaskKickoff(opts) {
83
+ const { commandMd, parsed } = opts;
84
+ const shortcuts = [];
85
+ if (parsed.sprintId)
86
+ shortcuts.push(`--sprint ${parsed.sprintId}`);
87
+ if (parsed.title)
88
+ shortcuts.push(`--title "${parsed.title}"`);
89
+ if (parsed.estimate)
90
+ shortcuts.push(`--estimate ${parsed.estimate}`);
91
+ if (parsed.pipeline)
92
+ shortcuts.push(`--pipeline ${parsed.pipeline}`);
93
+ const sections = ["# /forge:add-task", ""];
94
+ sections.push("## Dispatch", "");
95
+ sections.push("Run the add-task command below to add a new task to an existing sprint. Specifically:");
96
+ sections.push("");
97
+ sections.push("1. Follow the command file steps in order.");
98
+ if (shortcuts.length > 0) {
99
+ sections.push(`2. The following shortcuts were provided — skip the corresponding interview steps: \`${shortcuts.join(" ")}\``);
100
+ }
101
+ sections.push(`${shortcuts.length > 0 ? "3" : "2"}. Use \`forge_store\` for all store reads and writes (never raw bash \`forge store\`).`);
102
+ sections.push(`${shortcuts.length > 0 ? "4" : "3"}. Compute the next task ID from the sprint record's \`taskIds\` array per Step 3 in the command file.`);
103
+ sections.push("", "---", "", "## Command", "", commandMd.trim(), "", "---");
104
+ if (parsed.seed) {
105
+ sections.push("", `## Additional Input — ${parsed.sourceLabel}`, "", parsed.seed.trim());
106
+ }
107
+ else if (shortcuts.length === 0) {
108
+ sections.push("", "## Input", "", "(no args — begin mini-intake interview)");
109
+ }
110
+ return sections.join("\n");
111
+ }
112
+ // ── Registration ──────────────────────────────────────────────────────────
113
+ const COMMAND_NAME = "add-task";
114
+ export function registerAddTask(pi, options) {
115
+ pi.registerCommand("forge:add-task", {
116
+ description: "Add a new task to an existing sprint mid-flight — mini intake, sequential ID assignment, store write. " +
117
+ "Usage: /forge:add-task [--sprint <ID>] [--title <text>] [--estimate <S|M|L|XL>] [--pipeline <name>] [@<file> | <text>]",
118
+ async handler(args, ctx) {
119
+ const { forgeRoot } = options;
120
+ const cwd = options.cwd ?? process.cwd();
121
+ if (!forgeRoot) {
122
+ ctx.ui.notify("× forge:add-task — no Forge project at cwd; run /forge:init to bootstrap", "warning");
123
+ return;
124
+ }
125
+ const commandPath = path.join(forgeRoot, "commands", `${COMMAND_NAME}.md`);
126
+ let commandMd;
127
+ try {
128
+ commandMd = fs.readFileSync(commandPath, "utf8");
129
+ }
130
+ catch (err) {
131
+ const e = err;
132
+ if (e.code === "ENOENT") {
133
+ ctx.ui.notify(`× forge:add-task — command file not found at commands/${COMMAND_NAME}.md; run /forge:init or /forge:regenerate first.`, "error");
134
+ }
135
+ else {
136
+ ctx.ui.notify(`× forge:add-task — failed to read command file: ${e.message ?? "unknown error"}`, "error");
137
+ }
138
+ return;
139
+ }
140
+ let parsed;
141
+ try {
142
+ parsed = parseAddTaskArgs(args, cwd);
143
+ }
144
+ catch (err) {
145
+ const e = err;
146
+ ctx.ui.notify(`× forge:add-task — failed to parse args: ${e.message ?? "unknown"}`, "error");
147
+ return;
148
+ }
149
+ const kickoff = composeAddTaskKickoff({ commandMd, parsed });
150
+ sendKickoff(pi, kickoff);
151
+ },
152
+ });
153
+ }
154
+ //# sourceMappingURL=add-task.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add-task.js","sourceRoot":"","sources":["../../../src/extensions/forgecli/add-task.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
+ import { type CalibrationBaseline } from "./init-context.js";
3
+ export interface ParsedCalibrateFlags {
4
+ /** Override project directory (from --path <dir>). Null = use cwd. */
5
+ path: string | null;
6
+ }
7
+ /**
8
+ * Parse /forge:calibrate arguments.
9
+ * Supports: --path <dir>
10
+ */
11
+ export declare function parseCalibrateFlags(args: string): ParsedCalibrateFlags;
12
+ export interface ForgeConfig {
13
+ paths?: {
14
+ engineering?: string;
15
+ forgeRoot?: string;
16
+ store?: string;
17
+ };
18
+ calibrationBaseline?: Partial<CalibrationBaseline> & {
19
+ masterIndexHash?: string | null;
20
+ };
21
+ calibrationHistory?: CalibrationHistoryEntry[];
22
+ [key: string]: unknown;
23
+ }
24
+ /** Read and parse .forge/config.json from projectRoot. Returns null on any error. */
25
+ export declare function readForgeConfig(projectRoot: string): ForgeConfig | null;
26
+ /**
27
+ * Compute SHA-256 of MASTER_INDEX.md, stripping blank lines and HTML comment lines.
28
+ * Returns null if the file does not exist.
29
+ */
30
+ export declare function computeCurrentHash(projectRoot: string, kbPath: string): string | null;
31
+ export interface DriftCategory {
32
+ category: "technical" | "business" | "retrospective" | "acceptance criteria";
33
+ evidence: string;
34
+ targets: string[];
35
+ }
36
+ /**
37
+ * Categorize drift by scanning MASTER_INDEX.md content for section keywords
38
+ * and identifying new sprints since last calibration.
39
+ */
40
+ export declare function categorizeDrift(projectRoot: string, kbPath: string, baseline: Partial<CalibrationBaseline> & {
41
+ masterIndexHash?: string | null;
42
+ }): DriftCategory[];
43
+ export interface PatchProposal {
44
+ target: string;
45
+ type: "regenerate";
46
+ rationale: string;
47
+ }
48
+ /** Extract PatchProposal objects from the architect's free-form response text. */
49
+ export declare function extractPatchProposals(text: string): PatchProposal[];
50
+ export interface CalibrationHistoryPatch {
51
+ target: string;
52
+ type: "regenerate";
53
+ applied: boolean;
54
+ }
55
+ export interface CalibrationHistoryEntry {
56
+ date: string;
57
+ version: string;
58
+ categories: string[];
59
+ patches: CalibrationHistoryPatch[];
60
+ }
61
+ export declare function registerCalibrate(pi: ExtensionAPI): void;