@wooojin/forgen 0.3.0 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +7 -2
- package/CHANGELOG.md +132 -0
- package/README.ja.md +29 -0
- package/README.ko.md +29 -0
- package/README.md +36 -3
- package/README.zh.md +29 -0
- package/agents/solution-evolver.md +115 -0
- package/dist/cli.js +11 -3
- package/dist/core/auto-compound-runner.js +6 -3
- package/dist/core/dashboard.js +57 -4
- package/dist/core/doctor.d.ts +6 -1
- package/dist/core/doctor.js +21 -1
- package/dist/core/global-config.d.ts +2 -2
- package/dist/core/global-config.js +6 -14
- package/dist/core/harness.d.ts +3 -5
- package/dist/core/harness.js +34 -338
- package/dist/core/installer.d.ts +10 -0
- package/dist/core/installer.js +185 -0
- package/dist/core/paths.d.ts +25 -34
- package/dist/core/paths.js +25 -35
- package/dist/core/settings-injector.d.ts +13 -0
- package/dist/core/settings-injector.js +167 -0
- package/dist/core/settings-lock.d.ts +35 -2
- package/dist/core/settings-lock.js +65 -7
- package/dist/core/spawn.js +100 -39
- package/dist/core/state-gc.d.ts +30 -0
- package/dist/core/state-gc.js +119 -0
- package/dist/core/uninstall.js +12 -4
- package/dist/core/v1-bootstrap.js +2 -2
- package/dist/engine/compound-cli.d.ts +27 -2
- package/dist/engine/compound-cli.js +69 -16
- package/dist/engine/compound-export.d.ts +15 -0
- package/dist/engine/compound-export.js +32 -5
- package/dist/engine/compound-loop.js +3 -2
- package/dist/engine/learn-cli.d.ts +1 -0
- package/dist/engine/learn-cli.js +234 -0
- package/dist/engine/match-eval-log.js +45 -0
- package/dist/engine/solution-candidate.d.ts +30 -0
- package/dist/engine/solution-candidate.js +124 -0
- package/dist/engine/solution-fitness.d.ts +52 -0
- package/dist/engine/solution-fitness.js +95 -0
- package/dist/engine/solution-fixup.d.ts +30 -0
- package/dist/engine/solution-fixup.js +116 -0
- package/dist/engine/solution-format.d.ts +8 -2
- package/dist/engine/solution-format.js +38 -27
- package/dist/engine/solution-index.js +10 -0
- package/dist/engine/solution-matcher.d.ts +8 -0
- package/dist/engine/solution-matcher.js +27 -1
- package/dist/engine/solution-outcomes.d.ts +74 -0
- package/dist/engine/solution-outcomes.js +319 -0
- package/dist/engine/solution-quarantine.d.ts +36 -0
- package/dist/engine/solution-quarantine.js +172 -0
- package/dist/engine/solution-weakness.d.ts +45 -0
- package/dist/engine/solution-weakness.js +225 -0
- package/dist/engine/solution-writer.d.ts +9 -1
- package/dist/engine/solution-writer.js +44 -2
- package/dist/fgx.js +9 -2
- package/dist/forge/cli.js +7 -7
- package/dist/hooks/context-guard.js +15 -1
- package/dist/hooks/hook-config.d.ts +9 -1
- package/dist/hooks/hook-config.js +25 -3
- package/dist/hooks/internal/run-lifecycle-check.d.ts +2 -0
- package/dist/hooks/internal/run-lifecycle-check.js +32 -0
- package/dist/hooks/notepad-injector.js +6 -3
- package/dist/hooks/permission-handler.d.ts +10 -2
- package/dist/hooks/permission-handler.js +31 -12
- package/dist/hooks/post-tool-failure.js +7 -0
- package/dist/hooks/pre-tool-use.js +10 -4
- package/dist/hooks/secret-filter.js +6 -0
- package/dist/hooks/session-recovery.js +15 -7
- package/dist/hooks/shared/hook-response.d.ts +0 -2
- package/dist/hooks/shared/hook-response.js +3 -8
- package/dist/hooks/shared/hook-timing.js +10 -1
- package/dist/hooks/solution-injector.d.ts +21 -0
- package/dist/hooks/solution-injector.js +80 -1
- package/dist/mcp/solution-reader.d.ts +2 -0
- package/dist/mcp/solution-reader.js +28 -1
- package/dist/mcp/tools.js +13 -2
- package/dist/preset/preset-manager.js +12 -2
- package/dist/store/evidence-store.js +5 -5
- package/dist/store/profile-store.d.ts +9 -0
- package/dist/store/profile-store.js +25 -4
- package/dist/store/rule-store.js +8 -8
- package/package.json +1 -1
- package/plugin.json +7 -2
- package/scripts/postinstall.js +52 -5
package/scripts/postinstall.js
CHANGED
|
@@ -679,7 +679,21 @@ function applyMcpToClaudeJson() {
|
|
|
679
679
|
const claudeJsonPath = join(HOME, '.claude.json');
|
|
680
680
|
let claudeJson = {};
|
|
681
681
|
if (existsSync(claudeJsonPath)) {
|
|
682
|
-
try {
|
|
682
|
+
try {
|
|
683
|
+
claudeJson = JSON.parse(readFileSync(claudeJsonPath, 'utf-8'));
|
|
684
|
+
} catch (e) {
|
|
685
|
+
// Audit fix #10 (2026-04-21): silent parse-failure used to let the
|
|
686
|
+
// merged write below overwrite the user's malformed-but-original
|
|
687
|
+
// ~/.claude.json, wiping all their other plugin configs. Preserve
|
|
688
|
+
// and skip instead.
|
|
689
|
+
const corruptPath = `${claudeJsonPath}.corrupt-${Date.now()}`;
|
|
690
|
+
try { copyFileSync(claudeJsonPath, corruptPath); } catch { /* best-effort */ }
|
|
691
|
+
console.error(
|
|
692
|
+
`[forgen] ${claudeJsonPath} failed to parse; preserved at ${corruptPath}. ` +
|
|
693
|
+
`Skipping MCP registration.`,
|
|
694
|
+
);
|
|
695
|
+
return false;
|
|
696
|
+
}
|
|
683
697
|
}
|
|
684
698
|
|
|
685
699
|
const mcpServers = claudeJson.mcpServers ?? {};
|
|
@@ -689,7 +703,11 @@ function applyMcpToClaudeJson() {
|
|
|
689
703
|
};
|
|
690
704
|
claudeJson.mcpServers = mcpServers;
|
|
691
705
|
|
|
692
|
-
|
|
706
|
+
// Atomic write — tmp file + rename so a partial write never leaves
|
|
707
|
+
// ~/.claude.json in a torn state for any concurrent reader.
|
|
708
|
+
const tmpPath = `${claudeJsonPath}.tmp.${process.pid}`;
|
|
709
|
+
writeFileSync(tmpPath, JSON.stringify(claudeJson, null, 2));
|
|
710
|
+
renameSync(tmpPath, claudeJsonPath);
|
|
693
711
|
fixOwnership(claudeJsonPath);
|
|
694
712
|
return true;
|
|
695
713
|
}
|
|
@@ -721,9 +739,29 @@ function main() {
|
|
|
721
739
|
ensureDirectories();
|
|
722
740
|
|
|
723
741
|
// ── 1. settings.json 한 번 읽기 ──
|
|
742
|
+
//
|
|
743
|
+
// Audit finding #2/#10 (2026-04-21): prior `catch { settings = {} }`
|
|
744
|
+
// silently swallowed parse failures and let the merged write below
|
|
745
|
+
// clobber the user's malformed-but-original settings.json — a data
|
|
746
|
+
// loss path triggered by any partial edit or external corruption.
|
|
747
|
+
// Now: preserve the corrupt file as `.corrupt-<ts>`, abort the
|
|
748
|
+
// settings write (and subsequent MCP registration + ownership fix
|
|
749
|
+
// that also touches ~/.claude.json), surface the warning via npm's
|
|
750
|
+
// postinstall output. The outer try/catch at the bottom ensures
|
|
751
|
+
// `npm install` still succeeds; only the settings mutation is
|
|
752
|
+
// skipped.
|
|
724
753
|
let settings = {};
|
|
725
754
|
if (existsSync(SETTINGS_PATH)) {
|
|
726
|
-
try {
|
|
755
|
+
try {
|
|
756
|
+
settings = JSON.parse(readFileSync(SETTINGS_PATH, 'utf-8'));
|
|
757
|
+
} catch (e) {
|
|
758
|
+
const corruptPath = `${SETTINGS_PATH}.corrupt-${Date.now()}`;
|
|
759
|
+
try { copyFileSync(SETTINGS_PATH, corruptPath); } catch { /* best-effort */ }
|
|
760
|
+
throw new Error(
|
|
761
|
+
`[forgen] ${SETTINGS_PATH} failed to parse: ${e?.message ?? e}. ` +
|
|
762
|
+
`Preserved corrupt copy at ${corruptPath}. Skipping settings injection to avoid data loss.`,
|
|
763
|
+
);
|
|
764
|
+
}
|
|
727
765
|
}
|
|
728
766
|
|
|
729
767
|
// ── 2. 플러그인 등록 (installed_plugins.json + skills) ──
|
|
@@ -787,10 +825,19 @@ function main() {
|
|
|
787
825
|
console.error(`[forgen] MCP server registration failed: ${err?.message ?? err}`);
|
|
788
826
|
}
|
|
789
827
|
|
|
790
|
-
// ── 7. settings.json 한 번 쓰기 ──
|
|
828
|
+
// ── 7. settings.json 한 번 쓰기 (atomic) ──
|
|
829
|
+
//
|
|
830
|
+
// Audit fix #10 (2026-04-21): prior direct writeFileSync could leave
|
|
831
|
+
// settings.json truncated / partially-written if the process was
|
|
832
|
+
// interrupted (sudo shell SIGINT, npm exit). Tmp + rename is atomic
|
|
833
|
+
// on POSIX within the same directory. Lock is NOT acquired here —
|
|
834
|
+
// postinstall is serialized by npm and we don't want to introduce a
|
|
835
|
+
// cross-module dependency from a build-time script.
|
|
791
836
|
try {
|
|
792
837
|
mkdirSync(dirname(SETTINGS_PATH), { recursive: true });
|
|
793
|
-
|
|
838
|
+
const tmpPath = `${SETTINGS_PATH}.tmp.${process.pid}`;
|
|
839
|
+
writeFileSync(tmpPath, JSON.stringify(settings, null, 2));
|
|
840
|
+
renameSync(tmpPath, SETTINGS_PATH);
|
|
794
841
|
} catch (err) {
|
|
795
842
|
console.error(`[forgen] settings.json write failed: ${err?.message ?? err}`);
|
|
796
843
|
}
|