@entelligentsia/forgecli 0.10.0 → 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 (188) hide show
  1. package/CHANGELOG.md +95 -0
  2. package/README.md +21 -3
  3. package/dist/CHANGELOG-forge-plugin.md +90 -0
  4. package/dist/bin/config.js +6 -0
  5. package/dist/bin/config.js.map +1 -1
  6. package/dist/extensions/forgecli/add-pipeline.d.ts +19 -0
  7. package/dist/extensions/forgecli/add-pipeline.js +143 -0
  8. package/dist/extensions/forgecli/add-pipeline.js.map +1 -0
  9. package/dist/extensions/forgecli/add-task.d.ts +20 -0
  10. package/dist/extensions/forgecli/add-task.js +154 -0
  11. package/dist/extensions/forgecli/add-task.js.map +1 -0
  12. package/dist/extensions/forgecli/calibrate.d.ts +61 -0
  13. package/dist/extensions/forgecli/calibrate.js +488 -0
  14. package/dist/extensions/forgecli/calibrate.js.map +1 -0
  15. package/dist/extensions/forgecli/fix-bug.d.ts +9 -1
  16. package/dist/extensions/forgecli/fix-bug.js +155 -45
  17. package/dist/extensions/forgecli/fix-bug.js.map +1 -1
  18. package/dist/extensions/forgecli/forge-commands.js +15 -22
  19. package/dist/extensions/forgecli/forge-commands.js.map +1 -1
  20. package/dist/extensions/forgecli/forge-subagent.d.ts +16 -1
  21. package/dist/extensions/forgecli/forge-subagent.js +45 -8
  22. package/dist/extensions/forgecli/forge-subagent.js.map +1 -1
  23. package/dist/extensions/forgecli/forge-update-command.d.ts +9 -0
  24. package/dist/extensions/forgecli/forge-update-command.js +106 -7
  25. package/dist/extensions/forgecli/forge-update-command.js.map +1 -1
  26. package/dist/extensions/forgecli/health-check.d.ts +22 -1
  27. package/dist/extensions/forgecli/health-check.js +177 -4
  28. package/dist/extensions/forgecli/health-check.js.map +1 -1
  29. package/dist/extensions/forgecli/hook-dispatcher.d.ts +25 -1
  30. package/dist/extensions/forgecli/hook-dispatcher.js +104 -9
  31. package/dist/extensions/forgecli/hook-dispatcher.js.map +1 -1
  32. package/dist/extensions/forgecli/hooks/check-update.d.ts +81 -0
  33. package/dist/extensions/forgecli/hooks/check-update.js +308 -0
  34. package/dist/extensions/forgecli/hooks/check-update.js.map +1 -0
  35. package/dist/extensions/forgecli/hooks/forge-permissions.d.ts +32 -0
  36. package/dist/extensions/forgecli/hooks/forge-permissions.js +119 -0
  37. package/dist/extensions/forgecli/hooks/forge-permissions.js.map +1 -0
  38. package/dist/extensions/forgecli/hooks/triage-error.d.ts +23 -0
  39. package/dist/extensions/forgecli/hooks/triage-error.js +62 -0
  40. package/dist/extensions/forgecli/hooks/triage-error.js.map +1 -0
  41. package/dist/extensions/forgecli/hooks/write-guard.d.ts +28 -0
  42. package/dist/extensions/forgecli/hooks/write-guard.js +225 -0
  43. package/dist/extensions/forgecli/hooks/write-guard.js.map +1 -0
  44. package/dist/extensions/forgecli/index.js +60 -0
  45. package/dist/extensions/forgecli/index.js.map +1 -1
  46. package/dist/extensions/forgecli/init-context.d.ts +1 -1
  47. package/dist/extensions/forgecli/init-context.js +21 -6
  48. package/dist/extensions/forgecli/init-context.js.map +1 -1
  49. package/dist/extensions/forgecli/materialize.d.ts +16 -0
  50. package/dist/extensions/forgecli/materialize.js +195 -0
  51. package/dist/extensions/forgecli/materialize.js.map +1 -0
  52. package/dist/extensions/forgecli/migrate.d.ts +19 -0
  53. package/dist/extensions/forgecli/migrate.js +258 -0
  54. package/dist/extensions/forgecli/migrate.js.map +1 -0
  55. package/dist/extensions/forgecli/migration-engine.d.ts +111 -0
  56. package/dist/extensions/forgecli/migration-engine.js +533 -0
  57. package/dist/extensions/forgecli/migration-engine.js.map +1 -0
  58. package/dist/extensions/forgecli/quiz-agent.d.ts +17 -0
  59. package/dist/extensions/forgecli/quiz-agent.js +98 -0
  60. package/dist/extensions/forgecli/quiz-agent.js.map +1 -0
  61. package/dist/extensions/forgecli/remove-command.d.ts +17 -0
  62. package/dist/extensions/forgecli/remove-command.js +124 -0
  63. package/dist/extensions/forgecli/remove-command.js.map +1 -0
  64. package/dist/extensions/forgecli/report-bug.d.ts +25 -0
  65. package/dist/extensions/forgecli/report-bug.js +159 -0
  66. package/dist/extensions/forgecli/report-bug.js.map +1 -0
  67. package/dist/extensions/forgecli/retrospective.d.ts +19 -0
  68. package/dist/extensions/forgecli/retrospective.js +156 -0
  69. package/dist/extensions/forgecli/retrospective.js.map +1 -0
  70. package/dist/extensions/forgecli/run-sprint.js +36 -3
  71. package/dist/extensions/forgecli/run-sprint.js.map +1 -1
  72. package/dist/extensions/forgecli/run-task.d.ts +9 -1
  73. package/dist/extensions/forgecli/run-task.js +66 -13
  74. package/dist/extensions/forgecli/run-task.js.map +1 -1
  75. package/dist/extensions/forgecli/session-registry.d.ts +40 -2
  76. package/dist/extensions/forgecli/session-registry.js +71 -1
  77. package/dist/extensions/forgecli/session-registry.js.map +1 -1
  78. package/dist/extensions/forgecli/status-command.d.ts +19 -0
  79. package/dist/extensions/forgecli/status-command.js +140 -0
  80. package/dist/extensions/forgecli/status-command.js.map +1 -0
  81. package/dist/extensions/forgecli/store-query.d.ts +22 -0
  82. package/dist/extensions/forgecli/store-query.js +107 -0
  83. package/dist/extensions/forgecli/store-query.js.map +1 -0
  84. package/dist/extensions/forgecli/store-repair.d.ts +17 -0
  85. package/dist/extensions/forgecli/store-repair.js +123 -0
  86. package/dist/extensions/forgecli/store-repair.js.map +1 -0
  87. package/dist/extensions/forgecli/test-orchestrate.js +1 -0
  88. package/dist/extensions/forgecli/test-orchestrate.js.map +1 -1
  89. package/dist/extensions/forgecli/thread-switcher.js +286 -41
  90. package/dist/extensions/forgecli/thread-switcher.js.map +1 -1
  91. package/dist/extensions/forgecli/transition-guard.js +7 -2
  92. package/dist/extensions/forgecli/transition-guard.js.map +1 -1
  93. package/dist/extensions/forgecli/update-tools.d.ts +23 -0
  94. package/dist/extensions/forgecli/update-tools.js +136 -0
  95. package/dist/extensions/forgecli/update-tools.js.map +1 -0
  96. package/dist/extensions/forgecli/viewport-events.js +10 -0
  97. package/dist/extensions/forgecli/viewport-events.js.map +1 -1
  98. package/dist/extensions/forgecli/viewport-renderer.d.ts +18 -0
  99. package/dist/extensions/forgecli/viewport-renderer.js +27 -0
  100. package/dist/extensions/forgecli/viewport-renderer.js.map +1 -1
  101. package/dist/extensions/forgecli/viewport-theme.js +4 -0
  102. package/dist/extensions/forgecli/viewport-theme.js.map +1 -1
  103. package/dist/extensions/forgecli/whats-new-widget.d.ts +13 -8
  104. package/dist/extensions/forgecli/whats-new-widget.js +111 -42
  105. package/dist/extensions/forgecli/whats-new-widget.js.map +1 -1
  106. package/dist/forge-payload/.base-pack/workflows/architect_approve.md +29 -3
  107. package/dist/forge-payload/.base-pack/workflows/commit_task.md +15 -8
  108. package/dist/forge-payload/.base-pack/workflows/fix_bug.md +327 -185
  109. package/dist/forge-payload/.base-pack/workflows/implement_plan.md +18 -10
  110. package/dist/forge-payload/.base-pack/workflows/plan_task.md +15 -9
  111. package/dist/forge-payload/.base-pack/workflows/review_code.md +14 -6
  112. package/dist/forge-payload/.base-pack/workflows/review_plan.md +18 -10
  113. package/dist/forge-payload/.claude-plugin/plugin.json +1 -1
  114. package/dist/forge-payload/.schemas/bug.schema.json +3 -2
  115. package/dist/forge-payload/.schemas/config.schema.json +83 -0
  116. package/dist/forge-payload/.schemas/migrations.json +2049 -0
  117. package/dist/forge-payload/commands/regenerate.md +17 -1
  118. package/dist/forge-payload/meta/personas/README.md +16 -0
  119. package/dist/forge-payload/meta/personas/meta-architect.md +70 -0
  120. package/dist/forge-payload/meta/personas/meta-bug-fixer.md +73 -0
  121. package/dist/forge-payload/meta/personas/meta-collator.md +72 -0
  122. package/dist/forge-payload/meta/personas/meta-engineer.md +70 -0
  123. package/dist/forge-payload/meta/personas/meta-orchestrator.md +71 -0
  124. package/dist/forge-payload/meta/personas/meta-product-manager.md +82 -0
  125. package/dist/forge-payload/meta/personas/meta-qa-engineer.md +91 -0
  126. package/dist/forge-payload/meta/personas/meta-supervisor.md +92 -0
  127. package/dist/forge-payload/meta/skill-recommendations.md +154 -0
  128. package/dist/forge-payload/meta/skills/meta-architect-skills.md +43 -0
  129. package/dist/forge-payload/meta/skills/meta-bug-fixer-skills.md +43 -0
  130. package/dist/forge-payload/meta/skills/meta-collator-skills.md +41 -0
  131. package/dist/forge-payload/meta/skills/meta-engineer-skills.md +43 -0
  132. package/dist/forge-payload/meta/skills/meta-generic-skills.md +58 -0
  133. package/dist/forge-payload/meta/skills/meta-qa-engineer-skills.md +46 -0
  134. package/dist/forge-payload/meta/skills/meta-supervisor-skills.md +43 -0
  135. package/dist/forge-payload/meta/store-schema/bug.schema.md +71 -0
  136. package/dist/forge-payload/meta/store-schema/event.schema.md +76 -0
  137. package/dist/forge-payload/meta/store-schema/feature.schema.md +65 -0
  138. package/dist/forge-payload/meta/store-schema/sprint.schema.md +64 -0
  139. package/dist/forge-payload/meta/store-schema/task.schema.md +78 -0
  140. package/dist/forge-payload/meta/templates/meta-code-review.md +26 -0
  141. package/dist/forge-payload/meta/templates/meta-plan-review.md +28 -0
  142. package/dist/forge-payload/meta/templates/meta-plan.md +28 -0
  143. package/dist/forge-payload/meta/templates/meta-progress.md +25 -0
  144. package/dist/forge-payload/meta/templates/meta-retrospective.md +28 -0
  145. package/dist/forge-payload/meta/templates/meta-sprint-manifest.md +26 -0
  146. package/dist/forge-payload/meta/templates/meta-sprint-requirements.md +91 -0
  147. package/dist/forge-payload/meta/templates/meta-task-prompt.md +26 -0
  148. package/dist/forge-payload/meta/tool-specs/collate.spec.md +88 -0
  149. package/dist/forge-payload/meta/tool-specs/generation-manifest.spec.md +139 -0
  150. package/dist/forge-payload/meta/tool-specs/manage-config.spec.md +143 -0
  151. package/dist/forge-payload/meta/tool-specs/seed-store.spec.md +91 -0
  152. package/dist/forge-payload/meta/tool-specs/store-cli.spec.md +328 -0
  153. package/dist/forge-payload/meta/tool-specs/validate-store.spec.md +191 -0
  154. package/dist/forge-payload/meta/workflows/_fragments/context-injection.md +75 -0
  155. package/dist/forge-payload/meta/workflows/_fragments/event-emission-schema.md +73 -0
  156. package/dist/forge-payload/meta/workflows/_fragments/finalize.md +13 -0
  157. package/dist/forge-payload/meta/workflows/_fragments/friction-emit.md +73 -0
  158. package/dist/forge-payload/meta/workflows/_fragments/progress-reporting.md +38 -0
  159. package/dist/forge-payload/meta/workflows/_fragments/store-cli-verbs.md +39 -0
  160. package/dist/forge-payload/meta/workflows/meta-approve.md +119 -0
  161. package/dist/forge-payload/meta/workflows/meta-collate.md +89 -0
  162. package/dist/forge-payload/meta/workflows/meta-commit.md +93 -0
  163. package/dist/forge-payload/meta/workflows/meta-enhance.md +286 -0
  164. package/dist/forge-payload/meta/workflows/meta-fix-bug.md +501 -0
  165. package/dist/forge-payload/meta/workflows/meta-implement.md +132 -0
  166. package/dist/forge-payload/meta/workflows/meta-migrate.md +455 -0
  167. package/dist/forge-payload/meta/workflows/meta-orchestrate.md +993 -0
  168. package/dist/forge-payload/meta/workflows/meta-plan-task.md +133 -0
  169. package/dist/forge-payload/meta/workflows/meta-quiz-agent.md +135 -0
  170. package/dist/forge-payload/meta/workflows/meta-retrospective.md +65 -0
  171. package/dist/forge-payload/meta/workflows/meta-review-implementation.md +119 -0
  172. package/dist/forge-payload/meta/workflows/meta-review-plan.md +108 -0
  173. package/dist/forge-payload/meta/workflows/meta-review-sprint-completion.md +65 -0
  174. package/dist/forge-payload/meta/workflows/meta-sprint-intake.md +76 -0
  175. package/dist/forge-payload/meta/workflows/meta-sprint-plan.md +147 -0
  176. package/dist/forge-payload/meta/workflows/meta-update-implementation.md +76 -0
  177. package/dist/forge-payload/meta/workflows/meta-update-plan.md +76 -0
  178. package/dist/forge-payload/meta/workflows/meta-validate.md +111 -0
  179. package/dist/forge-payload/tools/check-structure.cjs +344 -0
  180. package/dist/forge-payload/tools/collate.cjs +34 -9
  181. package/dist/forge-payload/tools/list-skills.js +76 -0
  182. package/dist/forge-payload/tools/parse-gates.cjs +8 -2
  183. package/dist/forge-payload/tools/store-cli.cjs +56 -11
  184. package/dist/forge-payload/tools/store.cjs +61 -0
  185. package/dist/forge-payload/tools/substitute-placeholders.cjs +60 -8
  186. package/dist/forge-payload/tools/validate-store.cjs +6 -2
  187. package/dist/forge-payload/tools/verify-integrity.cjs +86 -0
  188. package/package.json +2 -2
