@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
@@ -21,6 +21,7 @@ import { getNewCommits, getCommitMessages, getGitDiff, getDiffStats } from './ex
21
21
  import { gate0, evaluateExtractedSolution } from './extraction-gates.js';
22
22
  import { extractFromDiff } from './extraction-diff.js';
23
23
  import { extractFromSessionContext } from './extraction-session.js';
24
+ import { stripPrivate, isFullyPrivate } from './private-filter.js';
24
25
  import { loadLastExtraction, saveLastExtraction, saveExtractedSolution, updateReExtractedCounter, emitCompoundExtractActedOn, } from './extraction-persistence.js';
25
26
  const log = createLogger('compound-extractor');
26
27
  const MAX_EXTRACTIONS_PER_DAY = 5;
@@ -172,6 +173,15 @@ export function processExtractionResults(rawJson, sessionId) {
172
173
  return { saved, skipped };
173
174
  }
174
175
  for (const sol of solutions.slice(0, 3)) {
176
+ // W2-5 (private 태그): <private> 범위를 솔루션 content/context 에서 제거 후 저장.
177
+ // 통째로 private 이면 저장 skip (학습 코퍼스에 남기지 않음).
178
+ if (isFullyPrivate(sol.content) || isFullyPrivate(sol.context ?? '')) {
179
+ skipped.push(`${sol.name}: <private> (제외)`);
180
+ continue;
181
+ }
182
+ sol.content = stripPrivate(sol.content).cleaned;
183
+ if (sol.context)
184
+ sol.context = stripPrivate(sol.context).cleaned;
175
185
  const evaluation = evaluateExtractedSolution(sol);
176
186
  if (evaluation.action === 'skip' || evaluation.action === 'duplicate') {
177
187
  skipped.push(evaluation.message ?? `${sol.name}: skipped`);
@@ -190,11 +190,17 @@ export async function handleCompound(args) {
190
190
  forgen compound --lifecycle Run promotion/demotion/circuit-breaker check
191
191
  forgen compound --verify <name> Manually promote solution to verified
192
192
 
193
- Export/Import:
193
+ Export/Import (whole store, tar.gz):
194
194
  forgen compound export [--output path]
195
195
  Export knowledge to tar.gz archive
196
196
  forgen compound import <path> Import knowledge from archive (skip existing)
197
197
 
198
+ Export/Import (per-pattern, JSON — with confidence + provenance):
199
+ forgen compound export <name...> [--out file]
200
+ Export named solutions/rules as a portable bundle
201
+ forgen compound import <bundle.json> [--dry-run]
202
+ Import a bundle (probation trust, never overwrites)
203
+
198
204
  Auto-extraction:
199
205
  forgen compound --pause-auto Pause auto-extraction
200
206
  forgen compound --resume-auto Resume auto-extraction
@@ -205,15 +211,38 @@ export async function handleCompound(args) {
205
211
  return;
206
212
  }
207
213
  // --- export command ---
214
+ // 통짜 tar.gz export(플래그만, positional 없음) vs 이름 지정 패턴 export를
215
+ // positional 인자 유무로 구분한다. `compound export foo` = 패턴 export,
216
+ // `compound export --output x` = 기존 whole-store export.
208
217
  if (args[0] === 'export') {
209
- const { handleExport } = await import('./compound-export.js');
210
- await handleExport(args.slice(1));
218
+ const rest = args.slice(1);
219
+ const hasPatternNames = rest.length > 0 && !rest[0].startsWith('--');
220
+ if (hasPatternNames) {
221
+ const { handleShareExport } = await import('./compound-share.js');
222
+ await handleShareExport(rest);
223
+ }
224
+ else {
225
+ const { handleExport } = await import('./compound-export.js');
226
+ await handleExport(rest);
227
+ }
211
228
  return;
212
229
  }
213
230
  // --- import command ---
231
+ // 대상 파일이 JSON 패턴 번들인지 tar.gz 아카이브인지 확장자/매직바이트로
232
+ // sniff해서 라우팅한다 (looksLikeShareBundle). 기존 tar.gz import 동작은
233
+ // 그대로 유지.
214
234
  if (args[0] === 'import') {
215
- const { handleImport } = await import('./compound-export.js');
216
- await handleImport(args.slice(1));
235
+ const rest = args.slice(1);
236
+ const filePath = rest.find(a => !a.startsWith('--'));
237
+ const { looksLikeShareBundle } = await import('./compound-share.js');
238
+ if (filePath && looksLikeShareBundle(path.resolve(filePath))) {
239
+ const { handleShareImport } = await import('./compound-share.js');
240
+ await handleShareImport(rest);
241
+ }
242
+ else {
243
+ const { handleImport } = await import('./compound-export.js');
244
+ await handleImport(rest);
245
+ }
217
246
  return;
218
247
  }
219
248
  // --pause-auto / --resume-auto
@@ -399,7 +428,7 @@ export async function handleCompound(args) {
399
428
  '--lifecycle', '--verify', '--save', '--interactive',
400
429
  'list', 'inspect', 'remove', 'rollback', 'retag', 'lifecycle',
401
430
  '--list', '--inspect', '--remove', '--rollback', '--retag', '--since', 'interactive',
402
- 'export', 'import', '--output',
431
+ 'export', 'import', '--output', '--out', '--dry-run',
403
432
  ];
404
433
  const hasTypeFlag = knownFlags.some(f => args.includes(f));
405
434
  if (!hasTypeFlag) {
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Forgen — Compound Pattern Share (패턴별 export/import)
3
+ *
4
+ * `compound-export.ts`의 `export`/`import`는 `~/.forgen/me/` 전체를 tar.gz로
5
+ * 통짜 백업/이관한다. 이 모듈은 그와 달리 **이름 지정된 패턴 단위**로 신뢰도
6
+ * (confidence/status/evidence)와 provenance를 함께 담은 JSON 번들을 만들고,
7
+ * 받는 쪽에서 안전하게 병합한다 (ECC `/instinct-import/export` 대응, OSS gap #1).
8
+ *
9
+ * 핵심 설계:
10
+ * - 번들은 스키마 버전 고정 JSON. 최상위/패턴 필드 모두 화이트리스트 검증 —
11
+ * 예상 못한 필드가 있으면 통째로 reject (실행 가능한 콘텐츠가 섞여 들어올
12
+ * 여지 자체를 차단).
13
+ * - 패턴마다 contentHash(sha256)를 동봉 — import 시 재계산해 일치하지 않으면
14
+ * reject (변조/손상 탐지).
15
+ * - 이름 충돌 시: 로컬 콘텐츠 해시가 같으면 "동일 패턴 재발견"으로 간주해
16
+ * `reExtracted` 카운터만 증가(기존 신뢰도는 건드리지 않음 — 이미 solution-writer.ts
17
+ * 의 dual-path 금지 불변식과 일치). 다르면 절대 덮어쓰지 않고 suffix된
18
+ * 이름으로 새로 생성.
19
+ * - 신규 생성되는 패턴은 항상 probation: status='experiment', confidence는
20
+ * 신규 솔루션 표준 베이스라인(statusConfidence('experiment')=0.3, 참고:
21
+ * extraction-persistence.ts saveExtractedSolution)을 상한으로 export 시점
22
+ * confidence의 절반만 반영. evidence는 전부 0으로 리셋 — exporter의 로컬
23
+ * 사용 이력을 이 머신이 검증 없이 물려받지 않는다. 이후 승급은 기존
24
+ * compound-lifecycle.ts의 단일 경로(runLifecycleCheck)로만 진행된다.
25
+ */
26
+ import { type SolutionFrontmatter } from './solution-format.js';
27
+ export declare const SHARE_BUNDLE_SCHEMA_VERSION: 1;
28
+ export interface ShareBundlePatternV1 {
29
+ name: string;
30
+ category: 'solution' | 'rule';
31
+ frontmatter: SolutionFrontmatter;
32
+ context: string;
33
+ content: string;
34
+ /** sha256(type + sorted tags/identifiers + context + content) — confidence/evidence/timestamp 제외한 콘텐츠 지문. */
35
+ contentHash: string;
36
+ }
37
+ export interface ShareBundleV1 {
38
+ schemaVersion: 1;
39
+ exportedAt: string;
40
+ /** sha256(hostname:username) 앞 16자 — 원본 식별용, PII 비가역. */
41
+ originHash: string;
42
+ patterns: ShareBundlePatternV1[];
43
+ }
44
+ export interface BuildBundleResult {
45
+ bundle: ShareBundleV1;
46
+ notFound: string[];
47
+ rejectedSecrets: string[];
48
+ }
49
+ /**
50
+ * 이름 목록으로 패턴 번들 생성.
51
+ *
52
+ * 시크릿 감지된 패턴은 조용히 스킵하지 않고 `rejectedSecrets`로 보고하되,
53
+ * 번들 자체는 나머지 clean한 패턴으로 계속 진행한다 (부분 실패 허용).
54
+ */
55
+ export declare function buildShareBundle(names: string[]): BuildBundleResult;
56
+ export interface ShareBundleValidation {
57
+ ok: boolean;
58
+ bundle: ShareBundleV1 | null;
59
+ errors: string[];
60
+ }
61
+ /**
62
+ * 번들 검증: 크기 캡 → 최상위 필드 화이트리스트 → 패턴별 필드 화이트리스트 →
63
+ * frontmatter 정합성 → contentHash 재계산 일치. 하나라도 실패하면 번들 전체를
64
+ * reject한다 (부분 신뢰 없음 — 손상/변조된 번들은 통째로 버린다).
65
+ */
66
+ export declare function validateShareBundle(raw: unknown, rawSize: number): ShareBundleValidation;
67
+ export interface ShareImportAction {
68
+ sourceName: string;
69
+ category: 'solution' | 'rule';
70
+ action: 'merge-reextract' | 'create' | 'create-suffixed';
71
+ targetName: string;
72
+ detail: string;
73
+ }
74
+ export interface ShareImportSummary {
75
+ dryRun: boolean;
76
+ actions: ShareImportAction[];
77
+ }
78
+ /** dry-run과 실제 실행이 공유하는 계획 수립 — 파일시스템에 아무것도 쓰지 않는다. */
79
+ export declare function planShareImport(bundle: ShareBundleV1): ShareImportAction[];
80
+ export declare function executeShareImport(bundle: ShareBundleV1, opts?: {
81
+ dryRun?: boolean;
82
+ }): ShareImportSummary;
83
+ export declare function looksLikeShareBundle(filePath: string): boolean;
84
+ export declare function handleShareExport(args: string[]): Promise<void>;
85
+ export declare function handleShareImport(args: string[]): Promise<void>;