@wooojin/forgen 0.4.13 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/CHANGELOG.md +94 -0
  3. package/README.ja.md +4 -4
  4. package/README.md +89 -27
  5. package/README.zh.md +4 -4
  6. package/assets/claude/commands/forge-loop.md +7 -1
  7. package/assets/claude/commands/ship.md +18 -1
  8. package/assets/opencode/forgen.ts +52 -0
  9. package/dist/checks/_shared/meta-guard-dispatch.d.ts +7 -0
  10. package/dist/checks/_shared/meta-guard-dispatch.js +12 -2
  11. package/dist/checks/_shared/model-profile.d.ts +25 -0
  12. package/dist/checks/_shared/model-profile.js +63 -0
  13. package/dist/cli.js +99 -153
  14. package/dist/core/auto-compound-runner.d.ts +0 -11
  15. package/dist/core/auto-compound-runner.js +127 -79
  16. package/dist/core/compound-consent.d.ts +15 -0
  17. package/dist/core/compound-consent.js +48 -0
  18. package/dist/core/compound-sweep-cli.d.ts +57 -0
  19. package/dist/core/compound-sweep-cli.js +354 -0
  20. package/dist/core/config-injector.d.ts +16 -1
  21. package/dist/core/config-injector.js +47 -28
  22. package/dist/core/dashboard-cli.js +40 -16
  23. package/dist/core/dashboard.d.ts +3 -4
  24. package/dist/core/dashboard.js +15 -34
  25. package/dist/core/dev-cli.d.ts +13 -0
  26. package/dist/core/dev-cli.js +70 -0
  27. package/dist/core/doctor.d.ts +16 -5
  28. package/dist/core/doctor.js +161 -176
  29. package/dist/core/drift-score.d.ts +2 -0
  30. package/dist/core/drift-score.js +9 -1
  31. package/dist/core/harness.js +115 -43
  32. package/dist/core/health-cli.d.ts +2 -0
  33. package/dist/core/health-cli.js +6 -1
  34. package/dist/core/host-detect.d.ts +3 -1
  35. package/dist/core/host-detect.js +26 -1
  36. package/dist/core/migrate-cli.js +15 -0
  37. package/dist/core/migrate-evidence-host.d.ts +2 -1
  38. package/dist/core/migrate-tenetx.d.ts +50 -0
  39. package/dist/core/migrate-tenetx.js +262 -0
  40. package/dist/core/probe-workflow-cli.d.ts +3 -3
  41. package/dist/core/probe-workflow-cli.js +13 -13
  42. package/dist/core/recall-cli.js +1 -1
  43. package/dist/core/regress-map-cli.js +1 -1
  44. package/dist/core/rendered-rules-manifest.d.ts +29 -0
  45. package/dist/core/rendered-rules-manifest.js +60 -0
  46. package/dist/core/session-store.js +14 -3
  47. package/dist/core/settings-injector.d.ts +3 -0
  48. package/dist/core/settings-injector.js +12 -16
  49. package/dist/core/spawn.d.ts +11 -1
  50. package/dist/core/spawn.js +79 -7
  51. package/dist/core/state-gc.js +1 -0
  52. package/dist/core/status-cli.d.ts +20 -0
  53. package/dist/core/status-cli.js +100 -0
  54. package/dist/core/statusline-cli.d.ts +7 -0
  55. package/dist/core/statusline-cli.js +63 -19
  56. package/dist/core/transcript-summary.d.ts +18 -0
  57. package/dist/core/transcript-summary.js +81 -0
  58. package/dist/core/trust-layer-intent.d.ts +21 -1
  59. package/dist/core/trust-layer-intent.js +7 -0
  60. package/dist/core/types.d.ts +3 -2
  61. package/dist/core/uninstall.js +12 -0
  62. package/dist/core/usage-telemetry.d.ts +7 -1
  63. package/dist/core/usage-telemetry.js +7 -9
  64. package/dist/core/v1-bootstrap.js +1 -1
  65. package/dist/core/watch-cli.js +1 -1
  66. package/dist/engine/compound-extractor.js +10 -0
  67. package/dist/engine/compound-loop.js +35 -6
  68. package/dist/engine/compound-share.d.ts +85 -0
  69. package/dist/engine/compound-share.js +606 -0
  70. package/dist/engine/correction-cluster-runner.d.ts +38 -0
  71. package/dist/engine/correction-cluster-runner.js +188 -0
  72. package/dist/engine/correction-clustering.d.ts +80 -0
  73. package/dist/engine/correction-clustering.js +167 -0
  74. package/dist/engine/enforce-classifier.d.ts +10 -1
  75. package/dist/engine/enforce-classifier.js +111 -22
  76. package/dist/engine/extraction-session.js +10 -3
  77. package/dist/engine/private-filter.d.ts +36 -0
  78. package/dist/engine/private-filter.js +100 -0
  79. package/dist/engine/ranking-pipeline.js +4 -2
  80. package/dist/engine/relevance-gate.d.ts +12 -0
  81. package/dist/engine/relevance-gate.js +12 -0
  82. package/dist/engine/roi-demotion.d.ts +79 -0
  83. package/dist/engine/roi-demotion.js +159 -0
  84. package/dist/engine/solution-format.d.ts +1 -0
  85. package/dist/engine/solution-format.js +26 -0
  86. package/dist/engine/solution-matcher.js +10 -1
  87. package/dist/fgx.js +7 -6
  88. package/dist/forge/cli.js +8 -2
  89. package/dist/hooks/compound-reflection.js +6 -1
  90. package/dist/hooks/context-guard.d.ts +16 -1
  91. package/dist/hooks/context-guard.js +92 -46
  92. package/dist/hooks/post-tool-use.js +2 -3
  93. package/dist/hooks/pre-compact.js +14 -0
  94. package/dist/hooks/pre-tool-use.js +5 -1
  95. package/dist/hooks/shared/stop-triggers.d.ts +29 -2
  96. package/dist/hooks/shared/stop-triggers.js +35 -2
  97. package/dist/hooks/solution-injector.d.ts +28 -0
  98. package/dist/hooks/solution-injector.js +126 -28
  99. package/dist/hooks/stop-guard.js +5 -2
  100. package/dist/hooks/subagent-stop-guard.js +4 -1
  101. package/dist/host/capabilities-claude.js +1 -0
  102. package/dist/host/capabilities-codex.js +1 -0
  103. package/dist/host/capabilities-opencode.d.ts +26 -0
  104. package/dist/host/capabilities-opencode.js +78 -0
  105. package/dist/host/capabilities-registry.d.ts +7 -0
  106. package/dist/host/capabilities-registry.js +14 -0
  107. package/dist/host/exec-host.d.ts +4 -3
  108. package/dist/host/exec-host.js +2 -0
  109. package/dist/host/host-binding.d.ts +27 -0
  110. package/dist/host/host-binding.js +11 -0
  111. package/dist/host/host-runtime.js +18 -0
  112. package/dist/host/install-codex.d.ts +8 -0
  113. package/dist/host/install-codex.js +2 -2
  114. package/dist/host/install-opencode.d.ts +38 -0
  115. package/dist/host/install-opencode.js +148 -0
  116. package/dist/host/install-orchestrator.d.ts +4 -1
  117. package/dist/host/install-orchestrator.js +20 -1
  118. package/dist/host/invoke-agent.d.ts +3 -2
  119. package/dist/host/opencode/context-cli.d.ts +15 -0
  120. package/dist/host/opencode/context-cli.js +25 -0
  121. package/dist/host/opencode/guard-cli.d.ts +13 -0
  122. package/dist/host/opencode/guard-cli.js +39 -0
  123. package/dist/host/opencode/plugin/forgen.d.ts +31 -0
  124. package/dist/host/opencode/plugin/forgen.js +60 -0
  125. package/dist/host/opencode/translate.d.ts +49 -0
  126. package/dist/host/opencode/translate.js +96 -0
  127. package/dist/host/parity-harness.d.ts +10 -2
  128. package/dist/host/projection.js +11 -0
  129. package/dist/mcp/tools.js +17 -4
  130. package/dist/store/evidence-store.d.ts +2 -6
  131. package/dist/store/evidence-store.js +68 -14
  132. package/dist/store/host-mismatch.d.ts +2 -1
  133. package/dist/store/host-mismatch.js +8 -8
  134. package/dist/store/profile-store.d.ts +3 -2
  135. package/dist/store/types.d.ts +9 -2
  136. package/package.json +3 -2
  137. package/plugin.json +2 -2
  138. package/skills/forge-loop/SKILL.md +7 -1
  139. package/skills/ship/SKILL.md +18 -1