@@ -0,0 +1,191 @@
1
+ # Tool Spec: validate-store
2
+
3
+ ## Purpose
4
+
5
+ Check store integrity: required fields present, referential integrity
6
+ between sprints/tasks/bugs/events, no orphaned records.
7
+
8
+ ## Inputs
9
+
10
+ - `.forge/config.json` — paths
11
+ - `.forge/schemas/` — JSON Schema files (task, event, sprint, bug, feature); written during init Phase 8
12
+ - `.forge/store/` — all JSON files including `features/`
13
+
14
+ ## Outputs
15
+
16
+ - Validation report to stdout (text or JSON)
17
+ - Exit 0 if valid, 1 if errors found
18
+
19
+ ## CLI Interface
20
+
21
+ ```
22
+ <tool> validate-store # full validation (text output)
23
+ <tool> validate-store --dry-run # same checks, just report (text)
24
+ <tool> validate-store --fix # auto-fix where possible
25
+ <tool> validate-store --fix --dry-run # preview fixes without writing
26
+ <tool> validate-store --json # JSON structured output
27
+ <tool> validate-store --dry-run --json # JSON diagnosis, no fixes
28
+ <tool> validate-store --fix --dry-run --json # JSON preview of fixes, no writes
29
+ <tool> validate-store --fix --json # JSON output with fixes applied
30
+ ```
31
+
32
+ ## JSON Output Mode (`--json`)
33
+
34
+ When `--json` is present, the tool emits a single JSON object to stdout instead
35
+ of human-readable text. The JSON structure:
36
+
37
+ ```json
38
+ {
39
+ "ok": true,
40
+ "errors": [
41
+ {
42
+ "entity": "sprint",
43
+ "id": "FORGE-S07",
44
+ "category": "invalid-enum",
45
+ "field": "status",
46
+ "message": "field \"status\": value \"in-progress\" not in [planning, active, ...]",
47
+ "value": "in-progress",
48
+ "expected": ["planning", "active", "completed", ...]
49
+ }
50
+ ],
51
+ "warnings": [
52
+ {
53
+ "entity": "sprint",
54
+ "id": "FORGE-S03",
55
+ "category": "orphan-directory",
56
+ "field": null,
57
+ "message": "directory \"FORGE-S03-lean-migration\" has no sprint record in store"
58
+ }
59
+ ],
60
+ "fixes": [
61
+ {
62
+ "entity": "sprint",
63
+ "id": "FORGE-S01",
64
+ "category": "backfill",
65
+ "field": "createdAt",
66
+ "message": "backfilled \"createdAt\" = \"2026-01-15T10:00:00.000Z\"",
67
+ "applied": true
68
+ }
69
+ ],
70
+ "summary": {
71
+ "sprints": 7,
72
+ "tasks": 50,
73
+ "bugs": 4,
74
+ "features": 1,
75
+ "errors": 3,
76
+ "warnings": 2,
77
+ "fixes": 1
78
+ }
79
+ }
80
+ ```
81
+
82
+ ### Error Categories
83
+
84
+ | Category | Description |
85
+ |----------|-------------|
86
+ | `missing-required` | Required field is null, undefined, or empty string |
87
+ | `type-mismatch` | Field value has wrong JSON type (e.g., string where number expected) |
88
+ | `invalid-enum` | Field value is not in the declared enum set |
89
+ | `undeclared-field` | Field not in schema with `additionalProperties: false` |
90
+ | `orphaned-fk` | Foreign key references a non-existent entity |
91
+ | `filename-mismatch` | Event filename does not match its eventId |
92
+ | `minimum-violation` | Numeric value below declared minimum |
93
+ | `orphan-directory` | Filesystem directory has no corresponding store record |
94
+ | `stale-path` | `path` field references a nonexistent directory |
95
+ | `missing-optional` | Optional field is absent (warning, not error) |
96
+
97
+ ### Fix Categories
98
+
99
+ | Category | Description |
100
+ |----------|-------------|
101
+ | `backfill` | Missing field filled with a derived default |
102
+ | `orphaned-fk` | Orphaned foreign key nullified |
103
+ | `filename-mismatch` | Event file renamed or eventId corrected |
104
+
105
+ The `applied` field on fixes is `true` when the fix was actually written to disk,
106
+ `false` when `--dry-run` is active (preview only).
107
+
108
+ ### `--fix --dry-run` Combination
109
+
110
+ When both `--fix` and `--dry-run` are specified, the tool previews what fixes
111
+ *would* be applied without writing anything. Each fix in the JSON output has
112
+ `applied: false`. This is useful for the `/forge:store:repair` skill to assess
113
+ what auto-fixes are available before applying them.
114
+
115
+ ## Validation Rules
116
+
117
+ ### Required Fields
118
+
119
+ Load the JSON Schema files from `.forge/schemas/` at runtime and derive required
120
+ fields from each schema's `"required"` array. Do NOT hardcode field names.
121
+
122
+ If a schema file is missing, fall back to these defaults and warn:
123
+ - Sprint: `sprintId`, `title`, `status`
124
+ - Task: `taskId`, `sprintId`, `title`, `status`, `path`
125
+ - Bug: `bugId`, `title`, `severity`, `status`, `path`, `reportedAt`
126
+ - Event: `eventId`, `sprintId`, `role`, `action`, `startTimestamp`, `endTimestamp`, `durationMinutes`
127
+
128
+ When schemas are present, also validate field types and enum values per the
129
+ schema definitions — not just field presence.
130
+
131
+ ### Nullable Foreign Keys
132
+
133
+ `sprintId` and `taskId` are nullable foreign keys — `null` means "not associated"
134
+ (e.g. standalone bug fix with no sprint, sprint-level event with no task).
135
+ The validator must accept `null` for these fields without reporting an error.
136
+
137
+ `feature_id` on sprint and task records is a nullable FK pointing to
138
+ `.forge/store/features/{FEATURE_ID}.json`. A `null` value is valid (the record is
139
+ not associated with any feature). A non-null value must match the `id` field of an
140
+ existing feature record.
141
+
142
+ ### Referential Integrity
143
+ - Every task.sprintId references an existing sprint (when non-null)
144
+ - Every event.taskId references an existing task OR bug (when non-null)
145
+ - Every event.sprintId references an existing sprint OR matches the parent directory name (virtual sprint dirs like `events/bugs/`, `events/ops/`)
146
+ - Every bug.similarBugs[] references existing bugs
147
+ - Every sprint.feature_id and task.feature_id references an existing feature (when non-null)
148
+
149
+ ### Orphan Detection
150
+ - Task directories in `engineering/sprints/` without corresponding store JSON
151
+ - Store JSON without corresponding artifact directory
152
+
153
+ ### Status Consistency
154
+ - Task status matches artifact presence (e.g., `committed` tasks should have all artifacts)
155
+ - Sprint status consistent with task statuses
156
+
157
+ ### Undeclared Fields
158
+
159
+ When a schema has `additionalProperties: false`, any field not in the schema's
160
+ `properties` is reported as an error with category `undeclared-field`. This
161
+ catches fields that were valid in older schema versions but are no longer accepted.
162
+
163
+ ## Error Handling
164
+
165
+ - Wrap the entire entry point in a top-level exception handler.
166
+ - On unexpected errors (missing files, JSON parse failures, unhandled
167
+ exceptions), print a clear one-line message to stderr and exit 1.
168
+ - Never let the tool crash with an unhandled exception or stack trace visible
169
+ to the caller — all errors are caught and reported cleanly.
170
+ - Python pattern:
171
+ ```python
172
+ if __name__ == "__main__":
173
+ try:
174
+ sys.exit(main())
175
+ except Exception as e:
176
+ print(f"Error: {e}", file=sys.stderr)
177
+ sys.exit(1)
178
+ ```
179
+ - JS/TS pattern:
180
+ ```js
181
+ process.on('uncaughtException', (e) => {
182
+ process.stderr.write(`Error: ${e.message}\n`);
183
+ process.exit(1);
184
+ });
185
+ ```
186
+
187
+ ## Auto-Fix Rules (--fix mode)
188
+ - Add missing optional fields with defaults
189
+ - Create missing `.gitkeep` files in empty directories
190
+ - Nullify orphaned `feature_id` references on sprint and task records (log each fix)
191
+ - Do NOT delete orphaned records — only report them
@@ -0,0 +1,75 @@
1
+ # Fragment: Context Injection
2
+
3
+ <!-- Canonical definition of architecture_block + summary_block assembly patterns.
4
+ Referenced by meta-orchestrate.md and meta-fix-bug.md. -->
5
+
6
+ ## Architecture Context Block
7
+
8
+ Read `.forge/cache/context-pack.md` (if it exists) and inject into the subagent prompt
9
+ under the heading `### Architecture context (summary — full docs available at paths listed below)`.
10
+ If the pack is absent, omit this block silently — the subagent falls back to reading
11
+ architecture docs directly.
12
+
13
+ ```python
14
+ context_pack_path = ".forge/cache/context-pack.md"
15
+ context_pack_json_path = ".forge/cache/context-pack.json"
16
+ if file_exists(context_pack_path):
17
+ context_pack_md = read_file(context_pack_path)
18
+ try:
19
+ context_pack_json = read_json(context_pack_json_path)
20
+ full_doc_paths = "\n".join(f"- {s['path']}" for s in context_pack_json.get("sources", []))
21
+ except:
22
+ full_doc_paths = "engineering/architecture/ (see context-pack.json for full list)"
23
+ architecture_block = (
24
+ "### Architecture context (summary — full docs available at paths listed below)\n\n"
25
+ + context_pack_md
26
+ + "\n\nRead full architecture docs only if the summary above is insufficient for "
27
+ + "your decision. Full docs:\n"
28
+ + full_doc_paths
29
+ + "\n\n"
30
+ )
31
+ else:
32
+ architecture_block = ""
33
+ ```
34
+
35
+ ## Prior Phase Summary Block
36
+
37
+ Re-read the record from disk after each phase so summaries accumulate.
38
+ For bugs, pass `record_type="bug"` to read from the bugs store path.
39
+
40
+ ```python
41
+ # record_type: "task" (default) or "bug"
42
+ if record_type == "bug":
43
+ record_fresh = read_json(f".forge/store/bugs/{record_id}.json")
44
+ else:
45
+ record_fresh = read_json(f".forge/store/tasks/{record_id}.json")
46
+ summaries = (record_fresh or {}).get("summaries", {})
47
+
48
+ SUMMARY_PHASE_LABELS = {
49
+ "plan": "Plan", "review_plan": "Plan review",
50
+ "implementation": "Implementation", "code_review": "Code review",
51
+ "validation": "Validation", "approve": "Approve", "triage": "Triage"
52
+ }
53
+ summary_lines = []
54
+ for phase_key, label in SUMMARY_PHASE_LABELS.items():
55
+ s = summaries.get(phase_key)
56
+ if s:
57
+ summary_lines.append(f"- {label}: {s.get('objective', '(no objective)')}")
58
+ if s.get('key_changes'):
59
+ for c in s['key_changes'][:3]:
60
+ summary_lines.append(f" • {c}")
61
+ if s.get('findings'):
62
+ for f_ in s['findings'][:3]:
63
+ summary_lines.append(f" • {f_}")
64
+ if s.get('verdict') and s['verdict'] != 'n/a':
65
+ summary_lines.append(f" Verdict: {s['verdict']} Full: {s.get('artifact_ref', '(unknown)')}")
66
+
67
+ if summary_lines:
68
+ summary_block = (
69
+ "### Prior phase summaries (fast path — read full artifacts if you need more detail)\n\n"
70
+ + "\n".join(summary_lines)
71
+ + "\n\nIf any summary above is missing or insufficient, read the corresponding full artifact from disk before proceeding.\n\n"
72
+ )
73
+ else:
74
+ summary_block = ""
75
+ ```
@@ -0,0 +1,73 @@
1
+ # Fragment: Event Emission Schema
2
+
3
+ <!-- Canonical contract: subagents write judgement-only SUMMARY files; the
4
+ orchestrator stitches runtime telemetry + judgement into the canonical
5
+ event and emits it. Referenced by meta-orchestrate.md and meta-fix-bug.md.
6
+
7
+ PLAN-11 / SLICE-2 (2026-05-14): the LLM no longer hand-builds event JSON.
8
+ Runtime facts (model, provider, eventId, timestamps, iteration, tokens)
9
+ are owned by the orchestrator, never the subagent. The subagent only
10
+ produces judgement and lets the orchestrator complete the record. -->
11
+
12
+ ## Who writes what
13
+
14
+ | Actor | Owns (writes) | Never touches |
15
+ |--------------------|-------------------------------------------------------------------------------------------------|---------------|
16
+ | **Subagent (LLM)** | judgement fields: `verdict`, `notes`, `findings`, `objective`, `type` | `eventId`, `model`, `provider`, `startTimestamp`, `endTimestamp`, `durationMinutes`, `iteration`, `inputTokens`, `outputTokens`, `cacheReadTokens`, `cacheWriteTokens`, `tokenSource` |
17
+ | **Orchestrator** | everything else — composes the canonical event from runtime telemetry + the subagent's SUMMARY | the judgement fields themselves (copies them through unchanged) |
18
+
19
+ The LLM is the wrong actor for runtime facts: it has no privileged access to
20
+ the model/provider it ran under, the wall clock at spawn time, or the token
21
+ counts reported by the runtime stream. Every LLM guess at these fields is
22
+ wrong by construction.
23
+
24
+ ## What the subagent does
25
+
26
+ After completing its phase, the subagent writes one file:
27
+
28
+ ```
29
+ .forge/cache/{PHASE}-SUMMARY.json
30
+ ```
31
+
32
+ Examples: `PLAN-SUMMARY.json`, `REVIEW-PLAN-SUMMARY.json`,
33
+ `IMPLEMENT-SUMMARY.json`, `REVIEW-CODE-SUMMARY.json`, `COMMIT-SUMMARY.json`.
34
+
35
+ The SUMMARY contains judgement only. Required keys are phase-specific
36
+ (see `forge/schemas/phase-summary.schema.json` for the exact shape per
37
+ phase) but typically include `verdict`, `notes`, and any `findings`
38
+ the phase produces. The subagent **must not** include runtime fields —
39
+ adding `model`, `provider`, timestamps, or token counts to the SUMMARY is
40
+ ignored at best and rejected at worst.
41
+
42
+ The subagent **does not** call `store-cli emit` for phase events. That
43
+ shell-out is reserved for the orchestrator.
44
+
45
+ ## What the orchestrator does
46
+
47
+ After the subagent returns, the orchestrator constructs the event from:
48
+
49
+ 1. **Runtime telemetry** captured during the subagent run:
50
+ `model`, `provider`, token usage (`inputTokens`, `outputTokens`,
51
+ `cacheReadTokens`, `cacheWriteTokens`, `tokenSource: "reported"`).
52
+ 2. **Known task context** the orchestrator already tracks for run-task:
53
+ `taskId`, `sprintId`, `phase`, `iteration`.
54
+ 3. **Bracketed wall times** the orchestrator records around the subagent
55
+ call: `startTimestamp`, `endTimestamp`, `durationMinutes`.
56
+ 4. **Judgement blob** read from `{PHASE}-SUMMARY.json`: `verdict`, `notes`,
57
+ `findings`, etc.
58
+
59
+ The orchestrator then emits via:
60
+
61
+ ```
62
+ node "$FORGE_ROOT/tools/store-cli.cjs" emit {sprintId} '{complete-event-json}'
63
+ ```
64
+
65
+ ## Why no example record here
66
+
67
+ This fragment intentionally contains **no hardcoded example model strings,
68
+ provider names, or timestamps**. Such examples were the historical source of
69
+ LLM hallucination — subagents would copy the example verbatim ("the model
70
+ is claude-sonnet-4-6 because the workflow says so") even when running on a
71
+ completely different runtime. The schema lives at
72
+ `.forge/schemas/event.schema.json`; consult it directly when verifying a
73
+ field set.
@@ -0,0 +1,13 @@
1
+ ## Finalize: Subagent Closure
2
+
3
+ Before returning, every subagent MUST:
4
+
5
+ 1. Write any phase-specific summary the workflow body requires (e.g. PLAN.md, CODE_REVIEW.md).
6
+ 2. Confirm `task.status` reflects the phase outcome (via `store-cli update-status` if applicable).
7
+ 3. Return cleanly.
8
+
9
+ **Subagents MUST NOT write token-usage sidecars.** Token telemetry is owned by the orchestrator, which captures provider-reported usage from the runtime as the subagent runs and emits the canonical event (with `provider`, `model`, `inputTokens`, `outputTokens`, `cacheReadTokens`, `cacheWriteTokens`, `tokenSource: "reported"`) on the subagent's behalf.
10
+
11
+ If the runtime does not surface usage (rare), the orchestrator emits the event **without** the token fields — never with placeholder zeros or a `"missing"` marker. Honest absence beats misleading presence.
12
+
13
+ The `eventId` is passed by the orchestrator in the subagent prompt and is used only for non-token writes (e.g. `set-summary`, `update-status` history).
@@ -0,0 +1,73 @@
1
+ <!-- Canonical Friction Emit fragment.
2
+ Referenced from meta-implement.md, meta-fix-bug.md, meta-validate.md,
3
+ meta-plan-task.md, and meta-orchestrate.md. /forge:enhance --phase 2
4
+ greps generated workflows for `## Friction Emit` to discover the channel.
5
+
6
+ PLAN-11 / SLICE-2 (2026-05-14): friction is now recorded via the
7
+ `friction-emit.cjs` tool which appends judgement-only records to
8
+ `.forge/cache/FRICTION-{workflow}.jsonl`. The orchestrator drains this
9
+ file at phase-end, stamps runtime attribution (model/provider/usage/
10
+ timestamps/eventId) onto each record, and emits the events. The LLM
11
+ never hand-builds a friction event JSON. -->
12
+
13
+ # Friction Emit (Fragment)
14
+
15
+ When the persona detects skill friction during the workflow — a referenced
16
+ skill is unused, fails on invocation, is missing from the registry, has gone
17
+ stale relative to current architecture, or is redundant with another skill —
18
+ record a judgement-only friction signal. The orchestrator drains the
19
+ signals and emits the corresponding events so `/forge:enhance --phase 2`
20
+ can act on them.
21
+
22
+ ## Trigger conditions
23
+
24
+ Set `--issue` on the emitted record to one of the following tokens:
25
+
26
+ | Token | When to emit |
27
+ |--------------------|----------------------------------------------------------------------------------|
28
+ | `skill_unused` | A skill listed in the persona's skill block was loaded but never consulted. |
29
+ | `skill_failed` | A skill was consulted but its guidance produced an error or required correction. |
30
+ | `skill_missing` | The workflow needed guidance the available skills did not cover. |
31
+ | `skill_stale` | A skill's guidance contradicts current architecture / supersedes its own advice. |
32
+ | `skill_redundant` | Two skills provided overlapping or conflicting guidance for the same decision. |
33
+
34
+ Emit one record per distinct friction signal — do not coalesce multiple
35
+ findings into a single record.
36
+
37
+ ## Judgement-only contract
38
+
39
+ The friction recorder accepts only judgement fields. Runtime-attribution
40
+ fields (`model`, `provider`, `eventId`, timestamps, token counts) are
41
+ **rejected** if passed — they belong to the orchestrator and are stamped on
42
+ at drain time.
43
+
44
+ ```sh
45
+ node "$FORGE_ROOT/tools/friction-emit.cjs" \
46
+ --workflow {workflow-key} \
47
+ --persona {persona-noun} \
48
+ --issue skill_unused \
49
+ [--subkind skill_unused] \
50
+ [--evidence '{"trajectory_excerpt":"...","tool_errors":["..."],"retrieval_score":0.0,"skillId":"..."}']
51
+ ```
52
+
53
+ Required flags: `--workflow`, `--persona`, `--issue`.
54
+ Optional flags: `--subkind` (frozen enum
55
+ `skill_unused|skill_failed|skill_missing|skill_stale|skill_redundant`
56
+ or experimental `^x_[a-z_]+$`), `--evidence` (JSON object with
57
+ `trajectory_excerpt`, `tool_errors`, `retrieval_score` (0..1), `skillId`).
58
+
59
+ The tool appends one line of judgement-only JSON to
60
+ `.forge/cache/FRICTION-{workflow}.jsonl`. The orchestrator reads this file
61
+ after the phase completes, stamps each record with the captured runtime
62
+ attribution (model, provider, usage, wall times, eventId), and emits the
63
+ resulting events via `store-cli emit`.
64
+
65
+ ## Per-workflow values
66
+
67
+ | Workflow | `workflow` | `persona` | `phase` |
68
+ |------------------|------------|---------------|--------------|
69
+ | meta-implement | implement | engineer | implement |
70
+ | meta-fix-bug | fix-bug | bug-fixer | fix-bug |
71
+ | meta-validate | validate | qa-engineer | validate |
72
+ | meta-plan-task | plan-task | architect | plan |
73
+ | meta-orchestrate | orchestrate| orchestrator | orchestrate |
@@ -0,0 +1,38 @@
1
+ # Fragment: Progress Reporting
2
+
3
+ <!-- Canonical progress log format and store-cli commands for orchestrator subagents.
4
+ Referenced by meta-orchestrate.md and meta-fix-bug.md. -->
5
+
6
+ Each subagent writes progress entries to a transient log file that the
7
+ orchestrator monitors in real time.
8
+
9
+ **Log path:** `.forge/store/events/{sprintId}/progress.log`
10
+
11
+ **Format per line:**
12
+
13
+ ```
14
+ {ISO_TIMESTAMP}|{agent_name}|{banner_key}|{status}|{detail}
15
+ ```
16
+
17
+ | Field | Format | Example |
18
+ |-------|--------|---------|
19
+ | `ISO_TIMESTAMP` | ISO 8601 UTC | `2026-04-16T14:15:23Z` |
20
+ | `agent_name` | `{taskId}:{persona_noun}:{phase.role}:{iteration}` | `FORGE-S09-T01:engineer:plan:1` |
21
+ | `banner_key` | Banner identity key from BANNER_MAP | `forge` |
22
+ | `status` | One of: `start`, `progress`, `done`, `error` | `progress` |
23
+ | `detail` | Free text (no pipe characters) | `Reading codebase` |
24
+
25
+ **Writing entries:** Use `store-cli progress`:
26
+
27
+ ```
28
+ node "$FORGE_ROOT/tools/store-cli.cjs" progress {sprintId} {agentName} {bannerKey} {status} "detail text"
29
+ ```
30
+
31
+ **Monitoring:** The orchestrator starts a Monitor on the progress log before
32
+ spawning each subagent and stops it after the subagent returns.
33
+
34
+ **Clearing:** The orchestrator clears the progress log at task start:
35
+
36
+ ```
37
+ node "$FORGE_ROOT/tools/store-cli.cjs" progress-clear {sprintId}
38
+ ```
@@ -0,0 +1,39 @@
1
+ # Fragment: store-cli Verb Cheat-Sheet
2
+
3
+ <!-- Canonical store-cli verb list. Referenced by meta workflows that issue
4
+ store-cli calls. Surface it inline near the first store-cli invocation
5
+ so subagents stop inventing REST-style verbs (`get`, `set`, `delete`)
6
+ when they have to improvise a follow-up call. See forge#95 and
7
+ FORGE-S22-T02 (read-aliases). -->
8
+
9
+ store-cli verbs: `read` | `list` | `write` | `emit` | `update-status` | `set-summary` | `set-bug-summary` | `describe` | `template` | `nlp` | `query` | `delete`
10
+
11
+ Read-aliases (FORGE-S22-T02): `get` | `get-task` | `get-bug` | `get-sprint` | `get-summary` | `get-bug-summary`
12
+
13
+ Notes for subagents:
14
+
15
+ - **`read`** is the canonical "fetch one record" verb. The aliases
16
+ `get <entity> <id>`, `get-task <id>`, `get-bug <id>`, `get-sprint <id>`
17
+ are accepted and delegate byte-equally to `read`. Prefer the canonical
18
+ `read` form in new code; aliases exist to reduce friction when an agent
19
+ reaches for REST-style verbs.
20
+ - **`get-summary <taskId> <phase>`** and **`get-bug-summary <bugId> <phase>`**
21
+ are direct summary readers — they extract `record.summaries[phase]` and
22
+ exit 1 if the phase is absent. They are NOT write verbs (do not confuse
23
+ with `set-summary` / `set-bug-summary`).
24
+ - **`list`** filters by entity (`sprint`, `task`, `bug`, `event`, `feature`)
25
+ and optional flags. There is no `find` or `search` — use `nlp` for
26
+ natural-language lookup.
27
+ - **`update-status`** is the ONLY supported task/bug status mutation path.
28
+ Do not `write` a task back with a new `status` field; the FSM is enforced
29
+ by `update-status`.
30
+ - **`emit`** appends an event. There is no `append-event` / `add-event`.
31
+ - **`set-summary`** / **`set-bug-summary`** write summary sidecars referenced
32
+ from the entity record. Do not inline summaries into the entity via `write`.
33
+ - If you need a verb not on this list, run
34
+ `node "$FORGE_ROOT/tools/store-cli.cjs" --help` before improvising.
35
+ - If you supply an unknown verb, entity type, enum value, or field name,
36
+ store-cli appends a **Did you mean?** suggestion to the error message.
37
+ Suggestions use Levenshtein distance (≤ 2) and a curated drift map for
38
+ common agent misconceptions (e.g., `completed` → `committed`,
39
+ `task` → `taskId`, `set` → `set-summary`). See FORGE-S22-T03.
@@ -0,0 +1,119 @@
1
+ ---
2
+ requirements:
3
+ reasoning: High
4
+ context: Medium
5
+ speed: Low
6
+ audience: subagent
7
+ phase: approve
8
+ context:
9
+ architecture: true
10
+ prior_summaries: all
11
+ persona: summary
12
+ master_index: false
13
+ diff_mode: false
14
+ deps:
15
+ personas: [architect]
16
+ skills: [architect, generic]
17
+ templates: []
18
+ sub_workflows: []
19
+ kb_docs: [architecture/stack.md]
20
+ config_fields: [paths.engineering]
21
+ ---
22
+
23
+ # 🗻 Meta-Workflow: Approve Task
24
+
25
+ ## Purpose
26
+
27
+ The Architect gives final sign-off on a completed task after Supervisor approval. This is the last gate before commit.
28
+
29
+ ## Iron Laws
30
+
31
+ - Approve only when the implementation is consistent with the project's architecture and the deployment posture is understood. Architectural sign-off is not a rubber stamp — it is the last point at which cross-cutting concerns can be caught cheaply.
32
+ - Read `.forge/personas/architect.md` first; print the persona identity line (emoji, name, tagline) to stdout before any other tool use.
33
+ - All store I/O via `forge_store` (or `node "$FORGE_ROOT/tools/store-cli.cjs"`). Never edit `.forge/store/*.json` directly.
34
+
35
+ ## Store-Write Verification
36
+
37
+ Every `forge_store` write MUST succeed before advancing. If `store-cli` exits
38
+ non-zero or the `PreToolUse` write-boundary hook blocks the call (exit 2):
39
+
40
+ 1. Parse the structured error (names the offending field + schema file).
41
+ 2. Correct the JSON to satisfy the schema.
42
+ 3. Retry. Repeat up to 3 times.
43
+ 4. After 3 failures, halt and escalate with original payload, corrected payload, and all error messages.
44
+
45
+ Never set `FORGE_SKIP_WRITE_VALIDATION=1` — operator-only emergency switch.
46
+
47
+ ## Algorithm
48
+
49
+ ```
50
+
51
+ 0. Pre-flight Gate Check:
52
+ - Resolve FORGE_ROOT (`node -e "console.log(require('./.forge/config.json').paths.forgeRoot)"`).
53
+ - **Entity-mode resolution:** read the kickoff arguments. `--task {id}` → `entity_kind = "task"`, `record_id = {id}`. `--bug {id}` → `entity_kind = "bug"`, `record_id = {id}`. All store-cli calls below substitute `{entity_kind}` and `{record_id}` for the literal "task"/{taskId} placeholders.
54
+ - Run: `node "$FORGE_ROOT/tools/preflight-gate.cjs" --phase approve --{entity_kind} {record_id}`
55
+ - Exit 1 (gate failed) → print stderr and HALT. Do not proceed; do not attempt to produce the artifact.
56
+ - Exit 2 (misconfiguration) → print stderr and HALT.
57
+ - Exit 0 → continue.
58
+ 1. Load Context:
59
+ - Read task prompt
60
+ - Read final PLAN.md
61
+ - Read approved CODE_REVIEW.md
62
+ - Read PROGRESS.md
63
+
64
+ 2. Architectural Review:
65
+ - Verify implementation aligns with project architecture
66
+ - Check for cross-cutting concerns (impact on other modules)
67
+ - Assess operational impact (deployment changes, migrations)
68
+
69
+ 3. Sign Off:
70
+ - Write ARCHITECT_APPROVAL.md containing:
71
+ - A canonical verdict line for human readers, on its own line, in this exact form:
72
+ ```
73
+ **Verdict:** [Approved | Revision Required]
74
+ ```
75
+ - Approval status rationale
76
+ - Deployment notes
77
+ - Follow-up items for future sprints
78
+ - The downstream commit-phase preflight gate does NOT read this markdown. **Task mode:** it reads `task.status === "approved"` set in step 4. **Bug mode:** it reads `bug.summaries.approve.verdict === "approved"` set in step 5. The `**Verdict:**` line is a human breadcrumb only.
79
+
80
+ 4. Finalize:
81
+ - Transitions:
82
+ - **Task mode** — Update status: `node "$FORGE_ROOT/tools/store-cli.cjs" update-status task {taskId} status approved`. The status IS the verdict signal for task-mode commit gate (`STATUS_SOURCE` in `read-verdict.cjs`).
83
+ - **Bug mode** — NO status write. The bug remains `in-progress`. The verdict signal travels through `summaries.approve.verdict` written in step 5 below (read by `read-verdict.cjs § BUG_PHASE_VERDICT_SOURCE`). Writing `bug.status` here — especially writing `approved` or `verified` — violates `meta-fix-bug.md § Iron Laws #2` and is the trap that produced the FORGE-BUG-002 regression.
84
+ - **Do NOT emit a phase event yourself.** The orchestrator (or kickoff handler) owns event emission — it composes the canonical event from runtime telemetry (model, provider, tokens, wall times) plus the SUMMARY you write in the next step. Subagents that call `store-cli emit` for phase events hallucinate runtime facts (see Plan 11 / Slice 2). Write the SUMMARY and return.
85
+
86
+ 5. Emit Summary Sidecar:
87
+ - Write `APPROVE-SUMMARY.json` to the record's directory with the following shape:
88
+ ```json
89
+ {
90
+ "objective": "<one sentence — what this approval covered>",
91
+ "findings": ["<up to 12 bullets, 200 chars each — architectural notes, deployment concerns>"],
92
+ "verdict": "<approved | revision>",
93
+ "written_at": "<current ISO 8601 timestamp>",
94
+ "artifact_ref":"ARCHITECT_APPROVAL.md"
95
+ }
96
+ ```
97
+ - Call (task mode) — optional for tasks, since `task.status` is the canonical signal:
98
+ ```
99
+ node "$FORGE_ROOT/tools/store-cli.cjs" set-summary {taskId} approve \
100
+ engineering/sprints/{sprint}/{task}/APPROVE-SUMMARY.json
101
+ ```
102
+ Or (bug mode) — REQUIRED for bugs, this is the canonical verdict signal:
103
+ ```
104
+ node "$FORGE_ROOT/tools/store-cli.cjs" set-bug-summary {bugId} approve \
105
+ engineering/bugs/{bugDir}/APPROVE-SUMMARY.json
106
+ ```
107
+ - In bug mode, if the set-bug-summary call exits non-zero, fix the sidecar JSON and retry. Do not return without a valid summary — the downstream commit gate has no other way to read the approval verdict.
108
+ ```
109
+
110
+ ## Generation Instructions
111
+
112
+ - **Workflow Structure:** The generated `approve_task.md` must follow the strict "Algorithm" block format.
113
+ - **Verdict Detection:** Instruct the architect to write a literal `**Verdict:** [Approved | Revision Required]` line in ARCHITECT_APPROVAL.md for human readability. Downstream gates read `task.status` via read-verdict.cjs, not this markdown — but the line remains a useful breadcrumb for operators reviewing artifacts.
114
+ - **Context Isolation:** Forbid inline execution of complex architectural analysis; use the `Agent` tool for sub-tasks.
115
+ - **Project Specifics:**
116
+ - Reference project's architecture docs.
117
+ - Include project-specific deployment concerns.
118
+ - **Token Reporting:** See `_fragments/finalize.md` — wire via `file_ref:`.
119
+ - **Event Emission:** Ensure the "complete" event includes the `eventId` passed by the orchestrator.