@wooojin/forgen 0.4.0 → 0.4.3
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 +5 -5
- package/CHANGELOG.md +194 -15
- package/CONTRIBUTING.md +2 -2
- package/README.ja.md +74 -9
- package/README.ko.md +77 -12
- package/README.md +127 -25
- package/README.zh.md +43 -9
- package/assets/README.md +86 -0
- package/assets/architecture.svg +100 -0
- package/assets/banner.png +0 -0
- package/assets/banner.svg +53 -0
- package/assets/demo/01-install.gif +0 -0
- package/assets/demo/01-install.tape +54 -0
- package/assets/demo/02-compound-learning.gif +0 -0
- package/assets/demo/02-compound-learning.tape +50 -0
- package/assets/demo/03-forge-personalization.gif +0 -0
- package/assets/demo/03-forge-personalization.tape +64 -0
- package/assets/demo/before-after.gif +0 -0
- package/assets/demo/before-after.tape +98 -0
- package/assets/demo-preview.svg +96 -0
- package/assets/icon.png +0 -0
- package/{hooks → assets/shared}/hook-registry.json +2 -1
- package/dist/checks/conclusion-verification-ratio.d.ts +37 -0
- package/dist/checks/conclusion-verification-ratio.js +86 -0
- package/dist/checks/fact-vs-agreement.d.ts +47 -0
- package/dist/checks/fact-vs-agreement.js +92 -0
- package/dist/checks/self-score-deflation.d.ts +38 -0
- package/dist/checks/self-score-deflation.js +108 -0
- package/dist/cli.js +98 -6
- package/dist/core/auto-compound-runner.js +137 -49
- package/dist/core/behavior-classifier.d.ts +28 -0
- package/dist/core/behavior-classifier.js +46 -0
- package/dist/core/dashboard.d.ts +7 -0
- package/dist/core/dashboard.js +41 -2
- package/dist/core/doctor.js +118 -5
- package/dist/core/extraction-notice.d.ts +18 -0
- package/dist/core/extraction-notice.js +64 -0
- package/dist/core/git-stats.d.ts +36 -0
- package/dist/core/git-stats.js +79 -0
- package/dist/core/harness.d.ts +1 -1
- package/dist/core/harness.js +27 -20
- package/dist/core/host-detect.d.ts +42 -0
- package/dist/core/host-detect.js +68 -0
- package/dist/core/init-cli.d.ts +26 -0
- package/dist/core/init-cli.js +104 -0
- package/dist/core/init.js +17 -0
- package/dist/core/inspect-cli.js +1 -2
- package/dist/core/installer.js +2 -2
- package/dist/core/migrate-cli.d.ts +11 -0
- package/dist/core/migrate-cli.js +53 -0
- package/dist/core/migrate-evidence-host.d.ts +36 -0
- package/dist/core/migrate-evidence-host.js +49 -0
- package/dist/core/paths.d.ts +8 -1
- package/dist/core/paths.js +11 -2
- package/dist/core/recall-cli.d.ts +26 -0
- package/dist/core/recall-cli.js +125 -0
- package/dist/core/recall-reference-detector.d.ts +43 -0
- package/dist/core/recall-reference-detector.js +65 -0
- package/dist/core/settings-injector.js +4 -2
- package/dist/core/spawn.d.ts +1 -1
- package/dist/core/spawn.js +4 -11
- package/dist/core/stats-cli.d.ts +21 -0
- package/dist/core/stats-cli.js +133 -10
- package/dist/core/trust-layer-intent.d.ts +35 -0
- package/dist/core/trust-layer-intent.js +30 -0
- package/dist/core/types.d.ts +1 -1
- package/dist/core/uninstall.js +2 -1
- package/dist/engine/compound-cli.js +1 -0
- package/dist/engine/compound-export.js +8 -3
- package/dist/engine/compound-extractor.js +7 -9
- package/dist/engine/learn-cli.js +5 -6
- package/dist/engine/lifecycle/bypass-detector.d.ts +6 -1
- package/dist/engine/lifecycle/bypass-detector.js +57 -5
- package/dist/engine/lifecycle/lifecycle-cli.js +4 -4
- package/dist/engine/lifecycle/meta-reclassifier.js +3 -3
- package/dist/engine/lifecycle/orchestrator.js +2 -2
- package/dist/engine/lifecycle/signals.js +6 -6
- package/dist/engine/meta-learning/session-quality-scorer.d.ts +1 -6
- package/dist/engine/meta-learning/session-quality-scorer.js +2 -21
- package/dist/engine/skill-promoter.js +3 -6
- package/dist/fgx.js +2 -1
- package/dist/forge/evidence-processor.js +12 -0
- package/dist/forge/onboarding.d.ts +3 -2
- package/dist/forge/onboarding.js +3 -2
- package/dist/hooks/context-guard.js +1 -1
- package/dist/hooks/dangerous-patterns.json +3 -3
- package/dist/hooks/db-guard.js +21 -5
- package/dist/hooks/forge-loop-progress.d.ts +9 -0
- package/dist/hooks/forge-loop-progress.js +38 -0
- package/dist/hooks/hook-registry.js +1 -1
- package/dist/hooks/hooks-generator.d.ts +15 -1
- package/dist/hooks/hooks-generator.js +18 -16
- package/dist/hooks/intent-classifier.js +1 -1
- package/dist/hooks/keyword-detector.js +2 -2
- package/dist/hooks/notepad-injector.js +1 -1
- package/dist/hooks/permission-handler.js +1 -1
- package/dist/hooks/post-tool-failure.js +1 -1
- package/dist/hooks/post-tool-use.d.ts +7 -1
- package/dist/hooks/post-tool-use.js +50 -23
- package/dist/hooks/pre-compact.js +2 -2
- package/dist/hooks/pre-tool-use.d.ts +7 -0
- package/dist/hooks/pre-tool-use.js +28 -10
- package/dist/hooks/rate-limiter.js +3 -3
- package/dist/hooks/secret-filter.js +1 -1
- package/dist/hooks/session-recovery.js +12 -1
- package/dist/hooks/shared/blocking-allowlist.d.ts +28 -0
- package/dist/hooks/shared/blocking-allowlist.js +38 -0
- package/dist/hooks/shared/command-parser.d.ts +44 -0
- package/dist/hooks/shared/command-parser.js +50 -0
- package/dist/hooks/shared/forge-loop-state.d.ts +36 -0
- package/dist/hooks/shared/forge-loop-state.js +116 -0
- package/dist/hooks/shared/hook-response.d.ts +30 -2
- package/dist/hooks/shared/hook-response.js +61 -3
- package/dist/hooks/skill-injector.js +2 -2
- package/dist/hooks/slop-detector.js +2 -2
- package/dist/hooks/solution-injector.d.ts +9 -0
- package/dist/hooks/solution-injector.js +48 -5
- package/dist/hooks/stop-guard.js +152 -13
- package/dist/hooks/subagent-tracker.js +1 -1
- package/dist/host/capabilities-claude.d.ts +8 -0
- package/dist/host/capabilities-claude.js +46 -0
- package/dist/host/capabilities-codex.d.ts +11 -0
- package/dist/host/capabilities-codex.js +50 -0
- package/dist/host/capabilities-registry.d.ts +11 -0
- package/dist/host/capabilities-registry.js +30 -0
- package/dist/host/codex-adapter.d.ts +8 -5
- package/dist/host/codex-adapter.js +10 -82
- package/dist/host/codex-output-parser.d.ts +39 -0
- package/dist/host/codex-output-parser.js +75 -0
- package/dist/host/exec-host.d.ts +54 -0
- package/dist/host/exec-host.js +92 -0
- package/dist/host/host-runtime.d.ts +37 -0
- package/dist/host/host-runtime.js +51 -0
- package/dist/host/install-claude.d.ts +35 -0
- package/dist/host/install-claude.js +238 -0
- package/dist/host/install-codex.d.ts +44 -0
- package/dist/host/install-codex.js +276 -0
- package/dist/host/install-orchestrator.d.ts +34 -0
- package/dist/host/install-orchestrator.js +126 -0
- package/dist/host/invoke-agent.d.ts +27 -0
- package/dist/host/invoke-agent.js +115 -0
- package/dist/host/parity-harness.d.ts +62 -0
- package/dist/host/parity-harness.js +283 -0
- package/dist/host/projection.d.ts +35 -0
- package/dist/host/projection.js +126 -0
- package/dist/i18n/index.js +3 -5
- package/dist/mcp/server.js +11 -0
- package/dist/mcp/tools.js +47 -0
- package/dist/services/session.d.ts +6 -3
- package/dist/services/session.js +33 -4
- package/dist/store/evidence-store.d.ts +1 -0
- package/dist/store/evidence-store.js +45 -3
- package/dist/store/host-mismatch.d.ts +42 -0
- package/dist/store/host-mismatch.js +65 -0
- package/dist/store/implicit-feedback-store.d.ts +59 -0
- package/dist/store/implicit-feedback-store.js +153 -0
- package/dist/store/profile-store.d.ts +29 -0
- package/dist/store/profile-store.js +53 -0
- package/dist/store/rule-store.js +8 -0
- package/dist/store/types.d.ts +13 -0
- package/hooks/hooks.json +6 -1
- package/package.json +7 -5
- package/plugin.json +4 -4
- package/scripts/postinstall.js +100 -25
- /package/{agents → assets/claude/agents}/analyst.md +0 -0
- /package/{agents → assets/claude/agents}/architect.md +0 -0
- /package/{agents → assets/claude/agents}/code-reviewer.md +0 -0
- /package/{agents → assets/claude/agents}/critic.md +0 -0
- /package/{agents → assets/claude/agents}/debugger.md +0 -0
- /package/{agents → assets/claude/agents}/designer.md +0 -0
- /package/{agents → assets/claude/agents}/executor.md +0 -0
- /package/{agents → assets/claude/agents}/explore.md +0 -0
- /package/{agents → assets/claude/agents}/git-master.md +0 -0
- /package/{agents → assets/claude/agents}/planner.md +0 -0
- /package/{agents → assets/claude/agents}/solution-evolver.md +0 -0
- /package/{agents → assets/claude/agents}/test-engineer.md +0 -0
- /package/{agents → assets/claude/agents}/verifier.md +0 -0
- /package/{commands → assets/claude/commands}/architecture-decision.md +0 -0
- /package/{commands → assets/claude/commands}/calibrate.md +0 -0
- /package/{commands → assets/claude/commands}/code-review.md +0 -0
- /package/{commands → assets/claude/commands}/compound.md +0 -0
- /package/{commands → assets/claude/commands}/deep-interview.md +0 -0
- /package/{commands → assets/claude/commands}/docker.md +0 -0
- /package/{commands → assets/claude/commands}/forge-loop.md +0 -0
- /package/{commands → assets/claude/commands}/learn.md +0 -0
- /package/{commands → assets/claude/commands}/retro.md +0 -0
- /package/{commands → assets/claude/commands}/ship.md +0 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# forgen — Compound Learning Demo
|
|
2
|
+
# Shows: Claude using accumulated knowledge → auto-compound extracting patterns
|
|
3
|
+
|
|
4
|
+
Output assets/demo/02-compound-learning.gif
|
|
5
|
+
|
|
6
|
+
Set Shell "zsh"
|
|
7
|
+
Set FontFamily "JetBrains Mono"
|
|
8
|
+
Set FontSize 15
|
|
9
|
+
Set Width 1200
|
|
10
|
+
Set Height 700
|
|
11
|
+
Set Padding 20
|
|
12
|
+
Set Theme "Catppuccin Mocha"
|
|
13
|
+
Set TypingSpeed 35ms
|
|
14
|
+
Set WindowBar Colorful
|
|
15
|
+
Set BorderRadius 10
|
|
16
|
+
Set Margin 20
|
|
17
|
+
Set MarginFill "#1e1e2e"
|
|
18
|
+
|
|
19
|
+
Hide
|
|
20
|
+
Type "cd /tmp/forgen-demo && clear"
|
|
21
|
+
Enter
|
|
22
|
+
Sleep 1s
|
|
23
|
+
Show
|
|
24
|
+
|
|
25
|
+
# Step 1: Ask Claude about TDD — compound should inject knowledge
|
|
26
|
+
Type "claude -p 'tdd 방식으로 isPrime 함수 만들어줘' --allowedTools Bash,Write,Edit"
|
|
27
|
+
Sleep 500ms
|
|
28
|
+
Enter
|
|
29
|
+
Sleep 15s
|
|
30
|
+
|
|
31
|
+
# Step 2: Show compound solutions matched
|
|
32
|
+
Type "# Compound matched starter-tdd-red-green-refactor"
|
|
33
|
+
Enter
|
|
34
|
+
Sleep 2s
|
|
35
|
+
|
|
36
|
+
# Step 3: Search compound knowledge via MCP
|
|
37
|
+
Type "claude -p 'compound-search MCP 도구로 typescript를 검색해줘'"
|
|
38
|
+
Sleep 500ms
|
|
39
|
+
Enter
|
|
40
|
+
Sleep 10s
|
|
41
|
+
|
|
42
|
+
# Step 4: Show accumulated solutions
|
|
43
|
+
Type "ls ~/.compound/me/solutions/ | wc -l"
|
|
44
|
+
Sleep 500ms
|
|
45
|
+
Enter
|
|
46
|
+
Sleep 1s
|
|
47
|
+
|
|
48
|
+
Type "# Knowledge grows with every session"
|
|
49
|
+
Enter
|
|
50
|
+
Sleep 3s
|
|
Binary file
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# forgen — Forge Personalization Demo
|
|
2
|
+
# Shows: forge interview → profile generated → personalized config
|
|
3
|
+
|
|
4
|
+
Output assets/demo/03-forge-personalization.gif
|
|
5
|
+
|
|
6
|
+
Set Shell "zsh"
|
|
7
|
+
Set FontFamily "JetBrains Mono"
|
|
8
|
+
Set FontSize 15
|
|
9
|
+
Set Width 1200
|
|
10
|
+
Set Height 700
|
|
11
|
+
Set Padding 20
|
|
12
|
+
Set Theme "Catppuccin Mocha"
|
|
13
|
+
Set TypingSpeed 35ms
|
|
14
|
+
Set WindowBar Colorful
|
|
15
|
+
Set BorderRadius 10
|
|
16
|
+
Set Margin 20
|
|
17
|
+
Set MarginFill "#1e1e2e"
|
|
18
|
+
|
|
19
|
+
Hide
|
|
20
|
+
Type "cd /tmp/forgen-demo && clear"
|
|
21
|
+
Enter
|
|
22
|
+
Sleep 1s
|
|
23
|
+
Show
|
|
24
|
+
|
|
25
|
+
# Step 1: Start forge
|
|
26
|
+
Type "forgen forge"
|
|
27
|
+
Sleep 500ms
|
|
28
|
+
Enter
|
|
29
|
+
Sleep 3s
|
|
30
|
+
|
|
31
|
+
# Answer questions (simulated — quality-focused developer)
|
|
32
|
+
Type "2"
|
|
33
|
+
Enter
|
|
34
|
+
Sleep 2s
|
|
35
|
+
|
|
36
|
+
Type "1"
|
|
37
|
+
Enter
|
|
38
|
+
Sleep 2s
|
|
39
|
+
|
|
40
|
+
Type "2"
|
|
41
|
+
Enter
|
|
42
|
+
Sleep 2s
|
|
43
|
+
|
|
44
|
+
Type "1"
|
|
45
|
+
Enter
|
|
46
|
+
Sleep 2s
|
|
47
|
+
|
|
48
|
+
Type "2"
|
|
49
|
+
Enter
|
|
50
|
+
Sleep 2s
|
|
51
|
+
|
|
52
|
+
# Wait for profile generation
|
|
53
|
+
Sleep 5s
|
|
54
|
+
|
|
55
|
+
# Step 2: Show generated rules
|
|
56
|
+
Type "cat .claude/rules/forge-quality.md | head -15"
|
|
57
|
+
Sleep 500ms
|
|
58
|
+
Enter
|
|
59
|
+
Sleep 3s
|
|
60
|
+
|
|
61
|
+
# Step 3: Show that Claude behavior is now personalized
|
|
62
|
+
Type "# Claude is now tuned to YOUR coding style"
|
|
63
|
+
Enter
|
|
64
|
+
Sleep 3s
|
|
Binary file
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# forgen — Same Tool, Different Developer
|
|
2
|
+
# Shows how forge adapts Claude to YOUR coding style
|
|
3
|
+
|
|
4
|
+
Output assets/demo/before-after.gif
|
|
5
|
+
|
|
6
|
+
Set Shell "zsh"
|
|
7
|
+
Set FontFamily "JetBrains Mono"
|
|
8
|
+
Set FontSize 14
|
|
9
|
+
Set Width 1200
|
|
10
|
+
Set Height 750
|
|
11
|
+
Set Padding 20
|
|
12
|
+
Set Theme "Catppuccin Mocha"
|
|
13
|
+
Set TypingSpeed 25ms
|
|
14
|
+
Set WindowBar Colorful
|
|
15
|
+
Set BorderRadius 10
|
|
16
|
+
Set Margin 20
|
|
17
|
+
Set MarginFill "#1e1e2e"
|
|
18
|
+
|
|
19
|
+
# ═══════════════════════════════════════
|
|
20
|
+
# Developer A: Senior — wants terse, severity-only
|
|
21
|
+
# ═══════════════════════════════════════
|
|
22
|
+
|
|
23
|
+
Hide
|
|
24
|
+
Type `TMPDIR=$(mktemp -d) && cd "$TMPDIR" && git init -q && git config user.email "t@t" && git config user.name "T" && mkdir -p .claude/rules && cat > .claude/rules/forge-communication.md << 'EOF'`
|
|
25
|
+
Enter
|
|
26
|
+
Type "# Forgen Forge — Communication Style (terse profile)"
|
|
27
|
+
Enter
|
|
28
|
+
Type "- Keep responses under 3 sentences unless showing code"
|
|
29
|
+
Enter
|
|
30
|
+
Type "- No preamble or trailing summary"
|
|
31
|
+
Enter
|
|
32
|
+
Type "- For code review: use [SEVERITY] format only"
|
|
33
|
+
Enter
|
|
34
|
+
Type "EOF"
|
|
35
|
+
Enter
|
|
36
|
+
Type "clear"
|
|
37
|
+
Enter
|
|
38
|
+
Sleep 1s
|
|
39
|
+
Show
|
|
40
|
+
|
|
41
|
+
Type "echo ' Developer A: Senior engineer — prefers terse, severity-only'"
|
|
42
|
+
Enter
|
|
43
|
+
Sleep 2s
|
|
44
|
+
|
|
45
|
+
Type "cat .claude/rules/forge-communication.md"
|
|
46
|
+
Enter
|
|
47
|
+
Sleep 3s
|
|
48
|
+
|
|
49
|
+
Type@20ms `claude -p "이 코드를 리뷰해줘: function add(a, b) { let result = a + b; return result; } 파일은 만들지 마."`
|
|
50
|
+
Sleep 500ms
|
|
51
|
+
Enter
|
|
52
|
+
Sleep 20s
|
|
53
|
+
|
|
54
|
+
Sleep 5s
|
|
55
|
+
|
|
56
|
+
# ═══════════════════════════════════════
|
|
57
|
+
# Developer B: Junior — wants explanations & examples
|
|
58
|
+
# ═══════════════════════════════════════
|
|
59
|
+
|
|
60
|
+
Hide
|
|
61
|
+
Type `TMPDIR2=$(mktemp -d) && cd "$TMPDIR2" && git init -q && git config user.email "t@t" && git config user.name "T" && mkdir -p .claude/rules && cat > .claude/rules/forge-communication.md << 'EOF'`
|
|
62
|
+
Enter
|
|
63
|
+
Type "# Forgen Forge — Communication Style (educational profile)"
|
|
64
|
+
Enter
|
|
65
|
+
Type "- Explain reasoning and trade-offs for every suggestion"
|
|
66
|
+
Enter
|
|
67
|
+
Type "- Include examples showing what could go wrong"
|
|
68
|
+
Enter
|
|
69
|
+
Type "- Teach concepts — explain the why not just the what"
|
|
70
|
+
Enter
|
|
71
|
+
Type "EOF"
|
|
72
|
+
Enter
|
|
73
|
+
Type "clear"
|
|
74
|
+
Enter
|
|
75
|
+
Sleep 1s
|
|
76
|
+
Show
|
|
77
|
+
|
|
78
|
+
Type ""
|
|
79
|
+
Enter
|
|
80
|
+
Type "echo ' Developer B: Junior engineer — wants explanations & examples'"
|
|
81
|
+
Enter
|
|
82
|
+
Sleep 2s
|
|
83
|
+
|
|
84
|
+
Type "cat .claude/rules/forge-communication.md"
|
|
85
|
+
Enter
|
|
86
|
+
Sleep 3s
|
|
87
|
+
|
|
88
|
+
Type@20ms `claude -p "이 코드를 리뷰해줘: function add(a, b) { let result = a + b; return result; } 파일은 만들지 마."`
|
|
89
|
+
Sleep 500ms
|
|
90
|
+
Enter
|
|
91
|
+
Sleep 25s
|
|
92
|
+
|
|
93
|
+
Sleep 3s
|
|
94
|
+
Type ""
|
|
95
|
+
Enter
|
|
96
|
+
Type "echo ' Same question. Same tool. Different developer. ⚡'"
|
|
97
|
+
Enter
|
|
98
|
+
Sleep 5s
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="800" height="340" viewBox="0 0 800 340">
|
|
2
|
+
<style>
|
|
3
|
+
.term { font-family: 'JetBrains Mono', 'Fira Code', 'Cascadia Code', 'SF Mono', monospace; font-size: 13px; }
|
|
4
|
+
.prompt { fill: #a6e3a1; }
|
|
5
|
+
.cmd { fill: #cdd6f4; }
|
|
6
|
+
.tag { fill: #89b4fa; }
|
|
7
|
+
.haiku { fill: #f9e2af; }
|
|
8
|
+
.sonnet { fill: #a6e3a1; }
|
|
9
|
+
.opus { fill: #cba6f7; }
|
|
10
|
+
.dim { fill: #6c7086; }
|
|
11
|
+
.box { fill: #a6e3a1; }
|
|
12
|
+
@keyframes typeIn { from { opacity: 0; } to { opacity: 1; } }
|
|
13
|
+
@keyframes fadeIn { 0% { opacity: 0; } 100% { opacity: 1; } }
|
|
14
|
+
@keyframes blink { 0%, 100% { opacity: 0.8; } 50% { opacity: 0; } }
|
|
15
|
+
.line1 { animation: typeIn 0.1s 0.3s both; }
|
|
16
|
+
.line2 { animation: fadeIn 0.2s 0.8s both; }
|
|
17
|
+
.line3 { animation: fadeIn 0.2s 1.1s both; }
|
|
18
|
+
.line4 { animation: fadeIn 0.2s 1.4s both; }
|
|
19
|
+
.line5 { animation: fadeIn 0.2s 1.7s both; }
|
|
20
|
+
.line6 { animation: fadeIn 0.2s 2.0s both; }
|
|
21
|
+
.line7 { animation: fadeIn 0.3s 2.5s both; }
|
|
22
|
+
.cursor { animation: blink 1s 2.8s infinite; }
|
|
23
|
+
</style>
|
|
24
|
+
|
|
25
|
+
<!-- Terminal window -->
|
|
26
|
+
<rect width="800" height="340" rx="10" ry="10" fill="#1e1e2e"/>
|
|
27
|
+
<rect width="800" height="36" rx="10" ry="10" fill="#313244"/>
|
|
28
|
+
<rect y="26" width="800" height="10" fill="#313244"/>
|
|
29
|
+
|
|
30
|
+
<!-- Traffic lights -->
|
|
31
|
+
<circle cx="20" cy="18" r="6" fill="#f38ba8"/>
|
|
32
|
+
<circle cx="40" cy="18" r="6" fill="#f9e2af"/>
|
|
33
|
+
<circle cx="60" cy="18" r="6" fill="#a6e3a1"/>
|
|
34
|
+
<text x="400" y="23" text-anchor="middle" class="term" font-size="12" fill="#6c7086">forgen — terminal</text>
|
|
35
|
+
|
|
36
|
+
<!-- Line 1: command -->
|
|
37
|
+
<g class="line1">
|
|
38
|
+
<text x="24" y="68" class="term prompt">$</text>
|
|
39
|
+
<text x="40" y="68" class="term cmd">forgen</text>
|
|
40
|
+
</g>
|
|
41
|
+
|
|
42
|
+
<!-- Line 2: philosophy -->
|
|
43
|
+
<g class="line2">
|
|
44
|
+
<text x="24" y="96" class="term tag">[forgen]</text>
|
|
45
|
+
<text x="96" y="96" class="term cmd">Philosophy: </text>
|
|
46
|
+
<text x="194" y="96" class="term" fill="#f9e2af">my-engineering</text>
|
|
47
|
+
<text x="310" y="96" class="term dim"> (global)</text>
|
|
48
|
+
</g>
|
|
49
|
+
|
|
50
|
+
<!-- Line 3: scope -->
|
|
51
|
+
<g class="line3">
|
|
52
|
+
<text x="24" y="120" class="term tag">[forgen]</text>
|
|
53
|
+
<text x="96" y="120" class="term cmd">Scope: Me(5) │ 3 rules, 2 solutions</text>
|
|
54
|
+
</g>
|
|
55
|
+
|
|
56
|
+
<!-- Line 4: routing -->
|
|
57
|
+
<g class="line4">
|
|
58
|
+
<text x="24" y="144" class="term tag">[forgen]</text>
|
|
59
|
+
<text x="96" y="144" class="term cmd">Routing: </text>
|
|
60
|
+
<text x="172" y="144" class="term haiku">haiku:3</text>
|
|
61
|
+
<text x="232" y="144" class="term dim"> │ </text>
|
|
62
|
+
<text x="256" y="144" class="term sonnet">sonnet:5</text>
|
|
63
|
+
<text x="324" y="144" class="term dim"> │ </text>
|
|
64
|
+
<text x="348" y="144" class="term opus">opus:4</text>
|
|
65
|
+
</g>
|
|
66
|
+
|
|
67
|
+
<!-- Line 5: pack -->
|
|
68
|
+
<g class="line5">
|
|
69
|
+
<text x="24" y="168" class="term tag">[forgen]</text>
|
|
70
|
+
<text x="96" y="168" class="term cmd">Pack: backend v1.0.0 (5 rules, 3 solutions)</text>
|
|
71
|
+
</g>
|
|
72
|
+
|
|
73
|
+
<!-- Line 6: launching -->
|
|
74
|
+
<g class="line6">
|
|
75
|
+
<text x="24" y="192" class="term tag">[forgen]</text>
|
|
76
|
+
<text x="96" y="192" class="term cmd">Starting Claude Code...</text>
|
|
77
|
+
</g>
|
|
78
|
+
|
|
79
|
+
<!-- Separator -->
|
|
80
|
+
<g class="line7">
|
|
81
|
+
<line x1="24" y1="212" x2="776" y2="212" stroke="#313244" stroke-width="1"/>
|
|
82
|
+
|
|
83
|
+
<!-- Claude Code box -->
|
|
84
|
+
<text x="24" y="236" class="term dim">╭──────────────────────────────────────────────────╮</text>
|
|
85
|
+
<text x="24" y="256" class="term dim">│</text>
|
|
86
|
+
<text x="40" y="256" class="term box"> ✓ Claude Code (philosophy-driven mode)</text>
|
|
87
|
+
<text x="430" y="256" class="term dim">│</text>
|
|
88
|
+
<text x="24" y="276" class="term dim">│</text>
|
|
89
|
+
<text x="40" y="276" class="term" fill="#cdd6f4"> 19 agents │ 19 skills │ 18 hooks loaded</text>
|
|
90
|
+
<text x="430" y="276" class="term dim">│</text>
|
|
91
|
+
<text x="24" y="296" class="term dim">╰──────────────────────────────────────────────────╯</text>
|
|
92
|
+
|
|
93
|
+
<!-- Blinking cursor -->
|
|
94
|
+
<rect x="24" y="310" width="8" height="16" fill="#cdd6f4" class="cursor"/>
|
|
95
|
+
</g>
|
|
96
|
+
</svg>
|
package/assets/icon.png
ADDED
|
Binary file
|
|
@@ -18,5 +18,6 @@
|
|
|
18
18
|
{ "name": "subagent-tracker-stop", "tier": "workflow", "event": "SubagentStop", "matcher": "*", "script": "hooks/subagent-tracker.js stop", "timeout": 2, "compoundCritical": false },
|
|
19
19
|
{ "name": "post-tool-failure", "tier": "workflow", "event": "PostToolUseFailure", "matcher": "*", "script": "hooks/post-tool-failure.js", "timeout": 3, "compoundCritical": false },
|
|
20
20
|
{ "name": "solution-injector", "tier": "compound-core", "event": "UserPromptSubmit", "matcher": "*", "script": "hooks/solution-injector.js", "timeout": 5, "compoundCritical": true },
|
|
21
|
-
{ "name": "skill-injector", "tier": "compound-core", "event": "UserPromptSubmit", "matcher": "*", "script": "hooks/skill-injector.js", "timeout": 5, "compoundCritical": true }
|
|
21
|
+
{ "name": "skill-injector", "tier": "compound-core", "event": "UserPromptSubmit", "matcher": "*", "script": "hooks/skill-injector.js", "timeout": 5, "compoundCritical": true },
|
|
22
|
+
{ "name": "forge-loop-progress", "tier": "compound-core", "event": "UserPromptSubmit", "matcher": "*", "script": "hooks/forge-loop-progress.js", "timeout": 2, "compoundCritical": false }
|
|
22
23
|
]
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forgen v0.4.1 — TEST-3: 결론 vs 검증 비율 가드
|
|
3
|
+
*
|
|
4
|
+
* Claude 응답 텍스트에서 **결론 키워드** 와 **검증 키워드** 빈도 비율을 측정.
|
|
5
|
+
* 결론 / 검증 > 3 이면 "결론을 쏟아내지만 검증이 부족한" 합의-기반 완료 선언
|
|
6
|
+
* 패턴 — stop-guard 에서 block.
|
|
7
|
+
*
|
|
8
|
+
* 배경 (RC3): v0.4.0 self-interview 에서 "통과했다 / 완료됐다" 같은 결론이
|
|
9
|
+
* 한 응답에 5~8회 반복되지만 "테스트 실행했나 / 증거가 뭔가" 관련 표현은
|
|
10
|
+
* 0회인 케이스 반복 관찰. TEST-1 이 "측정 도구 호출 0건" 을 봤다면, TEST-3
|
|
11
|
+
* 은 같은 문제를 **텍스트-내부** 비율로 잡는다 (도구 호출이 있어도 서술이
|
|
12
|
+
* 결론-편향이면 감지).
|
|
13
|
+
*
|
|
14
|
+
* 순수 함수 — Stop hook 이 `block_message` 로 주입할 수 있도록 reason 문자열을
|
|
15
|
+
* 직접 반환.
|
|
16
|
+
*/
|
|
17
|
+
export interface RatioCheckInput {
|
|
18
|
+
text: string;
|
|
19
|
+
/** 비율 임계값. 기본 3 (결론이 검증의 3배 넘으면 block). */
|
|
20
|
+
threshold?: number;
|
|
21
|
+
/**
|
|
22
|
+
* 결론/검증 둘 다 합쳐 이 개수 미만이면 판정 보류 (sparse text).
|
|
23
|
+
* 기본 4 — 짧은 1-2줄 응답에 오탐 방지.
|
|
24
|
+
*/
|
|
25
|
+
minTotal?: number;
|
|
26
|
+
}
|
|
27
|
+
export interface RatioCheckResult {
|
|
28
|
+
/** true = 결론 편향 감지 — block 후보. */
|
|
29
|
+
block: boolean;
|
|
30
|
+
conclusionCount: number;
|
|
31
|
+
verificationCount: number;
|
|
32
|
+
/** 검증이 0이면 Infinity, 아니면 결론/검증. */
|
|
33
|
+
ratio: number;
|
|
34
|
+
/** block 시 stop-guard block_message 로 주입할 사람-읽기 문장. */
|
|
35
|
+
reason: string;
|
|
36
|
+
}
|
|
37
|
+
export declare function checkConclusionVerificationRatio(input: RatioCheckInput): RatioCheckResult;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forgen v0.4.1 — TEST-3: 결론 vs 검증 비율 가드
|
|
3
|
+
*
|
|
4
|
+
* Claude 응답 텍스트에서 **결론 키워드** 와 **검증 키워드** 빈도 비율을 측정.
|
|
5
|
+
* 결론 / 검증 > 3 이면 "결론을 쏟아내지만 검증이 부족한" 합의-기반 완료 선언
|
|
6
|
+
* 패턴 — stop-guard 에서 block.
|
|
7
|
+
*
|
|
8
|
+
* 배경 (RC3): v0.4.0 self-interview 에서 "통과했다 / 완료됐다" 같은 결론이
|
|
9
|
+
* 한 응답에 5~8회 반복되지만 "테스트 실행했나 / 증거가 뭔가" 관련 표현은
|
|
10
|
+
* 0회인 케이스 반복 관찰. TEST-1 이 "측정 도구 호출 0건" 을 봤다면, TEST-3
|
|
11
|
+
* 은 같은 문제를 **텍스트-내부** 비율로 잡는다 (도구 호출이 있어도 서술이
|
|
12
|
+
* 결론-편향이면 감지).
|
|
13
|
+
*
|
|
14
|
+
* 순수 함수 — Stop hook 이 `block_message` 로 주입할 수 있도록 reason 문자열을
|
|
15
|
+
* 직접 반환.
|
|
16
|
+
*/
|
|
17
|
+
/** 결론 키워드 — 상태를 단정적으로 선언하는 어휘. */
|
|
18
|
+
const CONCLUSION_PATTERNS = [
|
|
19
|
+
/\b(pass(es|ed)?|passing)\b/gi,
|
|
20
|
+
/\b(done|ready|shipped|finished|complete)\b/gi,
|
|
21
|
+
/\bLGTM\b/g,
|
|
22
|
+
/\bconfirmed\b/gi,
|
|
23
|
+
/\bverified\b/gi,
|
|
24
|
+
/\bvalidated\b/gi,
|
|
25
|
+
/(통과(했|됐|함|합니다))/g,
|
|
26
|
+
/(완료(했|됐|됨|됐습니다))/g,
|
|
27
|
+
/(성공(했|했습니다|적))/g,
|
|
28
|
+
/(동작(합니다|함|한다))/g,
|
|
29
|
+
];
|
|
30
|
+
/** 검증 키워드 — 측정/확인/실행 행위를 서술하는 어휘. */
|
|
31
|
+
const VERIFICATION_PATTERNS = [
|
|
32
|
+
/\b(test(s|ed|ing)?|tested)\b/gi,
|
|
33
|
+
/\b(verify|verifying|verification)\b/gi,
|
|
34
|
+
/\b(check(ed|ing)?)\b/gi,
|
|
35
|
+
/\b(run|ran|running)\b/gi,
|
|
36
|
+
/\b(measure(d|ment)?)\b/gi,
|
|
37
|
+
/\bevidence\b/gi,
|
|
38
|
+
/증거/g,
|
|
39
|
+
/테스트/g,
|
|
40
|
+
/확인/g,
|
|
41
|
+
/검증/g,
|
|
42
|
+
/실행/g,
|
|
43
|
+
/측정/g,
|
|
44
|
+
];
|
|
45
|
+
function countMatches(text, patterns) {
|
|
46
|
+
let n = 0;
|
|
47
|
+
for (const p of patterns) {
|
|
48
|
+
const m = text.match(p);
|
|
49
|
+
if (m)
|
|
50
|
+
n += m.length;
|
|
51
|
+
}
|
|
52
|
+
return n;
|
|
53
|
+
}
|
|
54
|
+
export function checkConclusionVerificationRatio(input) {
|
|
55
|
+
const threshold = input.threshold ?? 3;
|
|
56
|
+
const minTotal = input.minTotal ?? 4;
|
|
57
|
+
const conclusionCount = countMatches(input.text, CONCLUSION_PATTERNS);
|
|
58
|
+
const verificationCount = countMatches(input.text, VERIFICATION_PATTERNS);
|
|
59
|
+
const total = conclusionCount + verificationCount;
|
|
60
|
+
const ratio = verificationCount === 0
|
|
61
|
+
? (conclusionCount === 0 ? 0 : Infinity)
|
|
62
|
+
: conclusionCount / verificationCount;
|
|
63
|
+
// sparse text → 판정 보류
|
|
64
|
+
if (total < minTotal) {
|
|
65
|
+
return {
|
|
66
|
+
block: false,
|
|
67
|
+
conclusionCount,
|
|
68
|
+
verificationCount,
|
|
69
|
+
ratio,
|
|
70
|
+
reason: '',
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
// 결론이 전혀 없으면 비율 자체가 의미 없음
|
|
74
|
+
if (conclusionCount === 0) {
|
|
75
|
+
return { block: false, conclusionCount, verificationCount, ratio, reason: '' };
|
|
76
|
+
}
|
|
77
|
+
const block = ratio > threshold;
|
|
78
|
+
let reason = '';
|
|
79
|
+
if (block) {
|
|
80
|
+
reason =
|
|
81
|
+
verificationCount === 0
|
|
82
|
+
? `결론 ${conclusionCount}건 vs 검증 0건. 완료 선언 전에 실제 실행/측정 증거 (npm test, curl, Read 결과 등) 를 턴에 포함시켜 재응답.`
|
|
83
|
+
: `결론/검증 비율 ${ratio.toFixed(1)} (${conclusionCount}/${verificationCount}) > ${threshold}. 결론에 비해 검증 서술이 적음 — 증거(실행 결과/측정값) 를 추가하여 재응답.`;
|
|
84
|
+
}
|
|
85
|
+
return { block, conclusionCount, verificationCount, ratio, reason };
|
|
86
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forgen v0.4.1 — TEST-1: 사실 vs 합의 가드
|
|
3
|
+
*
|
|
4
|
+
* 목적: Claude 가 "동작합니다 / 통과했습니다 / 검증됐습니다" 같은 **사실 주장**을
|
|
5
|
+
* 내놓을 때, 그 턴(또는 최근 N턴)에 실제 측정/검증을 수행한 도구 호출이 있었는가?
|
|
6
|
+
* 측정 없이 합의(agreement)만으로 사실로 변환된다면 alert.
|
|
7
|
+
*
|
|
8
|
+
* 배경 (RC1): v0.4.0 릴리즈 직전 self-assessment 에서 점수가 조금씩 올라가는데
|
|
9
|
+
* 측정 도구 호출은 0건인 케이스가 반복. 메타 점수 인플레이션 (TEST-2 / US-13)
|
|
10
|
+
* 의 직전 단계. 여기서는 alert 레벨까지만 — block 은 TEST-2 에서.
|
|
11
|
+
*
|
|
12
|
+
* 순수 함수 설계: I/O 없이 텍스트 + 측정 신호 메타데이터만 받아 판정.
|
|
13
|
+
* Stop hook / session scorer / CLI 어느 쪽에서도 호출 가능.
|
|
14
|
+
*/
|
|
15
|
+
/** TEST-1 판정 입력. */
|
|
16
|
+
export interface FactCheckInput {
|
|
17
|
+
/** Claude 의 최근 턴 응답 텍스트. */
|
|
18
|
+
text: string;
|
|
19
|
+
/**
|
|
20
|
+
* 최근 N 턴에서 실행된 도구 이름 목록 (중복 OK). 없으면 빈 배열.
|
|
21
|
+
* 호출지가 0턴/전체 세션 등 윈도우를 결정한다.
|
|
22
|
+
*/
|
|
23
|
+
recentTools: string[];
|
|
24
|
+
/**
|
|
25
|
+
* optional: 측정으로 간주할 최소 tool count. 기본 1.
|
|
26
|
+
* 빌드/테스트같은 확정 측정 1회면 충분하다고 간주.
|
|
27
|
+
*/
|
|
28
|
+
minMeasurements?: number;
|
|
29
|
+
}
|
|
30
|
+
export interface FactCheckResult {
|
|
31
|
+
/** true = 측정 없는 사실-주장 감지, alert 필요. */
|
|
32
|
+
alert: boolean;
|
|
33
|
+
/** 매칭된 사실-주장 키워드 (최대 3개). */
|
|
34
|
+
factAssertions: string[];
|
|
35
|
+
/** 감지된 합의/추측 신호 (최대 3개). */
|
|
36
|
+
agreementSofteners: string[];
|
|
37
|
+
/** 관찰된 측정성 도구 호출 수. */
|
|
38
|
+
measurementCount: number;
|
|
39
|
+
/** 호출지가 surface 하기 좋은 사람-읽기 이유. */
|
|
40
|
+
reason: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* 핵심 판정 — 텍스트에 사실-주장이 있고 측정 도구가 없으면 alert.
|
|
44
|
+
* 측정이 있거나 사실-주장이 없으면 alert=false.
|
|
45
|
+
* 합의 softener 는 참고용 — softener 많을수록 reason 에 경고 추가.
|
|
46
|
+
*/
|
|
47
|
+
export declare function checkFactVsAgreement(input: FactCheckInput): FactCheckResult;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forgen v0.4.1 — TEST-1: 사실 vs 합의 가드
|
|
3
|
+
*
|
|
4
|
+
* 목적: Claude 가 "동작합니다 / 통과했습니다 / 검증됐습니다" 같은 **사실 주장**을
|
|
5
|
+
* 내놓을 때, 그 턴(또는 최근 N턴)에 실제 측정/검증을 수행한 도구 호출이 있었는가?
|
|
6
|
+
* 측정 없이 합의(agreement)만으로 사실로 변환된다면 alert.
|
|
7
|
+
*
|
|
8
|
+
* 배경 (RC1): v0.4.0 릴리즈 직전 self-assessment 에서 점수가 조금씩 올라가는데
|
|
9
|
+
* 측정 도구 호출은 0건인 케이스가 반복. 메타 점수 인플레이션 (TEST-2 / US-13)
|
|
10
|
+
* 의 직전 단계. 여기서는 alert 레벨까지만 — block 은 TEST-2 에서.
|
|
11
|
+
*
|
|
12
|
+
* 순수 함수 설계: I/O 없이 텍스트 + 측정 신호 메타데이터만 받아 판정.
|
|
13
|
+
* Stop hook / session scorer / CLI 어느 쪽에서도 호출 가능.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* 측정성 도구 — 실행 결과가 사실 주장을 뒷받침할 수 있는 카테고리.
|
|
17
|
+
*
|
|
18
|
+
* v0.4.1 coverage fix: TEST-2 와 같은 논리로, Read/Edit/Write/Grep/Glob 은 파일
|
|
19
|
+
* 내용 확인/수정이지 "통과/검증/완료" 같은 실 실행 주장을 뒷받침 못 함. 오직
|
|
20
|
+
* Bash (실 실행) + NotebookEdit (실행 결과) 만 strong measurement.
|
|
21
|
+
*
|
|
22
|
+
* 이전 넓은 집합은 신규 사용자 시나리오 (buyer-day1 R4) 에서 Claude 가 Read
|
|
23
|
+
* 한 번만 해도 alert 회피 → TEST-1 본 의도 훼손.
|
|
24
|
+
*/
|
|
25
|
+
const MEASUREMENT_TOOL_CATEGORIES = new Set([
|
|
26
|
+
'Bash',
|
|
27
|
+
'NotebookEdit',
|
|
28
|
+
]);
|
|
29
|
+
/** 사실-주장 키워드 — "측정됐다/검증됐다" 류 강한 확정 언어. */
|
|
30
|
+
const FACT_ASSERTION_PATTERNS = [
|
|
31
|
+
/\b(pass(es|ed)?|passing)\b/i,
|
|
32
|
+
/\bverified\b/i,
|
|
33
|
+
/\bconfirmed\b/i,
|
|
34
|
+
/\bvalidated\b/i,
|
|
35
|
+
/\ball tests? pass/i,
|
|
36
|
+
/(통과(했|됐|함|합니다))/,
|
|
37
|
+
/(검증(됐|했|됨|완료))/,
|
|
38
|
+
/(동작(합니다|함|한다))/,
|
|
39
|
+
/(성공(했|했습니다|적))/,
|
|
40
|
+
/(완료(했|됐|됨|됐습니다))/,
|
|
41
|
+
];
|
|
42
|
+
/** 합의/추측 표현 — 측정 없이 확언으로 가는 다리. 이 패턴이 많으면 합의→사실 전환 위험. */
|
|
43
|
+
const AGREEMENT_SOFTENERS = [
|
|
44
|
+
/\b(should|would|might)\s+(work|pass)/i,
|
|
45
|
+
/\blikely\b/i,
|
|
46
|
+
/\bprobably\b/i,
|
|
47
|
+
/(생각합니다|생각함|생각해|봅니다|예상(합니다|돼))/,
|
|
48
|
+
/(그럴\s*것\s*같|맞을\s*것\s*같)/,
|
|
49
|
+
];
|
|
50
|
+
function findMatches(text, patterns, max = 3) {
|
|
51
|
+
const out = [];
|
|
52
|
+
for (const p of patterns) {
|
|
53
|
+
if (out.length >= max)
|
|
54
|
+
break;
|
|
55
|
+
const m = text.match(p);
|
|
56
|
+
if (m)
|
|
57
|
+
out.push(m[0]);
|
|
58
|
+
}
|
|
59
|
+
return out;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* 핵심 판정 — 텍스트에 사실-주장이 있고 측정 도구가 없으면 alert.
|
|
63
|
+
* 측정이 있거나 사실-주장이 없으면 alert=false.
|
|
64
|
+
* 합의 softener 는 참고용 — softener 많을수록 reason 에 경고 추가.
|
|
65
|
+
*/
|
|
66
|
+
export function checkFactVsAgreement(input) {
|
|
67
|
+
const { text, recentTools } = input;
|
|
68
|
+
const minMeasurements = input.minMeasurements ?? 1;
|
|
69
|
+
const factAssertions = findMatches(text, FACT_ASSERTION_PATTERNS);
|
|
70
|
+
const agreementSofteners = findMatches(text, AGREEMENT_SOFTENERS);
|
|
71
|
+
const measurementCount = recentTools.filter((t) => MEASUREMENT_TOOL_CATEGORIES.has(t)).length;
|
|
72
|
+
const hasFactAssertion = factAssertions.length > 0;
|
|
73
|
+
const measurementMissing = measurementCount < minMeasurements;
|
|
74
|
+
const alert = hasFactAssertion && measurementMissing;
|
|
75
|
+
let reason = '';
|
|
76
|
+
if (alert) {
|
|
77
|
+
const parts = [];
|
|
78
|
+
parts.push(`사실-주장 키워드 ${factAssertions.length}건 감지 ("${factAssertions.join('", "')}")`);
|
|
79
|
+
parts.push(`그러나 최근 측정 도구 호출 ${measurementCount}회 (< ${minMeasurements})`);
|
|
80
|
+
if (agreementSofteners.length > 0) {
|
|
81
|
+
parts.push(`합의성 표현 ${agreementSofteners.length}건 (${agreementSofteners.join(', ')})`);
|
|
82
|
+
}
|
|
83
|
+
reason = parts.join('. ');
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
alert,
|
|
87
|
+
factAssertions,
|
|
88
|
+
agreementSofteners,
|
|
89
|
+
measurementCount,
|
|
90
|
+
reason,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forgen v0.4.1 — TEST-2: 자가 점수 인플레이션 가드
|
|
3
|
+
*
|
|
4
|
+
* Claude 가 자신의 작업 품질/확신도/완성도를 **숫자**로 상향 선언하면서 해당
|
|
5
|
+
* 턴(또는 세션)에 측정 도구 호출이 0 건이면 block. TEST-1 (사실 vs 합의) 보다
|
|
6
|
+
* 강한 신호 — 구체적 숫자 인플레이션은 합의-기반 자기-아부(sycophancy)의
|
|
7
|
+
* 가장 또렷한 표식.
|
|
8
|
+
*
|
|
9
|
+
* 배경 (RC2): v0.4.0 self-interview 에서 "8/10", "신뢰도 90%", "0.85 → 0.95"
|
|
10
|
+
* 같은 자가 점수가 턴마다 올라갔지만 `npm test` / `curl` / `Read` 등 실제
|
|
11
|
+
* 측정 호출은 0건. TEST-1 이 서술체 사실 주장을 잡았다면, TEST-2 는 **숫자**
|
|
12
|
+
* 점수의 인플레이션에 초점을 맞춘다.
|
|
13
|
+
*
|
|
14
|
+
* 순수 함수 — Stop hook block 경로에 붙는다.
|
|
15
|
+
*/
|
|
16
|
+
export interface SelfScoreCheckInput {
|
|
17
|
+
text: string;
|
|
18
|
+
/** 이번 턴(또는 윈도우) 내 실행된 도구 이름 목록. */
|
|
19
|
+
recentTools: string[];
|
|
20
|
+
/** score delta 임계 — 이 이상의 증가를 인플레이션으로 간주. 기본 0 (모든 상승). */
|
|
21
|
+
minDelta?: number;
|
|
22
|
+
/** 측정 도구 최소 호출 수 — 기본 1. */
|
|
23
|
+
minMeasurements?: number;
|
|
24
|
+
}
|
|
25
|
+
export interface SelfScoreCheckResult {
|
|
26
|
+
/** true = 자가 점수 인플레이션 감지 (측정 없이 숫자 증가 선언). block 대상. */
|
|
27
|
+
block: boolean;
|
|
28
|
+
/** 매칭된 점수 표현 raw 스트링 (최대 3개). */
|
|
29
|
+
scoreSignals: string[];
|
|
30
|
+
/** 감지된 positive delta 목록 (from → to). */
|
|
31
|
+
deltas: Array<{
|
|
32
|
+
from: number;
|
|
33
|
+
to: number;
|
|
34
|
+
}>;
|
|
35
|
+
measurementCount: number;
|
|
36
|
+
reason: string;
|
|
37
|
+
}
|
|
38
|
+
export declare function checkSelfScoreInflation(input: SelfScoreCheckInput): SelfScoreCheckResult;
|