cap-pro 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (275) hide show
  1. package/.claude-plugin/README.md +26 -0
  2. package/.claude-plugin/marketplace.json +24 -0
  3. package/.claude-plugin/plugin.json +24 -0
  4. package/LICENSE +21 -0
  5. package/README.ja-JP.md +834 -0
  6. package/README.ko-KR.md +823 -0
  7. package/README.md +806 -0
  8. package/README.pt-BR.md +452 -0
  9. package/README.zh-CN.md +800 -0
  10. package/agents/cap-architect.md +269 -0
  11. package/agents/cap-brainstormer.md +207 -0
  12. package/agents/cap-curator.md +276 -0
  13. package/agents/cap-debugger.md +365 -0
  14. package/agents/cap-designer.md +246 -0
  15. package/agents/cap-historian.md +464 -0
  16. package/agents/cap-migrator.md +291 -0
  17. package/agents/cap-prototyper.md +197 -0
  18. package/agents/cap-validator.md +308 -0
  19. package/bin/install.js +5433 -0
  20. package/cap/bin/cap-tools.cjs +853 -0
  21. package/cap/bin/lib/arc-scanner.cjs +344 -0
  22. package/cap/bin/lib/cap-affinity-engine.cjs +862 -0
  23. package/cap/bin/lib/cap-anchor.cjs +228 -0
  24. package/cap/bin/lib/cap-annotation-writer.cjs +340 -0
  25. package/cap/bin/lib/cap-checkpoint.cjs +434 -0
  26. package/cap/bin/lib/cap-cluster-detect.cjs +945 -0
  27. package/cap/bin/lib/cap-cluster-display.cjs +52 -0
  28. package/cap/bin/lib/cap-cluster-format.cjs +245 -0
  29. package/cap/bin/lib/cap-cluster-helpers.cjs +295 -0
  30. package/cap/bin/lib/cap-cluster-io.cjs +212 -0
  31. package/cap/bin/lib/cap-completeness.cjs +540 -0
  32. package/cap/bin/lib/cap-deps.cjs +583 -0
  33. package/cap/bin/lib/cap-design-families.cjs +332 -0
  34. package/cap/bin/lib/cap-design.cjs +966 -0
  35. package/cap/bin/lib/cap-divergence-detector.cjs +400 -0
  36. package/cap/bin/lib/cap-doctor.cjs +752 -0
  37. package/cap/bin/lib/cap-feature-map-internals.cjs +19 -0
  38. package/cap/bin/lib/cap-feature-map-migrate.cjs +335 -0
  39. package/cap/bin/lib/cap-feature-map-monorepo.cjs +885 -0
  40. package/cap/bin/lib/cap-feature-map-shard.cjs +315 -0
  41. package/cap/bin/lib/cap-feature-map.cjs +1943 -0
  42. package/cap/bin/lib/cap-fitness-score.cjs +1075 -0
  43. package/cap/bin/lib/cap-impact-analysis.cjs +652 -0
  44. package/cap/bin/lib/cap-learn-review.cjs +1072 -0
  45. package/cap/bin/lib/cap-learning-signals.cjs +627 -0
  46. package/cap/bin/lib/cap-loader.cjs +227 -0
  47. package/cap/bin/lib/cap-logger.cjs +57 -0
  48. package/cap/bin/lib/cap-memory-bridge.cjs +764 -0
  49. package/cap/bin/lib/cap-memory-confidence.cjs +452 -0
  50. package/cap/bin/lib/cap-memory-dir.cjs +987 -0
  51. package/cap/bin/lib/cap-memory-engine.cjs +698 -0
  52. package/cap/bin/lib/cap-memory-extends.cjs +398 -0
  53. package/cap/bin/lib/cap-memory-graph.cjs +790 -0
  54. package/cap/bin/lib/cap-memory-migrate.cjs +2015 -0
  55. package/cap/bin/lib/cap-memory-pin.cjs +183 -0
  56. package/cap/bin/lib/cap-memory-platform.cjs +490 -0
  57. package/cap/bin/lib/cap-memory-prune.cjs +707 -0
  58. package/cap/bin/lib/cap-memory-schema.cjs +812 -0
  59. package/cap/bin/lib/cap-migrate-tags.cjs +309 -0
  60. package/cap/bin/lib/cap-migrate.cjs +540 -0
  61. package/cap/bin/lib/cap-pattern-apply.cjs +1203 -0
  62. package/cap/bin/lib/cap-pattern-pipeline.cjs +1034 -0
  63. package/cap/bin/lib/cap-plugin-manifest.cjs +80 -0
  64. package/cap/bin/lib/cap-realtime-affinity.cjs +399 -0
  65. package/cap/bin/lib/cap-reconcile.cjs +570 -0
  66. package/cap/bin/lib/cap-research-gate.cjs +218 -0
  67. package/cap/bin/lib/cap-scope-filter.cjs +402 -0
  68. package/cap/bin/lib/cap-semantic-pipeline.cjs +1038 -0
  69. package/cap/bin/lib/cap-session-extract.cjs +987 -0
  70. package/cap/bin/lib/cap-session.cjs +445 -0
  71. package/cap/bin/lib/cap-snapshot-linkage.cjs +963 -0
  72. package/cap/bin/lib/cap-stack-docs.cjs +646 -0
  73. package/cap/bin/lib/cap-tag-observer.cjs +371 -0
  74. package/cap/bin/lib/cap-tag-scanner.cjs +1766 -0
  75. package/cap/bin/lib/cap-telemetry.cjs +466 -0
  76. package/cap/bin/lib/cap-test-audit.cjs +1438 -0
  77. package/cap/bin/lib/cap-thread-migrator.cjs +307 -0
  78. package/cap/bin/lib/cap-thread-synthesis.cjs +545 -0
  79. package/cap/bin/lib/cap-thread-tracker.cjs +519 -0
  80. package/cap/bin/lib/cap-trace.cjs +399 -0
  81. package/cap/bin/lib/cap-trust-mode.cjs +336 -0
  82. package/cap/bin/lib/cap-ui-design-editor.cjs +642 -0
  83. package/cap/bin/lib/cap-ui-mind-map.cjs +712 -0
  84. package/cap/bin/lib/cap-ui-thread-nav.cjs +693 -0
  85. package/cap/bin/lib/cap-ui.cjs +1245 -0
  86. package/cap/bin/lib/cap-upgrade.cjs +1028 -0
  87. package/cap/bin/lib/cli/arg-helpers.cjs +49 -0
  88. package/cap/bin/lib/cli/frontmatter-router.cjs +31 -0
  89. package/cap/bin/lib/cli/init-router.cjs +68 -0
  90. package/cap/bin/lib/cli/phase-router.cjs +102 -0
  91. package/cap/bin/lib/cli/state-router.cjs +61 -0
  92. package/cap/bin/lib/cli/template-router.cjs +37 -0
  93. package/cap/bin/lib/cli/uat-router.cjs +29 -0
  94. package/cap/bin/lib/cli/validation-router.cjs +26 -0
  95. package/cap/bin/lib/cli/verification-router.cjs +31 -0
  96. package/cap/bin/lib/cli/workstream-router.cjs +39 -0
  97. package/cap/bin/lib/commands.cjs +961 -0
  98. package/cap/bin/lib/config.cjs +467 -0
  99. package/cap/bin/lib/convention-reader.cjs +258 -0
  100. package/cap/bin/lib/core.cjs +1241 -0
  101. package/cap/bin/lib/feature-aggregator.cjs +423 -0
  102. package/cap/bin/lib/frontmatter.cjs +337 -0
  103. package/cap/bin/lib/init.cjs +1443 -0
  104. package/cap/bin/lib/manifest-generator.cjs +383 -0
  105. package/cap/bin/lib/milestone.cjs +253 -0
  106. package/cap/bin/lib/model-profiles.cjs +69 -0
  107. package/cap/bin/lib/monorepo-context.cjs +226 -0
  108. package/cap/bin/lib/monorepo-migrator.cjs +509 -0
  109. package/cap/bin/lib/phase.cjs +889 -0
  110. package/cap/bin/lib/profile-output.cjs +989 -0
  111. package/cap/bin/lib/profile-pipeline.cjs +540 -0
  112. package/cap/bin/lib/roadmap.cjs +330 -0
  113. package/cap/bin/lib/security.cjs +394 -0
  114. package/cap/bin/lib/session-manager.cjs +292 -0
  115. package/cap/bin/lib/skeleton-generator.cjs +179 -0
  116. package/cap/bin/lib/state.cjs +1032 -0
  117. package/cap/bin/lib/template.cjs +231 -0
  118. package/cap/bin/lib/test-detector.cjs +62 -0
  119. package/cap/bin/lib/uat.cjs +283 -0
  120. package/cap/bin/lib/verify.cjs +889 -0
  121. package/cap/bin/lib/workspace-detector.cjs +371 -0
  122. package/cap/bin/lib/workstream.cjs +492 -0
  123. package/cap/commands/gsd/workstreams.md +63 -0
  124. package/cap/references/arc-standard.md +315 -0
  125. package/cap/references/cap-agent-architecture.md +101 -0
  126. package/cap/references/cap-gitignore-template +9 -0
  127. package/cap/references/cap-zero-deps.md +158 -0
  128. package/cap/references/checkpoints.md +778 -0
  129. package/cap/references/continuation-format.md +249 -0
  130. package/cap/references/contract-test-templates.md +312 -0
  131. package/cap/references/feature-map-template.md +25 -0
  132. package/cap/references/git-integration.md +295 -0
  133. package/cap/references/git-planning-commit.md +38 -0
  134. package/cap/references/model-profiles.md +174 -0
  135. package/cap/references/phase-numbering.md +126 -0
  136. package/cap/references/planning-config.md +202 -0
  137. package/cap/references/property-test-templates.md +316 -0
  138. package/cap/references/security-test-templates.md +347 -0
  139. package/cap/references/session-template.json +8 -0
  140. package/cap/references/tdd.md +263 -0
  141. package/cap/references/user-profiling.md +681 -0
  142. package/cap/references/verification-patterns.md +612 -0
  143. package/cap/templates/UAT.md +265 -0
  144. package/cap/templates/claude-md.md +175 -0
  145. package/cap/templates/codebase/architecture.md +255 -0
  146. package/cap/templates/codebase/concerns.md +310 -0
  147. package/cap/templates/codebase/conventions.md +307 -0
  148. package/cap/templates/codebase/integrations.md +280 -0
  149. package/cap/templates/codebase/stack.md +186 -0
  150. package/cap/templates/codebase/structure.md +285 -0
  151. package/cap/templates/codebase/testing.md +480 -0
  152. package/cap/templates/config.json +44 -0
  153. package/cap/templates/context.md +352 -0
  154. package/cap/templates/continue-here.md +78 -0
  155. package/cap/templates/copilot-instructions.md +7 -0
  156. package/cap/templates/debug-subagent-prompt.md +91 -0
  157. package/cap/templates/discussion-log.md +63 -0
  158. package/cap/templates/milestone-archive.md +123 -0
  159. package/cap/templates/milestone.md +115 -0
  160. package/cap/templates/phase-prompt.md +610 -0
  161. package/cap/templates/planner-subagent-prompt.md +117 -0
  162. package/cap/templates/project.md +186 -0
  163. package/cap/templates/requirements.md +231 -0
  164. package/cap/templates/research-project/ARCHITECTURE.md +204 -0
  165. package/cap/templates/research-project/FEATURES.md +147 -0
  166. package/cap/templates/research-project/PITFALLS.md +200 -0
  167. package/cap/templates/research-project/STACK.md +120 -0
  168. package/cap/templates/research-project/SUMMARY.md +170 -0
  169. package/cap/templates/research.md +552 -0
  170. package/cap/templates/roadmap.md +202 -0
  171. package/cap/templates/state.md +176 -0
  172. package/cap/templates/summary.md +364 -0
  173. package/cap/templates/user-preferences.md +498 -0
  174. package/cap/templates/verification-report.md +322 -0
  175. package/cap/workflows/add-phase.md +112 -0
  176. package/cap/workflows/add-tests.md +351 -0
  177. package/cap/workflows/add-todo.md +158 -0
  178. package/cap/workflows/audit-milestone.md +340 -0
  179. package/cap/workflows/audit-uat.md +109 -0
  180. package/cap/workflows/autonomous.md +891 -0
  181. package/cap/workflows/check-todos.md +177 -0
  182. package/cap/workflows/cleanup.md +152 -0
  183. package/cap/workflows/complete-milestone.md +767 -0
  184. package/cap/workflows/diagnose-issues.md +231 -0
  185. package/cap/workflows/discovery-phase.md +289 -0
  186. package/cap/workflows/discuss-phase-assumptions.md +653 -0
  187. package/cap/workflows/discuss-phase.md +1049 -0
  188. package/cap/workflows/do.md +104 -0
  189. package/cap/workflows/execute-phase.md +846 -0
  190. package/cap/workflows/execute-plan.md +514 -0
  191. package/cap/workflows/fast.md +105 -0
  192. package/cap/workflows/forensics.md +265 -0
  193. package/cap/workflows/health.md +181 -0
  194. package/cap/workflows/help.md +660 -0
  195. package/cap/workflows/insert-phase.md +130 -0
  196. package/cap/workflows/list-phase-assumptions.md +178 -0
  197. package/cap/workflows/list-workspaces.md +56 -0
  198. package/cap/workflows/manager.md +362 -0
  199. package/cap/workflows/map-codebase.md +377 -0
  200. package/cap/workflows/milestone-summary.md +223 -0
  201. package/cap/workflows/new-milestone.md +486 -0
  202. package/cap/workflows/new-project.md +1250 -0
  203. package/cap/workflows/new-workspace.md +237 -0
  204. package/cap/workflows/next.md +97 -0
  205. package/cap/workflows/node-repair.md +92 -0
  206. package/cap/workflows/note.md +156 -0
  207. package/cap/workflows/pause-work.md +176 -0
  208. package/cap/workflows/plan-milestone-gaps.md +273 -0
  209. package/cap/workflows/plan-phase.md +857 -0
  210. package/cap/workflows/plant-seed.md +169 -0
  211. package/cap/workflows/pr-branch.md +129 -0
  212. package/cap/workflows/profile-user.md +449 -0
  213. package/cap/workflows/progress.md +507 -0
  214. package/cap/workflows/quick.md +757 -0
  215. package/cap/workflows/remove-phase.md +155 -0
  216. package/cap/workflows/remove-workspace.md +90 -0
  217. package/cap/workflows/research-phase.md +82 -0
  218. package/cap/workflows/resume-project.md +326 -0
  219. package/cap/workflows/review.md +228 -0
  220. package/cap/workflows/session-report.md +146 -0
  221. package/cap/workflows/settings.md +283 -0
  222. package/cap/workflows/ship.md +228 -0
  223. package/cap/workflows/stats.md +60 -0
  224. package/cap/workflows/transition.md +671 -0
  225. package/cap/workflows/ui-phase.md +298 -0
  226. package/cap/workflows/ui-review.md +161 -0
  227. package/cap/workflows/update.md +323 -0
  228. package/cap/workflows/validate-phase.md +170 -0
  229. package/cap/workflows/verify-phase.md +254 -0
  230. package/cap/workflows/verify-work.md +637 -0
  231. package/commands/cap/annotate.md +165 -0
  232. package/commands/cap/brainstorm.md +393 -0
  233. package/commands/cap/checkpoint.md +106 -0
  234. package/commands/cap/completeness.md +94 -0
  235. package/commands/cap/continue.md +72 -0
  236. package/commands/cap/debug.md +588 -0
  237. package/commands/cap/deps.md +169 -0
  238. package/commands/cap/design.md +479 -0
  239. package/commands/cap/init.md +354 -0
  240. package/commands/cap/iterate.md +249 -0
  241. package/commands/cap/learn.md +459 -0
  242. package/commands/cap/memory.md +275 -0
  243. package/commands/cap/migrate-feature-map.md +91 -0
  244. package/commands/cap/migrate-memory.md +108 -0
  245. package/commands/cap/migrate-tags.md +91 -0
  246. package/commands/cap/migrate.md +131 -0
  247. package/commands/cap/prototype.md +510 -0
  248. package/commands/cap/reconcile.md +121 -0
  249. package/commands/cap/review.md +360 -0
  250. package/commands/cap/save.md +72 -0
  251. package/commands/cap/scan.md +404 -0
  252. package/commands/cap/start.md +356 -0
  253. package/commands/cap/status.md +118 -0
  254. package/commands/cap/test-audit.md +262 -0
  255. package/commands/cap/test.md +394 -0
  256. package/commands/cap/trace.md +133 -0
  257. package/commands/cap/ui.md +167 -0
  258. package/hooks/dist/cap-check-update.js +115 -0
  259. package/hooks/dist/cap-context-monitor.js +185 -0
  260. package/hooks/dist/cap-learn-review-hook.js +114 -0
  261. package/hooks/dist/cap-learning-hook.js +192 -0
  262. package/hooks/dist/cap-memory.js +299 -0
  263. package/hooks/dist/cap-prompt-guard.js +97 -0
  264. package/hooks/dist/cap-statusline.js +157 -0
  265. package/hooks/dist/cap-tag-observer.js +115 -0
  266. package/hooks/dist/cap-version-check.js +112 -0
  267. package/hooks/dist/cap-workflow-guard.js +175 -0
  268. package/hooks/hooks.json +55 -0
  269. package/package.json +58 -0
  270. package/scripts/base64-scan.sh +262 -0
  271. package/scripts/build-hooks.js +93 -0
  272. package/scripts/cap-removal-checklist.md +202 -0
  273. package/scripts/prompt-injection-scan.sh +199 -0
  274. package/scripts/run-tests.cjs +181 -0
  275. package/scripts/secret-scan.sh +227 -0
