omniconductor 0.5.0 → 0.6.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/CHANGELOG.md +5 -0
- package/README.md +46 -10
- package/adapters/claude/README.md +1 -1
- package/adapters/claude/SUPPORTED-FEATURES.md +3 -3
- package/adapters/claude/transform-spec.md +1 -1
- package/adapters/claude/transform.sh +10 -4
- package/adapters/codex/transform.sh +2 -2
- package/adapters/copilot/transform.sh +2 -2
- package/adapters/cursor/transform.sh +2 -2
- package/adapters/gemini/transform.sh +2 -2
- package/adapters/windsurf/transform.sh +2 -2
- package/core/hooks/README.md +1 -0
- package/core/hooks/pretool-loop-guard.sh.template +177 -0
- package/core/recipes/README.md +4 -2
- package/core/recipes/loop-engineering.md +73 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,11 @@ Format follows [Keep a Changelog](https://keepachangelog.com/); versioning is [S
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
7
7
|
|
|
8
|
+
## [0.6.0] — 2026-07-07
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **`loop-engineering` recipe + `pretool-loop-guard` PreToolUse hook** — opt-in discipline for bounded, externally-verified agent loops (G1–G6): explicit done-criterion, iteration+token budget, require-progress, escalate-on-stall, **verify externally never by self-judgment**, oscillation/infinite-loop guard. Grounded in a 5-source verification pass (Huang/DeepMind "Cannot Self-Correct Yet", CRITIC, Reflexion, "When Agents Do Not Stop", Anthropic *Building Effective Agents* — verify hierarchy rules/tests > visual > LLM-judge). The Claude hook is a non-blocking `permissionDecision: ask` soft-warn that self-gates on the recipe, detects same-action-repeat / runaway tool-call budget, is fail-open, and honors `CONDUCTOR_SKIP_LOOP_GUARD` / `CONDUCTOR_LOOP_REPEAT_MAX` / `CONDUCTOR_LOOP_BUDGET` / `CONDUCTOR_LOOP_COOLDOWN_SECONDS`. Recipe count **12 → 13**, hook templates **9 → 10**. Hook is Claude-only (ADR-034); other tools use the rule text. — **ADR-038**.
|
|
12
|
+
|
|
8
13
|
## [0.5.0] — 2026-07-07
|
|
9
14
|
|
|
10
15
|
### Added
|
package/README.md
CHANGED
|
@@ -6,11 +6,11 @@ Write your project's rules, workflow, and discipline ONCE. Install into any AI c
|
|
|
6
6
|
|
|
7
7
|
> Born from one year of production iteration at LFamily Labs — the rules, agents, hooks, and memory patterns that survived real shipping pressure.
|
|
8
8
|
|
|
9
|
-
> **Status (v0.
|
|
9
|
+
> **Status (v0.6.0 — 2026-07-07)**: All 6 adapters ship a working `transform.sh` — **Claude Code** (full: rules + hooks + sub-agents + per-call model routing), **Cursor**, **GitHub Copilot** (one install covers 5 IDEs), **Gemini CLI** (`GEMINI.md` + `.gemini/styleguide.md`), **Codex** (`AGENTS.md`), **Windsurf / Devin Desktop** (`.windsurfrules` + `.devin/rules/*.md`). Published to npm as [`omniconductor`](https://www.npmjs.com/package/omniconductor) (v0.6.0). Output is emit-verified (format-validator + CI on all 6); live runtime consumption by Gemini / Codex / Windsurf is adopter-pending — see [`docs/ADAPTER-LIVE-VERIFICATION.md`](./docs/ADAPTER-LIVE-VERIFICATION.md). Manual install ([`docs/MANUAL-INSTALL.md`](./docs/MANUAL-INSTALL.md)) remains a fallback.
|
|
10
10
|
>
|
|
11
|
-
> **New in 0.
|
|
11
|
+
> **New in 0.6.0**: an opt-in **`loop-engineering` recipe** — bounded, externally-verified agent loops (explicit done-criterion, iteration+token budget, require-progress, escalate-on-stall, **verify externally never by self-judgment**, oscillation guard), grounded in a 5-source research pass; Claude adds a non-blocking PreToolUse loop-guard, other tools use the rule text (ADR-038). **In 0.5.0**: **`git-hygiene`** shared-repo discipline (ADR-037). **In 0.4.0**: instruction-fidelity **token economy** (ADR-035/036). **In 0.3.0**: **self-improvement / Reflector loop** (ADR-030/032/033) + compatibility-matrix correction (ADR-031). Full history: [`CHANGELOG.md`](./CHANGELOG.md).
|
|
12
12
|
>
|
|
13
|
-
> Marketplace listing (VSCode Marketplace + Open VSX) remains **Phase 2** (post-0.
|
|
13
|
+
> Marketplace listing (VSCode Marketplace + Open VSX) remains **Phase 2** (post-0.6) — see ADR-023.
|
|
14
14
|
|
|
15
15
|
---
|
|
16
16
|
|
|
@@ -21,7 +21,7 @@ Write your project's rules, workflow, and discipline ONCE. Install into any AI c
|
|
|
21
21
|
- [Tool coverage matrix](#tool-coverage-matrix)
|
|
22
22
|
- [Install paths (3 options)](#install-paths)
|
|
23
23
|
- [Cross-platform: Mac and Windows](#cross-platform-mac-and-windows)
|
|
24
|
-
- [Recipes catalog (
|
|
24
|
+
- [Recipes catalog (13)](#recipes-catalog)
|
|
25
25
|
- [`transform.sh` options reference](#transformsh-options-reference)
|
|
26
26
|
- [Update / Maintenance / Uninstall](#update--maintenance--uninstall)
|
|
27
27
|
- [Token measurement & KPI baseline](#token-measurement--kpi-baseline)
|
|
@@ -74,7 +74,41 @@ bash ~/conductor/adapters/claude/transform.sh . \
|
|
|
74
74
|
# 5. Claude Code 재시작 → /agents 로 6 에이전트 확인
|
|
75
75
|
```
|
|
76
76
|
|
|
77
|
-
|
|
77
|
+
### 설치 방법 (3가지)
|
|
78
|
+
|
|
79
|
+
- **Path A — `npx` (권장, 클론 불필요)**: `npx omniconductor init --target=<tool> <dir>` — `<tool>` = `claude` / `cursor` / `copilot` / `gemini` / `codex` / `windsurf`. `list` · `--dry-run` · `--recipes=A,B` · `--uninstall` 지원.
|
|
80
|
+
- **Path B — bash 어댑터**: CONDUCTOR 클론 후 `bash adapters/<tool>/transform.sh <dir> [--recipes=...] [--dry-run]`.
|
|
81
|
+
- **Path C — 수동 복사**: 스크립트 없이 `cp`/`cat` 으로. [`docs/MANUAL-INSTALL.md`](./docs/MANUAL-INSTALL.md) 참조.
|
|
82
|
+
- **Windows**: Git Bash 또는 WSL2 — [Cross-platform](#cross-platform-mac-and-windows) 참조.
|
|
83
|
+
|
|
84
|
+
### Recipe 카탈로그 (13개, opt-in)
|
|
85
|
+
|
|
86
|
+
5개 universal rule 은 항상 설치되고, recipe 는 프로젝트에 맞게 골라 담습니다 (`--recipes=`).
|
|
87
|
+
|
|
88
|
+
| Recipe | 설치 시점 |
|
|
89
|
+
|---|---|
|
|
90
|
+
| `coding-conventions` | TypeScript/TSX — 네이밍·Result 패턴·에러 처리 규약 |
|
|
91
|
+
| `monorepo` | npm/pnpm workspaces (apps + packages) |
|
|
92
|
+
| `i18n` | 2개 이상 로케일 — 새 텍스트는 모든 로케일 동시 |
|
|
93
|
+
| `branch-strategy` | main/develop/release 3-브랜치 모델 |
|
|
94
|
+
| `web-mobile-parity` | 웹+모바일 로직 공유 — 버그·기능 양쪽 반영 |
|
|
95
|
+
| `auto-mock-data` | DB 스키마 변경 시 mock seed 자동생성 |
|
|
96
|
+
| `tdd` | 테스트 프레임워크 + Red-Green-Refactor |
|
|
97
|
+
| `debugging` | 재현→원인→수정→회귀테스트 (증상 패치 금지) |
|
|
98
|
+
| `database-discipline` | 관계형 DB — 마이그레이션 우선·접근제어·dev/prod 패리티 |
|
|
99
|
+
| `design-system` | 디자인 토큰 시스템 — 토큰 우선·컴포넌트 재사용·접근성 |
|
|
100
|
+
| `self-improvement` | 세션 회고 Reflector (propose-only, 사람이 승인) |
|
|
101
|
+
| `git-hygiene` | git 프로젝트 (특히 멀티세션/공유 repo) — worktree·push·브랜치 위생 |
|
|
102
|
+
| `loop-engineering` | 에이전트 루프 (fix→verify 반복) — 종료조건·예산·**외부검증** |
|
|
103
|
+
|
|
104
|
+
### 업데이트 / 제거
|
|
105
|
+
|
|
106
|
+
- **업데이트**: CONDUCTOR 클론을 `git pull` 후 어댑터 재실행 (또는 `npx omniconductor` 최신 버전).
|
|
107
|
+
- **제거**: `bash adapters/<tool>/transform.sh <dir> --uninstall` — manifest 기반으로 CONDUCTOR 가 넣은 파일만 복원/삭제 (직접 커스터마이즈한 건 보존).
|
|
108
|
+
|
|
109
|
+
### 상세 레퍼런스 (영문)
|
|
110
|
+
|
|
111
|
+
도구별 지원 매트릭스, `transform.sh` 전체 옵션, 토큰 측정, 트러블슈팅, FAQ 는 아래 영문 섹션을 참조하세요: [Tool coverage matrix](#tool-coverage-matrix) · [transform.sh options](#transformsh-options-reference) · [Troubleshooting](#troubleshooting) · [FAQ](#faq).
|
|
78
112
|
|
|
79
113
|
---
|
|
80
114
|
|
|
@@ -248,7 +282,7 @@ For tools without an adapter (Gemini / Codex / Windsurf), or for adopters in con
|
|
|
248
282
|
|
|
249
283
|
## Recipes catalog
|
|
250
284
|
|
|
251
|
-
|
|
285
|
+
13 opt-in recipes layer project-specific discipline on top of the 5 universal rule bundles. Universal rules always install; recipes are pick-and-mix.
|
|
252
286
|
|
|
253
287
|
| Recipe | Install when | Adds |
|
|
254
288
|
|---|---|---|
|
|
@@ -264,6 +298,7 @@ For tools without an adapter (Gemini / Codex / Windsurf), or for adopters in con
|
|
|
264
298
|
| `design-system` | Design-token system in use | Tokens over raw hex, component reuse, accessibility + spacing scale adherence |
|
|
265
299
|
| `self-improvement` | Want periodic, human-approved review of your sessions | A **Reflector** reads recent session trajectories + git and **proposes** lessons-learned to `docs/REFLECTION-PROPOSALS.md` (propose-only; you apply). Emits a session-end trajectory hook, a `/reflect` command, a reflector agent, a deterministic prune, and a weekly runner + scheduling guide — on all six tools. See ADR-030/032/033. |
|
|
266
300
|
| `git-hygiene` | Any git project — esp. multi-session/agent repos or protected branches | Shared-repo discipline (G1–G7): no unrequested worktrees, push-don't-hoard, merge=delete-branch, backup≠applied (verify by real code), no reckless force/rebase on shared repos, bundle PRs for CI, session-end hygiene check. Claude adds a non-blocking Stop-hook reminder; other tools use the rule text. See ADR-037. |
|
|
301
|
+
| `loop-engineering` | Any agentic loop (generate→verify→fix→re-verify, test-fix, multi-step) | Bounded, externally-verified loops (G1–G6): explicit done-criterion, iteration+token budget, require-progress, escalate-on-stall, **verify externally never by self-judgment**, oscillation guard. Grounded in the research that self-correction without an external check is unreliable. Claude adds a non-blocking PreToolUse loop-guard (repeat/runaway detection); other tools use the rule text. See ADR-038. |
|
|
267
302
|
|
|
268
303
|
#### Decision tree
|
|
269
304
|
|
|
@@ -280,6 +315,7 @@ Relational DB + migrations? YES → database-discipline
|
|
|
280
315
|
Design-token system? YES → design-system
|
|
281
316
|
Want weekly session self-review? YES → self-improvement
|
|
282
317
|
Use git (esp. shared/multi-session)? YES → git-hygiene
|
|
318
|
+
Agent loops / iterative fix-verify? YES → loop-engineering
|
|
283
319
|
```
|
|
284
320
|
|
|
285
321
|
#### Recommended combos
|
|
@@ -304,7 +340,7 @@ Usage: bash adapters/<tool>/transform.sh <target-project> [options]
|
|
|
304
340
|
| Option | Description |
|
|
305
341
|
|---|---|
|
|
306
342
|
| `<target-project>` | Project directory to install into (required). `.` for current dir. |
|
|
307
|
-
| `--recipes=A,B,C` | Comma-separated recipes from the
|
|
343
|
+
| `--recipes=A,B,C` | Comma-separated recipes from the 13 in `core/recipes/`. |
|
|
308
344
|
| `--dry-run` | Preview only — no files written. |
|
|
309
345
|
| `--measure-baseline` | Run `tools/measure-tokens.sh --latest` after install; save CSV; auto-show anti-patterns if cache hit < 95%. |
|
|
310
346
|
| `--no-prompt` | Skip wizard, apply defaults (CI-safe). Combine with `--recipes` and `--measure-baseline` as needed. |
|
|
@@ -313,7 +349,7 @@ Usage: bash adapters/<tool>/transform.sh <target-project> [options]
|
|
|
313
349
|
| `--force` | Bypass uninstall safety gates (active rebase/merge, missing manifest). |
|
|
314
350
|
| `-h` `--help` | Print usage. |
|
|
315
351
|
|
|
316
|
-
**Recipe names** (
|
|
352
|
+
**Recipe names** (13): `web-mobile-parity`, `i18n`, `monorepo`, `branch-strategy`, `auto-mock-data`, `coding-conventions`, `tdd`, `debugging`, `database-discipline`, `design-system`, `self-improvement`, `git-hygiene`, `loop-engineering`.
|
|
317
353
|
|
|
318
354
|
#### File overwrite behavior
|
|
319
355
|
|
|
@@ -412,7 +448,7 @@ diff CLAUDE.md.conductor-backup-* CLAUDE.md
|
|
|
412
448
|
|
|
413
449
|
#### "recipe not found" warning
|
|
414
450
|
|
|
415
|
-
Check recipe name spelling. Available: `web-mobile-parity`, `i18n`, `monorepo`, `branch-strategy`, `auto-mock-data`, `coding-conventions`, `tdd`, `debugging`, `database-discipline`, `design-system`, `self-improvement`, `git-hygiene`.
|
|
451
|
+
Check recipe name spelling. Available: `web-mobile-parity`, `i18n`, `monorepo`, `branch-strategy`, `auto-mock-data`, `coding-conventions`, `tdd`, `debugging`, `database-discipline`, `design-system`, `self-improvement`, `git-hygiene`, `loop-engineering`.
|
|
416
452
|
|
|
417
453
|
#### "Tool doesn't recognize the new rules"
|
|
418
454
|
|
|
@@ -495,7 +531,7 @@ A: Open VSX. Cursor is a VSCode fork but cannot pull from Microsoft's marketplac
|
|
|
495
531
|
|
|
496
532
|
**Q: My project uses Go / Python / Rust, not TypeScript.**
|
|
497
533
|
|
|
498
|
-
A: Skip `coding-conventions` (TypeScript-specific). The 5 universal rule bundles and the other
|
|
534
|
+
A: Skip `coding-conventions` (TypeScript-specific). The 5 universal rule bundles and the other 12 recipes are stack-agnostic.
|
|
499
535
|
|
|
500
536
|
**Q: Windows native PowerShell?**
|
|
501
537
|
|
|
@@ -45,7 +45,7 @@ bash adapters/claude/transform.sh <target> [--dry-run]
|
|
|
45
45
|
│ │ ├── quality-gates.md
|
|
46
46
|
│ │ ├── operations.md
|
|
47
47
|
│ │ └── meta-discipline.md
|
|
48
|
-
│ ├── hooks/ #
|
|
48
|
+
│ ├── hooks/ # 10 hook scripts
|
|
49
49
|
│ │ ├── pretool-agent-routing.sh
|
|
50
50
|
│ │ ├── pretool-commit-current-work-check.sh
|
|
51
51
|
│ │ ├── pretool-commit-test-coverage-check.sh
|
|
@@ -32,7 +32,7 @@ CONDUCTOR's universal `meta-discipline.md` rubric (token economy + model routing
|
|
|
32
32
|
|
|
33
33
|
## Hook execution model
|
|
34
34
|
|
|
35
|
-
CONDUCTOR ships
|
|
35
|
+
CONDUCTOR ships 10 hooks, all registered in the generated `.claude/settings.json` (written directly by `transform.sh` — there is no `settings.template.json`):
|
|
36
36
|
|
|
37
37
|
| Hook | Event | Purpose |
|
|
38
38
|
|---|---|---|
|
|
@@ -58,9 +58,9 @@ The Claude adapter ships a working `transform.sh`. Verified by fresh-target inst
|
|
|
58
58
|
|
|
59
59
|
| Feature claim | Verified-by-real-install | Verification command / observation |
|
|
60
60
|
|---|---|---|
|
|
61
|
-
| `transform.sh` emits 6 roles, 5 rules,
|
|
61
|
+
| `transform.sh` emits 6 roles, 5 rules, 10 hooks, settings.json, docs | ✅ | `bash adapters/claude/transform.sh <tmp>` then inspect `<tmp>/.claude/` |
|
|
62
62
|
| Sub-agent dispatch works | ✅ | `.claude/agents/{planner,builder,reviewer,helper,designer,scribe}.md` recognized by `/help` |
|
|
63
63
|
| Lazy / always-loaded rules present | ✅ | `.claude/rules/{workflow,spec-as-you-go,quality-gates,operations,meta-discipline}.md` |
|
|
64
|
-
| Hooks registered in settings.json | ✅ | `.claude/settings.json` `hooks:` block lists
|
|
64
|
+
| Hooks registered in settings.json | ✅ | `.claude/settings.json` `hooks:` block lists 5 PreToolUse + 5 Stop |
|
|
65
65
|
| Stop hook blocks on missing spec update | ✅ | commit code without spec → `stop-session-log-check.sh` fires |
|
|
66
66
|
| Idempotent re-run | ✅ | second run reports "SKIP (exists)" for every emitted file |
|
|
@@ -31,7 +31,7 @@ core/docs-templates/specs/_example.md
|
|
|
31
31
|
core/memory-pattern/README.md
|
|
32
32
|
core/memory-pattern/EXAMPLES.md
|
|
33
33
|
core/roles/*.md # 6 role personas → .claude/agents/ (planner/builder/reviewer/helper/designer/scribe)
|
|
34
|
-
core/hooks/*.sh.template #
|
|
34
|
+
core/hooks/*.sh.template # 10 hook templates
|
|
35
35
|
adapters/claude/_native/CLAUDE.md.tpl # Claude-specific orchestrator manual template
|
|
36
36
|
```
|
|
37
37
|
|
|
@@ -70,7 +70,7 @@ Options:
|
|
|
70
70
|
manifest are preserved.
|
|
71
71
|
--force Bypass uninstall safety checks (active worktrees, missing manifest)
|
|
72
72
|
|
|
73
|
-
Recipes available: web-mobile-parity, i18n, monorepo, branch-strategy, auto-mock-data, coding-conventions, tdd, debugging, database-discipline, design-system, self-improvement, git-hygiene
|
|
73
|
+
Recipes available: web-mobile-parity, i18n, monorepo, branch-strategy, auto-mock-data, coding-conventions, tdd, debugging, database-discipline, design-system, self-improvement, git-hygiene, loop-engineering
|
|
74
74
|
EOF
|
|
75
75
|
exit 0
|
|
76
76
|
;;
|
|
@@ -593,7 +593,7 @@ if [ "$IS_ADOPTER_CASE" = "true" ] && [ "$NO_PROMPT" = "false" ] && [ "$DRY_RUN"
|
|
|
593
593
|
# 3. Select recipes
|
|
594
594
|
echo ""
|
|
595
595
|
echo "Available recipes:"
|
|
596
|
-
echo " web-mobile-parity, i18n, monorepo, branch-strategy, auto-mock-data, coding-conventions, tdd, debugging, database-discipline, design-system, self-improvement, git-hygiene"
|
|
596
|
+
echo " web-mobile-parity, i18n, monorepo, branch-strategy, auto-mock-data, coding-conventions, tdd, debugging, database-discipline, design-system, self-improvement, git-hygiene, loop-engineering"
|
|
597
597
|
printf "Select recipes (comma-separated, or leave blank for none): "
|
|
598
598
|
read -r _recipe_answer
|
|
599
599
|
if [ -n "$_recipe_answer" ]; then
|
|
@@ -725,7 +725,7 @@ mkdir_if_real "$TARGET_ABS/.claude/hooks"
|
|
|
725
725
|
# read guard) emit only if their templates are present in the CONDUCTOR core/ tree, allowing the
|
|
726
726
|
# adapter to remain forward-compatible with P1.7 work in progress.
|
|
727
727
|
INSTALLED_HOOKS=()
|
|
728
|
-
for hook in pretool-agent-routing stop-session-log-check stop-r6-review-check stop-cache-hit-baseline-check pretool-large-file-read-guard pretool-commit-current-work-check pretool-commit-test-coverage-check stop-trajectory-log stop-git-hygiene-guard; do
|
|
728
|
+
for hook in pretool-agent-routing stop-session-log-check stop-r6-review-check stop-cache-hit-baseline-check pretool-large-file-read-guard pretool-commit-current-work-check pretool-commit-test-coverage-check stop-trajectory-log stop-git-hygiene-guard pretool-loop-guard; do
|
|
729
729
|
src="$CORE_ROOT/hooks/$hook.sh.template"
|
|
730
730
|
dest="$TARGET_ABS/.claude/hooks/$hook.sh"
|
|
731
731
|
if [ ! -f "$src" ]; then
|
|
@@ -796,6 +796,12 @@ else
|
|
|
796
796
|
"hooks": [
|
|
797
797
|
{ "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/pretool-large-file-read-guard.sh" }
|
|
798
798
|
]
|
|
799
|
+
},
|
|
800
|
+
{
|
|
801
|
+
"matcher": "*",
|
|
802
|
+
"hooks": [
|
|
803
|
+
{ "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/pretool-loop-guard.sh" }
|
|
804
|
+
]
|
|
799
805
|
}
|
|
800
806
|
],
|
|
801
807
|
"Stop": [
|
|
@@ -812,7 +818,7 @@ else
|
|
|
812
818
|
}
|
|
813
819
|
}
|
|
814
820
|
SETTINGS_EOF
|
|
815
|
-
log " wrote $SETTINGS_PATH ($(printf '%s' "${INSTALLED_HOOKS[*]}" | /usr/bin/wc -w | /usr/bin/tr -d ' ') hook(s) installed in .claude/hooks; settings.json registers
|
|
821
|
+
log " wrote $SETTINGS_PATH ($(printf '%s' "${INSTALLED_HOOKS[*]}" | /usr/bin/wc -w | /usr/bin/tr -d ' ') hook(s) installed in .claude/hooks; settings.json registers 10 core hooks: 5 PreToolUse + 5 Stop)"
|
|
816
822
|
record_emit ".claude/settings.json" "<synthesized>" ""
|
|
817
823
|
fi
|
|
818
824
|
|
|
@@ -75,7 +75,7 @@ Output (single-file Codex model):
|
|
|
75
75
|
<target>/AGENTS.md Bundled intro + 5 universal rules + compressed workflow + recipes
|
|
76
76
|
<target>/docs/*.md Universal doc templates (CURRENT_WORK, REMAINING_TASKS, ...)
|
|
77
77
|
|
|
78
|
-
Recipes available: web-mobile-parity, i18n, monorepo, branch-strategy, auto-mock-data, coding-conventions, tdd, debugging, database-discipline, design-system, self-improvement, git-hygiene
|
|
78
|
+
Recipes available: web-mobile-parity, i18n, monorepo, branch-strategy, auto-mock-data, coding-conventions, tdd, debugging, database-discipline, design-system, self-improvement, git-hygiene, loop-engineering
|
|
79
79
|
|
|
80
80
|
What this adapter does NOT install (per ADR-004 honesty):
|
|
81
81
|
- Hook guards (CONDUCTOR emits the Reflector hook when --recipes=self-improvement, ADR-032; other guards remain Claude-only, ADR-034)
|
|
@@ -448,7 +448,7 @@ if [ "$IS_ADOPTER_CASE" = "true" ] && [ "$NO_PROMPT" = "false" ] && [ "$DRY_RUN"
|
|
|
448
448
|
|
|
449
449
|
echo ""
|
|
450
450
|
echo "Available recipes:"
|
|
451
|
-
echo " web-mobile-parity, i18n, monorepo, branch-strategy, auto-mock-data, coding-conventions, tdd, debugging, database-discipline, design-system, self-improvement, git-hygiene"
|
|
451
|
+
echo " web-mobile-parity, i18n, monorepo, branch-strategy, auto-mock-data, coding-conventions, tdd, debugging, database-discipline, design-system, self-improvement, git-hygiene, loop-engineering"
|
|
452
452
|
printf "Select recipes (comma-separated, or leave blank for none): "
|
|
453
453
|
read -r _recipe_answer
|
|
454
454
|
if [ -n "$_recipe_answer" ]; then
|
|
@@ -87,7 +87,7 @@ Options:
|
|
|
87
87
|
Conductor-emitted files when none.
|
|
88
88
|
--force Bypass uninstall safety checks (active worktrees, missing manifest)
|
|
89
89
|
|
|
90
|
-
Recipes available: web-mobile-parity, i18n, monorepo, branch-strategy, auto-mock-data, coding-conventions, tdd, debugging, database-discipline, design-system, self-improvement, git-hygiene
|
|
90
|
+
Recipes available: web-mobile-parity, i18n, monorepo, branch-strategy, auto-mock-data, coding-conventions, tdd, debugging, database-discipline, design-system, self-improvement, git-hygiene, loop-engineering
|
|
91
91
|
|
|
92
92
|
Output (default):
|
|
93
93
|
<target>/.github/copilot-instructions.md (5 universal rules merged)
|
|
@@ -523,7 +523,7 @@ if [ "$IS_ADOPTER_CASE" = "true" ] && [ "$NO_PROMPT" = "false" ] && [ "$DRY_RUN"
|
|
|
523
523
|
|
|
524
524
|
echo ""
|
|
525
525
|
echo "Available recipes:"
|
|
526
|
-
echo " web-mobile-parity, i18n, monorepo, branch-strategy, auto-mock-data, coding-conventions, tdd, debugging, database-discipline, design-system, self-improvement, git-hygiene"
|
|
526
|
+
echo " web-mobile-parity, i18n, monorepo, branch-strategy, auto-mock-data, coding-conventions, tdd, debugging, database-discipline, design-system, self-improvement, git-hygiene, loop-engineering"
|
|
527
527
|
printf "Select recipes (comma-separated, blank for none): "
|
|
528
528
|
read -r _recipe_answer
|
|
529
529
|
if [ -n "$_recipe_answer" ]; then
|
|
@@ -67,7 +67,7 @@ Options:
|
|
|
67
67
|
manifest are preserved.
|
|
68
68
|
--force Bypass uninstall safety checks (active worktrees, missing manifest)
|
|
69
69
|
|
|
70
|
-
Recipes available: web-mobile-parity, i18n, monorepo, branch-strategy, auto-mock-data, coding-conventions, tdd, debugging, database-discipline, design-system, self-improvement, git-hygiene
|
|
70
|
+
Recipes available: web-mobile-parity, i18n, monorepo, branch-strategy, auto-mock-data, coding-conventions, tdd, debugging, database-discipline, design-system, self-improvement, git-hygiene, loop-engineering
|
|
71
71
|
|
|
72
72
|
What this adapter does NOT install (per ADR-004 honesty + ADR-021):
|
|
73
73
|
- Hook guards (CONDUCTOR emits the Reflector hook when --recipes=self-improvement, ADR-032; other guards remain Claude-only, ADR-034)
|
|
@@ -490,7 +490,7 @@ if [ "$IS_ADOPTER_CASE" = "true" ] && [ "$NO_PROMPT" = "false" ] && [ "$DRY_RUN"
|
|
|
490
490
|
|
|
491
491
|
echo ""
|
|
492
492
|
echo "Available recipes:"
|
|
493
|
-
echo " web-mobile-parity, i18n, monorepo, branch-strategy, auto-mock-data, coding-conventions, tdd, debugging, database-discipline, design-system, self-improvement, git-hygiene"
|
|
493
|
+
echo " web-mobile-parity, i18n, monorepo, branch-strategy, auto-mock-data, coding-conventions, tdd, debugging, database-discipline, design-system, self-improvement, git-hygiene, loop-engineering"
|
|
494
494
|
printf "Select recipes (comma-separated, or leave blank for none): "
|
|
495
495
|
read -r _recipe_answer
|
|
496
496
|
if [ -n "$_recipe_answer" ]; then
|
|
@@ -71,7 +71,7 @@ Options:
|
|
|
71
71
|
manifest are preserved.
|
|
72
72
|
--force Bypass uninstall safety checks (active worktrees, missing manifest)
|
|
73
73
|
|
|
74
|
-
Recipes available: web-mobile-parity, i18n, monorepo, branch-strategy, auto-mock-data, coding-conventions, tdd, debugging, database-discipline, design-system, self-improvement, git-hygiene
|
|
74
|
+
Recipes available: web-mobile-parity, i18n, monorepo, branch-strategy, auto-mock-data, coding-conventions, tdd, debugging, database-discipline, design-system, self-improvement, git-hygiene, loop-engineering
|
|
75
75
|
|
|
76
76
|
Gemini single-file model:
|
|
77
77
|
- All 5 universal rules + selected recipes are bundled into one always-loaded GEMINI.md.
|
|
@@ -486,7 +486,7 @@ if [ "$IS_ADOPTER_CASE" = "true" ] && [ "$NO_PROMPT" = "false" ] && [ "$DRY_RUN"
|
|
|
486
486
|
|
|
487
487
|
echo ""
|
|
488
488
|
echo "Available recipes:"
|
|
489
|
-
echo " web-mobile-parity, i18n, monorepo, branch-strategy, auto-mock-data, coding-conventions, tdd, debugging, database-discipline, design-system, self-improvement, git-hygiene"
|
|
489
|
+
echo " web-mobile-parity, i18n, monorepo, branch-strategy, auto-mock-data, coding-conventions, tdd, debugging, database-discipline, design-system, self-improvement, git-hygiene, loop-engineering"
|
|
490
490
|
printf "Select recipes (comma-separated, or leave blank for none): "
|
|
491
491
|
read -r _recipe_answer
|
|
492
492
|
if [ -n "$_recipe_answer" ]; then
|
|
@@ -67,7 +67,7 @@ Options:
|
|
|
67
67
|
manifest are preserved.
|
|
68
68
|
--force Bypass uninstall safety checks (active worktrees, missing manifest)
|
|
69
69
|
|
|
70
|
-
Recipes available: web-mobile-parity, i18n, monorepo, branch-strategy, auto-mock-data, coding-conventions, tdd, debugging, database-discipline, design-system, self-improvement, git-hygiene
|
|
70
|
+
Recipes available: web-mobile-parity, i18n, monorepo, branch-strategy, auto-mock-data, coding-conventions, tdd, debugging, database-discipline, design-system, self-improvement, git-hygiene, loop-engineering
|
|
71
71
|
|
|
72
72
|
What this adapter does NOT install (per ADR-004 honesty + ADR-021):
|
|
73
73
|
- Hook guards (CONDUCTOR emits the Reflector hook when --recipes=self-improvement, ADR-032; other guards remain Claude-only, ADR-034)
|
|
@@ -453,7 +453,7 @@ if [ "$IS_ADOPTER_CASE" = "true" ] && [ "$NO_PROMPT" = "false" ] && [ "$DRY_RUN"
|
|
|
453
453
|
|
|
454
454
|
echo ""
|
|
455
455
|
echo "Available recipes:"
|
|
456
|
-
echo " web-mobile-parity, i18n, monorepo, branch-strategy, auto-mock-data, coding-conventions, tdd, debugging, database-discipline, design-system, self-improvement, git-hygiene"
|
|
456
|
+
echo " web-mobile-parity, i18n, monorepo, branch-strategy, auto-mock-data, coding-conventions, tdd, debugging, database-discipline, design-system, self-improvement, git-hygiene, loop-engineering"
|
|
457
457
|
printf "Select recipes (comma-separated, or leave blank for none): "
|
|
458
458
|
read -r _recipe_answer
|
|
459
459
|
if [ -n "$_recipe_answer" ]; then
|
package/core/hooks/README.md
CHANGED
|
@@ -15,6 +15,7 @@ CONDUCTOR's universal hook spec. Templates here are compiled into native shell s
|
|
|
15
15
|
| `stop-cache-hit-baseline-check.sh.template` | Session stop event | Non-blocking diagnostic — reads the latest session JSONL, computes cache hit rate, reminds when below baseline (token-economy). Fail-open. Override env disables: `CONDUCTOR_SKIP_CACHE_CHECK=1`. | Claude `.claude/hooks/stop-cache-hit-baseline-check.sh` |
|
|
16
16
|
| `stop-trajectory-log.sh.template` | Session stop event | Non-blocking — reads `transcript_path` + `session_id` from the Stop hook's **stdin** (exact provenance; no `~/.claude/projects` dir-scan) and **upserts** one pointer record per session (session id, transcript path, git HEAD, cwd) into `.conductor/trajectories/index.jsonl` for the Reflector (recipes/self-improvement.md). Same stdin approach as the non-Claude portable logger `core/reflector/trajectory-log.sh`. **Opt-in gated: no-ops unless `.conductor/reflect/` exists** (created only by the self-improvement recipe). Anchors to the project root; fail-open. Override: `CONDUCTOR_SKIP_TRAJLOG=1`. | Claude `.claude/hooks/stop-trajectory-log.sh` |
|
|
17
17
|
| `stop-git-hygiene-guard.sh.template` | Session stop event | Non-blocking — detects git-hygiene collapse (extra worktrees, local-only commits not on any remote, abnormally many local branches) and injects a cleanup reminder per `recipes/git-hygiene.md` (G1/G2/G3/G7). **Opt-in gated: no-ops unless `.claude/rules/git-hygiene.md` exists** (created only by the git-hygiene recipe). Anchors to the project root; 15-min cool-down; fail-open, always exits 0. Overrides: `CONDUCTOR_SKIP_GIT_HYGIENE=1`, `CONDUCTOR_GIT_HYGIENE_BRANCH_MAX` (default 20). | Claude `.claude/hooks/stop-git-hygiene-guard.sh` |
|
|
18
|
+
| `pretool-loop-guard.sh.template` | Before each tool call (PreToolUse, `*` matcher) | Non-blocking soft-warn (`permissionDecision: ask`) — tracks a per-session signature of each tool call and surfaces a reminder when the **same action repeats** ≥ `CONDUCTOR_LOOP_REPEAT_MAX` (default 5; oscillation/no-progress) or the session's **total tool calls** ≥ `CONDUCTOR_LOOP_BUDGET` (default 120; runaway), per `recipes/loop-engineering.md` (G2/G3/G6). **Opt-in gated: no-ops unless `.claude/rules/loop-engineering.md` exists.** Per-session cool-down (`CONDUCTOR_LOOP_COOLDOWN_SECONDS`, default 120); trace in `$TMPDIR`, not the repo; fail-open, always exits 0. Override: `CONDUCTOR_SKIP_LOOP_GUARD=1`. | Claude `.claude/hooks/pretool-loop-guard.sh` |
|
|
18
19
|
|
|
19
20
|
The two `pretool-commit-*` templates are **soft `ask` warns**: they emit
|
|
20
21
|
`{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"ask","permissionDecisionReason":...}}`,
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# CONDUCTOR universal hook template
|
|
4
|
+
# hook_id: pretool-loop-guard
|
|
5
|
+
# trigger: pretool
|
|
6
|
+
# action: Before each tool call, track a per-session signature of the call and
|
|
7
|
+
# soft-warn (non-blocking "ask") when the SAME action repeats too often
|
|
8
|
+
# (oscillation / no-progress loop) or the session's total tool calls
|
|
9
|
+
# exceed a budget (runaway loop). Enforces the loop-engineering recipe.
|
|
10
|
+
# compile_targets: claude
|
|
11
|
+
# fallback: rule-text-reminder
|
|
12
|
+
#
|
|
13
|
+
# Generated by adapters/<tool>/transform.sh.
|
|
14
|
+
#
|
|
15
|
+
# Enforces:
|
|
16
|
+
# - recipes/loop-engineering.md (bound the loop: iteration budget G2, no-progress
|
|
17
|
+
# halt G3, oscillation/infinite-loop guard G6)
|
|
18
|
+
#
|
|
19
|
+
# Behavior (fail-open, non-blocking):
|
|
20
|
+
# 1. No-op unless the loop-engineering recipe is installed (self-gate on
|
|
21
|
+
# .claude/rules/loop-engineering.md).
|
|
22
|
+
# 2. Per session, keep a trace of tool-call signatures in a private tmp file.
|
|
23
|
+
# A "signature" = tool_name + hash(tool_input): identical calls collide.
|
|
24
|
+
# 3. Warn (permissionDecision:ask + reason) when the CURRENT signature has
|
|
25
|
+
# occurred >= REPEAT_MAX times (same action repeated — likely looping without
|
|
26
|
+
# progress), OR the session's total tool calls >= BUDGET (runaway). A per-
|
|
27
|
+
# session cool-down keeps it from firing on every subsequent call.
|
|
28
|
+
# 4. ALWAYS exit 0. Any error, missing input, or missing python3 → allow silently.
|
|
29
|
+
# "ask" surfaces the reason and routes to the permission flow — it does NOT
|
|
30
|
+
# hard-block and does NOT auto-approve (same contract as the other pretool
|
|
31
|
+
# soft-warns).
|
|
32
|
+
#
|
|
33
|
+
# Overrides (runtime env, not compile-time placeholders):
|
|
34
|
+
# CONDUCTOR_SKIP_LOOP_GUARD=1 disable entirely
|
|
35
|
+
# CONDUCTOR_LOOP_REPEAT_MAX same-action repeat threshold (default 5)
|
|
36
|
+
# CONDUCTOR_LOOP_BUDGET total tool-calls-per-session threshold (default 120)
|
|
37
|
+
# CONDUCTOR_LOOP_COOLDOWN_SECONDS min seconds between warns per session (default 120)
|
|
38
|
+
|
|
39
|
+
set -u
|
|
40
|
+
|
|
41
|
+
# Honor opt-out before any work.
|
|
42
|
+
[ "${CONDUCTOR_SKIP_LOOP_GUARD:-}" = "1" ] && exit 0
|
|
43
|
+
|
|
44
|
+
# Anchor to the project root (emitted hook lives at <project>/.claude/hooks/).
|
|
45
|
+
_self_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)" || exit 0
|
|
46
|
+
_proj_root="$(cd "$_self_dir/../.." 2>/dev/null && pwd)" || exit 0
|
|
47
|
+
cd "$_proj_root" 2>/dev/null || exit 0
|
|
48
|
+
|
|
49
|
+
# Self-gate: only act when the loop-engineering recipe is installed.
|
|
50
|
+
[ -f ".claude/rules/loop-engineering.md" ] || exit 0
|
|
51
|
+
|
|
52
|
+
# Robust JSON handling needs python3; without it, degrade to silent allow.
|
|
53
|
+
command -v /usr/bin/python3 >/dev/null 2>&1 || exit 0
|
|
54
|
+
|
|
55
|
+
# Read the PreToolUse payload from stdin (no piped stdin → nothing to do).
|
|
56
|
+
export PAYLOAD_RAW="$(/bin/cat 2>/dev/null || true)"
|
|
57
|
+
[ -n "${PAYLOAD_RAW:-}" ] || exit 0
|
|
58
|
+
|
|
59
|
+
# All logic lives in python for safe parsing / hashing / file IO. It prints EITHER
|
|
60
|
+
# the ask-JSON (when a threshold is crossed and not cooling down) or nothing. Any
|
|
61
|
+
# exception prints nothing → the shell falls through to `exit 0` (allow).
|
|
62
|
+
REPEAT_MAX="${CONDUCTOR_LOOP_REPEAT_MAX:-5}" \
|
|
63
|
+
BUDGET="${CONDUCTOR_LOOP_BUDGET:-120}" \
|
|
64
|
+
COOLDOWN="${CONDUCTOR_LOOP_COOLDOWN_SECONDS:-120}" \
|
|
65
|
+
/usr/bin/python3 -c '
|
|
66
|
+
import json, os, sys, hashlib, re, time, tempfile
|
|
67
|
+
|
|
68
|
+
def out_nothing():
|
|
69
|
+
sys.exit(0)
|
|
70
|
+
|
|
71
|
+
try:
|
|
72
|
+
raw = os.environ.get("PAYLOAD_RAW", "") or ""
|
|
73
|
+
d = json.loads(raw)
|
|
74
|
+
if not isinstance(d, dict):
|
|
75
|
+
out_nothing()
|
|
76
|
+
|
|
77
|
+
tool = d.get("tool_name", "") or ""
|
|
78
|
+
if not tool:
|
|
79
|
+
out_nothing() # no identifiable action → nothing to track
|
|
80
|
+
|
|
81
|
+
tool_input = d.get("tool_input", {})
|
|
82
|
+
session = d.get("session_id", "") or d.get("sessionId", "") or "nosession"
|
|
83
|
+
|
|
84
|
+
# Sanitize identifiers used in file paths (defense against path injection).
|
|
85
|
+
session = re.sub(r"[^A-Za-z0-9_-]", "", str(session))[:64] or "nosession"
|
|
86
|
+
user = re.sub(r"[^A-Za-z0-9_-]", "", os.environ.get("USER", "") or "unknown")[:32] or "unknown"
|
|
87
|
+
|
|
88
|
+
# Thresholds (env-tunable, with safe fallbacks on garbage input).
|
|
89
|
+
def envint(name, default):
|
|
90
|
+
try:
|
|
91
|
+
v = int(os.environ.get(name, "") or default)
|
|
92
|
+
return v if v > 0 else default
|
|
93
|
+
except Exception:
|
|
94
|
+
return default
|
|
95
|
+
repeat_max = envint("REPEAT_MAX", 5)
|
|
96
|
+
budget = envint("BUDGET", 120)
|
|
97
|
+
cooldown = envint("COOLDOWN", 120)
|
|
98
|
+
|
|
99
|
+
# Signature = tool + stable hash of its input. Identical calls collide;
|
|
100
|
+
# a canonical (sorted-key) dump makes key order irrelevant.
|
|
101
|
+
try:
|
|
102
|
+
payload = json.dumps(tool_input, sort_keys=True, ensure_ascii=True, default=str)
|
|
103
|
+
except Exception:
|
|
104
|
+
payload = repr(tool_input)
|
|
105
|
+
sig = tool + ":" + hashlib.sha1(payload.encode("utf-8", "replace")).hexdigest()[:16]
|
|
106
|
+
|
|
107
|
+
tmp = tempfile.gettempdir()
|
|
108
|
+
base = os.path.join(tmp, "conductor-loop-%s-%s" % (user, session))
|
|
109
|
+
trace_path = base + ".trace"
|
|
110
|
+
cooldown_path = base + ".cooldown"
|
|
111
|
+
|
|
112
|
+
# Append this signature, then read the (bounded) trace back.
|
|
113
|
+
try:
|
|
114
|
+
with open(trace_path, "a", encoding="utf-8") as f:
|
|
115
|
+
f.write(sig + "\n")
|
|
116
|
+
except Exception:
|
|
117
|
+
out_nothing() # cannot persist → cannot reason about the loop; allow.
|
|
118
|
+
|
|
119
|
+
try:
|
|
120
|
+
with open(trace_path, "r", encoding="utf-8") as f:
|
|
121
|
+
lines = f.read().splitlines()
|
|
122
|
+
except Exception:
|
|
123
|
+
out_nothing()
|
|
124
|
+
|
|
125
|
+
# Bound work: only the last N entries matter for a runaway/oscillation view.
|
|
126
|
+
if len(lines) > 5000:
|
|
127
|
+
lines = lines[-5000:]
|
|
128
|
+
|
|
129
|
+
total = len(lines)
|
|
130
|
+
same = sum(1 for x in lines if x == sig)
|
|
131
|
+
|
|
132
|
+
hit_repeat = same >= repeat_max
|
|
133
|
+
hit_budget = total >= budget
|
|
134
|
+
if not (hit_repeat or hit_budget):
|
|
135
|
+
out_nothing()
|
|
136
|
+
|
|
137
|
+
# Cool-down: at most one warn per `cooldown` seconds per session.
|
|
138
|
+
now = int(time.time())
|
|
139
|
+
try:
|
|
140
|
+
with open(cooldown_path, "r", encoding="utf-8") as f:
|
|
141
|
+
last = int((f.read().strip() or "0"))
|
|
142
|
+
except Exception:
|
|
143
|
+
last = 0
|
|
144
|
+
if now - last < cooldown:
|
|
145
|
+
out_nothing()
|
|
146
|
+
try:
|
|
147
|
+
with open(cooldown_path, "w", encoding="utf-8") as f:
|
|
148
|
+
f.write(str(now))
|
|
149
|
+
except Exception:
|
|
150
|
+
pass # cool-down is best-effort; still warn this once.
|
|
151
|
+
|
|
152
|
+
if hit_repeat:
|
|
153
|
+
reason = ("[loop-guard] The same action (%s) has run %d times this session — "
|
|
154
|
+
"you may be looping without progress (recipe G3/G6). Before repeating: "
|
|
155
|
+
"confirm each iteration changes state, verify with an EXTERNAL check "
|
|
156
|
+
"(tests/rules/tool output — not self-judgment), and if stuck after a few "
|
|
157
|
+
"tries, stop and ask rather than loop (G4). " % (tool, same))
|
|
158
|
+
else:
|
|
159
|
+
reason = ("[loop-guard] %d tool calls this session — approaching a runaway loop "
|
|
160
|
+
"(recipe G2 iteration budget). Confirm you are converging on an explicit "
|
|
161
|
+
"done-criterion, not spinning. " % total)
|
|
162
|
+
reason += "(Silence: CONDUCTOR_SKIP_LOOP_GUARD=1; tune CONDUCTOR_LOOP_REPEAT_MAX / CONDUCTOR_LOOP_BUDGET.)"
|
|
163
|
+
|
|
164
|
+
print(json.dumps({
|
|
165
|
+
"hookSpecificOutput": {
|
|
166
|
+
"hookEventName": "PreToolUse",
|
|
167
|
+
"permissionDecision": "ask",
|
|
168
|
+
"permissionDecisionReason": reason,
|
|
169
|
+
}
|
|
170
|
+
}))
|
|
171
|
+
except SystemExit:
|
|
172
|
+
raise
|
|
173
|
+
except Exception:
|
|
174
|
+
# Absolutely never fail a tool call because of this guard.
|
|
175
|
+
pass
|
|
176
|
+
'
|
|
177
|
+
exit 0
|
package/core/recipes/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Per ADR-013, CONDUCTOR ships project-specific recipes as OPT-IN. They are not loaded by default. Adopters select the recipes that match their project and the adapter wires them into the appropriate native location.
|
|
4
4
|
|
|
5
|
-
## The
|
|
5
|
+
## The 13 recipes
|
|
6
6
|
|
|
7
7
|
| File | When to install |
|
|
8
8
|
|---|---|
|
|
@@ -18,6 +18,7 @@ Per ADR-013, CONDUCTOR ships project-specific recipes as OPT-IN. They are not lo
|
|
|
18
18
|
| `design-system.md` | Project maintains a design-token system (color/spacing/typography tokens). Ships 1 recipe-scoped hookify rule (raw-hex-instead-of-token) — see ADR-028 |
|
|
19
19
|
| `self-improvement.md` | Project wants a periodic, human-approved Reflector that distils session lessons into memory/rules. Propose-only; nothing auto-applies. Drives the `reflector` role — see ADR-030 |
|
|
20
20
|
| `git-hygiene.md` | Any git project — esp. repos worked by multiple sessions/agents or with protected branches. Shared-repo discipline (no orphan worktrees, push-don't-hoard, merge=delete-branch, backup≠applied). Ships a Claude-only Stop-hook reminder (`stop-git-hygiene-guard`); other tools use the rule text — see ADR-037 |
|
|
21
|
+
| `loop-engineering.md` | Any agentic loop (generate→verify→fix→re-verify, test-fix, multi-step). Bounded, externally-verified loops: explicit done-criterion, iteration+token budget, require-progress, escalate-on-stall, verify-externally-not-self-judgment, oscillation guard. Ships a Claude-only PreToolUse reminder (`pretool-loop-guard`); other tools use the rule text — see ADR-038 |
|
|
21
22
|
|
|
22
23
|
## Selection patterns
|
|
23
24
|
|
|
@@ -28,8 +29,9 @@ Per ADR-013, CONDUCTOR ships project-specific recipes as OPT-IN. They are not lo
|
|
|
28
29
|
| Multi-locale SaaS | `i18n` + `coding-conventions` + `tdd` + `debugging` |
|
|
29
30
|
| Relational-DB-backed SaaS (migrations + dev/prod) | `database-discipline` + `coding-conventions` + `tdd` + `debugging` |
|
|
30
31
|
| Token-driven design system (theming / dark-mode) | `design-system` + `coding-conventions` + `tdd` + `debugging` |
|
|
31
|
-
| Full-stack SaaS with web + mobile + i18n | All
|
|
32
|
+
| Full-stack SaaS with web + mobile + i18n | All 13 |
|
|
32
33
|
| Any git repo, esp. shared / multi-session | add `git-hygiene` to any of the above |
|
|
34
|
+
| Agentic / iterative loops (fix-verify, test-fix) | add `loop-engineering` to any of the above |
|
|
33
35
|
| Greenfield experiment | None — universal-rules + roles only is enough |
|
|
34
36
|
|
|
35
37
|
## How adapters consume these files
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
recipe_id: loop-engineering
|
|
3
|
+
recipe_name: "Loop Engineering (bounded, externally-verified agent loops)"
|
|
4
|
+
applies_when: "any agentic coding work that iterates — generate→verify→fix→re-verify, test-fix loops, multi-step tasks"
|
|
5
|
+
severity: STRONG (when installed)
|
|
6
|
+
linked_rules:
|
|
7
|
+
- quality-gates
|
|
8
|
+
- meta-discipline
|
|
9
|
+
- workflow
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Recipe — Loop Engineering
|
|
13
|
+
|
|
14
|
+
> Opt-in recipe. Install for any project where the agent works in a **loop** — "do → check → fix → re-check until done." It codifies how to run that loop so it **terminates correctly, stays bounded, and never declares success without an external check.** Install if you want agent loops that are reliable instead of ones that thrash, run away, or report "done" on unverified work.
|
|
15
|
+
|
|
16
|
+
## Why this exists
|
|
17
|
+
|
|
18
|
+
An agent that loops "until it's right" fails in a few well-documented ways. The evidence (peer-reviewed + Anthropic primary sources) is blunt:
|
|
19
|
+
|
|
20
|
+
- **Self-correction without an external signal is unreliable and can make things WORSE.** Models asked to fix their own work with no external feedback often flip correct answers to wrong ones (*LLMs Cannot Self-Correct Reasoning Yet*, Huang et al., DeepMind, ICLR'24). The real gains come from loops grounded in **tests/tools** (Reflexion, CRITIC), not self-judgment.
|
|
21
|
+
- **"The model says it's done" is not evidence.** LLM self-assessment is systematically over-confident, and LLM-as-judge carries position/verbosity/self-preference bias (*Judging LLM-as-a-Judge*, Zheng et al., NeurIPS'23). Declaring victory without running the check ("early victory") is the most common fidelity failure.
|
|
22
|
+
- **Unbounded loops run away.** Infinite / oscillation (edit↔revert) loops are a documented structural failure — in one study **95.6% ended in cost exhaustion / model-DoS** (*When Agents Do Not Stop*, 2026). More iterations help only up to a point, then *saturate and hurt*; long trajectories degrade (context rot, error compounding).
|
|
23
|
+
|
|
24
|
+
So a good loop is **bounded, progress-checked, and terminated by an external verifier** — not by the model's opinion. Prose gets forgotten, so on the Claude adapter this recipe is backed by a `pretool-loop-guard` hook.
|
|
25
|
+
|
|
26
|
+
## The loop shape (well-supported)
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
Plan → (act → verify) loop → replan on failure → escalate on repeated stall
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
- **Plan first**, then act (ReAct: interleave reason+act+observe beats act-only).
|
|
33
|
+
- On a failed check, **reflect and replan** using the failure (Reflexion) — not a blind retry.
|
|
34
|
+
- Reserve expensive search/branching (Tree-of-Thoughts) for genuinely exploratory tasks; the default loop stays simple (Anthropic: "the simplest solution possible; add complexity only when it demonstrably improves outcomes").
|
|
35
|
+
|
|
36
|
+
## The 6 obligations
|
|
37
|
+
|
|
38
|
+
### G1 — Terminate on an explicit, verified done-criterion
|
|
39
|
+
Before looping, state what "done" IS (a passing test, a matching value, a satisfied spec item). The loop ends when that criterion is **verified true** — never on a vibe or a word-count of effort.
|
|
40
|
+
|
|
41
|
+
### G2 — Bound the loop (iteration + token budget)
|
|
42
|
+
Set a ceiling before you start: a max number of iterations AND a token/time budget. When the ceiling is hit, **stop and report** (with what's done and what's left) — do not silently keep going. Anthropic ships this as `max_turns` / `max_budget_usd` ("a good default for production agents").
|
|
43
|
+
|
|
44
|
+
### G3 — Require progress each iteration
|
|
45
|
+
Every pass must change state toward the goal. If an iteration produces no new information or the same result, that is a **no-progress signal** — stop and rethink rather than repeat. (More iterations past the point of progress saturate, then degrade quality.)
|
|
46
|
+
|
|
47
|
+
### G4 — Escalate on stall, don't loop forever
|
|
48
|
+
After a small number of failed/no-progress iterations (default ~3–5), **hand back to the human** with the state and the blocker, instead of looping. Ties to `meta-discipline.md` AMB — when stuck or the next step is non-trivially reversible, ASK.
|
|
49
|
+
|
|
50
|
+
### G5 — Verify externally, never by self-judgment (the core rule)
|
|
51
|
+
A loop's exit signal MUST be an **external / ground-truth check** — run the test, execute the code, lint against the rule, diff the value — **not** the model asserting "looks correct." Verify hierarchy (Anthropic, strongest first):
|
|
52
|
+
|
|
53
|
+
1. **Rules / tests / tool output** — deterministic, best (e.g. run the test suite; lint TS instead of eyeballing).
|
|
54
|
+
2. **Visual / rendered feedback** — screenshots, output diffs.
|
|
55
|
+
3. **LLM-as-judge** — weakest, last resort, and never the sole gate.
|
|
56
|
+
|
|
57
|
+
This is `quality-gates.md` Q4 (verify-after-changes) applied inside the loop. "Declared done without running the check" = the early-victory anti-pattern; it is a rule violation here.
|
|
58
|
+
|
|
59
|
+
### G6 — Guard against oscillation / infinite loops
|
|
60
|
+
Detect and break repetition: the same action repeated, or an edit↔revert cycle, means the loop is spinning. Track what you've already tried; if you're repeating, **change approach or escalate (G4)** — never keep re-issuing the same failing action.
|
|
61
|
+
|
|
62
|
+
## Conductor Integration
|
|
63
|
+
|
|
64
|
+
- **Claude** — a PreToolUse hook `pretool-loop-guard` (from `core/hooks/`) tracks a per-session signature of each tool call and fires a **non-blocking soft-warn** (`permissionDecision: ask`) when the **same action repeats too often** (G3/G6 — likely looping without progress) or the **session's total tool calls exceed a budget** (G2 — runaway). It self-gates on this recipe being installed, is fail-open (never blocks a tool call on error), and honors `CONDUCTOR_SKIP_LOOP_GUARD=1`, `CONDUCTOR_LOOP_REPEAT_MAX` (default 5), `CONDUCTOR_LOOP_BUDGET` (default 120), `CONDUCTOR_LOOP_COOLDOWN_SECONDS` (default 120).
|
|
65
|
+
- **Cursor / Copilot / Gemini / Codex / Windsurf** — the hook is Claude-only (per `docs/DESIGN-DECISIONS.md` ADR-034/ADR-038). On these tools this recipe's rule text is the enforcement: follow G1–G6 by discipline (the loop shape + external-verify rule are tool-agnostic).
|
|
66
|
+
|
|
67
|
+
## Cross-References
|
|
68
|
+
|
|
69
|
+
- `quality-gates.md` §4 (verify-after-changes) — G5's external-verify rule is Q4 applied inside the loop.
|
|
70
|
+
- `meta-discipline.md` §3 (AMB) — G4's escalate-on-stall / ASK-when-stuck gate.
|
|
71
|
+
- `meta-discipline.md` §5.9 (output brevity) + §5.7 — G2's token budget shares the token-economy ceiling.
|
|
72
|
+
- `tdd.md` / `debugging.md` recipes — concrete instances of a G1–G6 loop (Red-Green; reproduce→root-cause→fix→regression).
|
|
73
|
+
- `self-improvement.md` recipe — the session-level Reflector loop is itself a G1–G6 instance (propose → human-verify → apply).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "omniconductor",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Multi-coding-agent workflow framework. Write your project's rules, workflow, and discipline ONCE — install into Claude Code, Cursor, GitHub Copilot, Gemini CLI, Codex, or Windsurf. Encodes the discipline developers most often skip — spec-before-code, review gates, session continuity — so your AI agents catch what's easy to miss.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "LFamily Labs LLC",
|