package/dist/cli.js CHANGED
@@ -20,7 +20,7 @@ const runtime = launchContext.runtime;
20
20
  const commands = [
21
21
  {
22
22
  name: 'forge',
23
- description: 'Personalization profile (--profile|--export|--reset)',
23
+ description: 'Personalization single entry (--onboarding|--profile|--export|--reset)',
24
24
  handler: async (args) => {
25
25
  const { handleForge } = await import('./forge/cli.js');
26
26
  await handleForge(args);
@@ -28,8 +28,31 @@ const commands = [
28
28
  },
29
29
  {
30
30
  name: 'compound',
31
- description: 'Preview/save compound insights and manage accumulated knowledge',
31
+ description: 'Preview/save compound insights and manage accumulated knowledge (subcmd: sweep)',
32
32
  handler: async (args) => {
33
+ // ADR-011: 시간-기반 compound backstop. cron 에서 `forgen compound sweep` 호출.
34
+ if (args[0] === 'sweep') {
35
+ const { compoundSweepCli } = await import('./core/compound-sweep-cli.js');
36
+ compoundSweepCli(args.slice(1));
37
+ return;
38
+ }
39
+ // ADR-012: Haiku 추출 동의 토글. `forgen compound consent on|off|status`
40
+ if (args[0] === 'consent') {
41
+ const { getHaikuConsentState, setHaikuCompoundConsent } = await import('./core/compound-consent.js');
42
+ const sub = args[1];
43
+ if (sub === 'on' || sub === 'off') {
44
+ setHaikuCompoundConsent(sub === 'on');
45
+ console.log(`[forgen] auto-compound Haiku 추출: ${sub === 'on' ? '활성(ON)' : '비활성(OFF)'}. (결정론 룰 승급은 항상 동작)`);
46
+ }
47
+ else {
48
+ const s = getHaikuConsentState();
49
+ console.log(`[forgen] auto-compound Haiku 추출: ${s.enabled ? 'ON' : 'OFF'} (source: ${s.source})\n` +
50
+ ' ON = 세션 요약을 Haiku 로 전송해 행동패턴 추론 (본인 쿼터, redaction 적용)\n' +
51
+ ' OFF = 결정론 교정→룰 승급만 (egress 0, 입증된 δ 경로는 유지)\n' +
52
+ ' 변경: forgen compound consent on|off (env: FORGEN_AUTO_COMPOUND=1 / FORGEN_NO_AUTO_COMPOUND=1)');
53
+ }
54
+ return;
55
+ }
33
56
  const { handleCompound } = await import('./engine/compound-loop.js');
34
57
  await handleCompound(args);
35
58
  },
@@ -72,11 +95,11 @@ const commands = [
72
95
  },
73
96
  },
74
97
  {
75
- name: 'dashboard',
76
- description: 'Compound system dashboard with rich overview',
77
- handler: async (_args) => {
78
- const { handleDashboard } = await import('./core/dashboard.js');
79
- await handleDashboard();
98
+ name: 'status',
99
+ description: 'Unified status: forgen status [--compound|--profile|--rules|--blocks [N]|--overview|--live]',
100
+ handler: async (args) => {
101
+ const { handleStatus } = await import('./core/status-cli.js');
102
+ await handleStatus(args);
80
103
  },
81
104
  },
82
105
  {
@@ -87,14 +110,6 @@ const commands = [
87
110
  await handleLearn(args);
88
111
  },
89
112
  },
90
- {
91
- name: 'me',
92
- description: 'Personal dashboard (→ inspect profile)',
93
- handler: async (_args) => {
94
- const { handleInspect } = await import('./core/inspect-cli.js');
95
- await handleInspect(['profile']);
96
- },
97
- },
98
113
  {
99
114
  name: 'statusline',
100
115
  description: 'Compact HUD for Claude Code statusLine (reads stdin JSON)',
@@ -137,7 +152,7 @@ const commands = [
137
152
  const { setDefaultHost } = await import('./store/profile-store.js');
138
153
  const ok = setDefaultHost(value);
139
154
  if (!ok) {
140
- console.log(' ✗ Profile not found. Run `forgen onboarding` first.');
155
+ console.log(' ✗ Profile not found. Run `forgen forge --onboarding` first.');
141
156
  process.exit(1);
142
157
  }
143
158
  console.log(` ✓ default_host set to: ${value}`);
@@ -166,12 +181,12 @@ const commands = [
166
181
  },
167
182
  {
168
183
  name: 'install',
169
- description: 'Install forgen into a host. Usage: forgen install [claude|codex|both] [--dry-run] [--no-mcp]',
184
+ description: 'Install forgen into a host. Usage: forgen install [claude|codex|opencode|both] [--dry-run] [--no-mcp]',
170
185
  handler: async (args) => {
171
- const knownSubs = new Set(['claude', 'codex', 'both']);
186
+ const knownSubs = new Set(['claude', 'codex', 'opencode', 'both']);
172
187
  const target = args[0] && knownSubs.has(args[0]) ? args[0] : args[0]?.startsWith('--') ? undefined : args[0];
173
188
  if (target !== undefined && !knownSubs.has(target)) {
174
- console.log('Usage:\n forgen install [claude|codex|both] [--dry-run] [--no-mcp]\n\n No arg → interactive 3-choice (Claude/Codex/Both).');
189
+ console.log('Usage:\n forgen install [claude|codex|opencode|both] [--dry-run] [--no-mcp]\n\n No arg → interactive 3-choice (Claude/Codex/Both). opencode: 명시 타겟(P1 실험적).');
175
190
  return;
176
191
  }
177
192
  const dryRun = args.includes('--dry-run');
@@ -186,18 +201,6 @@ const commands = [
186
201
  console.log(renderResult(result, dryRun));
187
202
  },
188
203
  },
189
- {
190
- name: 'status',
191
- description: 'Observability dashboard (--watch, --json, --interval N)',
192
- handler: async (args) => {
193
- const { runDashboard } = await import('./core/dashboard-cli.js');
194
- const watch = args.includes('--watch');
195
- const json = args.includes('--json');
196
- const intervalIdx = args.indexOf('--interval');
197
- const intervalSec = intervalIdx !== -1 ? Number(args[intervalIdx + 1]) || 5 : 5;
198
- await runDashboard({ watch, json, intervalSec });
199
- },
200
- },
201
204
  {
202
205
  name: 'maintenance',
203
206
  description: 'Maintenance utilities (--backfill [--phase A|B|all] [--force] [--dry-run])',
@@ -229,28 +232,11 @@ const commands = [
229
232
  },
230
233
  },
231
234
  {
232
- name: 'parity',
233
- description: 'Run host parity checks. Usage: forgen parity codex [--dry-run]',
235
+ name: 'dev',
236
+ description: 'Developer/maintenance utilities: dev <probe-workflow|parity|migrate|regress-map>',
234
237
  handler: async (args) => {
235
- const sub = args[0];
236
- if (sub !== 'codex') {
237
- console.log('Usage:\n forgen parity codex [--dry-run]\n\nNotes:\n - source 체크아웃에서만 작동합니다 (tests/ 디렉토리 필요).\n - npm install 로 설치된 패키지에서는 run-parity.sh 가 없습니다.');
238
- return;
239
- }
240
- const here = path.dirname(fileURLToPath(import.meta.url));
241
- const scriptPath = path.resolve(here, '..', 'tests', 'e2e', 'codex', 'run-parity.sh');
242
- if (!fs.existsSync(scriptPath)) {
243
- console.error('[forgen] run-parity.sh 는 source 체크아웃에서만 작동. 직접 git clone 후 실행하세요.');
244
- console.error(` expected: ${scriptPath}`);
245
- process.exit(1);
246
- }
247
- const { spawnSync } = await import('node:child_process');
248
- const dryRun = args.includes('--dry-run');
249
- const spawnArgs = dryRun ? ['--dry-run'] : [];
250
- const result = spawnSync('bash', [scriptPath, ...spawnArgs], { stdio: 'inherit' });
251
- if (result.status !== 0) {
252
- process.exit(result.status ?? 1);
253
- }
238
+ const { handleDev } = await import('./core/dev-cli.js');
239
+ await handleDev(args);
254
240
  },
255
241
  },
256
242
  {
@@ -269,23 +255,17 @@ const commands = [
269
255
  await handleInspect(args);
270
256
  },
271
257
  },
272
- {
273
- name: 'onboarding',
274
- description: 'v1 4-question onboarding flow',
275
- handler: async (_args) => {
276
- const { runOnboarding } = await import('./forge/onboarding-cli.js');
277
- await runOnboarding();
278
- },
279
- },
280
258
  {
281
259
  name: 'doctor',
282
- description: 'Diagnostics (--quick for fast check, --prune-state to GC, --repair to auto-fix)',
260
+ description: 'Diagnostics (--quick fast check, --prune-state GC, --repair auto-fix, --reclaim legacy-rules scan)',
283
261
  handler: async (args) => {
284
262
  const { runDoctor } = await import('./core/doctor.js');
285
263
  await runDoctor({
286
264
  pruneState: args.includes('--prune-state'),
287
265
  repair: args.includes('--repair'),
288
266
  quick: args.includes('--quick'),
267
+ reclaim: args.includes('--reclaim'),
268
+ verbose: args.includes('--verbose'),
289
269
  });
290
270
  },
291
271
  },
@@ -334,38 +314,6 @@ const commands = [
334
314
  await handleLifecycleScan(args);
335
315
  },
336
316
  },
337
- {
338
- name: 'stats',
339
- description: 'One-screen dashboard: active rules, corrections, blocks/bypass/drift (7d).',
340
- handler: async (args) => {
341
- const { handleStats } = await import('./core/stats-cli.js');
342
- await handleStats(args);
343
- },
344
- },
345
- {
346
- name: 'watch',
347
- description: 'Real-time hook event stream (hook firings, blocks, solution matches)',
348
- handler: async () => {
349
- const { handleWatch } = await import('./core/watch-cli.js');
350
- await handleWatch();
351
- },
352
- },
353
- {
354
- name: 'health',
355
- description: 'Single-line health score (0-100) combining utilization, effectiveness, growth.',
356
- handler: async () => {
357
- const { handleHealth } = await import('./core/health-cli.js');
358
- await handleHealth();
359
- },
360
- },
361
- {
362
- name: 'probe-workflow',
363
- description: 'ADR-009 §1: measure whether dynamic-workflow subagents fire forgen hooks (arm|report|status).',
364
- handler: async (args) => {
365
- const { handleProbeWorkflow } = await import('./core/probe-workflow-cli.js');
366
- await handleProbeWorkflow(args);
367
- },
368
- },
369
317
  {
370
318
  name: 'workflows',
371
319
  description: 'Install/list forgen dynamic-workflow templates (install [--project] | list).',
@@ -374,14 +322,6 @@ const commands = [
374
322
  await handleWorkflows(args);
375
323
  },
376
324
  },
377
- {
378
- name: 'explain',
379
- description: 'Explain the most recent block — what rule, why, and how to resolve.',
380
- handler: async (args) => {
381
- const { handleExplain } = await import('./core/explain-cli.js');
382
- await handleExplain(args);
383
- },
384
- },
385
325
  {
386
326
  name: 'changelog',
387
327
  description: 'Auto-summarize changes since last release tag (conventional commits).',
@@ -390,38 +330,6 @@ const commands = [
390
330
  await handleChangelog();
391
331
  },
392
332
  },
393
- {
394
- name: 'last-block',
395
- description: 'Show the most recent Mech-A/B block event with rule detail (R6-UX2).',
396
- handler: async (_args) => {
397
- const { handleInspect } = await import('./core/inspect-cli.js');
398
- await handleInspect(['violations', '--last', '1']);
399
- },
400
- },
401
- {
402
- name: 'recall',
403
- description: 'Show recent compound recalls (matched solutions) with optional body preview.',
404
- handler: async (args) => {
405
- const { handleRecall } = await import('./core/recall-cli.js');
406
- await handleRecall(args);
407
- },
408
- },
409
- {
410
- name: 'migrate',
411
- description: 'One-shot schema migrations (implicit-feedback category backfill).',
412
- handler: async (args) => {
413
- const { handleMigrate } = await import('./core/migrate-cli.js');
414
- await handleMigrate(args);
415
- },
416
- },
417
- {
418
- name: 'regress-map',
419
- description: 'Top fix-touched files in the last N days (--days 30 --top 10 --json).',
420
- handler: async (args) => {
421
- const { handleRegressMap } = await import('./core/regress-map-cli.js');
422
- await handleRegressMap(args);
423
- },
424
- },
425
333
  {
426
334
  name: 'suppress-rule',
427
335
  description: '[alias: rule suppress] Disable a rule by id/prefix. Hard rules refused.',
@@ -460,6 +368,7 @@ async function handleRuleNamespace(args) {
460
368
  forgen rule health-scan [--apply] Scan drift → Mech downgrade candidates
461
369
  forgen rule classify [--apply] [--force]
462
370
  Propose enforce_via for legacy rules
371
+ forgen rule unmerge-cluster <id> Undo a W3-2 correction-cluster merge (restore originals)
463
372
  `);
464
373
  return;
465
374
  }
@@ -494,6 +403,24 @@ async function handleRuleNamespace(args) {
494
403
  await handleClassifyEnforce(rest);
495
404
  return;
496
405
  }
406
+ case 'unmerge-cluster': {
407
+ // W3-2: 교정 클러스터 통합 취소 — 원본 룰 복원 + 재통합 억제.
408
+ const mergedId = rest[0];
409
+ if (!mergedId) {
410
+ console.error('[forgen] usage: forgen rule unmerge-cluster <merged-rule-id>');
411
+ process.exit(1);
412
+ }
413
+ const { unmergeCluster } = await import('./engine/correction-cluster-runner.js');
414
+ const res = unmergeCluster(mergedId);
415
+ if (res.ok) {
416
+ console.log(`✓ [forgen] 클러스터 통합 취소 — 원본 ${res.restored.length}룰 복원 (재통합 억제됨)`);
417
+ }
418
+ else {
419
+ console.error(`[forgen] unmerge 실패: ${res.reason}`);
420
+ process.exit(1);
421
+ }
422
+ return;
423
+ }
497
424
  default: {
498
425
  console.error(`[forgen] Unknown rule subcommand: ${sub}\n Run "forgen rule help" for options.`);
499
426
  process.exit(1);
@@ -532,6 +459,18 @@ async function main() {
532
459
  console.log(PKG_VERSION);
533
460
  return;
534
461
  }
462
+ // W3-3: OpenCode plugin 슬림이 per-tool-call 로 호출하는 경량 브릿지 (heavy init 우회).
463
+ if (args[0] === 'opencode-guard') {
464
+ const { runOpencodeGuard } = await import('./host/opencode/guard-cli.js');
465
+ await runOpencodeGuard();
466
+ return;
467
+ }
468
+ // W3-3: OpenCode plugin 이 compaction 시 주입할 forgen context (forge-loop 상태) 출력.
469
+ if (args[0] === 'opencode-context') {
470
+ const { runOpencodeContext } = await import('./host/opencode/context-cli.js');
471
+ runOpencodeContext();
472
+ return;
473
+ }
535
474
  const cmd = findCommand(args[0]);
536
475
  if (cmd) {
537
476
  await cmd.handler(args.slice(1));
@@ -540,11 +479,24 @@ async function main() {
540
479
  // 등록되지 않은 서브커맨드는 에러 처리
541
480
  // 플래그(--resume 등), 따옴표 프롬프트, 인자 없는 실행은 하네스로 통과
542
481
  if (args[0] && !args[0].startsWith('-') && !args[0].startsWith('"') && !args[0].startsWith("'")) {
543
- const suggestion = commands
544
- .map(c => ({ name: c.name, dist: levenshtein(args[0], c.name) }))
545
- .filter(c => c.dist <= 3)
546
- .sort((a, b) => a.dist - b.dist)[0];
547
- const hint = suggestion ? `\n Did you mean: forgen ${suggestion.name}` : '';
482
+ // Wave 1 통합(feature-audit): 제거된 명령 → 새 위치 명시 매핑 (levenshtein 오유도 방지).
483
+ const RENAMED = {
484
+ stats: 'status', health: 'status', dashboard: 'status --overview', me: 'status --profile',
485
+ recall: 'status --compound', explain: 'status --blocks', 'last-block': 'status --blocks',
486
+ watch: 'status --live', 'probe-workflow': 'dev probe-workflow', parity: 'dev parity',
487
+ migrate: 'dev migrate', 'regress-map': 'dev regress-map', onboarding: 'forge --onboarding',
488
+ };
489
+ let hint;
490
+ if (RENAMED[args[0]]) {
491
+ hint = `\n → moved: forgen ${RENAMED[args[0]]}`;
492
+ }
493
+ else {
494
+ const suggestion = commands
495
+ .map(c => ({ name: c.name, dist: levenshtein(args[0], c.name) }))
496
+ .filter(c => c.dist <= 3)
497
+ .sort((a, b) => a.dist - b.dist)[0];
498
+ hint = suggestion ? `\n Did you mean: forgen ${suggestion.name}` : '';
499
+ }
548
500
  console.error(`[forgen] Unknown command: ${args[0]}${hint}\n Run "forgen help" for available commands.`);
549
501
  process.exit(1);
550
502
  }
@@ -621,28 +573,22 @@ function printHelp() {
621
573
  forgen --runtime claude|codex Select launch runtime
622
574
 
623
575
  Commands:
624
- forgen forge Personalize your coding profile
625
- forgen onboarding Run 4-question onboarding
576
+ forgen forge [--onboarding|--profile|--reset]
577
+ Personalization single entry (first run = 4-question onboarding)
626
578
  forgen inspect [profile|rules|corrections|session]
627
579
  Inspect v1 state (alias: evidence → corrections)
628
580
  forgen rule <list|suppress|activate|scan|health-scan|classify>
629
581
  Rule management (see: forgen rule help)
630
- forgen stats One-screen trust-layer dashboard (+ philosophy)
631
- forgen health Single-line health score (0-100) with grade
632
- forgen probe-workflow arm|report Measure if dynamic-workflow subagents fire hooks (ADR-009 §1)
582
+ forgen status [view] Unified status — one screen; views:
583
+ --compound compound health + recent recalls
584
+ --profile 4-axis profile + recent corrections
585
+ --rules active rules
586
+ --blocks [N] recent block(s): rule/reason/fix
587
+ --overview rich dashboard (hooks·history·curve)
588
+ --live real-time hook event stream
633
589
  forgen workflows install|list Install forgen dynamic-workflow templates to .claude/workflows/
634
- forgen watch Real-time hook event stream (tail logs live)
635
- forgen explain [N] Explain the last N block(s) — rule, reason, resolution
636
590
  forgen changelog Auto-summarize commits since last release tag
637
- forgen last-block Show the most recent block event
638
- forgen recall [--limit N] [--show]
639
- 최근 compound 주입 이력 (solution body preview)
640
- forgen migrate [implicit-feedback|evidence-host|all]
641
- One-shot schema migration (category backfill / host backfill)
642
- forgen parity codex [--dry-run] Run codex parity checks (source checkout only)
643
591
  forgen compound Manage accumulated knowledge
644
- forgen dashboard Compound system dashboard
645
- forgen me Personal dashboard
646
592
  forgen init Initialize project (+ starter-pack solutions)
647
593
  forgen config hooks Hook management
648
594
  forgen mcp MCP server management
@@ -10,15 +10,4 @@
10
10
  * 인자: [cwd] [transcriptPath] [sessionId]
11
11
  */
12
12
  import { type ExecFileOptions } from 'node:child_process';
13
- /**
14
- * 0.4.6 perf #12 — async 변형. 3 LLM 호출 (solution / user-pattern / learning) 을
15
- * Promise.allSettled 로 병렬 실행하여 wall-clock 을 sum → max 로 단축 (~3x).
16
- *
17
- * 0.4.6 에서는 adaptive cooldown 으로 wasted runs 차단을 우선 적용했고, 호출부
18
- * full parallelization 은 0.4.7 로 분리 (refactor surface 큼 — solution call 의
19
- * `--allowedTools` sandbox 와 file-write 순서 invariant 검증 필요).
20
- *
21
- * 본 함수는 0.4.7 작업의 foundation 으로 박제 — export 하여 unused warning 회피.
22
- * 동작은 sync 버전과 동일: Claude/Codex 분기 + retry on transient.
23
- */
24
13
  export declare function execClaudeRetryAsync(args: string[], opts: ExecFileOptions): Promise<string>;