@wooojin/forgen 0.4.13 → 0.5.5
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 +1 -1
- package/CHANGELOG.md +261 -0
- package/README.ja.md +16 -12
- package/README.ko.md +12 -8
- package/README.md +90 -27
- package/README.zh.md +16 -12
- package/assets/claude/commands/forge-loop.md +7 -1
- package/assets/claude/commands/ship.md +18 -1
- package/assets/opencode/forgen.ts +52 -0
- package/assets/shared/hook-registry.json +210 -22
- package/dist/checks/_shared/meta-guard-dispatch.d.ts +7 -0
- package/dist/checks/_shared/meta-guard-dispatch.js +12 -2
- package/dist/checks/_shared/model-profile.d.ts +25 -0
- package/dist/checks/_shared/model-profile.js +63 -0
- package/dist/cli.js +99 -153
- package/dist/core/auto-compound-runner.d.ts +0 -11
- package/dist/core/auto-compound-runner.js +199 -92
- package/dist/core/changelog-cli.d.ts +4 -1
- package/dist/core/changelog-cli.js +8 -7
- package/dist/core/compound-consent.d.ts +15 -0
- package/dist/core/compound-consent.js +48 -0
- package/dist/core/compound-sweep-cli.d.ts +60 -0
- package/dist/core/compound-sweep-cli.js +374 -0
- package/dist/core/config-injector.d.ts +16 -1
- package/dist/core/config-injector.js +47 -28
- package/dist/core/dashboard-cli.js +40 -16
- package/dist/core/dashboard.d.ts +3 -4
- package/dist/core/dashboard.js +15 -34
- package/dist/core/dev-cli.d.ts +13 -0
- package/dist/core/dev-cli.js +70 -0
- package/dist/core/doctor.d.ts +16 -5
- package/dist/core/doctor.js +190 -176
- package/dist/core/drift-score.d.ts +2 -0
- package/dist/core/drift-score.js +9 -1
- package/dist/core/harness.js +115 -43
- package/dist/core/health-cli.d.ts +2 -0
- package/dist/core/health-cli.js +6 -1
- package/dist/core/host-detect.d.ts +3 -1
- package/dist/core/host-detect.js +26 -1
- package/dist/core/migrate-cli.js +15 -0
- package/dist/core/migrate-evidence-host.d.ts +2 -1
- package/dist/core/migrate-tenetx.d.ts +50 -0
- package/dist/core/migrate-tenetx.js +262 -0
- package/dist/core/probe-workflow-cli.d.ts +3 -3
- package/dist/core/probe-workflow-cli.js +13 -13
- package/dist/core/recall-cli.js +1 -1
- package/dist/core/regress-map-cli.js +1 -1
- package/dist/core/rendered-rules-manifest.d.ts +29 -0
- package/dist/core/rendered-rules-manifest.js +60 -0
- package/dist/core/session-store.js +14 -3
- package/dist/core/settings-injector.d.ts +3 -0
- package/dist/core/settings-injector.js +12 -16
- package/dist/core/spawn.d.ts +37 -1
- package/dist/core/spawn.js +116 -9
- package/dist/core/state-gc.js +1 -0
- package/dist/core/status-cli.d.ts +20 -0
- package/dist/core/status-cli.js +100 -0
- package/dist/core/statusline-cli.d.ts +7 -0
- package/dist/core/statusline-cli.js +63 -19
- package/dist/core/transcript-summary.d.ts +18 -0
- package/dist/core/transcript-summary.js +81 -0
- package/dist/core/trust-layer-intent.d.ts +21 -1
- package/dist/core/trust-layer-intent.js +7 -0
- package/dist/core/types.d.ts +3 -2
- package/dist/core/uninstall.js +12 -0
- package/dist/core/usage-telemetry.d.ts +7 -1
- package/dist/core/usage-telemetry.js +7 -9
- package/dist/core/v1-bootstrap.js +1 -1
- package/dist/core/watch-cli.js +1 -1
- package/dist/engine/compound-extractor.js +10 -0
- package/dist/engine/compound-loop.js +55 -7
- package/dist/engine/compound-share.d.ts +85 -0
- package/dist/engine/compound-share.js +606 -0
- package/dist/engine/correction-cluster-runner.d.ts +38 -0
- package/dist/engine/correction-cluster-runner.js +188 -0
- package/dist/engine/correction-clustering.d.ts +80 -0
- package/dist/engine/correction-clustering.js +167 -0
- package/dist/engine/enforce-classifier.d.ts +10 -1
- package/dist/engine/enforce-classifier.js +111 -22
- package/dist/engine/extraction-session.js +10 -3
- package/dist/engine/private-filter.d.ts +36 -0
- package/dist/engine/private-filter.js +100 -0
- package/dist/engine/ranking-pipeline.js +4 -2
- package/dist/engine/relevance-gate.d.ts +12 -0
- package/dist/engine/relevance-gate.js +12 -0
- package/dist/engine/roi-demotion.d.ts +79 -0
- package/dist/engine/roi-demotion.js +159 -0
- package/dist/engine/solution-format.d.ts +1 -0
- package/dist/engine/solution-format.js +26 -0
- package/dist/engine/solution-matcher.js +10 -1
- package/dist/fgx.js +7 -6
- package/dist/forge/cli.js +8 -2
- package/dist/hooks/compound-reflection.js +6 -1
- package/dist/hooks/context-guard.d.ts +16 -1
- package/dist/hooks/context-guard.js +99 -49
- package/dist/hooks/hook-config.js +5 -0
- package/dist/hooks/hook-registry.d.ts +6 -1
- package/dist/hooks/hooks-generator.js +3 -0
- package/dist/hooks/post-tool-use.js +2 -3
- package/dist/hooks/pre-compact.js +14 -0
- package/dist/hooks/pre-tool-use.js +5 -1
- package/dist/hooks/session-end.d.ts +34 -0
- package/dist/hooks/session-end.js +100 -0
- package/dist/hooks/session-recovery.js +18 -1
- package/dist/hooks/shared/hook-timing.js +6 -1
- package/dist/hooks/shared/stop-triggers.d.ts +29 -2
- package/dist/hooks/shared/stop-triggers.js +35 -2
- package/dist/hooks/solution-injector.d.ts +28 -0
- package/dist/hooks/solution-injector.js +126 -28
- package/dist/hooks/stop-guard.js +5 -2
- package/dist/hooks/subagent-stop-guard.js +4 -1
- package/dist/host/capabilities-claude.js +1 -0
- package/dist/host/capabilities-codex.js +1 -0
- package/dist/host/capabilities-opencode.d.ts +26 -0
- package/dist/host/capabilities-opencode.js +78 -0
- package/dist/host/capabilities-registry.d.ts +7 -0
- package/dist/host/capabilities-registry.js +14 -0
- package/dist/host/codex-rules-context.d.ts +25 -0
- package/dist/host/codex-rules-context.js +62 -0
- package/dist/host/exec-host.d.ts +14 -3
- package/dist/host/exec-host.js +15 -2
- package/dist/host/host-binding.d.ts +27 -0
- package/dist/host/host-binding.js +11 -0
- package/dist/host/host-runtime.js +18 -0
- package/dist/host/install-codex.d.ts +66 -0
- package/dist/host/install-codex.js +293 -25
- package/dist/host/install-opencode.d.ts +38 -0
- package/dist/host/install-opencode.js +148 -0
- package/dist/host/install-orchestrator.d.ts +4 -1
- package/dist/host/install-orchestrator.js +30 -1
- package/dist/host/invoke-agent.d.ts +3 -2
- package/dist/host/invoke-agent.js +1 -0
- package/dist/host/opencode/context-cli.d.ts +15 -0
- package/dist/host/opencode/context-cli.js +25 -0
- package/dist/host/opencode/guard-cli.d.ts +13 -0
- package/dist/host/opencode/guard-cli.js +39 -0
- package/dist/host/opencode/plugin/forgen.d.ts +31 -0
- package/dist/host/opencode/plugin/forgen.js +60 -0
- package/dist/host/opencode/translate.d.ts +49 -0
- package/dist/host/opencode/translate.js +96 -0
- package/dist/host/parity-harness.d.ts +10 -2
- package/dist/host/parity-harness.js +7 -3
- package/dist/host/projection.d.ts +37 -3
- package/dist/host/projection.js +104 -42
- package/dist/mcp/tools.js +17 -4
- package/dist/store/evidence-store.d.ts +2 -6
- package/dist/store/evidence-store.js +164 -46
- package/dist/store/host-mismatch.d.ts +2 -1
- package/dist/store/host-mismatch.js +8 -8
- package/dist/store/profile-store.d.ts +3 -2
- package/dist/store/rule-store.d.ts +41 -0
- package/dist/store/rule-store.js +77 -2
- package/dist/store/types.d.ts +9 -2
- package/hooks/hooks.json +13 -1
- package/package.json +3 -2
- package/plugin.json +2 -2
- package/skills/architecture-decision/SKILL.md +18 -0
- package/skills/calibrate/SKILL.md +18 -0
- package/skills/code-review/SKILL.md +17 -0
- package/skills/compound/SKILL.md +17 -0
- package/skills/deep-interview/SKILL.md +7 -0
- package/skills/docker/SKILL.md +18 -0
- package/skills/forge-loop/SKILL.md +30 -1
- package/skills/learn/SKILL.md +15 -0
- package/skills/retro/SKILL.md +16 -0
- package/skills/ship/SKILL.md +36 -1
package/README.md
CHANGED
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
5
|
<p align="center">
|
|
6
|
-
<strong>
|
|
7
|
-
|
|
6
|
+
<strong>forgen makes Claude fit <em>you</em> — and measures whether that actually helps, honestly.</strong><br/>
|
|
7
|
+
Your corrections become persistent rules; past solutions resurface when relevant; stale ones fade.<br/>
|
|
8
|
+
For <strong>Claude Code</strong> and <strong>Codex CLI</strong>, at <strong>$0 extra API cost</strong>.
|
|
8
9
|
</p>
|
|
9
10
|
|
|
10
11
|
<p align="center">
|
|
@@ -35,7 +36,7 @@
|
|
|
35
36
|
|
|
36
37
|
## The first block (30 seconds)
|
|
37
38
|
|
|
38
|
-
|
|
39
|
+
Here's forgen's most *visible* mechanism — a live guard you can trigger in 30 seconds. Fair warning up front (this is the honest-measurement tool, after all): on current frontier models this particular guard rarely fires, because Opus 4.8 / Sonnet 5 mostly stopped making unverified "done" claims on their own (we measured **blocks = 0** — see the caveat below). So treat this as a **safety net for weaker models and the occasional tail case**, not forgen's daily value. The daily value is quieter: your corrections becoming rules, and past solutions resurfacing. But the guard is the fastest thing to *see*, so we lead with it.
|
|
39
40
|
|
|
40
41
|
```
|
|
41
42
|
You: "Update the auth middleware."
|
|
@@ -57,7 +58,7 @@ Claude: "측정 없이 점수를 매겼습니다. 실 테스트부터 실행합
|
|
|
57
58
|
|
|
58
59
|
The same mechanism also fires when Claude writes conclusions faster than evidence ("done. passed. shipped. verified." with no measurement context), or claims facts ("테스트가 통과합니다") without ever having executed them. You can also define **custom rules** (e.g. "require npm test evidence before saying 'done' in this repo") via `forgen compound --rule` — they slot into the same Stop-hook dispatcher.
|
|
59
60
|
|
|
60
|
-
This is **Mech-B self-check prompt-inject**. It works because Claude Code's Stop hook accepts `decision: "block"` + `reason`, and Claude in the next turn reads that reason as input. Codex CLI gets the same treatment via the symmetric host adapter (v0.4.3, [multi-host core design](docs/superpowers/specs/2026-04-27-forgen-multi-host-core-design.md)). We verified it end-to-end on 10 scenarios at $1.74 total cost (
|
|
61
|
+
This is **Mech-B self-check prompt-inject**. It works because Claude Code's Stop hook accepts `decision: "block"` + `reason`, and Claude in the next turn reads that reason as input. Codex CLI gets the same treatment via the symmetric host adapter (v0.4.3, [multi-host core design](docs/superpowers/specs/2026-04-27-forgen-multi-host-core-design.md)). We verified it end-to-end on 10 scenarios at $1.74 total cost (A1 spike report — archived in git history, `docs/spike/` pre-v0.5.0), and v0.4.1 added built-in guards so you get the first block **without writing any rule**.
|
|
61
62
|
|
|
62
63
|
> **v0.4.3 self-correction story:** the same guards detected their own 16-day false-positive (strict φ 65.66% — 84% from a single Korean-regex bug), and the [`forgen-eval`](packages/forgen-eval/) introspect testbed (alpha) flagged a `TEST-1` wiring gap on top of it. Both fixes shipped in v0.4.3 — forgen finding and fixing forgen. Details in [CHANGELOG](CHANGELOG.md).
|
|
63
64
|
|
|
@@ -73,18 +74,53 @@ This is **Mech-B self-check prompt-inject**. It works because Claude Code's Stop
|
|
|
73
74
|
> is rescinded as a broken-testbed artifact; ψ (forgen+mem coexistence) is
|
|
74
75
|
> confirmed as ≈0 — **forgen alone is the recommended path**. See
|
|
75
76
|
> [`docs/release/v0.4.5-draft.md`](docs/release/v0.4.5-draft.md).
|
|
76
|
-
|
|
77
|
-
|
|
77
|
+
>
|
|
78
|
+
> **Scope caveat (v0.5.0, ADR-010 + 2026-07-20 honest null):** the δ numbers
|
|
79
|
+
> above were measured on the **models of their era** (Claude Sonnet 4.x-class,
|
|
80
|
+
> Codex) and we do **not** carry them forward as a claim about current frontier
|
|
81
|
+
> models. Two separate current-model findings, kept distinct:
|
|
82
|
+
>
|
|
83
|
+
> 1. **Completion-guard / false-completion pressure → null (honest).** On
|
|
84
|
+
> **Opus 4.8** and **Sonnet 5** we measured completion-guard **blocks = 0** —
|
|
85
|
+
> frontier models got honest on their own. Our v0.5.0 judge redesign re-scored the
|
|
86
|
+
> hard "false-completion pressure" cases and found **no measurable behavioral δ
|
|
87
|
+
> on that dataset** (all arms avoid blatant false completion;
|
|
88
|
+
> [`docs/release/v0.5.0-recalibration.md`](docs/release/v0.5.0-recalibration.md)).
|
|
89
|
+
> We publish that null rather than bury it.
|
|
90
|
+
>
|
|
91
|
+
> 2. **Cross-session user-specific policy adherence → δ > 0 (measured).** forgen's
|
|
92
|
+
> real mechanism is not blocking but *re-injecting your corrections in a later
|
|
93
|
+
> session where a vanilla model has no memory of them*. On that — the honest place
|
|
94
|
+
> the effect lives — we measured a **significant δ**: forgen makes the model follow
|
|
95
|
+
> the user's prior-session policies **14/14**, vanilla **4/14 (Sonnet 5)** / **7/14
|
|
96
|
+
> (Opus 4.8)** → **δ = 0.714, 95% CI [0.429, 0.929]** (Sonnet 5) and **δ = 0.500,
|
|
97
|
+
> 95% CI [0.214, 0.786]** (Opus 4.8), confirmed by a blind human rater (Cohen's
|
|
98
|
+
> κ = 0.748 vs the LLM judge)
|
|
99
|
+
> ([`docs/release/v0.5.0-persistence-delta.md`](docs/release/v0.5.0-persistence-delta.md)).
|
|
100
|
+
> **δ is orthogonal to model capability** — the stronger model (Opus) follows more
|
|
101
|
+
> general good-practice on its own, so δ shrinks there, but on *user-specific*
|
|
102
|
+
> policies neither model guesses right and only forgen does. This is
|
|
103
|
+
> **"internal measurement" grade**: the dataset is maintainer-authored (bootstrap),
|
|
104
|
+
> the judge is intra-family (Claude), and only one human rater has confirmed it. We
|
|
105
|
+
> do **not** make external effect claims until an independent rater panel + external
|
|
106
|
+
> reviewer + a cross-family judge reproduce it.
|
|
107
|
+
>
|
|
108
|
+
> What forgen reliably provides: **personalization** (corrections → persistent
|
|
109
|
+
> rules, cross-session δ above), **recall** (past solutions injected when relevant),
|
|
110
|
+
> **ROI demotion** of stale knowledge, and **deterministic guards** (secrets,
|
|
111
|
+
> destructive commands) that fire regardless of model honesty. Per-model guard
|
|
112
|
+
> behavior: measured-honest models get advisory mode instead of blocking.
|
|
113
|
+
|
|
114
|
+
🎬 **See it happen** — try the guard live on your own install:
|
|
78
115
|
|
|
79
116
|
```bash
|
|
80
|
-
#
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
#
|
|
84
|
-
asciinema play docs/demo/mech-b-block-unblock.cast
|
|
117
|
+
# Real hook, real block: a self-score claim with zero measurement evidence
|
|
118
|
+
echo '{"session_id":"demo","last_assistant_message":"이번 작업 신뢰도 90% 로 평가됩니다."}' \
|
|
119
|
+
| node "$(npm root -g)/@wooojin/forgen/dist/hooks/stop-guard.js"
|
|
120
|
+
# → decision:"block" + the exact reason Claude reads on its next turn
|
|
85
121
|
```
|
|
86
122
|
|
|
87
|
-
|
|
123
|
+
(The pre-v0.5.0 scripted demo lived in `docs/demo/` — archived in git history.)
|
|
88
124
|
|
|
89
125
|
---
|
|
90
126
|
|
|
@@ -179,20 +215,21 @@ Behind the scenes:
|
|
|
179
215
|
|
|
180
216
|
You say: "Don't refactor files I didn't ask you to touch."
|
|
181
217
|
|
|
182
|
-
Claude calls the `correction-record` MCP tool. The correction is stored as structured evidence with axis classification (`judgment_philosophy`), kind (`avoid-this`), and confidence score. A temporary rule is created for immediate effect in the current session.
|
|
218
|
+
Claude calls the `correction-record` MCP tool. The correction is stored as structured evidence with axis classification (`judgment_philosophy`), kind (`avoid-this`), and confidence score. A temporary rule is created for immediate effect in the current session. At session end it promotes to a **permanent rule** — this deterministic corrections → rules path runs with **zero network egress** and is what our measured cross-session δ rides on.
|
|
219
|
+
|
|
220
|
+
Softer corrections you never explicitly flag ("음… 이렇게 최소로만 짜면 나중에 다 다시 해야 하는 거 아니야?") are harder to catch in real time. If you opt into transcript extraction (below), forgen also **retroactively mines** those from the conversation — but such auto-mined rules are **advisory-only** (they surface as context, never block or enforce) and age out if you never act on them.
|
|
183
221
|
|
|
184
222
|
### Between sessions (automatic)
|
|
185
223
|
|
|
186
|
-
|
|
187
|
-
- Solutions (reusable patterns with context)
|
|
188
|
-
- Behavioral observations (how you work)
|
|
189
|
-
- A session learning summary
|
|
224
|
+
**Always on (deterministic, zero egress):** your explicit corrections promote to permanent rules; near-duplicate corrections cluster and strengthen; facets micro-adjust from accumulated evidence; a time-based `compound sweep` backstop (optionally on cron) makes sure long or interrupted sessions don't lose that learning.
|
|
190
225
|
|
|
191
|
-
|
|
226
|
+
**Opt-in (`forgen compound consent on`):** a background Haiku pass reads a *redacted summary* of the session transcript to extract reusable solutions, behavioral observations, and the softer corrections above. This is **off by default** — forgen does not send your conversations anywhere unless you turn it on, and secrets / `<private>` ranges are stripped before anything is sent. `forgen doctor` always shows the current state.
|
|
227
|
+
|
|
228
|
+
If your corrections consistently point away from your current pack, mismatch detection triggers after 3 sessions and recommends a pack change.
|
|
192
229
|
|
|
193
230
|
### Next session
|
|
194
231
|
|
|
195
|
-
Updated rules are rendered with your corrections included. Compound knowledge is searchable via MCP.
|
|
232
|
+
Updated rules are rendered with your corrections included. Compound knowledge is searchable via MCP. The retrieval mechanism is in place from day 1 (starter-pack covers common dev queries on a fresh install); as you accumulate your own solutions, low-fitness ones get auto-demoted (ROI loop) and your specific patterns get promoted, so what surfaces skews toward *your* corpus over time. We describe this as a mechanism, not a measured speedup — we make no effect-size claim (see the honest-null caveat above).
|
|
196
233
|
|
|
197
234
|
---
|
|
198
235
|
|
|
@@ -207,6 +244,7 @@ forgen install both # 3-choice interactive: claude / codex / both
|
|
|
207
244
|
# or non-interactive:
|
|
208
245
|
forgen install claude
|
|
209
246
|
forgen install codex
|
|
247
|
+
# Codex only: trust the forgen hooks once with `/hooks` inside codex — Codex skips untrusted hooks (forgen doctor shows [Codex Hooks])
|
|
210
248
|
|
|
211
249
|
# 3. First run — 4-question onboarding (English or Korean)
|
|
212
250
|
forgen # default: Claude
|
|
@@ -229,7 +267,7 @@ forgen doctor --quick
|
|
|
229
267
|
|
|
230
268
|
> **Vendor dependency:** Forgen wraps Claude Code and Codex CLI symmetrically (Claude is the behavior reference; Codex extends with equivalence). Upstream API/CLI changes may affect behavior. Tested with Claude Code 1.0.x / 2.1.x and Codex 0.x.
|
|
231
269
|
|
|
232
|
-
> **Upgrading from v0.4.x?** Run `forgen install claude` (or `codex` / `both`) after upgrading — v0.4.3+ requires explicit host registration. Then `forgen doctor --quick` to verify.
|
|
270
|
+
> **Upgrading from v0.4.x?** Run `forgen install claude` (or `codex` / `both`) after upgrading — v0.4.3+ requires explicit host registration. Then run `forgen migrate tenetx --dry-run` to preview and reclaim legacy global rule sprawl (v0.5.0 moved ALL rule injection to project scope — stale `~/.claude/rules/forge-*.md` from older versions should be reclaimed; see CHANGELOG). Finally `forgen doctor --quick` to verify.
|
|
233
271
|
|
|
234
272
|
### Try your first block
|
|
235
273
|
|
|
@@ -349,8 +387,8 @@ entries in `~/.forgen/state/implicit-feedback.jsonl`. Idempotent — safe to re-
|
|
|
349
387
|
| |
|
|
350
388
|
v |
|
|
351
389
|
+------------------+ |
|
|
352
|
-
| Session Ends |
|
|
353
|
-
| |
|
|
390
|
+
| Session Ends | corrections -> rules (always, egress 0) |
|
|
391
|
+
| | transcript extract: opt-in (Haiku) |
|
|
354
392
|
+--------+---------+ |
|
|
355
393
|
| |
|
|
356
394
|
v |
|
|
@@ -399,6 +437,30 @@ Each solution starts as an `experiment`. As it gets reflected in your code acros
|
|
|
399
437
|
| **Behavioral patterns** | Auto-detected at 3+ observations | Applied to `forge-behavioral.md` |
|
|
400
438
|
| **Evidence** | Corrections + observations | Drives facet adjustments + rule creation |
|
|
401
439
|
|
|
440
|
+
*Solutions and behavioral patterns come from the **opt-in** transcript-extraction pass (`forgen compound consent on`, off by default). Corrections → rules and facet adjustments are always-on and never leave your machine.*
|
|
441
|
+
|
|
442
|
+
### Keeping things out of the corpus (`<private>`)
|
|
443
|
+
|
|
444
|
+
Wrap anything you don't want learned in a `<private>…</private>` block, or end a
|
|
445
|
+
line with a `// forgen:private` marker (`#` and `/*` comment styles also work):
|
|
446
|
+
|
|
447
|
+
```
|
|
448
|
+
Here's the approach — <private>internal API key rotation playbook</private> — use it.
|
|
449
|
+
const token = "…"; // forgen:private
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
Those ranges are stripped before every learning-corpus capture path: correction
|
|
453
|
+
records, solution extraction, the automatic session-end compound runner,
|
|
454
|
+
prompt-history, and session-search indexing. Unclosed or malformed tags **fail
|
|
455
|
+
closed** (treated as private to end-of-text) so a forgotten `</private>` never
|
|
456
|
+
leaks.
|
|
457
|
+
|
|
458
|
+
> **Scope:** `<private>` controls **what forgen learns from**, not what the model
|
|
459
|
+
> sees. The text was already sent to Claude as part of your conversation — the tag
|
|
460
|
+
> excludes it from persistent capture (compound solutions, evidence, search index),
|
|
461
|
+
> it does not make the current turn private. This is a separate axis from the
|
|
462
|
+
> secret-filter, which blocks credentials from being committed.
|
|
463
|
+
|
|
402
464
|
### Solution auto-injection
|
|
403
465
|
|
|
404
466
|
Every prompt you type is matched against your accumulated solutions. Relevant ones are automatically injected into Claude's context — no manual lookup needed.
|
|
@@ -672,9 +734,10 @@ forgen skill list # List promoted skills
|
|
|
672
734
|
|
|
673
735
|
```bash
|
|
674
736
|
forgen init # Initialize project (+ 15 starter-pack solutions)
|
|
675
|
-
forgen migrate [implicit-feedback|all]
|
|
676
|
-
# One-shot
|
|
677
|
-
|
|
737
|
+
forgen migrate [implicit-feedback|evidence-host|tenetx|all]
|
|
738
|
+
# One-shot migrations (idempotent). tenetx: reclaim
|
|
739
|
+
# legacy global rules (--dry-run/--yes/--apply-settings)
|
|
740
|
+
forgen doctor # Forgen-specific diagnostics (plugin cache, hooks, state, parity, gates — env health: native /doctor)
|
|
678
741
|
forgen doctor --prune-state # Daily hygiene: state GC + T4 rule decay (90d idle → retire)
|
|
679
742
|
forgen dashboard # Knowledge overview (6 sections)
|
|
680
743
|
forgen config hooks # View hook status + context budget
|
|
@@ -712,7 +775,7 @@ Three CI gates prove forgen does not violate its own L1 rules before release:
|
|
|
712
775
|
```bash
|
|
713
776
|
node scripts/self-gate.cjs # Static: mock-in-prod, secrets, enforce_via, release-artifact
|
|
714
777
|
node scripts/self-gate-runtime.cjs # Runtime smoke: 6 hook scenarios
|
|
715
|
-
node scripts/self-gate-release.cjs # Tag-only: version/tag/CHANGELOG/dist/
|
|
778
|
+
node scripts/self-gate-release.cjs # Tag-only: version/tag/CHANGELOG/dist/smoke-report consistency
|
|
716
779
|
```
|
|
717
780
|
|
|
718
781
|
Triggered by `.github/workflows/self-gate.yml` on push main / PR main / tag v*. Dogfood opt-in: see [.forgen/README.md](.forgen/README.md).
|
|
@@ -843,7 +906,7 @@ forgen and [claude-mem](https://github.com/thedotmack/claude-mem) solve **comple
|
|
|
843
906
|
| **Trigger** | Stop / PreToolUse hooks | UserPromptSubmit hook |
|
|
844
907
|
| **Cost** | $0 (in-turn block/reason) | $0 (vector recall, local) |
|
|
845
908
|
|
|
846
|
-
Install both as separate Claude Code plugins (Plugin model — forgen does not bundle claude-mem; AGPL-3.0 stays at arm's length). When both are present forgen's auto-detect yields context budget so claude-mem's recall has room to land, and the orchestration contract — order, failure isolation, Stop-hook ownership — is documented in [ADR-004](docs/adr/ADR-004-claude-mem-hook-orchestration.md). The pairing is one of the 5 arms tracked by [forgen-eval](packages/forgen-eval/) (
|
|
909
|
+
Install both as separate Claude Code plugins (Plugin model — forgen does not bundle claude-mem; AGPL-3.0 stays at arm's length). When both are present forgen's auto-detect yields context budget so claude-mem's recall has room to land, and the orchestration contract — order, failure isolation, Stop-hook ownership — is documented in [ADR-004](docs/adr/ADR-004-claude-mem-hook-orchestration.md). The pairing is one of the 5 arms tracked by [forgen-eval](packages/forgen-eval/) (claude-mem spike report — archived in git history, `docs/spike/` pre-v0.5.0).
|
|
847
910
|
|
|
848
911
|
```
|
|
849
912
|
You: "fix the auth flow"
|
package/README.zh.md
CHANGED
|
@@ -55,19 +55,19 @@ Claude: "撤回完成声明。证据文件不存在。先执行 e2e..."
|
|
|
55
55
|
|
|
56
56
|
**刚刚发生了什么**: Claude 的 Stop hook 被你定义的规则 (`L1-e2e-before-done`) 拦截。Claude 读取了 block `reason`, 撤回过早的完成声明, 产生证据, 重新提交。**零额外 API 调用** — 全部发生在 Claude 本来就会产出的同一个 session turn 内。
|
|
57
57
|
|
|
58
|
-
这就是 **Mech-B 自检 prompt-inject**。它工作是因为 Claude Code 的 Stop hook 接受 `decision: "block"` + `reason`, 而 Claude 在下一轮把那个 reason 作为输入读取。我们用 10 个场景、$1.74 总成本端到端验证 (
|
|
58
|
+
这就是 **Mech-B 自检 prompt-inject**。它工作是因为 Claude Code 的 Stop hook 接受 `decision: "block"` + `reason`, 而 Claude 在下一轮把那个 reason 作为输入读取。我们用 10 个场景、$1.74 总成本端到端验证 (A1 spike report — 已归档于 git 历史, `docs/spike/` pre-v0.5.0)。
|
|
59
59
|
|
|
60
60
|
🎬 **观看实际运行** (27秒):
|
|
61
61
|
|
|
62
62
|
```bash
|
|
63
63
|
# 现场观看完整循环 — 真实的 hook、真实的规则、真实的 block/approve 周期
|
|
64
|
-
|
|
64
|
+
# demo 脚本已归档于 git 历史 (docs/demo/ pre-v0.5.0)
|
|
65
65
|
|
|
66
66
|
# 或重放预录制的 asciinema cast
|
|
67
|
-
asciinema
|
|
67
|
+
# asciinema cast 同上
|
|
68
68
|
```
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
|
|
71
71
|
|
|
72
72
|
---
|
|
73
73
|
|
|
@@ -162,16 +162,17 @@ forgen # 用它代替 `claude`
|
|
|
162
162
|
|
|
163
163
|
你说: "不要重构我没要求你动的文件。"
|
|
164
164
|
|
|
165
|
-
Claude 调用 `correction-record` MCP 工具。纠正作为结构化证据存储,包含轴分类(`judgment_philosophy`)、种类(`avoid-this
|
|
165
|
+
Claude 调用 `correction-record` MCP 工具。纠正作为结构化证据存储,包含轴分类(`judgment_philosophy`)、种类(`avoid-this`)和置信度分数。为当前会话创建一条临时规则以立即生效。会话结束时,该规则会晋升为**永久规则** —— 这条确定性的 corrections → rules 路径以**零网络 egress** 运行,我们测得的 cross-session δ 正是建立在这条路径上。
|
|
166
|
+
|
|
167
|
+
那些你从未明确指出的柔性纠正("嗯…只写这么点最小实现,以后不会全部返工吗?")在实时中更难捕捉。如果你 opt-in 启用 transcript 提取(见下文),forgen 还会从对话中**回溯挖掘(retroactively mine)**这类纠正 —— 但这样自动挖掘出的规则是 **advisory-only**(仅作为上下文呈现,绝不阻断或强制),若你始终不采纳,它们会随时间 age-out。
|
|
166
168
|
|
|
167
169
|
### 会话之间(自动)
|
|
168
170
|
|
|
169
|
-
|
|
170
|
-
- 解决方案(带上下文的可复用模式)
|
|
171
|
-
- 行为观察(你的工作方式)
|
|
172
|
-
- 会话学习摘要
|
|
171
|
+
**Always on(确定性,egress 0):** 你的明确纠正晋升为永久规则; 近乎重复的纠正被聚类并强化; facet 基于累积证据微调; 一个基于时间的 `compound sweep` 兜底机制(可选择挂到 cron)确保漫长或被中断的会话不会丢失这些学习。
|
|
173
172
|
|
|
174
|
-
|
|
173
|
+
**Opt-in(`forgen compound consent on`):** 后台的 Haiku 通道读取会话 transcript 的*脱敏(redacted)摘要*,提取可复用的解决方案、行为观察,以及上述柔性纠正。它**默认关闭** —— 除非你开启,否则 forgen 不会把你的对话发送到任何地方,且在发送前会剥离 secret / `<private>` 区间。`forgen doctor` 始终显示当前状态。
|
|
174
|
+
|
|
175
|
+
如果你的纠正持续指向与当前 pack 不同的方向,3个会话后触发不匹配检测,推荐更换 pack。
|
|
175
176
|
|
|
176
177
|
### 下一个会话
|
|
177
178
|
|
|
@@ -190,6 +191,7 @@ forgen install both # 三选交互: claude / codex / both
|
|
|
190
191
|
# 或非交互:
|
|
191
192
|
forgen install claude
|
|
192
193
|
forgen install codex
|
|
194
|
+
# 仅 Codex: 在 codex 内用 `/hooks` 信任一次 forgen 钩子 — Codex 会跳过未信任的钩子 (用 forgen doctor 的 [Codex Hooks] 查看)
|
|
193
195
|
|
|
194
196
|
# 3. 首次运行 — 4题引导问卷 (英语/韩语选择)
|
|
195
197
|
forgen # 默认: Claude
|
|
@@ -269,8 +271,8 @@ forgen config default-host codex # 设置持久默认主机
|
|
|
269
271
|
| |
|
|
270
272
|
v |
|
|
271
273
|
+------------------+ |
|
|
272
|
-
| 会话结束 |
|
|
273
|
-
| |
|
|
274
|
+
| 会话结束 | corrections -> rules (始终, egress 0) |
|
|
275
|
+
| | transcript 提取: opt-in (Haiku) |
|
|
274
276
|
+--------+---------+ |
|
|
275
277
|
| |
|
|
276
278
|
v |
|
|
@@ -300,6 +302,8 @@ experiment (0.30) → candidate (0.55) → verified (0.75) → mature (0.90)
|
|
|
300
302
|
| **行为模式** | 3次以上观察时自动检测 | 应用到 `forge-behavioral.md` |
|
|
301
303
|
| **证据** | 纠正 + 观察 | 驱动 facet 调整 + 规则创建 |
|
|
302
304
|
|
|
305
|
+
*解决方案与行为模式来自 **opt-in** 的 transcript 提取通道(`forgen compound consent on`,默认关闭)。corrections → rules 与 facet 调整则始终在线(always-on),绝不离开你的机器。*
|
|
306
|
+
|
|
303
307
|
### 解决方案自动注入
|
|
304
308
|
|
|
305
309
|
你输入的每个提示都会与你积累的解决方案进行匹配。相关的解决方案会自动注入 Claude 的上下文 — 无需手动查找。
|
|
@@ -88,13 +88,19 @@ PRD 확정 직후 **반드시** `~/.forgen/state/forge-loop.json`에 저장:
|
|
|
88
88
|
mkdir -p ~/.forgen/state
|
|
89
89
|
cat > ~/.forgen/state/forge-loop.json <<EOF
|
|
90
90
|
{"active":true,"startedAt":"$(date -u +%Y-%m-%dT%H:%M:%SZ)","stories":[
|
|
91
|
-
{"id":"US-001","title":"...","passes":false,"attempts":0}
|
|
91
|
+
{"id":"US-001","title":"...","passes":false,"attempts":0,"acceptanceCriteria":["..."]}
|
|
92
92
|
]}
|
|
93
93
|
EOF
|
|
94
94
|
```
|
|
95
95
|
|
|
96
96
|
이 파일이 있어야 Claude가 중간에 멈추지 않도록 Stop 훅이 차단합니다.
|
|
97
|
+
소유 세션은 최초 차단 시점에 Stop 훅이 자동 귀속하므로(`sessionId` 필드) 이
|
|
98
|
+
파일을 쓸 때 세션 ID를 직접 넣을 필요는 없습니다 — 단, 귀속된 세션과 다른
|
|
99
|
+
세션에서는 이 루프가 차단하지 않습니다. 24시간 이상 갱신이 없으면 자동
|
|
100
|
+
해제(1회성 안내 포함)되며, 연속 30회 차단 시에도 안전 상한으로 자동 해제됩니다.
|
|
97
101
|
스토리 완료 시 `passes: true`로 업데이트. 전체 완료는 Stop 훅이 자동 처리.
|
|
102
|
+
`acceptanceCriteria[0]`은 차단 메시지에 `AC1:`로 노출되므로 있으면 첫 항목을
|
|
103
|
+
구체적이고 검증 가능한 문장으로 작성하세요 (없어도 정상 동작).
|
|
98
104
|
|
|
99
105
|
### goal-only 모드 — Phase 1 종료 분기
|
|
100
106
|
|
|
@@ -166,10 +166,27 @@ npm version {patch|minor|major} --no-git-tag-version
|
|
|
166
166
|
|
|
167
167
|
커밋을 주제별 그룹핑 -> CHANGELOG.md 상단에 추가.
|
|
168
168
|
|
|
169
|
+
## Step 6.5: Smoke 증거 생성 (forgen 레포 한정)
|
|
170
|
+
|
|
171
|
+
forgen 레포 자체를 ship 할 때는 릴리스 커밋 전에 smoke 증거를 생성한다
|
|
172
|
+
(ADR-010 W0-2 — CI self-gate 가 릴리스 커밋에서 smoke-report 를 요구).
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
# forgen 레포에서만. vitest 는 Step 3 에서 이미 돌았지만 게이트 증거는
|
|
176
|
+
# smoke.cjs 산출물만 인정 — 전체 실행 (실제 프로세스 산출물 원칙).
|
|
177
|
+
if [ -f scripts/smoke.cjs ]; then
|
|
178
|
+
node scripts/smoke.cjs || ABORT
|
|
179
|
+
fi
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
- 실패 -> ABORT ("smoke 증거 생성 실패 — 게이트 통과 불가")
|
|
183
|
+
|
|
169
184
|
## Step 7: 릴리스 커밋
|
|
170
185
|
|
|
171
186
|
```bash
|
|
172
|
-
git add package.json CHANGELOG.md
|
|
187
|
+
git add package.json package-lock.json CHANGELOG.md
|
|
188
|
+
# forgen 레포: smoke 증거 포함
|
|
189
|
+
[ -f .forgen-release/smoke-report.json ] && git add .forgen-release/smoke-report.json
|
|
173
190
|
git commit -m "release: v{version}"
|
|
174
191
|
```
|
|
175
192
|
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// forgen-managed — do not edit; regenerated by `forgen install opencode`
|
|
2
|
+
/**
|
|
3
|
+
* forgen — OpenCode plugin (W3-3 P1). forgen 결정적 가드 + 개인화 브릿지:
|
|
4
|
+
* - tool.execute.before → forgen opencode-guard → block 이면 throw(도구 차단).
|
|
5
|
+
* - experimental.session.compacting → forgen opencode-context → forge-loop 상태 유지.
|
|
6
|
+
* 얇은 shim — 로직은 forgen 소유(drift-free). async execFile(이벤트루프 비차단).
|
|
7
|
+
* GUARD_CMD/CONTEXT_CMD 는 install-opencode 가 절대경로로 치환(런타임 PATH 비의존).
|
|
8
|
+
*/
|
|
9
|
+
import { execFile } from "node:child_process"
|
|
10
|
+
|
|
11
|
+
// forgen:guard-cmd — install-opencode 가 [node, <절대 cli 경로>, opencode-guard] 로 치환
|
|
12
|
+
const GUARD_CMD: string[] = ["forgen", "opencode-guard"]
|
|
13
|
+
// forgen:context-cmd — install-opencode 가 [node, <절대 cli 경로>, opencode-context] 로 치환
|
|
14
|
+
const CONTEXT_CMD: string[] = ["forgen", "opencode-context"]
|
|
15
|
+
|
|
16
|
+
function runForgen(cmd: string[], stdin: string, timeout: number): Promise<string> {
|
|
17
|
+
return new Promise((resolve) => {
|
|
18
|
+
const [bin, ...rest] = cmd
|
|
19
|
+
const child = execFile(bin, rest, { timeout, encoding: "utf-8" }, (err, stdout) => {
|
|
20
|
+
if (err) console.error("[forgen] 호출 실패(fail-open):", err.message)
|
|
21
|
+
resolve(stdout || "")
|
|
22
|
+
})
|
|
23
|
+
child.stdin?.end(stdin)
|
|
24
|
+
})
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const forgen = async () => ({
|
|
28
|
+
"tool.execute.before": async (
|
|
29
|
+
input: { tool?: string },
|
|
30
|
+
output: { args?: Record<string, unknown> },
|
|
31
|
+
) => {
|
|
32
|
+
const out = await runForgen(GUARD_CMD, JSON.stringify({ tool: input?.tool, args: output?.args }), 8000)
|
|
33
|
+
let decision: { block?: boolean; reason?: string } = { block: false }
|
|
34
|
+
try {
|
|
35
|
+
if (out) decision = JSON.parse(out)
|
|
36
|
+
} catch {
|
|
37
|
+
/* fail-open */
|
|
38
|
+
}
|
|
39
|
+
if (decision.block) throw new Error(decision.reason || "[forgen] blocked by guard")
|
|
40
|
+
},
|
|
41
|
+
"experimental.session.compacting": async (
|
|
42
|
+
_input: unknown,
|
|
43
|
+
output: { context?: string[] },
|
|
44
|
+
) => {
|
|
45
|
+
const ctx = await runForgen(CONTEXT_CMD, "", 5000)
|
|
46
|
+
if (ctx.trim() && Array.isArray(output?.context)) {
|
|
47
|
+
output.context.push(ctx.trim())
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
export default forgen
|
|
@@ -1,24 +1,212 @@
|
|
|
1
1
|
[
|
|
2
|
-
{
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
{
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
{
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
2
|
+
{
|
|
3
|
+
"name": "notepad-injector",
|
|
4
|
+
"tier": "compound-core",
|
|
5
|
+
"event": "UserPromptSubmit",
|
|
6
|
+
"matcher": "*",
|
|
7
|
+
"script": "hooks/notepad-injector.js",
|
|
8
|
+
"timeout": 3,
|
|
9
|
+
"compoundCritical": false
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"name": "context-guard",
|
|
13
|
+
"tier": "compound-core",
|
|
14
|
+
"event": "UserPromptSubmit",
|
|
15
|
+
"matcher": "*",
|
|
16
|
+
"script": "hooks/context-guard.js",
|
|
17
|
+
"timeout": 2,
|
|
18
|
+
"compoundCritical": false
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"name": "session-recovery",
|
|
22
|
+
"tier": "compound-core",
|
|
23
|
+
"event": "SessionStart",
|
|
24
|
+
"matcher": "*",
|
|
25
|
+
"script": "hooks/session-recovery.js",
|
|
26
|
+
"timeout": 3,
|
|
27
|
+
"compoundCritical": true
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"name": "post-tool-use",
|
|
31
|
+
"tier": "compound-core",
|
|
32
|
+
"event": "PostToolUse",
|
|
33
|
+
"matcher": "*",
|
|
34
|
+
"script": "hooks/post-tool-use.js",
|
|
35
|
+
"timeout": 3,
|
|
36
|
+
"compoundCritical": true
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"name": "pre-compact",
|
|
40
|
+
"tier": "compound-core",
|
|
41
|
+
"event": "PreCompact",
|
|
42
|
+
"matcher": "*",
|
|
43
|
+
"script": "hooks/pre-compact.js",
|
|
44
|
+
"timeout": 3,
|
|
45
|
+
"compoundCritical": false
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"name": "context-guard-stop",
|
|
49
|
+
"tier": "compound-core",
|
|
50
|
+
"event": "Stop",
|
|
51
|
+
"matcher": "*",
|
|
52
|
+
"script": "hooks/context-guard.js",
|
|
53
|
+
"timeout": 5,
|
|
54
|
+
"compoundCritical": false
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"name": "stop-guard",
|
|
58
|
+
"tier": "compound-core",
|
|
59
|
+
"event": "Stop",
|
|
60
|
+
"matcher": "*",
|
|
61
|
+
"script": "hooks/stop-guard.js",
|
|
62
|
+
"timeout": 10,
|
|
63
|
+
"compoundCritical": true
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"name": "pre-tool-use",
|
|
67
|
+
"tier": "compound-core",
|
|
68
|
+
"event": "PreToolUse",
|
|
69
|
+
"matcher": "*",
|
|
70
|
+
"script": "hooks/pre-tool-use.js",
|
|
71
|
+
"timeout": 3,
|
|
72
|
+
"compoundCritical": true
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"name": "secret-filter",
|
|
76
|
+
"tier": "safety",
|
|
77
|
+
"event": "PostToolUse",
|
|
78
|
+
"matcher": "Write|Edit|Bash",
|
|
79
|
+
"script": "hooks/secret-filter.js",
|
|
80
|
+
"timeout": 3,
|
|
81
|
+
"compoundCritical": false
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"name": "slop-detector",
|
|
85
|
+
"tier": "safety",
|
|
86
|
+
"event": "PostToolUse",
|
|
87
|
+
"matcher": "Write|Edit",
|
|
88
|
+
"script": "hooks/slop-detector.js",
|
|
89
|
+
"timeout": 3,
|
|
90
|
+
"compoundCritical": false
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"name": "db-guard",
|
|
94
|
+
"tier": "safety",
|
|
95
|
+
"event": "PreToolUse",
|
|
96
|
+
"matcher": "Bash",
|
|
97
|
+
"script": "hooks/db-guard.js",
|
|
98
|
+
"timeout": 3,
|
|
99
|
+
"compoundCritical": false
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"name": "rate-limiter",
|
|
103
|
+
"tier": "safety",
|
|
104
|
+
"event": "PreToolUse",
|
|
105
|
+
"matcher": "*",
|
|
106
|
+
"script": "hooks/rate-limiter.js",
|
|
107
|
+
"timeout": 2,
|
|
108
|
+
"compoundCritical": false
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"name": "intent-classifier",
|
|
112
|
+
"tier": "workflow",
|
|
113
|
+
"event": "UserPromptSubmit",
|
|
114
|
+
"matcher": "*",
|
|
115
|
+
"script": "hooks/intent-classifier.js",
|
|
116
|
+
"timeout": 3,
|
|
117
|
+
"compoundCritical": false
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"name": "keyword-detector",
|
|
121
|
+
"tier": "workflow",
|
|
122
|
+
"event": "UserPromptSubmit",
|
|
123
|
+
"matcher": "*",
|
|
124
|
+
"script": "hooks/keyword-detector.js",
|
|
125
|
+
"timeout": 5,
|
|
126
|
+
"compoundCritical": false
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"name": "permission-handler",
|
|
130
|
+
"tier": "workflow",
|
|
131
|
+
"event": "PermissionRequest",
|
|
132
|
+
"matcher": "*",
|
|
133
|
+
"script": "hooks/permission-handler.js",
|
|
134
|
+
"timeout": 2,
|
|
135
|
+
"compoundCritical": false
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
"name": "subagent-tracker-start",
|
|
139
|
+
"tier": "workflow",
|
|
140
|
+
"event": "SubagentStart",
|
|
141
|
+
"matcher": "*",
|
|
142
|
+
"script": "hooks/subagent-tracker.js start",
|
|
143
|
+
"timeout": 2,
|
|
144
|
+
"compoundCritical": false
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
"name": "subagent-tracker-stop",
|
|
148
|
+
"tier": "workflow",
|
|
149
|
+
"event": "SubagentStop",
|
|
150
|
+
"matcher": "*",
|
|
151
|
+
"script": "hooks/subagent-tracker.js stop",
|
|
152
|
+
"timeout": 2,
|
|
153
|
+
"compoundCritical": false
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
"name": "subagent-stop-guard",
|
|
157
|
+
"tier": "workflow",
|
|
158
|
+
"event": "SubagentStop",
|
|
159
|
+
"matcher": "*",
|
|
160
|
+
"script": "hooks/subagent-stop-guard.js",
|
|
161
|
+
"timeout": 10,
|
|
162
|
+
"compoundCritical": false
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
"name": "post-tool-failure",
|
|
166
|
+
"tier": "workflow",
|
|
167
|
+
"event": "PostToolUseFailure",
|
|
168
|
+
"matcher": "*",
|
|
169
|
+
"script": "hooks/post-tool-failure.js",
|
|
170
|
+
"timeout": 3,
|
|
171
|
+
"compoundCritical": false
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
"name": "solution-injector",
|
|
175
|
+
"tier": "compound-core",
|
|
176
|
+
"event": "UserPromptSubmit",
|
|
177
|
+
"matcher": "*",
|
|
178
|
+
"script": "hooks/solution-injector.js",
|
|
179
|
+
"timeout": 5,
|
|
180
|
+
"compoundCritical": true
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
"name": "skill-injector",
|
|
184
|
+
"tier": "compound-core",
|
|
185
|
+
"event": "UserPromptSubmit",
|
|
186
|
+
"matcher": "*",
|
|
187
|
+
"script": "hooks/skill-injector.js",
|
|
188
|
+
"timeout": 5,
|
|
189
|
+
"compoundCritical": true
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
"name": "forge-loop-progress",
|
|
193
|
+
"tier": "compound-core",
|
|
194
|
+
"event": "UserPromptSubmit",
|
|
195
|
+
"matcher": "*",
|
|
196
|
+
"script": "hooks/forge-loop-progress.js",
|
|
197
|
+
"timeout": 2,
|
|
198
|
+
"compoundCritical": false
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
"name": "session-end",
|
|
202
|
+
"tier": "compound-core",
|
|
203
|
+
"event": "SessionEnd",
|
|
204
|
+
"matcher": "*",
|
|
205
|
+
"script": "hooks/session-end.js",
|
|
206
|
+
"timeout": 3,
|
|
207
|
+
"compoundCritical": true,
|
|
208
|
+
"hosts": [
|
|
209
|
+
"claude"
|
|
210
|
+
]
|
|
211
|
+
}
|
|
24
212
|
]
|