@@ -0,0 +1,459 @@
1
+ ---
2
+ name: cap:learn
3
+ description: "Extract patterns from F-070 learning signals — Stage 1 deterministic heuristics + Stage 2 LLM-briefing pattern (counts + hashes only). Promotes candidates that hit the threshold (>=3 overrides OR >=1 regret) within the per-session LLM budget. Subcommands: --unlearn P-NNN reverses an applied pattern; --retract-check runs the 5-session post-apply check."
4
+ argument-hint: "[--features F-NNN] [--dry-run] [--budget N] [--session SID] [--unlearn P-NNN] [--retract-check] [review]"
5
+ allowed-tools:
6
+ - Read
7
+ - Write
8
+ - Bash
9
+ - Glob
10
+ - Grep
11
+ ---
12
+
13
+ <!-- @cap-context CAP F-071 — Pattern Pipeline orchestrator. Manual trigger only (D2). -->
14
+ <!-- @cap-decision(F-071/D1) Host-LLM via Skill-Briefing pattern: this skill writes briefings to .cap/learning/queue/P-NNN.md, instructs the outer agent to read each briefing and write the result to .cap/learning/patterns/P-NNN.json. No HTTPS client, no SDK dep. -->
15
+ <!-- @cap-decision(F-071/D2) Trigger is MANUAL via /cap:learn. NOT auto on /cap:scan, NOT on Stop-Hook. Auto-triggering would burn through the user's LLM budget without consent. -->
16
+ <!-- @cap-decision(F-071/D3) LLM input shape — Counts + Hashes only. The strict path. The briefing schema is { candidateId, signalType, count, byFeature, topContextHashes }. Anything beyond this MUST go through hashContext first. -->
17
+
18
+ <objective>
19
+ <!-- @cap-todo(ac:F-071/AC-1) Stage 1 — TF-IDF + RegEx-Cluster + Frequency on signal records. -->
20
+ <!-- @cap-todo(ac:F-071/AC-2) Stage 2 trigger when count >= 3 overrides OR >= 1 regret. -->
21
+ <!-- @cap-todo(ac:F-071/AC-3) PRIVACY-CRITICAL — LLM input is counts + hashes only. -->
22
+ <!-- @cap-todo(ac:F-071/AC-4) Budget hard-limit — 3 LLM calls per session by default; overflow → queue/ with deferred:budget. -->
23
+ <!-- @cap-todo(ac:F-071/AC-5) Graceful degradation — heuristic-only L1 pattern persisted with degraded:true when Stage 2 doesn't run. -->
24
+ <!-- @cap-todo(ac:F-071/AC-6) Every pattern gets a P-NNN ID — sequential, never renumbered. -->
25
+ <!-- @cap-todo(ac:F-071/AC-7) Budget override — .cap/learning/config.json#llmBudgetPerSession replaces the default 3. -->
26
+
27
+ Extract actionable patterns (P-NNN) from the F-070 learning-signal corpus. Stage 1 runs a deterministic heuristic engine (TF-IDF on hash-tuples + frequency thresholding); Stage 2 conditionally hands off candidates to the host LLM via a Counts+Hashes-only briefing markdown — never raw signals, never user text, never file paths.
28
+
29
+ **Arguments:**
30
+ - `--features F-NNN` -- restrict the input signal set to one or more featureIds (comma-separated)
31
+ - `--dry-run` -- run Stage 1 + threshold check + budget read but do NOT write briefings or pattern files
32
+ - `--budget N` -- override the per-session LLM call budget (otherwise read from `.cap/learning/config.json` or default 3)
33
+ - `--session SID` -- override the active session id (mostly for tests / replay)
34
+ </objective>
35
+
36
+ <context>
37
+ $ARGUMENTS
38
+
39
+ @FEATURE-MAP.md
40
+ @.cap/SESSION.json
41
+ </context>
42
+
43
+ <process>
44
+
45
+ ## Step 0: Parse flags
46
+
47
+ Check `$ARGUMENTS` for:
48
+ - `--features NAME` -- store comma-separated values as `feature_filter`
49
+ - `--dry-run` -- set `dry_run = true`
50
+ - `--budget N` -- store `budget_override` (integer)
51
+ - `--session SID` -- store `session_override`
52
+
53
+ ## Step 1: Load session context + budget state
54
+
55
+ ```bash
56
+ node -e "
57
+ const session = require('./cap/bin/lib/cap-session.cjs');
58
+ const pipeline = require('./cap/bin/lib/cap-pattern-pipeline.cjs');
59
+ const telemetry = require('./cap/bin/lib/cap-telemetry.cjs');
60
+
61
+ const root = process.cwd();
62
+ const s = session.loadSession(root) || {};
63
+ const sessionId = process.argv[1] || s.sessionId || null;
64
+
65
+ const budgetState = pipeline.getSessionBudgetState(root, sessionId);
66
+ console.log(JSON.stringify({
67
+ sessionId,
68
+ activeFeature: s.activeFeature || null,
69
+ budget: budgetState.budget,
70
+ used: budgetState.used,
71
+ remaining: budgetState.remaining,
72
+ budgetSource: budgetState.source,
73
+ }, null, 2));
74
+ " '<SESSION_OVERRIDE_OR_EMPTY>'
75
+ ```
76
+
77
+ Store as `ctx`. If `budget_override` is set, treat `ctx.budget` as `budget_override` and recompute `ctx.remaining = max(0, budget_override - ctx.used)`.
78
+
79
+ Log: `Session: {ctx.sessionId} · Budget: {ctx.budget} ({ctx.budgetSource}) · Used: {ctx.used} · Remaining: {ctx.remaining}`
80
+
81
+ ## Step 2: Run Stage 1 — heuristic engine
82
+
83
+ <!-- @cap-todo(ac:F-071/AC-1) Heuristic engine — TF-IDF + Frequency-arm + RegEx-Cluster (cluster key is the (signalType, featureId) prefix of the tuple-token). -->
84
+
85
+ ```bash
86
+ node -e "
87
+ const pipeline = require('./cap/bin/lib/cap-pattern-pipeline.cjs');
88
+ const root = process.cwd();
89
+ const sessionFilter = process.argv[1] || undefined;
90
+ const opts = sessionFilter ? { sessionId: sessionFilter } : {};
91
+ const result = pipeline.runHeuristicStage(root, opts);
92
+ console.log(JSON.stringify({
93
+ candidates: result.candidates.length,
94
+ errors: result.errors,
95
+ }, null, 2));
96
+ " '<SESSION_OVERRIDE_OR_EMPTY>'
97
+ ```
98
+
99
+ Store as `stage1`. Log: `Stage 1: {stage1.candidates} candidates persisted to .cap/learning/candidates/`.
100
+
101
+ **If `stage1.errors.length > 0`, ABORT promotion.** Stage 1 ran on a partial corpus (one or more `getSignals` collectors failed — overrides, memory-refs, or regrets). Promoting candidates against an incomplete signal set would burn the LLM budget on data we know is missing. Surface the error list to the user and stop:
102
+
103
+ ```
104
+ Stage 1 produced errors — refusing to promote candidates to Stage 2.
105
+ Errors: {stage1.errors}
106
+ Re-run /cap:learn after fixing the underlying signal-collector failures, or
107
+ inspect .cap/learning/signals/ to confirm the JSONL files are readable.
108
+ ```
109
+
110
+ Skip Steps 3-7 in this case; the user resolves the I/O issue and re-runs.
111
+
112
+ If `feature_filter` is set, the orchestrator filters the candidate set in Step 3 by intersecting `candidate.featureId` with the filter.
113
+
114
+ ## Step 3: Determine Stage-2 promotions
115
+
116
+ ```bash
117
+ node -e "
118
+ const fs = require('node:fs');
119
+ const path = require('node:path');
120
+ const pipeline = require('./cap/bin/lib/cap-pattern-pipeline.cjs');
121
+
122
+ const root = process.cwd();
123
+ const candidatesDir = pipeline.candidatesDir(root);
124
+ const filterRaw = process.argv[1] || '';
125
+ const featureFilter = filterRaw ? new Set(filterRaw.split(',').map(s => s.trim())) : null;
126
+
127
+ const candidates = [];
128
+ if (fs.existsSync(candidatesDir)) {
129
+ for (const f of fs.readdirSync(candidatesDir)) {
130
+ if (!f.endsWith('.json')) continue;
131
+ try { candidates.push(JSON.parse(fs.readFileSync(path.join(candidatesDir, f), 'utf8'))); } catch (_e) {}
132
+ }
133
+ }
134
+
135
+ // AC-2 threshold check + optional feature filter.
136
+ const promotable = candidates.filter(c => {
137
+ if (!pipeline.checkThreshold(c)) return false;
138
+ if (featureFilter && c.featureId && !featureFilter.has(c.featureId)) return false;
139
+ return true;
140
+ });
141
+ console.log(JSON.stringify({
142
+ total: candidates.length,
143
+ promotable: promotable.length,
144
+ ids: promotable.map(c => c.candidateId),
145
+ }));
146
+ " '<FEATURE_FILTER_OR_EMPTY>'
147
+ ```
148
+
149
+ Store as `gate`. Log: `Stage 2 candidates: {gate.promotable} of {gate.total} cleared the threshold.`
150
+
151
+ If `dry_run`: stop here, print the gate summary, do NOT write briefings or pattern files.
152
+
153
+ ## Step 4: Promote within budget; overflow → deferred queue
154
+
155
+ <!-- @cap-todo(ac:F-071/AC-4) Budget hard-limit — promote at most `ctx.remaining` candidates this session. Overflow lands in queue/ with deferred:budget. -->
156
+ <!-- @cap-risk(F-071/AC-4) Every promotion path goes through this step. A regression that bypasses ctx.remaining would silently burn through the user's wallet. -->
157
+
158
+ For each promotable candidate (sorted by score descending):
159
+
160
+ - If `promoted < ctx.remaining`:
161
+ 1. Allocate `P-NNN` via `pipeline.allocatePatternId(root)`.
162
+ 2. Build briefing: `pipeline.buildBriefing(candidate, root, { id })` — writes `.cap/learning/queue/P-NNN.md`.
163
+ 3. **Hand off to the outer agent**: read the briefing markdown, generate ONE of L1 / L2 / L3 (your choice based on the briefing), and write the result to `.cap/learning/patterns/P-NNN.json` with the documented schema:
164
+
165
+ ```json
166
+ {
167
+ "id": "P-NNN",
168
+ "createdAt": "<ISO timestamp>",
169
+ "level": "L1" | "L2" | "L3",
170
+ "featureRef": "F-NNN" | null,
171
+ "source": "llm",
172
+ "degraded": false,
173
+ "confidence": 0.0-1.0,
174
+ "suggestion": { /* L1 / L2 / L3 shape */ },
175
+ "evidence": { "candidateId": "<hex>", "signalType": "...", "count": <int>, "topContextHashes": [...] }
176
+ }
177
+ ```
178
+
179
+ 4. After the result is written, increment session usage so the budget is consumed:
180
+
181
+ ```bash
182
+ node -e "
183
+ const t = require('./cap/bin/lib/cap-telemetry.cjs');
184
+ t.recordLlmCall(process.cwd(), {
185
+ model: 'claude-opus-4-7',
186
+ promptTokens: 0, completionTokens: 0, durationMs: 0,
187
+ sessionId: '<SESSION_ID>',
188
+ commandContext: { command: '/cap:learn', feature: 'F-071' },
189
+ });
190
+ "
191
+ ```
192
+
193
+ - Else (budget exhausted):
194
+ 1. Allocate `P-NNN`.
195
+ 2. Build a deferred briefing: `pipeline.buildBriefing(candidate, root, { id, deferred: true })` — the markdown carries `deferred: budget` in frontmatter.
196
+ 3. The candidate keeps its allocated ID across sessions; next `/cap:learn` invocation will see the queued briefing and pick up where this session left off.
197
+
198
+ **Privacy contract — the briefing markdown contains ONLY counts and hex hashes.** AC-3 forbids any other content. The orchestrator must never inject raw paths, decision text, or signal records into the briefing or the pattern result. (F-071/AC-3)
199
+
200
+ ## Step 5: Persist degraded-path patterns (AC-5)
201
+
202
+ <!-- @cap-todo(ac:F-071/AC-5) When Stage 2 didn't run for a candidate this session (LLM unavailable, network errors, outer agent didn't process the briefing), persist the heuristic-only L1 suggestion with degraded:true. -->
203
+
204
+ For each promotable candidate that **did not** receive a Stage 2 result during this session (i.e. no `.cap/learning/patterns/P-NNN.json` was written by the outer agent), call:
205
+
206
+ ```bash
207
+ node -e "
208
+ const pipeline = require('./cap/bin/lib/cap-pattern-pipeline.cjs');
209
+ const fs = require('node:fs');
210
+ const candidate = JSON.parse(process.argv[1]);
211
+ const id = process.argv[2];
212
+ pipeline.markDegraded(process.cwd(), id, candidate);
213
+ " '<CANDIDATE_JSON>' '<P_NNN>'
214
+ ```
215
+
216
+ Skip degraded persistence for candidates that are deferred to a future session — they're already represented by their queue entry.
217
+
218
+ ## Step 6.5: Refresh fitness scores (F-072 courtesy pass)
219
+
220
+ <!-- @cap-decision(F-072/D7) /cap:learn auto-refreshes fitness as a courtesy. Additive step (Step 6.5) — does NOT refactor Steps 0–6/7. F-073 / F-074 will read these records, so keeping them fresh after every learn invocation reduces "stale fitness" foot-guns. Cost is bounded by the F-072 perf probe (<500ms for 100 patterns × 1000 signals). -->
221
+
222
+ Run a fitness pass over every persisted pattern AND auto-mark expired ones (no usage over 20 sessions). The pass is idempotent: re-running yields the same per-pattern record (AC-7 determinism).
223
+
224
+ ```bash
225
+ node -e "
226
+ const fitness = require('./cap/bin/lib/cap-fitness-score.cjs');
227
+ const root = process.cwd();
228
+ const result = fitness.runFitnessPass(root);
229
+ console.log(JSON.stringify({
230
+ recorded: result.recorded.length,
231
+ expired: result.expired.length,
232
+ expiredIds: result.expired,
233
+ errors: result.errors,
234
+ }, null, 2));
235
+ "
236
+ ```
237
+
238
+ Surface in the Step 6 final report as `Fitness: {recorded} refreshed, {expired} marked expired`. Errors here are non-fatal — log them but do not fail the run; the pattern pipeline already wrote its outputs and the user shouldn't lose the run on a fitness-side hiccup.
239
+
240
+ ## Step 6: Final report
241
+
242
+ ```
243
+ cap:learn complete.
244
+
245
+ Session: {sessionId}
246
+ Budget: {budget} ({budgetSource}) · Used: {used} · Remaining (post-run): {remaining_post}
247
+
248
+ Stage 1: {stage1.candidates} candidates
249
+ Stage 2: {promoted} promoted via LLM, {degraded} persisted heuristic-only (degraded:true), {deferred} deferred to .cap/learning/queue/ (deferred:budget)
250
+
251
+ Patterns this run:
252
+ P-NNN: level={L1|L2|L3} source={llm|heuristic} confidence={0.0-1.0} feature={F-NNN}
253
+ ...
254
+
255
+ {If deferred > 0:}
256
+ Deferred briefings will be processed on the next /cap:learn invocation when budget is available.
257
+
258
+ {If errors:}
259
+ Errors:
260
+ - {error}
261
+ ```
262
+
263
+ ## Step 7: Update session
264
+
265
+ ```bash
266
+ node -e "
267
+ const session = require('./cap/bin/lib/cap-session.cjs');
268
+ session.updateSession(process.cwd(), {
269
+ lastCommand: '/cap:learn',
270
+ lastCommandTimestamp: new Date().toISOString(),
271
+ });
272
+ "
273
+ ```
274
+
275
+ </process>
276
+
277
+ ## Subcommand: `/cap:learn --unlearn P-NNN`
278
+
279
+ <!-- @cap-feature(feature:F-074) Pattern Unlearn — reverses an applied pattern, writes the unlearn audit, creates a `learn: unlearn P-NNN` commit. -->
280
+ <!-- @cap-todo(ac:F-074/AC-3) `/cap:learn unlearn <P-ID>` generates a reverse patch, applies it, and commits as `learn: unlearn P-NNN`. -->
281
+ <!-- @cap-todo(ac:F-074/AC-4) Writes the unlearn audit at .cap/learning/unlearned/P-NNN.json with reason + ts + commitHash. -->
282
+ <!-- @cap-todo(ac:F-074/AC-7) Idempotent — second invocation on already-unlearned P-NNN is a no-op. -->
283
+
284
+ When `$ARGUMENTS` contains `--unlearn P-NNN`, skip Steps 1–7 above and run this subcommand instead. The unlearn path is independent of Stage 1 / Stage 2 / fitness — it only reverses an already-applied pattern.
285
+
286
+ **Steps:**
287
+
288
+ 1. Parse the P-NNN id from `--unlearn P-NNN`. Validate it matches `^P-\d+$`. If not, abort with `invalid pattern id`.
289
+ 2. Call `unlearnPattern`:
290
+
291
+ ```bash
292
+ node -e "
293
+ const apply = require('./cap/bin/lib/cap-pattern-apply.cjs');
294
+ const id = process.argv[1];
295
+ const result = apply.unlearnPattern(process.cwd(), id, { reason: 'manual' });
296
+ console.log(JSON.stringify(result, null, 2));
297
+ " '<P_NNN>'
298
+ ```
299
+
300
+ 3. Report the outcome:
301
+ - `{ unlearned: true, commitHash, audit }` → log: `Unlearned P-NNN. Commit: <commitHash>. Audit: .cap/learning/unlearned/P-NNN.json`
302
+ - `{ unlearned: false, reason: 'already-unlearned', priorRecord }` → log: `P-NNN was already unlearned at <priorRecord.unlearnedAt>. No action.` (Idempotent — AC-7.)
303
+ - `{ unlearned: false, reason: 'l3-drift', commitHashToRevert }` → log: `Refusing to unlearn P-NNN — the L3 target file has drifted since apply. Resolve manually with: git revert <commitHashToRevert>`. Surface this prominently — the user must intervene.
304
+ - `{ unlearned: false, reason: 'apply-not-found' }` → log: `P-NNN was never applied. Nothing to unlearn.`
305
+ - `{ unlearned: false, reason: 'pending-hook-fail', error }` → log: `Pre-commit hook failed: <error>. The reverse patch is staged. Resolve and retry.`
306
+ 4. Update session (same as Step 7 above), but with `lastCommand: '/cap:learn --unlearn'`.
307
+
308
+ **Privacy contract — no signal data flows through this path.** Unlearn is pure git + file ops; F-074 never reads override / memory-ref / regret JSONLs during unlearn.
309
+
310
+ ## Subcommand: `/cap:learn --retract-check`
311
+
312
+ <!-- @cap-feature(feature:F-074) 5-session post-apply check — auto-flags patches whose Layer-1 override-rate worsens. -->
313
+ <!-- @cap-todo(ac:F-074/AC-5) For each applied pattern: when post-apply session count crosses 5, compare current Layer-1 to snapshot. If worse, append to retract-recommendations.jsonl. -->
314
+ <!-- @cap-todo(ac:F-074/AC-6) F-073 (review board, future) reads listRetractRecommended() and labels patterns "Rückzug empfohlen". -->
315
+
316
+ When `$ARGUMENTS` contains `--retract-check`, run the 5-session post-apply check:
317
+
318
+ ```bash
319
+ node -e "
320
+ const apply = require('./cap/bin/lib/cap-pattern-apply.cjs');
321
+ const result = apply.runRetractCheck(process.cwd());
322
+ console.log(JSON.stringify({
323
+ checked: result.checked.length,
324
+ recommended: result.recommended,
325
+ errors: result.errors,
326
+ }, null, 2));
327
+ "
328
+ ```
329
+
330
+ Surface in a final report:
331
+ - `Retract check: {checked} applied patterns scrutinised, {recommended.length} flagged for retraction.`
332
+ - For each recommended id: ` - <P-NNN> — Layer-1 worse than snapshot (see .cap/learning/retract-recommendations.jsonl).`
333
+ - Errors are non-fatal — log them but exit 0.
334
+
335
+ ## Subcommand: `/cap:learn review`
336
+
337
+ <!-- @cap-feature(feature:F-073) Pattern Review Board — gated user-facing review of pending patterns. -->
338
+ <!-- @cap-decision(F-073/D2) Briefing-pattern review UX (mirrors F-071's LLM Skill-Briefing): the skill renders board.md and INSTRUCTS the outer agent to call applyPattern / unlearnPattern / skipPattern / rejectPattern per pattern. NO interactive CLI. -->
339
+ <!-- @cap-decision(F-073/D4) Threshold gate: ≥1 high-confidence (layer2.ready=true AND value>=0.75 AND n>=5) OR ≥3 candidates of any kind. Below the gate, the skill exits 0 silently with "no review needed". -->
340
+ <!-- @cap-todo(ac:F-073/AC-1) Review board lists pending patterns (persisted ∧ ¬applied ∧ ¬unlearned ∧ ¬archived ∧ ¬skipped/rejected this session). -->
341
+ <!-- @cap-todo(ac:F-073/AC-2) Threshold gate: only show when high-confidence or any-kind threshold met. -->
342
+ <!-- @cap-todo(ac:F-073/AC-5) Stale-archive sweep before building the board: patterns un-reviewed > 7 sessions move to archive/. -->
343
+ <!-- @cap-todo(ac:F-073/AC-6) Per-pattern options: Approve / Reject / Skip [/ Unlearn when retract-recommended]. -->
344
+ <!-- @cap-todo(ac:F-073/AC-7) Approve → applyPattern; exit 0 ONLY when every approve produced applied:true. Any apply failure → non-zero exit + failure description. -->
345
+
346
+ When `$ARGUMENTS` contains `review` (and not `--unlearn` / `--retract-check`), run the review board flow. The review path is independent of Stage 1 / Stage 2 / fitness — it consumes already-persisted patterns + fitness + apply-state.
347
+
348
+ **Steps:**
349
+
350
+ 1. Compute the gate first — bail early if there's nothing to review.
351
+
352
+ ```bash
353
+ node -e "
354
+ const review = require('./cap/bin/lib/cap-learn-review.cjs');
355
+ const should = review.shouldShowBoard(process.cwd());
356
+ console.log(JSON.stringify({ shouldShow: should }));
357
+ "
358
+ ```
359
+
360
+ If `shouldShow === false`: log `cap:learn review — no review needed (threshold not met).` and exit 0.
361
+
362
+ 2. Sweep stale patterns to archive/ BEFORE rendering the board. This keeps the board free of patterns the user has long since drifted past.
363
+
364
+ ```bash
365
+ node -e "
366
+ const review = require('./cap/bin/lib/cap-learn-review.cjs');
367
+ const result = review.archiveStalePatterns(process.cwd());
368
+ console.log(JSON.stringify({ archived: result.archived, errors: result.errors }, null, 2));
369
+ "
370
+ ```
371
+
372
+ Surface `Archived stale patterns: {archived.length}` and forward the ids in the final report. Errors are non-fatal — log them but continue.
373
+
374
+ 3. Build + render + write the board.
375
+
376
+ ```bash
377
+ node -e "
378
+ const review = require('./cap/bin/lib/cap-learn-review.cjs');
379
+ const root = process.cwd();
380
+ const board = review.buildReviewBoard(root);
381
+ const md = review.renderBoardMarkdown(board);
382
+ const ok = review.writeBoardFile(root, md);
383
+ console.log(JSON.stringify({
384
+ written: ok,
385
+ eligible: board.eligible.length,
386
+ thresholdMet: board.threshold.met,
387
+ thresholdReason: board.threshold.reason,
388
+ }, null, 2));
389
+ "
390
+ ```
391
+
392
+ Log: `Board written to .cap/learning/board.md ({eligible} patterns).`
393
+
394
+ 4. **Hand off to the outer agent.** Read `.cap/learning/board.md`. For each pattern listed there, decide ONE of approve / reject / skip / unlearn:
395
+
396
+ - **approve** → call `cap-pattern-apply.applyPattern(projectRoot, patternId)`. Capture `result.commitHash` and `result.applied`. **If `applied !== true`, the skill MUST surface the failure and exit non-zero (F-073/AC-7).** Do not retry silently. The failure reason is `result.reason` (e.g. `'pending-hook-fail'`, `'l3-target-not-allowed'`).
397
+ - **unlearn** → call `cap-pattern-apply.unlearnPattern(projectRoot, patternId, { reason: 'manual' })`. Surface drift / refusal cases as documented in `--unlearn` above.
398
+ - **skip** → call `cap-learn-review.skipPattern(projectRoot, patternId)`. Per-session only — a new session re-shows the pattern.
399
+ - **reject** → call `cap-learn-review.rejectPattern(projectRoot, patternId)`.
400
+
401
+ Example single-pattern call (the agent inlines these per pattern):
402
+
403
+ ```bash
404
+ node -e "
405
+ const apply = require('./cap/bin/lib/cap-pattern-apply.cjs');
406
+ const id = process.argv[1];
407
+ const result = apply.applyPattern(process.cwd(), id);
408
+ console.log(JSON.stringify(result, null, 2));
409
+ if (result.applied !== true) process.exit(1);
410
+ " '<P_NNN>'
411
+ ```
412
+
413
+ ```bash
414
+ node -e "
415
+ const review = require('./cap/bin/lib/cap-learn-review.cjs');
416
+ const id = process.argv[1];
417
+ const ok = review.skipPattern(process.cwd(), id);
418
+ console.log(JSON.stringify({ skipped: ok }));
419
+ " '<P_NNN>'
420
+ ```
421
+
422
+ 5. **Exit-code propagation (F-073/AC-7).** If ANY approve action returned `applied !== true`, exit non-zero with a structured report:
423
+
424
+ ```
425
+ cap:learn review — apply failures detected:
426
+ - P-001: applied=false, reason=pending-hook-fail
427
+ - P-007: applied=false, reason=l3-target-not-allowed
428
+ ```
429
+
430
+ Exit 0 only when every approve produced `applied:true`. Skip / reject / unlearn outcomes do NOT affect the exit code (they're not gated by AC-7).
431
+
432
+ 6. After the board has been processed, clear the pending flag.
433
+
434
+ ```bash
435
+ node -e "
436
+ const review = require('./cap/bin/lib/cap-learn-review.cjs');
437
+ review.clearBoardPendingFlag(process.cwd());
438
+ "
439
+ ```
440
+
441
+ 7. Final report:
442
+
443
+ ```
444
+ cap:learn review complete.
445
+
446
+ Eligible: {eligible}
447
+ Approved: {n} (commits: {hashes})
448
+ Skipped: {n}
449
+ Rejected: {n}
450
+ Unlearned: {n}
451
+ Archived (stale): {n}
452
+
453
+ {If any apply failed:}
454
+ ✗ Apply failures: {list} (exit non-zero)
455
+ ```
456
+
457
+ 8. Update session (same as Step 7 in the main flow), but with `lastCommand: '/cap:learn review'`.
458
+
459
+ **Privacy contract.** The board contains only structured metadata — counts, hashes, ids, fitness numbers. No raw paths, no decision text, no record verbatim. The Stop-hook (`hooks/cap-learn-review-hook.js`) flags pending reviews via `.cap/learning/board-pending.flag`; it never spawns the skill itself.