@wooojin/forgen 0.4.1 → 0.4.4

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 (151) hide show
  1. package/.claude-plugin/plugin.json +5 -5
  2. package/CHANGELOG.md +267 -15
  3. package/CONTRIBUTING.md +2 -2
  4. package/README.ja.md +17 -9
  5. package/README.ko.md +34 -12
  6. package/README.md +65 -12
  7. package/README.zh.md +17 -9
  8. package/assets/README.md +86 -0
  9. package/assets/architecture.svg +100 -0
  10. package/assets/banner.png +0 -0
  11. package/assets/banner.svg +53 -0
  12. package/{commands → assets/claude/commands}/calibrate.md +4 -3
  13. package/{commands → assets/claude/commands}/retro.md +2 -2
  14. package/assets/demo/01-install.gif +0 -0
  15. package/assets/demo/01-install.tape +54 -0
  16. package/assets/demo/02-compound-learning.gif +0 -0
  17. package/assets/demo/02-compound-learning.tape +50 -0
  18. package/assets/demo/03-forge-personalization.gif +0 -0
  19. package/assets/demo/03-forge-personalization.tape +64 -0
  20. package/assets/demo/before-after.gif +0 -0
  21. package/assets/demo/before-after.tape +98 -0
  22. package/assets/demo-preview.svg +96 -0
  23. package/assets/icon.png +0 -0
  24. package/{hooks → assets/shared}/hook-registry.json +2 -1
  25. package/dist/checks/_shared/text-sanitizer.d.ts +21 -0
  26. package/dist/checks/_shared/text-sanitizer.js +60 -0
  27. package/dist/checks/dangerous-response-pattern.d.ts +32 -0
  28. package/dist/checks/dangerous-response-pattern.js +65 -0
  29. package/dist/checks/fact-vs-agreement.js +25 -1
  30. package/dist/cli.js +78 -6
  31. package/dist/core/auto-compound-runner.js +90 -39
  32. package/dist/core/behavior-classifier.d.ts +28 -0
  33. package/dist/core/behavior-classifier.js +46 -0
  34. package/dist/core/dashboard.d.ts +7 -0
  35. package/dist/core/dashboard.js +32 -0
  36. package/dist/core/doctor.js +92 -0
  37. package/dist/core/git-stats.d.ts +36 -0
  38. package/dist/core/git-stats.js +79 -0
  39. package/dist/core/harness.d.ts +1 -1
  40. package/dist/core/harness.js +27 -20
  41. package/dist/core/host-detect.d.ts +42 -0
  42. package/dist/core/host-detect.js +68 -0
  43. package/dist/core/installer.js +2 -2
  44. package/dist/core/migrate-cli.d.ts +1 -0
  45. package/dist/core/migrate-cli.js +19 -0
  46. package/dist/core/migrate-evidence-host.d.ts +36 -0
  47. package/dist/core/migrate-evidence-host.js +49 -0
  48. package/dist/core/settings-injector.js +4 -2
  49. package/dist/core/spawn.d.ts +1 -1
  50. package/dist/core/spawn.js +4 -11
  51. package/dist/core/stats-cli.js +12 -0
  52. package/dist/core/trust-layer-intent.d.ts +35 -0
  53. package/dist/core/trust-layer-intent.js +30 -0
  54. package/dist/core/types.d.ts +1 -1
  55. package/dist/engine/compound-extractor.js +7 -9
  56. package/dist/engine/learn-cli.js +4 -2
  57. package/dist/engine/lifecycle/bypass-detector.d.ts +6 -1
  58. package/dist/engine/lifecycle/bypass-detector.js +57 -5
  59. package/dist/fgx.js +2 -1
  60. package/dist/forge/evidence-processor.js +12 -0
  61. package/dist/forge/onboarding.d.ts +3 -2
  62. package/dist/forge/onboarding.js +3 -2
  63. package/dist/hooks/db-guard.js +3 -3
  64. package/dist/hooks/forge-loop-progress.d.ts +9 -0
  65. package/dist/hooks/forge-loop-progress.js +38 -0
  66. package/dist/hooks/hook-registry.js +1 -1
  67. package/dist/hooks/hooks-generator.d.ts +15 -1
  68. package/dist/hooks/hooks-generator.js +18 -16
  69. package/dist/hooks/keyword-detector.js +1 -1
  70. package/dist/hooks/post-tool-use.d.ts +1 -1
  71. package/dist/hooks/post-tool-use.js +13 -4
  72. package/dist/hooks/pre-compact.js +1 -1
  73. package/dist/hooks/pre-tool-use.js +4 -4
  74. package/dist/hooks/rate-limiter.js +2 -2
  75. package/dist/hooks/session-recovery.js +11 -0
  76. package/dist/hooks/shared/blocking-allowlist.d.ts +28 -0
  77. package/dist/hooks/shared/blocking-allowlist.js +38 -0
  78. package/dist/hooks/shared/forge-loop-state.d.ts +36 -0
  79. package/dist/hooks/shared/forge-loop-state.js +116 -0
  80. package/dist/hooks/shared/hook-response.d.ts +18 -0
  81. package/dist/hooks/shared/hook-response.js +31 -0
  82. package/dist/hooks/skill-injector.js +1 -1
  83. package/dist/hooks/stop-guard.js +57 -25
  84. package/dist/host/capabilities-claude.d.ts +8 -0
  85. package/dist/host/capabilities-claude.js +46 -0
  86. package/dist/host/capabilities-codex.d.ts +11 -0
  87. package/dist/host/capabilities-codex.js +50 -0
  88. package/dist/host/capabilities-registry.d.ts +11 -0
  89. package/dist/host/capabilities-registry.js +30 -0
  90. package/dist/host/codex-adapter.d.ts +8 -5
  91. package/dist/host/codex-adapter.js +10 -82
  92. package/dist/host/codex-output-parser.d.ts +39 -0
  93. package/dist/host/codex-output-parser.js +75 -0
  94. package/dist/host/exec-host.d.ts +54 -0
  95. package/dist/host/exec-host.js +92 -0
  96. package/dist/host/host-runtime.d.ts +37 -0
  97. package/dist/host/host-runtime.js +51 -0
  98. package/dist/host/install-claude.d.ts +35 -0
  99. package/dist/host/install-claude.js +238 -0
  100. package/dist/host/install-codex.d.ts +44 -0
  101. package/dist/host/install-codex.js +276 -0
  102. package/dist/host/install-orchestrator.d.ts +34 -0
  103. package/dist/host/install-orchestrator.js +126 -0
  104. package/dist/host/invoke-agent.d.ts +27 -0
  105. package/dist/host/invoke-agent.js +115 -0
  106. package/dist/host/parity-harness.d.ts +62 -0
  107. package/dist/host/parity-harness.js +283 -0
  108. package/dist/host/projection.d.ts +35 -0
  109. package/dist/host/projection.js +126 -0
  110. package/dist/mcp/server.js +11 -0
  111. package/dist/mcp/tools.js +51 -0
  112. package/dist/renderer/rule-renderer.d.ts +1 -1
  113. package/dist/renderer/rule-renderer.js +73 -1
  114. package/dist/services/session.d.ts +6 -3
  115. package/dist/services/session.js +33 -4
  116. package/dist/store/compound-usage-store.d.ts +28 -0
  117. package/dist/store/compound-usage-store.js +59 -0
  118. package/dist/store/evidence-store.d.ts +1 -0
  119. package/dist/store/evidence-store.js +34 -3
  120. package/dist/store/host-mismatch.d.ts +42 -0
  121. package/dist/store/host-mismatch.js +65 -0
  122. package/dist/store/profile-store.d.ts +29 -0
  123. package/dist/store/profile-store.js +53 -0
  124. package/dist/store/types.d.ts +13 -0
  125. package/hooks/hooks.json +6 -1
  126. package/package.json +6 -4
  127. package/plugin.json +4 -4
  128. package/scripts/postinstall.js +100 -25
  129. package/skills/calibrate/SKILL.md +4 -3
  130. package/skills/retro/SKILL.md +2 -2
  131. /package/{agents → assets/claude/agents}/analyst.md +0 -0
  132. /package/{agents → assets/claude/agents}/architect.md +0 -0
  133. /package/{agents → assets/claude/agents}/code-reviewer.md +0 -0
  134. /package/{agents → assets/claude/agents}/critic.md +0 -0
  135. /package/{agents → assets/claude/agents}/debugger.md +0 -0
  136. /package/{agents → assets/claude/agents}/designer.md +0 -0
  137. /package/{agents → assets/claude/agents}/executor.md +0 -0
  138. /package/{agents → assets/claude/agents}/explore.md +0 -0
  139. /package/{agents → assets/claude/agents}/git-master.md +0 -0
  140. /package/{agents → assets/claude/agents}/planner.md +0 -0
  141. /package/{agents → assets/claude/agents}/solution-evolver.md +0 -0
  142. /package/{agents → assets/claude/agents}/test-engineer.md +0 -0
  143. /package/{agents → assets/claude/agents}/verifier.md +0 -0
  144. /package/{commands → assets/claude/commands}/architecture-decision.md +0 -0
  145. /package/{commands → assets/claude/commands}/code-review.md +0 -0
  146. /package/{commands → assets/claude/commands}/compound.md +0 -0
  147. /package/{commands → assets/claude/commands}/deep-interview.md +0 -0
  148. /package/{commands → assets/claude/commands}/docker.md +0 -0
  149. /package/{commands → assets/claude/commands}/forge-loop.md +0 -0
  150. /package/{commands → assets/claude/commands}/learn.md +0 -0
  151. /package/{commands → assets/claude/commands}/ship.md +0 -0
