@wooojin/forgen 0.1.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.
- package/.claude-plugin/plugin.json +20 -0
- package/CHANGELOG.md +353 -0
- package/CONTRIBUTING.md +98 -0
- package/LICENSE +21 -0
- package/README.ja.md +469 -0
- package/README.ko.md +469 -0
- package/README.md +483 -0
- package/README.zh.md +469 -0
- package/agents/analyst.md +98 -0
- package/agents/architect.md +62 -0
- package/agents/code-reviewer.md +120 -0
- package/agents/code-simplifier.md +197 -0
- package/agents/critic.md +70 -0
- package/agents/debugger.md +117 -0
- package/agents/designer.md +131 -0
- package/agents/executor.md +54 -0
- package/agents/explore.md +145 -0
- package/agents/git-master.md +212 -0
- package/agents/performance-reviewer.md +172 -0
- package/agents/planner.md +29 -0
- package/agents/qa-tester.md +158 -0
- package/agents/refactoring-expert.md +168 -0
- package/agents/scientist.md +144 -0
- package/agents/security-reviewer.md +137 -0
- package/agents/test-engineer.md +153 -0
- package/agents/verifier.md +133 -0
- package/agents/writer.md +184 -0
- package/commands/api-design.md +268 -0
- package/commands/architecture-decision.md +314 -0
- package/commands/ci-cd.md +270 -0
- package/commands/code-review.md +233 -0
- package/commands/compound.md +117 -0
- package/commands/database.md +263 -0
- package/commands/debug-detective.md +99 -0
- package/commands/docker.md +274 -0
- package/commands/documentation.md +276 -0
- package/commands/ecomode.md +51 -0
- package/commands/frontend.md +271 -0
- package/commands/git-master.md +90 -0
- package/commands/incident-response.md +292 -0
- package/commands/migrate.md +101 -0
- package/commands/performance.md +288 -0
- package/commands/refactor.md +105 -0
- package/commands/security-review.md +288 -0
- package/commands/tdd.md +183 -0
- package/commands/testing-strategy.md +265 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +295 -0
- package/dist/core/auto-compound-runner.d.ts +12 -0
- package/dist/core/auto-compound-runner.js +460 -0
- package/dist/core/config-hooks.d.ts +10 -0
- package/dist/core/config-hooks.js +112 -0
- package/dist/core/config-injector.d.ts +50 -0
- package/dist/core/config-injector.js +455 -0
- package/dist/core/doctor.d.ts +1 -0
- package/dist/core/doctor.js +163 -0
- package/dist/core/errors.d.ts +81 -0
- package/dist/core/errors.js +133 -0
- package/dist/core/global-config.d.ts +43 -0
- package/dist/core/global-config.js +25 -0
- package/dist/core/harness.d.ts +24 -0
- package/dist/core/harness.js +621 -0
- package/dist/core/init.d.ts +7 -0
- package/dist/core/init.js +37 -0
- package/dist/core/inspect-cli.d.ts +7 -0
- package/dist/core/inspect-cli.js +47 -0
- package/dist/core/legacy-detector.d.ts +33 -0
- package/dist/core/legacy-detector.js +66 -0
- package/dist/core/logger.d.ts +34 -0
- package/dist/core/logger.js +121 -0
- package/dist/core/mcp-config.d.ts +44 -0
- package/dist/core/mcp-config.js +177 -0
- package/dist/core/notepad.d.ts +31 -0
- package/dist/core/notepad.js +88 -0
- package/dist/core/paths.d.ts +85 -0
- package/dist/core/paths.js +101 -0
- package/dist/core/plugin-detector.d.ts +44 -0
- package/dist/core/plugin-detector.js +226 -0
- package/dist/core/runtime-detector.d.ts +8 -0
- package/dist/core/runtime-detector.js +49 -0
- package/dist/core/scope-resolver.d.ts +8 -0
- package/dist/core/scope-resolver.js +45 -0
- package/dist/core/session-logger.d.ts +6 -0
- package/dist/core/session-logger.js +111 -0
- package/dist/core/session-store.d.ts +28 -0
- package/dist/core/session-store.js +218 -0
- package/dist/core/settings-lock.d.ts +18 -0
- package/dist/core/settings-lock.js +125 -0
- package/dist/core/spawn.d.ts +3 -0
- package/dist/core/spawn.js +135 -0
- package/dist/core/types.d.ts +108 -0
- package/dist/core/types.js +1 -0
- package/dist/core/uninstall.d.ts +4 -0
- package/dist/core/uninstall.js +307 -0
- package/dist/core/v1-bootstrap.d.ts +26 -0
- package/dist/core/v1-bootstrap.js +155 -0
- package/dist/engine/compound-cli.d.ts +24 -0
- package/dist/engine/compound-cli.js +250 -0
- package/dist/engine/compound-extractor.d.ts +68 -0
- package/dist/engine/compound-extractor.js +860 -0
- package/dist/engine/compound-lifecycle.d.ts +32 -0
- package/dist/engine/compound-lifecycle.js +305 -0
- package/dist/engine/compound-loop.d.ts +32 -0
- package/dist/engine/compound-loop.js +511 -0
- package/dist/engine/match-eval-log.d.ts +139 -0
- package/dist/engine/match-eval-log.js +270 -0
- package/dist/engine/phrase-blocklist.d.ts +119 -0
- package/dist/engine/phrase-blocklist.js +208 -0
- package/dist/engine/skill-promoter.d.ts +20 -0
- package/dist/engine/skill-promoter.js +115 -0
- package/dist/engine/solution-format.d.ts +160 -0
- package/dist/engine/solution-format.js +432 -0
- package/dist/engine/solution-index.d.ts +13 -0
- package/dist/engine/solution-index.js +252 -0
- package/dist/engine/solution-matcher.d.ts +364 -0
- package/dist/engine/solution-matcher.js +656 -0
- package/dist/engine/solution-writer.d.ts +76 -0
- package/dist/engine/solution-writer.js +157 -0
- package/dist/engine/term-matcher.d.ts +81 -0
- package/dist/engine/term-matcher.js +268 -0
- package/dist/engine/term-normalizer.d.ts +116 -0
- package/dist/engine/term-normalizer.js +171 -0
- package/dist/fgx.d.ts +6 -0
- package/dist/fgx.js +42 -0
- package/dist/forge/cli.d.ts +11 -0
- package/dist/forge/cli.js +100 -0
- package/dist/forge/evidence-processor.d.ts +21 -0
- package/dist/forge/evidence-processor.js +87 -0
- package/dist/forge/mismatch-detector.d.ts +44 -0
- package/dist/forge/mismatch-detector.js +83 -0
- package/dist/forge/onboarding-cli.d.ts +6 -0
- package/dist/forge/onboarding-cli.js +89 -0
- package/dist/forge/onboarding.d.ts +25 -0
- package/dist/forge/onboarding.js +122 -0
- package/dist/hooks/compound-reflection.d.ts +45 -0
- package/dist/hooks/compound-reflection.js +82 -0
- package/dist/hooks/context-guard.d.ts +24 -0
- package/dist/hooks/context-guard.js +156 -0
- package/dist/hooks/dangerous-patterns.json +18 -0
- package/dist/hooks/db-guard.d.ts +17 -0
- package/dist/hooks/db-guard.js +105 -0
- package/dist/hooks/hook-config.d.ts +29 -0
- package/dist/hooks/hook-config.js +92 -0
- package/dist/hooks/hook-registry.d.ts +43 -0
- package/dist/hooks/hook-registry.js +31 -0
- package/dist/hooks/hooks-generator.d.ts +49 -0
- package/dist/hooks/hooks-generator.js +99 -0
- package/dist/hooks/intent-classifier.d.ts +12 -0
- package/dist/hooks/intent-classifier.js +62 -0
- package/dist/hooks/keyword-detector.d.ts +25 -0
- package/dist/hooks/keyword-detector.js +389 -0
- package/dist/hooks/notepad-injector.d.ts +18 -0
- package/dist/hooks/notepad-injector.js +51 -0
- package/dist/hooks/permission-handler.d.ts +14 -0
- package/dist/hooks/permission-handler.js +114 -0
- package/dist/hooks/post-tool-failure.d.ts +11 -0
- package/dist/hooks/post-tool-failure.js +118 -0
- package/dist/hooks/post-tool-handlers.d.ts +17 -0
- package/dist/hooks/post-tool-handlers.js +115 -0
- package/dist/hooks/post-tool-use.d.ts +29 -0
- package/dist/hooks/post-tool-use.js +151 -0
- package/dist/hooks/pre-compact.d.ts +10 -0
- package/dist/hooks/pre-compact.js +165 -0
- package/dist/hooks/pre-tool-use.d.ts +31 -0
- package/dist/hooks/pre-tool-use.js +325 -0
- package/dist/hooks/prompt-injection-filter.d.ts +56 -0
- package/dist/hooks/prompt-injection-filter.js +287 -0
- package/dist/hooks/rate-limiter.d.ts +21 -0
- package/dist/hooks/rate-limiter.js +86 -0
- package/dist/hooks/secret-filter.d.ts +14 -0
- package/dist/hooks/secret-filter.js +65 -0
- package/dist/hooks/session-recovery.d.ts +27 -0
- package/dist/hooks/session-recovery.js +406 -0
- package/dist/hooks/shared/atomic-write.d.ts +41 -0
- package/dist/hooks/shared/atomic-write.js +148 -0
- package/dist/hooks/shared/context-budget.d.ts +37 -0
- package/dist/hooks/shared/context-budget.js +45 -0
- package/dist/hooks/shared/file-lock.d.ts +56 -0
- package/dist/hooks/shared/file-lock.js +253 -0
- package/dist/hooks/shared/hook-response.d.ts +33 -0
- package/dist/hooks/shared/hook-response.js +62 -0
- package/dist/hooks/shared/injection-caps.d.ts +39 -0
- package/dist/hooks/shared/injection-caps.js +52 -0
- package/dist/hooks/shared/plugin-signal.d.ts +23 -0
- package/dist/hooks/shared/plugin-signal.js +104 -0
- package/dist/hooks/shared/read-stdin.d.ts +8 -0
- package/dist/hooks/shared/read-stdin.js +63 -0
- package/dist/hooks/shared/sanitize-id.d.ts +7 -0
- package/dist/hooks/shared/sanitize-id.js +9 -0
- package/dist/hooks/shared/sanitize.d.ts +7 -0
- package/dist/hooks/shared/sanitize.js +22 -0
- package/dist/hooks/skill-injector.d.ts +38 -0
- package/dist/hooks/skill-injector.js +285 -0
- package/dist/hooks/slop-detector.d.ts +18 -0
- package/dist/hooks/slop-detector.js +93 -0
- package/dist/hooks/solution-injector.d.ts +58 -0
- package/dist/hooks/solution-injector.js +436 -0
- package/dist/hooks/subagent-tracker.d.ts +10 -0
- package/dist/hooks/subagent-tracker.js +90 -0
- package/dist/i18n/index.d.ts +43 -0
- package/dist/i18n/index.js +224 -0
- package/dist/lib.d.ts +14 -0
- package/dist/lib.js +14 -0
- package/dist/mcp/server.d.ts +8 -0
- package/dist/mcp/server.js +40 -0
- package/dist/mcp/solution-reader.d.ts +90 -0
- package/dist/mcp/solution-reader.js +273 -0
- package/dist/mcp/tools.d.ts +16 -0
- package/dist/mcp/tools.js +302 -0
- package/dist/preset/facet-catalog.d.ts +17 -0
- package/dist/preset/facet-catalog.js +46 -0
- package/dist/preset/preset-manager.d.ts +31 -0
- package/dist/preset/preset-manager.js +111 -0
- package/dist/renderer/inspect-renderer.d.ts +11 -0
- package/dist/renderer/inspect-renderer.js +123 -0
- package/dist/renderer/rule-renderer.d.ts +18 -0
- package/dist/renderer/rule-renderer.js +159 -0
- package/dist/store/evidence-store.d.ts +23 -0
- package/dist/store/evidence-store.js +58 -0
- package/dist/store/profile-store.d.ts +12 -0
- package/dist/store/profile-store.js +53 -0
- package/dist/store/recommendation-store.d.ts +22 -0
- package/dist/store/recommendation-store.js +64 -0
- package/dist/store/rule-store.d.ts +22 -0
- package/dist/store/rule-store.js +62 -0
- package/dist/store/session-state-store.d.ts +11 -0
- package/dist/store/session-state-store.js +44 -0
- package/dist/store/types.d.ts +159 -0
- package/dist/store/types.js +7 -0
- package/hooks/hook-registry.json +21 -0
- package/hooks/hooks.json +185 -0
- package/package.json +89 -0
- package/plugin.json +20 -0
- package/scripts/postinstall.js +826 -0
- package/skills/api-design/SKILL.md +262 -0
- package/skills/architecture-decision/SKILL.md +309 -0
- package/skills/ci-cd/SKILL.md +264 -0
- package/skills/code-review/SKILL.md +228 -0
- package/skills/compound/SKILL.md +101 -0
- package/skills/database/SKILL.md +257 -0
- package/skills/debug-detective/SKILL.md +95 -0
- package/skills/docker/SKILL.md +268 -0
- package/skills/documentation/SKILL.md +270 -0
- package/skills/ecomode/SKILL.md +46 -0
- package/skills/frontend/SKILL.md +265 -0
- package/skills/git-master/SKILL.md +86 -0
- package/skills/incident-response/SKILL.md +286 -0
- package/skills/migrate/SKILL.md +96 -0
- package/skills/performance/SKILL.md +282 -0
- package/skills/refactor/SKILL.md +100 -0
- package/skills/security-review/SKILL.md +282 -0
- package/skills/tdd/SKILL.md +178 -0
- package/skills/testing-strategy/SKILL.md +260 -0
- package/starter-pack/solutions/starter-api-error-responses.md +37 -0
- package/starter-pack/solutions/starter-async-patterns.md +40 -0
- package/starter-pack/solutions/starter-caching-strategy.md +40 -0
- package/starter-pack/solutions/starter-code-review-checklist.md +39 -0
- package/starter-pack/solutions/starter-debugging-systematic.md +40 -0
- package/starter-pack/solutions/starter-dependency-injection.md +40 -0
- package/starter-pack/solutions/starter-error-handling-patterns.md +38 -0
- package/starter-pack/solutions/starter-git-atomic-commits.md +36 -0
- package/starter-pack/solutions/starter-input-validation.md +40 -0
- package/starter-pack/solutions/starter-n-plus-one-queries.md +37 -0
- package/starter-pack/solutions/starter-refactor-safely.md +38 -0
- package/starter-pack/solutions/starter-secret-management.md +37 -0
- package/starter-pack/solutions/starter-separation-of-concerns.md +36 -0
- package/starter-pack/solutions/starter-tdd-red-green-refactor.md +40 -0
- package/starter-pack/solutions/starter-typescript-strict-types.md +39 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/** ~/.claude/ — Claude Code 설정 디렉토리 */
|
|
2
|
+
export declare const CLAUDE_DIR: string;
|
|
3
|
+
/** ~/.claude/settings.json — Claude Code 설정 파일 */
|
|
4
|
+
export declare const SETTINGS_PATH: string;
|
|
5
|
+
/**
|
|
6
|
+
* ~/.compound/ — LEGACY harness home (pre-v5).
|
|
7
|
+
*
|
|
8
|
+
* @deprecated A5 (2026-04-09): this path must NEVER be used for WRITES.
|
|
9
|
+
* It exists solely as the source path for `migrateToForgen()`.
|
|
10
|
+
* All new writes must target `FORGEN_HOME`-based paths. Consumers that
|
|
11
|
+
* read from this path should prefer the FORGEN_HOME equivalent first
|
|
12
|
+
* and fall back here only during migration.
|
|
13
|
+
*
|
|
14
|
+
* Pre-A5, `harness.ts:ensureDirectories` and several hooks actively
|
|
15
|
+
* created directories under this path, causing a dual-reality where
|
|
16
|
+
* state could diverge between `~/.compound/` and `~/.forgen/` when the
|
|
17
|
+
* migration symlink was broken (sudo install, SIP, CI, manual delete).
|
|
18
|
+
*/
|
|
19
|
+
export declare const COMPOUND_HOME: string;
|
|
20
|
+
/** ~/.forgen/ — v1 하네스 홈 디렉토리 */
|
|
21
|
+
export declare const FORGEN_HOME: string;
|
|
22
|
+
/** ~/.forgen/me/ — 개인 공간 (v5.1: ~/.compound/ → ~/.forgen/ 통합) */
|
|
23
|
+
export declare const ME_DIR: string;
|
|
24
|
+
/** ~/.forgen/me/philosophy.json — 개인 철학 */
|
|
25
|
+
export declare const ME_PHILOSOPHY: string;
|
|
26
|
+
/** ~/.forgen/me/solutions/ — 개인 솔루션 */
|
|
27
|
+
export declare const ME_SOLUTIONS: string;
|
|
28
|
+
/** ~/.forgen/me/behavior/ — 개인 행동 패턴 */
|
|
29
|
+
export declare const ME_BEHAVIOR: string;
|
|
30
|
+
/** ~/.forgen/me/rules/ — 개인 규칙 */
|
|
31
|
+
export declare const ME_RULES: string;
|
|
32
|
+
/** ~/.forgen/me/skills/ — 개인 스킬 (promoted solutions) */
|
|
33
|
+
export declare const ME_SKILLS: string;
|
|
34
|
+
/** ~/.forgen/packs/ — 팀 팩 저장소 */
|
|
35
|
+
export declare const PACKS_DIR: string;
|
|
36
|
+
/** ~/.forgen/handoffs/ — 세션 간 핸드오프 데이터 */
|
|
37
|
+
export declare const HANDOFFS_DIR: string;
|
|
38
|
+
/** ~/.forgen/state/ — 상태 파일 디렉토리 */
|
|
39
|
+
export declare const STATE_DIR: string;
|
|
40
|
+
/**
|
|
41
|
+
* ~/.forgen/state/match-eval-log.jsonl — JSONL ranking-decision log for the
|
|
42
|
+
* bootstrap evaluator and offline matcher debugging. Written best-effort by
|
|
43
|
+
* `src/engine/match-eval-log.ts`; never on the hook critical path.
|
|
44
|
+
*/
|
|
45
|
+
export declare const MATCH_EVAL_LOG_PATH: string;
|
|
46
|
+
/** ~/.forgen/sessions/ — 세션 로그 */
|
|
47
|
+
export declare const SESSIONS_DIR: string;
|
|
48
|
+
/** ~/.forgen/config.json — 글로벌 설정 */
|
|
49
|
+
export declare const GLOBAL_CONFIG: string;
|
|
50
|
+
/** ~/.forgen/lab/ — Lab 적응형 최적화 엔진 데이터 */
|
|
51
|
+
export declare const LAB_DIR: string;
|
|
52
|
+
/** ~/.forgen/lab/events.jsonl — Lab 이벤트 로그 (JSONL) */
|
|
53
|
+
export declare const LAB_EVENTS: string;
|
|
54
|
+
/** ~/.forgen/me/forge-profile.json — 글로벌 Forge 프로필 */
|
|
55
|
+
export declare const FORGE_PROFILE: string;
|
|
56
|
+
/** @deprecated use ME_DIR */
|
|
57
|
+
export declare const V1_ME_DIR: string;
|
|
58
|
+
/** @deprecated use FORGE_PROFILE */
|
|
59
|
+
export declare const V1_PROFILE: string;
|
|
60
|
+
/** @deprecated use ME_RULES */
|
|
61
|
+
export declare const V1_RULES_DIR: string;
|
|
62
|
+
/** @deprecated use ME_BEHAVIOR */
|
|
63
|
+
export declare const V1_EVIDENCE_DIR: string;
|
|
64
|
+
/** ~/.forgen/me/recommendations/ — Pack Recommendation */
|
|
65
|
+
export declare const V1_RECOMMENDATIONS_DIR: string;
|
|
66
|
+
/** @deprecated use ME_SOLUTIONS */
|
|
67
|
+
export declare const V1_SOLUTIONS_DIR: string;
|
|
68
|
+
/** @deprecated use STATE_DIR */
|
|
69
|
+
export declare const V1_STATE_DIR: string;
|
|
70
|
+
/** ~/.forgen/state/sessions/ — Session Effective State */
|
|
71
|
+
export declare const V1_SESSIONS_DIR: string;
|
|
72
|
+
/** ~/.forgen/state/raw-logs/ — Raw Log */
|
|
73
|
+
export declare const V1_RAW_LOGS_DIR: string;
|
|
74
|
+
/** @deprecated use GLOBAL_CONFIG */
|
|
75
|
+
export declare const V1_GLOBAL_CONFIG: string;
|
|
76
|
+
/** 모든 실행 모드 이름 (cancel/recovery 시 사용) */
|
|
77
|
+
export declare const ALL_MODES: readonly ["ralph", "autopilot", "ultrawork", "team", "pipeline", "ccg", "ralplan", "deep-interview", "ecomode"];
|
|
78
|
+
/** {repo}/.compound/ — 프로젝트 로컬 디렉토리 */
|
|
79
|
+
export declare function projectDir(cwd: string): string;
|
|
80
|
+
/** {repo}/.compound/pack.link — 팀 팩 연결 파일 */
|
|
81
|
+
export declare function packLinkPath(cwd: string): string;
|
|
82
|
+
/** {repo}/.compound/philosophy.json — 프로젝트별 철학 */
|
|
83
|
+
export declare function projectPhilosophyPath(cwd: string): string;
|
|
84
|
+
/** {repo}/.compound/forge-profile.json — 프로젝트별 Forge 프로필 */
|
|
85
|
+
export declare function projectForgeProfilePath(cwd: string): string;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import * as os from 'node:os';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
const HOME = os.homedir();
|
|
4
|
+
/** ~/.claude/ — Claude Code 설정 디렉토리 */
|
|
5
|
+
export const CLAUDE_DIR = path.join(HOME, '.claude');
|
|
6
|
+
/** ~/.claude/settings.json — Claude Code 설정 파일 */
|
|
7
|
+
export const SETTINGS_PATH = path.join(CLAUDE_DIR, 'settings.json');
|
|
8
|
+
/**
|
|
9
|
+
* ~/.compound/ — LEGACY harness home (pre-v5).
|
|
10
|
+
*
|
|
11
|
+
* @deprecated A5 (2026-04-09): this path must NEVER be used for WRITES.
|
|
12
|
+
* It exists solely as the source path for `migrateToForgen()`.
|
|
13
|
+
* All new writes must target `FORGEN_HOME`-based paths. Consumers that
|
|
14
|
+
* read from this path should prefer the FORGEN_HOME equivalent first
|
|
15
|
+
* and fall back here only during migration.
|
|
16
|
+
*
|
|
17
|
+
* Pre-A5, `harness.ts:ensureDirectories` and several hooks actively
|
|
18
|
+
* created directories under this path, causing a dual-reality where
|
|
19
|
+
* state could diverge between `~/.compound/` and `~/.forgen/` when the
|
|
20
|
+
* migration symlink was broken (sudo install, SIP, CI, manual delete).
|
|
21
|
+
*/
|
|
22
|
+
export const COMPOUND_HOME = path.join(HOME, '.compound');
|
|
23
|
+
/** ~/.forgen/ — v1 하네스 홈 디렉토리 */
|
|
24
|
+
export const FORGEN_HOME = path.join(HOME, '.forgen');
|
|
25
|
+
/** ~/.forgen/me/ — 개인 공간 (v5.1: ~/.compound/ → ~/.forgen/ 통합) */
|
|
26
|
+
export const ME_DIR = path.join(FORGEN_HOME, 'me');
|
|
27
|
+
/** ~/.forgen/me/philosophy.json — 개인 철학 */
|
|
28
|
+
export const ME_PHILOSOPHY = path.join(ME_DIR, 'philosophy.json');
|
|
29
|
+
/** ~/.forgen/me/solutions/ — 개인 솔루션 */
|
|
30
|
+
export const ME_SOLUTIONS = path.join(ME_DIR, 'solutions');
|
|
31
|
+
/** ~/.forgen/me/behavior/ — 개인 행동 패턴 */
|
|
32
|
+
export const ME_BEHAVIOR = path.join(ME_DIR, 'behavior');
|
|
33
|
+
/** ~/.forgen/me/rules/ — 개인 규칙 */
|
|
34
|
+
export const ME_RULES = path.join(ME_DIR, 'rules');
|
|
35
|
+
/** ~/.forgen/me/skills/ — 개인 스킬 (promoted solutions) */
|
|
36
|
+
export const ME_SKILLS = path.join(ME_DIR, 'skills');
|
|
37
|
+
/** ~/.forgen/packs/ — 팀 팩 저장소 */
|
|
38
|
+
export const PACKS_DIR = path.join(FORGEN_HOME, 'packs');
|
|
39
|
+
/** ~/.forgen/handoffs/ — 세션 간 핸드오프 데이터 */
|
|
40
|
+
export const HANDOFFS_DIR = path.join(FORGEN_HOME, 'handoffs');
|
|
41
|
+
/** ~/.forgen/state/ — 상태 파일 디렉토리 */
|
|
42
|
+
export const STATE_DIR = path.join(FORGEN_HOME, 'state');
|
|
43
|
+
/**
|
|
44
|
+
* ~/.forgen/state/match-eval-log.jsonl — JSONL ranking-decision log for the
|
|
45
|
+
* bootstrap evaluator and offline matcher debugging. Written best-effort by
|
|
46
|
+
* `src/engine/match-eval-log.ts`; never on the hook critical path.
|
|
47
|
+
*/
|
|
48
|
+
export const MATCH_EVAL_LOG_PATH = path.join(STATE_DIR, 'match-eval-log.jsonl');
|
|
49
|
+
/** ~/.forgen/sessions/ — 세션 로그 */
|
|
50
|
+
export const SESSIONS_DIR = path.join(FORGEN_HOME, 'sessions');
|
|
51
|
+
/** ~/.forgen/config.json — 글로벌 설정 */
|
|
52
|
+
export const GLOBAL_CONFIG = path.join(FORGEN_HOME, 'config.json');
|
|
53
|
+
/** ~/.forgen/lab/ — Lab 적응형 최적화 엔진 데이터 */
|
|
54
|
+
export const LAB_DIR = path.join(FORGEN_HOME, 'lab');
|
|
55
|
+
/** ~/.forgen/lab/events.jsonl — Lab 이벤트 로그 (JSONL) */
|
|
56
|
+
export const LAB_EVENTS = path.join(LAB_DIR, 'events.jsonl');
|
|
57
|
+
/** ~/.forgen/me/forge-profile.json — 글로벌 Forge 프로필 */
|
|
58
|
+
export const FORGE_PROFILE = path.join(ME_DIR, 'forge-profile.json');
|
|
59
|
+
// ── v1 호환 경로 (ME_*와 동일 — 점진 제거 예정) ──
|
|
60
|
+
/** @deprecated use ME_DIR */
|
|
61
|
+
export const V1_ME_DIR = ME_DIR;
|
|
62
|
+
/** @deprecated use FORGE_PROFILE */
|
|
63
|
+
export const V1_PROFILE = FORGE_PROFILE;
|
|
64
|
+
/** @deprecated use ME_RULES */
|
|
65
|
+
export const V1_RULES_DIR = ME_RULES;
|
|
66
|
+
/** @deprecated use ME_BEHAVIOR */
|
|
67
|
+
export const V1_EVIDENCE_DIR = ME_BEHAVIOR;
|
|
68
|
+
/** ~/.forgen/me/recommendations/ — Pack Recommendation */
|
|
69
|
+
export const V1_RECOMMENDATIONS_DIR = path.join(ME_DIR, 'recommendations');
|
|
70
|
+
/** @deprecated use ME_SOLUTIONS */
|
|
71
|
+
export const V1_SOLUTIONS_DIR = ME_SOLUTIONS;
|
|
72
|
+
/** @deprecated use STATE_DIR */
|
|
73
|
+
export const V1_STATE_DIR = STATE_DIR;
|
|
74
|
+
/** ~/.forgen/state/sessions/ — Session Effective State */
|
|
75
|
+
export const V1_SESSIONS_DIR = path.join(STATE_DIR, 'sessions');
|
|
76
|
+
/** ~/.forgen/state/raw-logs/ — Raw Log */
|
|
77
|
+
export const V1_RAW_LOGS_DIR = path.join(STATE_DIR, 'raw-logs');
|
|
78
|
+
/** @deprecated use GLOBAL_CONFIG */
|
|
79
|
+
export const V1_GLOBAL_CONFIG = GLOBAL_CONFIG;
|
|
80
|
+
// ── 레거시 ──
|
|
81
|
+
/** 모든 실행 모드 이름 (cancel/recovery 시 사용) */
|
|
82
|
+
export const ALL_MODES = [
|
|
83
|
+
'ralph', 'autopilot', 'ultrawork', 'team', 'pipeline',
|
|
84
|
+
'ccg', 'ralplan', 'deep-interview', 'ecomode',
|
|
85
|
+
];
|
|
86
|
+
/** {repo}/.compound/ — 프로젝트 로컬 디렉토리 */
|
|
87
|
+
export function projectDir(cwd) {
|
|
88
|
+
return path.join(cwd, '.compound');
|
|
89
|
+
}
|
|
90
|
+
/** {repo}/.compound/pack.link — 팀 팩 연결 파일 */
|
|
91
|
+
export function packLinkPath(cwd) {
|
|
92
|
+
return path.join(projectDir(cwd), 'pack.link');
|
|
93
|
+
}
|
|
94
|
+
/** {repo}/.compound/philosophy.json — 프로젝트별 철학 */
|
|
95
|
+
export function projectPhilosophyPath(cwd) {
|
|
96
|
+
return path.join(projectDir(cwd), 'philosophy.json');
|
|
97
|
+
}
|
|
98
|
+
/** {repo}/.compound/forge-profile.json — 프로젝트별 Forge 프로필 */
|
|
99
|
+
export function projectForgeProfilePath(cwd) {
|
|
100
|
+
return path.join(projectDir(cwd), 'forge-profile.json');
|
|
101
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forgen — Plugin Detector
|
|
3
|
+
*
|
|
4
|
+
* 다른 Claude Code 플러그인이 설치되어 있는지 감지하고,
|
|
5
|
+
* forgen와 기능이 중복되는 스킬/훅 목록을 반환합니다.
|
|
6
|
+
*
|
|
7
|
+
* 감지 방법:
|
|
8
|
+
* 1. ~/.claude/plugins/ 디렉토리에서 설치된 플러그인 스캔
|
|
9
|
+
* 2. 알려진 플러그인의 파일 시그니처 (.omc/, .claude-mem/ 등) 확인
|
|
10
|
+
* 3. 결과를 ~/.forgen/state/detected-plugins.json에 캐시 (1시간 TTL)
|
|
11
|
+
*
|
|
12
|
+
* 설계 결정:
|
|
13
|
+
* - 감지는 읽기 전용 — 다른 플러그인의 파일을 수정하지 않음
|
|
14
|
+
* - 실패 시 빈 배열 반환 (failure-tolerant) — 감지 실패 = 충돌 없음으로 간주
|
|
15
|
+
* - 캐시 TTL 1시간 — 플러그인 설치/제거 빈도가 낮으므로 충분
|
|
16
|
+
*/
|
|
17
|
+
export interface DetectedPlugin {
|
|
18
|
+
name: string;
|
|
19
|
+
/** 이 플러그인과 중복되는 forgen 스킬 이름 */
|
|
20
|
+
overlappingSkills: string[];
|
|
21
|
+
/** 이 플러그인과 중복되는 forgen 훅 이름 */
|
|
22
|
+
overlappingHooks: string[];
|
|
23
|
+
/** 감지 방법 (디버깅용) */
|
|
24
|
+
detectedBy: 'plugin-dir' | 'signature' | 'both';
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* 설치된 다른 플러그인을 감지합니다.
|
|
28
|
+
* 캐시가 유효하면 캐시를 반환합니다 (1시간 TTL).
|
|
29
|
+
*/
|
|
30
|
+
export declare function detectInstalledPlugins(cwd?: string): DetectedPlugin[];
|
|
31
|
+
/** forgen와 중복되는 스킬 이름 → 충돌 플러그인 이름 매핑 */
|
|
32
|
+
export declare function getSkillConflicts(cwd?: string): Map<string, string>;
|
|
33
|
+
/** forgen와 중복되는 훅 이름 → 충돌 플러그인 이름 매핑 */
|
|
34
|
+
export declare function getHookConflicts(cwd?: string): Map<string, string>;
|
|
35
|
+
/**
|
|
36
|
+
* 컨텍스트를 상시 주입하는 다른 플러그인이 있는지 확인합니다.
|
|
37
|
+
*
|
|
38
|
+
* 판정 기준: overlappingHooks가 있는 플러그인만 "컨텍스트 주입" 간주.
|
|
39
|
+
* MCP 기반 플러그인(claude-mem 등)이나 스킬만 중복되는 플러그인은
|
|
40
|
+
* 온디맨드 호출이므로 상시 컨텍스트를 점유하지 않아 제외합니다.
|
|
41
|
+
*/
|
|
42
|
+
export declare function hasContextInjectingPlugins(cwd?: string): boolean;
|
|
43
|
+
/** 감지 캐시를 무효화합니다 (플러그인 설치/제거 후 호출) */
|
|
44
|
+
export declare function invalidatePluginCache(): void;
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forgen — Plugin Detector
|
|
3
|
+
*
|
|
4
|
+
* 다른 Claude Code 플러그인이 설치되어 있는지 감지하고,
|
|
5
|
+
* forgen와 기능이 중복되는 스킬/훅 목록을 반환합니다.
|
|
6
|
+
*
|
|
7
|
+
* 감지 방법:
|
|
8
|
+
* 1. ~/.claude/plugins/ 디렉토리에서 설치된 플러그인 스캔
|
|
9
|
+
* 2. 알려진 플러그인의 파일 시그니처 (.omc/, .claude-mem/ 등) 확인
|
|
10
|
+
* 3. 결과를 ~/.forgen/state/detected-plugins.json에 캐시 (1시간 TTL)
|
|
11
|
+
*
|
|
12
|
+
* 설계 결정:
|
|
13
|
+
* - 감지는 읽기 전용 — 다른 플러그인의 파일을 수정하지 않음
|
|
14
|
+
* - 실패 시 빈 배열 반환 (failure-tolerant) — 감지 실패 = 충돌 없음으로 간주
|
|
15
|
+
* - 캐시 TTL 1시간 — 플러그인 설치/제거 빈도가 낮으므로 충분
|
|
16
|
+
*/
|
|
17
|
+
import * as fs from 'node:fs';
|
|
18
|
+
import * as os from 'node:os';
|
|
19
|
+
import * as path from 'node:path';
|
|
20
|
+
import { STATE_DIR } from './paths.js';
|
|
21
|
+
const KNOWN_PLUGINS = {
|
|
22
|
+
'oh-my-claudecode': {
|
|
23
|
+
signatures: ['.omc'],
|
|
24
|
+
localSignatures: ['.omc'],
|
|
25
|
+
overlappingSkills: [
|
|
26
|
+
'autopilot', 'team', 'code-review', 'tdd', 'debug-detective',
|
|
27
|
+
'refactor', 'security-review', 'git-master', 'migrate',
|
|
28
|
+
'pipeline', 'ultrawork',
|
|
29
|
+
],
|
|
30
|
+
overlappingHooks: ['intent-classifier', 'keyword-detector'],
|
|
31
|
+
},
|
|
32
|
+
'claude-mem': {
|
|
33
|
+
signatures: ['.claude-mem'],
|
|
34
|
+
localSignatures: [],
|
|
35
|
+
// claude-mem은 MCP 기반이라 스킬 충돌은 없지만 컨텍스트 주입 경쟁 있음
|
|
36
|
+
overlappingSkills: [],
|
|
37
|
+
overlappingHooks: [],
|
|
38
|
+
},
|
|
39
|
+
'macrodata': {
|
|
40
|
+
signatures: ['.macrodata'],
|
|
41
|
+
localSignatures: ['.macrodata'],
|
|
42
|
+
overlappingSkills: [],
|
|
43
|
+
overlappingHooks: [],
|
|
44
|
+
},
|
|
45
|
+
'superpowers': {
|
|
46
|
+
signatures: ['.codex/superpowers'], // Superpowers installs to ~/.codex/superpowers/
|
|
47
|
+
localSignatures: [],
|
|
48
|
+
overlappingSkills: [
|
|
49
|
+
'tdd', 'debug-detective', 'refactor', 'code-review',
|
|
50
|
+
],
|
|
51
|
+
overlappingHooks: [], // Superpowers uses skills, not conflicting hooks
|
|
52
|
+
},
|
|
53
|
+
'feature-dev': {
|
|
54
|
+
signatures: [],
|
|
55
|
+
localSignatures: [],
|
|
56
|
+
overlappingSkills: ['pipeline'],
|
|
57
|
+
overlappingHooks: [],
|
|
58
|
+
},
|
|
59
|
+
'code-review-plugin': {
|
|
60
|
+
signatures: [],
|
|
61
|
+
localSignatures: [],
|
|
62
|
+
overlappingSkills: ['code-review'],
|
|
63
|
+
overlappingHooks: [],
|
|
64
|
+
},
|
|
65
|
+
'commit-commands': {
|
|
66
|
+
signatures: [],
|
|
67
|
+
localSignatures: [],
|
|
68
|
+
overlappingSkills: ['git-master'],
|
|
69
|
+
overlappingHooks: [],
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
// ── 캐시 ──
|
|
73
|
+
const CACHE_PATH = path.join(STATE_DIR, 'detected-plugins.json');
|
|
74
|
+
const CACHE_TTL_MS = 60 * 60 * 1000; // 1시간
|
|
75
|
+
function loadCache(cwd) {
|
|
76
|
+
try {
|
|
77
|
+
if (!fs.existsSync(CACHE_PATH))
|
|
78
|
+
return null;
|
|
79
|
+
const data = JSON.parse(fs.readFileSync(CACHE_PATH, 'utf-8'));
|
|
80
|
+
const age = Date.now() - new Date(data.timestamp).getTime();
|
|
81
|
+
if (!Number.isFinite(age) || age > CACHE_TTL_MS)
|
|
82
|
+
return null;
|
|
83
|
+
// cwd가 다르면 캐시 무효 (프로젝트별 로컬 시그니처가 다를 수 있음)
|
|
84
|
+
if (data.cwd && cwd && data.cwd !== cwd)
|
|
85
|
+
return null;
|
|
86
|
+
return data.plugins;
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function saveCache(plugins, cwd) {
|
|
93
|
+
try {
|
|
94
|
+
fs.mkdirSync(path.dirname(CACHE_PATH), { recursive: true });
|
|
95
|
+
fs.writeFileSync(CACHE_PATH, JSON.stringify({
|
|
96
|
+
plugins,
|
|
97
|
+
timestamp: new Date().toISOString(),
|
|
98
|
+
cwd: cwd ?? undefined,
|
|
99
|
+
}));
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
// 캐시 저장 실패는 무시
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
// ── 감지 로직 ──
|
|
106
|
+
/** ~/.claude/plugins/ 디렉토리에서 설치된 플러그인 이름 추출 */
|
|
107
|
+
function scanPluginDirectory() {
|
|
108
|
+
const names = new Set();
|
|
109
|
+
const pluginsDir = path.join(os.homedir(), '.claude', 'plugins');
|
|
110
|
+
try {
|
|
111
|
+
if (!fs.existsSync(pluginsDir))
|
|
112
|
+
return names;
|
|
113
|
+
for (const entry of fs.readdirSync(pluginsDir)) {
|
|
114
|
+
const pluginJsonPath = path.join(pluginsDir, entry, 'plugin.json');
|
|
115
|
+
if (fs.existsSync(pluginJsonPath)) {
|
|
116
|
+
try {
|
|
117
|
+
const manifest = JSON.parse(fs.readFileSync(pluginJsonPath, 'utf-8'));
|
|
118
|
+
names.add(manifest.name ?? entry);
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
names.add(entry);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
// 디렉토리 접근 실패
|
|
128
|
+
}
|
|
129
|
+
return names;
|
|
130
|
+
}
|
|
131
|
+
/** 파일 시그니처로 알려진 플러그인 감지 */
|
|
132
|
+
function detectBySignature(cwd) {
|
|
133
|
+
const detected = new Map();
|
|
134
|
+
const home = os.homedir();
|
|
135
|
+
const effectiveCwd = cwd ?? process.cwd();
|
|
136
|
+
for (const [pluginName, entry] of Object.entries(KNOWN_PLUGINS)) {
|
|
137
|
+
// 홈 디렉토리 시그니처
|
|
138
|
+
for (const sig of entry.signatures) {
|
|
139
|
+
if (fs.existsSync(path.join(home, sig))) {
|
|
140
|
+
detected.set(pluginName, 'signature');
|
|
141
|
+
break;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// 프로젝트 로컬 시그니처
|
|
145
|
+
if (!detected.has(pluginName)) {
|
|
146
|
+
for (const sig of entry.localSignatures) {
|
|
147
|
+
if (fs.existsSync(path.join(effectiveCwd, sig))) {
|
|
148
|
+
detected.set(pluginName, 'signature');
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return detected;
|
|
155
|
+
}
|
|
156
|
+
// ── 공개 API ──
|
|
157
|
+
/**
|
|
158
|
+
* 설치된 다른 플러그인을 감지합니다.
|
|
159
|
+
* 캐시가 유효하면 캐시를 반환합니다 (1시간 TTL).
|
|
160
|
+
*/
|
|
161
|
+
export function detectInstalledPlugins(cwd) {
|
|
162
|
+
// 캐시 확인 (cwd별로 분리)
|
|
163
|
+
const cached = loadCache(cwd);
|
|
164
|
+
if (cached)
|
|
165
|
+
return cached;
|
|
166
|
+
const result = [];
|
|
167
|
+
// 방법 1: 플러그인 디렉토리 스캔
|
|
168
|
+
const dirPlugins = scanPluginDirectory();
|
|
169
|
+
// 방법 2: 파일 시그니처 감지
|
|
170
|
+
const sigPlugins = detectBySignature(cwd);
|
|
171
|
+
// 병합
|
|
172
|
+
const allNames = new Set([...dirPlugins, ...sigPlugins.keys()]);
|
|
173
|
+
for (const name of allNames) {
|
|
174
|
+
const known = KNOWN_PLUGINS[name];
|
|
175
|
+
const inDir = dirPlugins.has(name);
|
|
176
|
+
const inSig = sigPlugins.has(name);
|
|
177
|
+
result.push({
|
|
178
|
+
name,
|
|
179
|
+
overlappingSkills: known?.overlappingSkills ?? [],
|
|
180
|
+
overlappingHooks: known?.overlappingHooks ?? [],
|
|
181
|
+
detectedBy: inDir && inSig ? 'both' : inDir ? 'plugin-dir' : 'signature',
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
saveCache(result, cwd);
|
|
185
|
+
return result;
|
|
186
|
+
}
|
|
187
|
+
/** forgen와 중복되는 스킬 이름 → 충돌 플러그인 이름 매핑 */
|
|
188
|
+
export function getSkillConflicts(cwd) {
|
|
189
|
+
const conflicts = new Map();
|
|
190
|
+
for (const plugin of detectInstalledPlugins(cwd)) {
|
|
191
|
+
for (const skill of plugin.overlappingSkills) {
|
|
192
|
+
conflicts.set(skill, plugin.name);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return conflicts;
|
|
196
|
+
}
|
|
197
|
+
/** forgen와 중복되는 훅 이름 → 충돌 플러그인 이름 매핑 */
|
|
198
|
+
export function getHookConflicts(cwd) {
|
|
199
|
+
const conflicts = new Map();
|
|
200
|
+
for (const plugin of detectInstalledPlugins(cwd)) {
|
|
201
|
+
for (const hook of plugin.overlappingHooks) {
|
|
202
|
+
conflicts.set(hook, plugin.name);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return conflicts;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* 컨텍스트를 상시 주입하는 다른 플러그인이 있는지 확인합니다.
|
|
209
|
+
*
|
|
210
|
+
* 판정 기준: overlappingHooks가 있는 플러그인만 "컨텍스트 주입" 간주.
|
|
211
|
+
* MCP 기반 플러그인(claude-mem 등)이나 스킬만 중복되는 플러그인은
|
|
212
|
+
* 온디맨드 호출이므로 상시 컨텍스트를 점유하지 않아 제외합니다.
|
|
213
|
+
*/
|
|
214
|
+
export function hasContextInjectingPlugins(cwd) {
|
|
215
|
+
return detectInstalledPlugins(cwd).some(p => p.overlappingHooks.length > 0);
|
|
216
|
+
}
|
|
217
|
+
/** 감지 캐시를 무효화합니다 (플러그인 설치/제거 후 호출) */
|
|
218
|
+
export function invalidatePluginCache() {
|
|
219
|
+
try {
|
|
220
|
+
if (fs.existsSync(CACHE_PATH))
|
|
221
|
+
fs.unlinkSync(CACHE_PATH);
|
|
222
|
+
}
|
|
223
|
+
catch {
|
|
224
|
+
// 무시
|
|
225
|
+
}
|
|
226
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forgen v1 — Runtime Capability Detection
|
|
3
|
+
*
|
|
4
|
+
* 현재 Claude Code 권한 상태를 감지.
|
|
5
|
+
* Authoritative: docs/plans/2026-04-03-forgen-component-interface-design.md §4
|
|
6
|
+
*/
|
|
7
|
+
import type { RuntimeCapabilityState } from '../store/types.js';
|
|
8
|
+
export declare function detectRuntimeCapability(): RuntimeCapabilityState;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forgen v1 — Runtime Capability Detection
|
|
3
|
+
*
|
|
4
|
+
* 현재 Claude Code 권한 상태를 감지.
|
|
5
|
+
* Authoritative: docs/plans/2026-04-03-forgen-component-interface-design.md §4
|
|
6
|
+
*/
|
|
7
|
+
import { SETTINGS_PATH } from './paths.js';
|
|
8
|
+
import { safeReadJSON } from '../hooks/shared/atomic-write.js';
|
|
9
|
+
export function detectRuntimeCapability() {
|
|
10
|
+
// 1. CLI 플래그 확인
|
|
11
|
+
const args = process.argv.join(' ');
|
|
12
|
+
const dangerousSkip = args.includes('--dangerously-skip-permissions')
|
|
13
|
+
|| process.env.CLAUDE_DANGEROUS_SKIP_PERMISSIONS === 'true';
|
|
14
|
+
if (dangerousSkip) {
|
|
15
|
+
return {
|
|
16
|
+
permission_mode: 'bypassed',
|
|
17
|
+
dangerous_skip_permissions: true,
|
|
18
|
+
auto_accept_scope: ['all'],
|
|
19
|
+
detected_from: 'cli-flag',
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
// 2. settings.json에서 permission 관련 설정 확인
|
|
23
|
+
const settings = safeReadJSON(SETTINGS_PATH, {});
|
|
24
|
+
const autoApprove = settings.autoApprovePermissions;
|
|
25
|
+
if (autoApprove === true) {
|
|
26
|
+
return {
|
|
27
|
+
permission_mode: 'relaxed',
|
|
28
|
+
dangerous_skip_permissions: false,
|
|
29
|
+
auto_accept_scope: ['auto-approve'],
|
|
30
|
+
detected_from: 'settings',
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
// 3. 환경변수 확인
|
|
34
|
+
if (process.env.CLAUDE_AUTO_ACCEPT === 'true') {
|
|
35
|
+
return {
|
|
36
|
+
permission_mode: 'relaxed',
|
|
37
|
+
dangerous_skip_permissions: false,
|
|
38
|
+
auto_accept_scope: ['env-auto-accept'],
|
|
39
|
+
detected_from: 'env',
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
// 4. 기본값: guarded
|
|
43
|
+
return {
|
|
44
|
+
permission_mode: 'guarded',
|
|
45
|
+
dangerous_skip_permissions: false,
|
|
46
|
+
auto_accept_scope: [],
|
|
47
|
+
detected_from: 'default',
|
|
48
|
+
};
|
|
49
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forgen v1 — Scope Resolver (simplified)
|
|
3
|
+
*
|
|
4
|
+
* v1에서는 scope = me only. 팀 팩 시스템 제거.
|
|
5
|
+
* compound-loop, solution-injector 호환을 위해 유지.
|
|
6
|
+
*/
|
|
7
|
+
import type { ScopeInfo } from './types.js';
|
|
8
|
+
export declare function resolveScope(cwd: string, _philosophySource?: 'project' | 'global' | 'default'): ScopeInfo;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forgen v1 — Scope Resolver (simplified)
|
|
3
|
+
*
|
|
4
|
+
* v1에서는 scope = me only. 팀 팩 시스템 제거.
|
|
5
|
+
* compound-loop, solution-injector 호환을 위해 유지.
|
|
6
|
+
*/
|
|
7
|
+
import * as fs from 'node:fs';
|
|
8
|
+
import * as path from 'node:path';
|
|
9
|
+
import { ME_DIR, ME_SOLUTIONS, ME_RULES, projectDir } from './paths.js';
|
|
10
|
+
import { createLogger } from './logger.js';
|
|
11
|
+
const log = createLogger('scope-resolver');
|
|
12
|
+
/** 디렉토리 내 .md 파일 수 카운트 */
|
|
13
|
+
function countFiles(dir, ext = '.md') {
|
|
14
|
+
if (!fs.existsSync(dir))
|
|
15
|
+
return 0;
|
|
16
|
+
try {
|
|
17
|
+
return fs.readdirSync(dir).filter((f) => f.endsWith(ext)).length;
|
|
18
|
+
}
|
|
19
|
+
catch (e) {
|
|
20
|
+
log.debug(`countFiles 실패: ${dir}`, e);
|
|
21
|
+
return 0;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export function resolveScope(cwd, _philosophySource) {
|
|
25
|
+
const meSolutions = countFiles(ME_SOLUTIONS);
|
|
26
|
+
const meRules = countFiles(ME_RULES);
|
|
27
|
+
const projDir = projectDir(cwd);
|
|
28
|
+
const projSolutions = countFiles(path.join(projDir, 'solutions'));
|
|
29
|
+
const parts = [`Me(${meSolutions})`];
|
|
30
|
+
if (projSolutions > 0)
|
|
31
|
+
parts.push(`Project(${projSolutions})`);
|
|
32
|
+
return {
|
|
33
|
+
me: {
|
|
34
|
+
philosophyPath: path.join(ME_DIR, 'philosophy.json'),
|
|
35
|
+
solutionCount: meSolutions,
|
|
36
|
+
ruleCount: meRules,
|
|
37
|
+
},
|
|
38
|
+
// v1: team scope 제거
|
|
39
|
+
project: {
|
|
40
|
+
path: projDir,
|
|
41
|
+
solutionCount: projSolutions,
|
|
42
|
+
},
|
|
43
|
+
summary: parts.join(' + '),
|
|
44
|
+
};
|
|
45
|
+
}
|