@@ -89,7 +89,7 @@ function fixOwnership(...paths) {
89
89
  const HOME = resolveHome();
90
90
 
91
91
  // ── Paths ──
92
- const SKILLS_DIR = join(PKG_ROOT, 'commands');
92
+ const SKILLS_DIR = join(PKG_ROOT, 'assets', 'claude', 'commands');
93
93
  const DIST_HOOKS = join(PKG_ROOT, 'dist', 'hooks');
94
94
  const COMMANDS_DIR = join(HOME, '.claude', 'commands', 'forgen');
95
95
  const CLAUDE_DIR = join(HOME, '.claude');
@@ -214,7 +214,7 @@ function registerPlugin() {
214
214
  if (!linked) {
215
215
  // 2차: 필수 디렉토리 복사
216
216
  mkdirSync(CACHE_DIR, { recursive: true });
217
- const copyDirs = ['.claude-plugin', 'hooks', 'skills', 'commands', 'agents'];
217
+ const copyDirs = ['.claude-plugin', 'hooks', 'skills', 'assets'];
218
218
  for (const dir of copyDirs) {
219
219
  const src = join(PKG_ROOT, dir);
220
220
  if (existsSync(src)) {
@@ -330,7 +330,7 @@ function detectPluginConflicts() {
330
330
  * Claude Code 플러그인은 skills/{name}/SKILL.md 구조로 스킬을 인식.
331
331
  */
332
332
  function generateSkillsDir() {
333
- const skillsSrc = join(PKG_ROOT, 'commands');
333
+ const skillsSrc = join(PKG_ROOT, 'assets', 'claude', 'commands');
334
334
  const skillsDst = join(PKG_ROOT, 'skills');
335
335
  if (!existsSync(skillsSrc)) return;
336
336
 
@@ -381,7 +381,7 @@ function generateSkillsDir() {
381
381
  */
382
382
  let HOOK_REGISTRY = [];
383
383
  try {
384
- HOOK_REGISTRY = JSON.parse(readFileSync(join(PKG_ROOT, 'hooks', 'hook-registry.json'), 'utf-8'));
384
+ HOOK_REGISTRY = JSON.parse(readFileSync(join(PKG_ROOT, 'assets', 'shared', 'hook-registry.json'), 'utf-8'));
385
385
  } catch {
386
386
  console.warn('[forgen] hook-registry.json not found, skipping hook generation');
387
387
  }
@@ -738,6 +738,49 @@ function main() {
738
738
  migrateLegacyStorage();
739
739
  ensureDirectories();
740
740
 
741
+ // ── 0. 기존 forgen entry 감지 (마이그레이션 모드 분기) ──
742
+ //
743
+ // feat/codex-support (P1-6, 2026-04-27): postinstall 이 호스트 인젝션을 *자동*
744
+ // 으로 하던 v0.4.x 동작을 변경. 새로운 정책:
745
+ // - 기존 사용자 (settings.json 에 forgen hook entry 있음): 그대로 갱신 (행동
746
+ // 변화 없음 — 마이그레이션 안전). default_host 자동 설정 안내 banner 출력.
747
+ // - 신규 사용자 (forgen entry 없음): host 인젝션 자동 안 함. "Run `forgen
748
+ // install`" banner 만 출력. 사용자가 어느 host (Claude/Codex/Both) 에 등록할지
749
+ // 명시 선택.
750
+ //
751
+ // 사용자 의도와 무관한 Claude bias (postinstall 이 ~/.claude/ 자동 인젝션) 제거.
752
+ let isExistingForgenUser = false;
753
+ if (existsSync(SETTINGS_PATH)) {
754
+ try {
755
+ const probe = JSON.parse(readFileSync(SETTINGS_PATH, 'utf-8'));
756
+ const hooks = probe?.hooks ?? {};
757
+ for (const arr of Object.values(hooks)) {
758
+ if (!Array.isArray(arr)) continue;
759
+ for (const grp of arr) {
760
+ if (!grp?.hooks) continue;
761
+ for (const h of grp.hooks) {
762
+ const cmd = typeof h?.command === 'string' ? h.command : '';
763
+ // P1-6b detection: forgen hook command path 식별. cross-platform (POSIX + Windows)
764
+ // 및 다양한 install 위치 (npm global, plugin cache, dev) 커버.
765
+ if (
766
+ cmd.includes('CLAUDE_PLUGIN_ROOT') ||
767
+ cmd.includes('/forgen-local/forgen/') ||
768
+ cmd.includes('\\forgen-local\\forgen\\') ||
769
+ cmd.includes('/forgen/dist/hooks/') ||
770
+ cmd.includes('\\forgen\\dist\\hooks\\') ||
771
+ cmd.includes('/@wooojin/forgen/') ||
772
+ cmd.includes('\\@wooojin\\forgen\\')
773
+ ) {
774
+ isExistingForgenUser = true;
775
+ }
776
+ }
777
+ if (isExistingForgenUser) break;
778
+ }
779
+ if (isExistingForgenUser) break;
780
+ }
781
+ } catch { /* settings.json 손상 시 fall-through, 단계 1 의 corrupt handling 이 처리 */ }
782
+ }
783
+
741
784
  // ── 1. settings.json 한 번 읽기 ──
742
785
  //
743
786
  // Audit finding #2/#10 (2026-04-21): prior `catch { settings = {} }`
@@ -765,12 +808,16 @@ function main() {
765
808
  }
766
809
 
767
810
  // ── 2. 플러그인 등록 (installed_plugins.json + skills) ──
811
+ // P1-6b (옵션 Y): 신규 사용자에게는 자동 install 안 함. 기존 forgen 사용자만 갱신.
812
+ // 사용자 host 선택 권한 보장 (1원칙 = Claude bias 제거).
768
813
  let plugin = false;
769
- try {
770
- plugin = registerPlugin();
771
- if (plugin) applyPluginSettings(settings);
772
- } catch (err) {
773
- console.error(`[forgen] plugin registration failed: ${err?.message ?? err}`);
814
+ if (isExistingForgenUser) {
815
+ try {
816
+ plugin = registerPlugin();
817
+ if (plugin) applyPluginSettings(settings);
818
+ } catch (err) {
819
+ console.error(`[forgen] plugin registration failed: ${err?.message ?? err}`);
820
+ }
774
821
  }
775
822
 
776
823
  // ── 3. hooks.json 동적 생성 ──
@@ -800,29 +847,35 @@ function main() {
800
847
  }
801
848
  }
802
849
 
803
- // ── 4. 슬래시 커맨드 설치 ──
850
+ // ── 4. 슬래시 커맨드 설치 ── (기존 사용자만)
804
851
  let commands = 0;
805
- try {
806
- commands = installSlashCommands();
807
- } catch (err) {
808
- console.error(`[forgen] slash commands failed: ${err?.message ?? err}`);
852
+ if (isExistingForgenUser) {
853
+ try {
854
+ commands = installSlashCommands();
855
+ } catch (err) {
856
+ console.error(`[forgen] slash commands failed: ${err?.message ?? err}`);
857
+ }
809
858
  }
810
859
 
811
- // ── 5. settings에 훅 설정 적용 ──
860
+ // ── 5. settings에 훅 설정 적용 ── (기존 사용자만)
812
861
  let hooks = false;
813
- try {
814
- hooks = applyHookSettings(settings);
815
- } catch (err) {
816
- console.error(`[forgen] hooks settings failed: ${err?.message ?? err}`);
862
+ if (isExistingForgenUser) {
863
+ try {
864
+ hooks = applyHookSettings(settings);
865
+ } catch (err) {
866
+ console.error(`[forgen] hooks settings failed: ${err?.message ?? err}`);
867
+ }
817
868
  }
818
869
 
819
- // ── 6. MCP 서버를 ~/.claude.json 등록 (settings.json이 아닌 올바른 경로) ──
870
+ // ── 6. MCP 서버 ~/.claude.json 등록 ── (기존 사용자만)
820
871
  let mcp = false;
821
- try {
822
- mcp = applyMcpToClaudeJson();
823
- cleanLegacyMcpFromSettings(settings);
824
- } catch (err) {
825
- console.error(`[forgen] MCP server registration failed: ${err?.message ?? err}`);
872
+ if (isExistingForgenUser) {
873
+ try {
874
+ mcp = applyMcpToClaudeJson();
875
+ cleanLegacyMcpFromSettings(settings);
876
+ } catch (err) {
877
+ console.error(`[forgen] MCP server registration failed: ${err?.message ?? err}`);
878
+ }
826
879
  }
827
880
 
828
881
  // ── 7. settings.json 한 번 쓰기 (atomic) ──
@@ -863,6 +916,28 @@ function main() {
863
916
  if (parts.length > 0) {
864
917
  console.log(`[forgen] Installed: ${parts.join(', ')} → ${HOME}`);
865
918
  }
919
+
920
+ // First-run banner (신규 사용자 안내) — feat/codex-support P1-6
921
+ if (!isExistingForgenUser) {
922
+ console.log('');
923
+ console.log(' ╭─ forgen — multi-host support ─────────────────────────────╮');
924
+ console.log(' │ binaries installed: forgen, fgx, forgen-mcp │');
925
+ console.log(' │ │');
926
+ console.log(' │ Next: register forgen on a host (Claude or Codex): │');
927
+ console.log(' │ $ forgen install (interactive 3-choice) │');
928
+ console.log(' │ $ forgen install claude (Claude only) │');
929
+ console.log(' │ $ forgen install codex (Codex only) │');
930
+ console.log(' │ $ forgen install both (둘 다) │');
931
+ console.log(' ╰────────────────────────────────────────────────────────────╯');
932
+ console.log('');
933
+ } else {
934
+ // 기존 사용자: default_host 안내
935
+ console.log('');
936
+ console.log(' [forgen] Multi-host support added. Existing forgen entry preserved.');
937
+ console.log(' Optional: `forgen config default-host {claude|codex|ask}` to set fgx default.');
938
+ console.log(' Optional: `forgen install codex` to register on Codex too.');
939
+ console.log('');
940
+ }
866
941
  }
867
942
 
868
943
  try {
@@ -21,7 +21,8 @@ description: This skill should be used when the user asks to "calibrate, 캘리
21
21
  calibrate는 두 가지 데이터 소스를 사용합니다:
22
22
 
23
23
  ### 1차 소스: Evidence 파일
24
- `~/.forgen/me/evidence/` 디렉토리의 JSON 파일을 읽습니다.
24
+ `~/.forgen/me/behavior/` 디렉토리의 JSON 파일을 읽습니다.
25
+ (파일명: UUID.json — correction-record MCP 도구가 작성. 같은 디렉토리의 auto-*.md 는 auto-compound 산출이므로 calibrate 분석 대상 아님.)
25
26
  각 파일의 구조:
26
27
  ```json
27
28
  {
@@ -52,8 +53,8 @@ evidence 0건 + compound 교정 패턴 0건이면:
52
53
  ## Phase 1: Evidence 로드 및 검증
53
54
 
54
55
  ```bash
55
- ls ~/.forgen/me/evidence/ 2>/dev/null || echo "EMPTY"
56
- cat ~/.forgen/me/evidence/*.json 2>/dev/null || echo "NO_FILES"
56
+ ls ~/.forgen/me/behavior/*.json 2>/dev/null || echo "EMPTY"
57
+ cat ~/.forgen/me/behavior/*.json 2>/dev/null || echo "NO_FILES"
57
58
  ```
58
59
 
59
60
  로드한 JSON 파일마다 다음을 검증합니다:
@@ -53,8 +53,8 @@ compound-list
53
53
  ### 1-3: 교정 기록
54
54
 
55
55
  ```bash
56
- ls -la ~/.forgen/me/evidence/ 2>/dev/null || echo "교정 데이터 없음"
57
- find ~/.forgen/me/evidence/ -name "*.json" -mtime -{period_days} 2>/dev/null | wc -l
56
+ ls -la ~/.forgen/me/behavior/ 2>/dev/null || echo "교정 데이터 없음"
57
+ find ~/.forgen/me/behavior/ -name "*.json" -mtime -{period_days} 2>/dev/null | wc -l
58
58
  ```
59
59
 
60
60
  ## Phase 2: 코드 활동 분석
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes