ai-engineering-loop 1.0.7 → 1.0.9
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/agents/devil-advocate.md +13 -20
- package/.claude/agents/judge.md +1 -1
- package/.claude/commands/ai-engineering-loop.md +2 -1
- package/.claude/skills/ai-engineering-loop/SKILL.md +9 -3
- package/.grok/agents/devil-advocate.md +10 -7
- package/.grok/skills/ai-engineering-loop/SKILL.md +2 -2
- package/README.md +7 -3
- package/bin/ai-engineering-loop.js +1 -1
- package/docs/claude-code-feasibility.md +38 -3
- package/package.json +1 -1
- package/templates/repo-config/claude-permissions.json +10 -0
- package/tests/skill-host-compat.test.js +14 -2
|
@@ -7,25 +7,26 @@ model: inherit
|
|
|
7
7
|
|
|
8
8
|
You are the Devil's Advocate for the AI Engineering Loop. You are read-only. You never modify application source and never commit.
|
|
9
9
|
|
|
10
|
-
##
|
|
10
|
+
## Budget (hard stop)
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
- **Explicit review request.** The user or orchestrator asks for a devil's advocate pass.
|
|
12
|
+
Finish in at most 8 tool calls, then emit the Finding Ledger. Do not explore the rest of the repo. Do not spawn children. Do not run git log.
|
|
14
13
|
|
|
15
14
|
## Input barrier
|
|
16
15
|
|
|
17
|
-
Use only
|
|
16
|
+
Use only:
|
|
18
17
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
1. The diff file path in the spawn prompt. Read that file first. Do not run git diff if a diff path was given.
|
|
19
|
+
2. Goal Contract path (if given).
|
|
20
|
+
3. Verification log path (if given).
|
|
21
|
+
4. At most 8 source files that appear as paths in the diff.
|
|
23
22
|
|
|
24
|
-
|
|
23
|
+
Skip: `*.css`, files named like `*-css.ts` or `report-css.ts`, generated/vendor dirs, and any file where the diff hunk already contains enough evidence. Prefer quoting the hunk over opening the whole file.
|
|
24
|
+
|
|
25
|
+
Do not ask for Maker rationale.
|
|
25
26
|
|
|
26
27
|
## Output
|
|
27
28
|
|
|
28
|
-
Return a Finding Ledger as a fenced JSON block:
|
|
29
|
+
Return a Finding Ledger as a fenced JSON block and stop:
|
|
29
30
|
|
|
30
31
|
```json
|
|
31
32
|
{
|
|
@@ -42,19 +43,11 @@ Return a Finding Ledger as a fenced JSON block:
|
|
|
42
43
|
"acceptanceCriteria": "AC-1",
|
|
43
44
|
"failureScenario": "Concrete failing case",
|
|
44
45
|
"reproduction": "Steps to reproduce",
|
|
45
|
-
"evidence": "
|
|
46
|
+
"evidence": "Hunk or line you read",
|
|
46
47
|
"concreteAlternativeDiff": "diff snippet"
|
|
47
48
|
}
|
|
48
49
|
]
|
|
49
50
|
}
|
|
50
51
|
```
|
|
51
52
|
|
|
52
|
-
Rules:
|
|
53
|
-
|
|
54
|
-
- `validity` is VALID or INVALID.
|
|
55
|
-
- `severity` is BLOCKER, HIGH, MEDIUM, or LOW.
|
|
56
|
-
- `disposition` is STRONG, ACCEPTABLE, or WEAK.
|
|
57
|
-
- Every VALID BLOCKER or HIGH finding must include `concreteAlternativeDiff`.
|
|
58
|
-
- Empty `findings` is allowed when the diff is clean against the Goal Contract.
|
|
59
|
-
|
|
60
|
-
Use Read, Grep, Glob, and read-only Bash (`git diff`, `git log`, `git show`). Do not write files.
|
|
53
|
+
Rules: validity VALID or INVALID; severity BLOCKER, HIGH, MEDIUM, or LOW; disposition STRONG, ACCEPTABLE, or WEAK. VALID BLOCKER or HIGH must include concreteAlternativeDiff. Empty findings is allowed.
|
package/.claude/agents/judge.md
CHANGED
|
@@ -46,4 +46,4 @@ Return a fenced JSON block:
|
|
|
46
46
|
|
|
47
47
|
`verdict` must be exactly PASS, ITERATE, or ESCALATE.
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
Budget: at most 4 tool calls. Read the ledger and Goal Contract first. Open source only to fact-check a cited location. Do not run git log. Do not edit source.
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ai-engineering-loop
|
|
3
3
|
description: Run the AI Engineering Loop (init, status, refresh, or full Maker then Devil's Advocate then Judge).
|
|
4
|
+
allowed-tools: "Read, Grep, Glob, Edit, Write, Task, Bash(npm run *), Bash(npm test *), Bash(npx *), Bash(git *)"
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
Follow `.claude/skills/ai-engineering-loop/SKILL.md`.
|
|
7
8
|
|
|
8
|
-
Use the Task tool for Devil's Advocate and Judge. Pass
|
|
9
|
+
Use the Task tool for Devil's Advocate and Judge. Pass subagent_type, description, and prompt. If the schema includes run_in_background, set it false. Wait for each Task to finish. Write the git diff to a file and pass that path; do not let the reviewer roam the repo.
|
|
9
10
|
|
|
10
11
|
Arguments: init, status, refresh, or a task description.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ai-engineering-loop
|
|
3
3
|
description: Use when the user runs /ai-engineering-loop, asks to init or refresh living project context, or wants the Maker / Devil's Advocate / Judge engineering loop on Claude Code.
|
|
4
|
+
allowed-tools: "Read, Grep, Glob, Edit, Write, Task, Bash(npm run *), Bash(npm test *), Bash(npx *), Bash(git *)"
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
# AI Engineering Loop (Claude Code)
|
|
@@ -16,8 +17,10 @@ Claude Code talks to strict proxies (including Kiro). Follow this exactly:
|
|
|
16
17
|
- `subagent_type`
|
|
17
18
|
- `description`
|
|
18
19
|
- `prompt`
|
|
20
|
+
- `run_in_background: false` only if that key exists on the Task schema. Never invent other keys.
|
|
19
21
|
3. Do **not** add any other keys. Extra keys make Kiro return HTTP 400 `REQUEST_BODY_INVALID`.
|
|
20
22
|
4. If no Task/Agent tool exists, review in this session and label it `CONTEXT_ISOLATION_ONLY`. Do not invent a tool name.
|
|
23
|
+
5. If Bash or Write returns "cannot determine the safety" or HTTP 400 REQUEST_BODY_INVALID: stop that tool. Do not retry it. Continue with Read, Grep, and Glob. Tell the user to switch off auto permission mode (use default) or add a permissions.allow rule for the verification command, then start a new session.
|
|
21
24
|
|
|
22
25
|
## Commands
|
|
23
26
|
|
|
@@ -32,9 +35,12 @@ Parent session is Maker plus orchestrator. Spawn Devil's Advocate and Judge as *
|
|
|
32
35
|
2. Stage 1: write a Goal Contract. Schema: `core/goal-contract.md`.
|
|
33
36
|
3. Stages 2-4: Maker work in the parent. Surgical diff plus tests.
|
|
34
37
|
4. Stage 5: run commands from `.ai-engineering-loop/verification.md`. Keep command, exit code, stdout, test counts. Vague "seems green" is invalid.
|
|
35
|
-
5. Write
|
|
36
|
-
|
|
37
|
-
|
|
38
|
+
5. Write artifacts, then spawn. Before Devil's Advocate:
|
|
39
|
+
- Write `git diff` to a file (for example `.ai-engineering-loop/tasks/current.diff`).
|
|
40
|
+
- Write changed paths (`git diff --name-only`) into the Task prompt as a short list.
|
|
41
|
+
- Put those paths in the child prompt. Do not paste Maker rationale.
|
|
42
|
+
6. Stage 6: Task `subagent_type: devil-advocate`. Use `general-purpose` only if that type is rejected. If the Task schema includes `run_in_background`, set it false. Then wait for Task to return. Do not start Judge or more Maker work until the Finding Ledger is back. Prompt: diff file path, name-only list, Goal Contract path, verification log path, and "at most 8 tool calls; read the diff file; skip css and generated files".
|
|
43
|
+
7. Stage 7: Task `subagent_type: judge` the same way (wait, no background). Prompt: Goal Contract, verification evidence, Finding Ledger.
|
|
38
44
|
8. ITERATE with iteration under 3: fix in the parent, re-verify, spawn a **new** Devil's Advocate (do not resume the previous child).
|
|
39
45
|
9. Stage 8: delivery from `.ai-engineering-loop/adapter.md`.
|
|
40
46
|
|
|
@@ -15,12 +15,11 @@ never inherit Maker conversational history.
|
|
|
15
15
|
|
|
16
16
|
## Input barrier
|
|
17
17
|
|
|
18
|
-
Use only
|
|
18
|
+
Use only:
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
- Deterministic verification logs (exit code, stdout, test counts)
|
|
20
|
+
1. The diff file path in the spawn prompt. Read that file first.
|
|
21
|
+
2. Goal Contract path and verification log path if given.
|
|
22
|
+
3. At most 8 source files that appear as paths in the diff.
|
|
24
23
|
|
|
25
24
|
Do not ask the parent for Maker rationale. Do not treat parent narration as evidence.
|
|
26
25
|
|
|
@@ -62,6 +61,10 @@ Rules:
|
|
|
62
61
|
- Every VALID BLOCKER or HIGH finding must include `concreteAlternativeDiff`.
|
|
63
62
|
- Empty `findings` is allowed when the diff is clean against the Goal Contract.
|
|
64
63
|
|
|
65
|
-
##
|
|
64
|
+
## Budget (hard stop)
|
|
66
65
|
|
|
67
|
-
|
|
66
|
+
Finish in at most 8 tool calls, then emit the ledger. Do not run git log. Do not spawn children.
|
|
67
|
+
|
|
68
|
+
Read the diff file path from the prompt first. Do not run git diff if that path was given. Open at most 8 files that appear in the diff. Skip `*.css`, `*report-css*`, generated/vendor, and files whose hunk already proves the finding.
|
|
69
|
+
|
|
70
|
+
Use read/search and read-only shell only if the diff file is missing. Do not write files.
|
|
@@ -51,8 +51,8 @@ Run `npx ai-engineering-loop <command>` in the target repo. Do not commit unless
|
|
|
51
51
|
- Goal Contract path
|
|
52
52
|
- `git diff <base>...HEAD` (file)
|
|
53
53
|
- verification log (file)
|
|
54
|
-
6. Stage 6: `spawn_subagent` Devil's Advocate. `background: false`. `capability_mode: "execute"`. Do **not** pass `resume_from`. Prompt
|
|
55
|
-
7. Stage 7: `spawn_subagent` Judge
|
|
54
|
+
6. Stage 6: `spawn_subagent` Devil's Advocate. `background: false`. `capability_mode: "execute"`. Do **not** pass `resume_from`. Wait for the child. Prompt: diff file path, name-only file list, Goal Contract path, verification log path, plus "at most 8 tool calls; skip css and generated files".
|
|
55
|
+
7. Stage 7: `spawn_subagent` Judge the same way (`background: false`, wait). Prompt follows `agents/judge.md`.
|
|
56
56
|
8. If Judge says `ITERATE` and iteration < 3, Maker fixes in the parent, re-verify, spawn a **fresh** DA (new spawn, no resume).
|
|
57
57
|
9. Stage 8: delivery adapter from `.ai-engineering-loop/adapter.md`.
|
|
58
58
|
|
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
[](https://opensource.org/licenses/MIT)
|
|
7
7
|
[](https://github.com/egagofur/ai-engineering-loop/pulls)
|
|
8
8
|
[](https://github.com/egagofur/ai-engineering-loop)
|
|
9
|
-
[](https://github.com/egagofur/ai-engineering-loop/releases)
|
|
10
10
|
|
|
11
11
|
**A Reusable, Framework-Agnostic AI Engineering Operating System for Autonomous Coding Agents**
|
|
12
12
|
|
|
@@ -201,8 +201,10 @@ API Error: 400 [kiro/claude-sonnet-5] REQUEST_BODY_INVALID
|
|
|
201
201
|
| Loop role | Claude Code `subagent_type` | Task keys |
|
|
202
202
|
|---|---|---|
|
|
203
203
|
| Orchestrator / Maker | parent session | n/a |
|
|
204
|
-
| Devil's Advocate | `devil-advocate` (fallback `general-purpose`) | `subagent_type`, `description`, `prompt
|
|
205
|
-
| Judge | `judge` (fallback `general-purpose`) |
|
|
204
|
+
| Devil's Advocate | `devil-advocate` (fallback `general-purpose`) | `subagent_type`, `description`, `prompt`, wait (no background) |
|
|
205
|
+
| Judge | `judge` (fallback `general-purpose`) | same, after DA returns |
|
|
206
|
+
|
|
207
|
+
Parent writes `git diff` to a file and passes that path. DA is capped at 8 tool calls and skips css/generated blobs so review does not take tens of minutes.
|
|
206
208
|
|
|
207
209
|
Repo-local Claude Code files:
|
|
208
210
|
|
|
@@ -210,6 +212,8 @@ Repo-local Claude Code files:
|
|
|
210
212
|
- `.claude/skills/ai-engineering-loop/SKILL.md`
|
|
211
213
|
- `.claude/commands/ai-engineering-loop.md` → `/ai-engineering-loop`
|
|
212
214
|
|
|
215
|
+
On Kiro auto mode, pre-allow verification Bash or the safety classifier 400s the session. Copy `templates/repo-config/claude-permissions.json` into the target repo `.claude/settings.local.json` `permissions.allow` list. If Bash returns "cannot determine the safety", do not retry; switch permission mode to default and start a new session.
|
|
216
|
+
|
|
213
217
|
See [docs/claude-code-feasibility.md](docs/claude-code-feasibility.md).
|
|
214
218
|
|
|
215
219
|
---
|
|
@@ -15,7 +15,7 @@ const path = require('path');
|
|
|
15
15
|
const crypto = require('crypto');
|
|
16
16
|
const { execSync } = require('child_process');
|
|
17
17
|
|
|
18
|
-
const VERSION = '1.0.
|
|
18
|
+
const VERSION = '1.0.9';
|
|
19
19
|
const CWD = process.cwd();
|
|
20
20
|
const CONTEXT_DIR = path.join(CWD, '.ai-engineering-loop');
|
|
21
21
|
|
|
@@ -21,8 +21,10 @@ This is separate from 9router bugs that reject any Anthropic `system` field. Tho
|
|
|
21
21
|
| Loop role | Claude Code type | Task keys allowed |
|
|
22
22
|
|---|---|---|
|
|
23
23
|
| Orchestrator / Maker | parent session | n/a |
|
|
24
|
-
| Devil's Advocate | `devil-advocate` (fallback `general-purpose`) | `subagent_type`, `description`, `prompt` |
|
|
25
|
-
| Judge | `judge` (fallback `general-purpose`) |
|
|
24
|
+
| Devil's Advocate | `devil-advocate` (fallback `general-purpose`) | `subagent_type`, `description`, `prompt`, `run_in_background: false` |
|
|
25
|
+
| Judge | `judge` (fallback `general-purpose`) | same; wait for DA first |
|
|
26
|
+
|
|
27
|
+
Parent must write `git diff` to a file and pass that path. DA budget: 8 tool calls, skip css/generated, no git log. Do not leave DA running in the background.
|
|
26
28
|
|
|
27
29
|
Do not pass Grok keys (`spawn_subagent`, `capability_mode`, `resume_from`, `isolation`, `background`) on Claude Code.
|
|
28
30
|
|
|
@@ -40,6 +42,39 @@ Repo files:
|
|
|
40
42
|
| Task/Agent tool present, child result returned | `TRUE_INDEPENDENT_AGENT` |
|
|
41
43
|
| No subagent tool | `CONTEXT_ISOLATION_ONLY` |
|
|
42
44
|
|
|
43
|
-
## 4.
|
|
45
|
+
## 4. Second 400 path: auto-mode Bash classifier
|
|
46
|
+
|
|
47
|
+
A later failure looks like this:
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
Error: kr/claude-sonnet-5 is temporarily unavailable, so auto mode
|
|
51
|
+
cannot determine the safety of Bash right now.
|
|
52
|
+
API Error: 400 [kiro/claude-sonnet-5] REQUEST_BODY_INVALID
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Read/Grep still work. The first Bash that needs the auto-mode safety classifier (`npm run typecheck`, `npm test`) is sent to Kiro. When that classifier request is invalid or the model is down, Claude Code retries and Kiro returns 400.
|
|
56
|
+
|
|
57
|
+
Mitigations shipped in the skill:
|
|
58
|
+
|
|
59
|
+
1. `allowed-tools` pre-approves `Bash(npm run *)`, `Bash(npm test *)`, `Bash(npx *)`, `Bash(git *)` so those commands skip the classifier when the skill or slash command is active.
|
|
60
|
+
2. The skill tells the model not to retry Bash/Write after a classifier or 400 failure.
|
|
61
|
+
3. Project allow rules (copy into `.claude/settings.local.json`):
|
|
62
|
+
|
|
63
|
+
```json
|
|
64
|
+
{
|
|
65
|
+
"permissions": {
|
|
66
|
+
"allow": [
|
|
67
|
+
"Bash(npm run *)",
|
|
68
|
+
"Bash(npm test *)",
|
|
69
|
+
"Bash(npx *)",
|
|
70
|
+
"Bash(git *)"
|
|
71
|
+
]
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
If 400 still happens on a fresh session with no Bash yet, it is the 9router `system` field bug, not this package.
|
|
77
|
+
|
|
78
|
+
## 5. What stays in Grok-only files
|
|
44
79
|
|
|
45
80
|
Grok spawn details live in `.grok/skills/ai-engineering-loop/SKILL.md`. Claude Code must not load that file as its skill. Claude Code discovers `.claude/` first.
|
package/package.json
CHANGED
|
@@ -23,8 +23,10 @@ function parseFrontmatter(content, label) {
|
|
|
23
23
|
|
|
24
24
|
test('Claude Code skill is Kiro-safe: no mermaid, latex, HTML breaks, or Grok tool keys', () => {
|
|
25
25
|
const content = readRepo('.claude/skills/ai-engineering-loop/SKILL.md');
|
|
26
|
-
parseFrontmatter(content, 'claude skill');
|
|
26
|
+
const { fm } = parseFrontmatter(content, 'claude skill');
|
|
27
27
|
|
|
28
|
+
assert.match(fm, /^allowed-tools:/m);
|
|
29
|
+
assert.match(fm, /Bash\(npm run \*\)/);
|
|
28
30
|
assert.doesNotMatch(content, /```mermaid/);
|
|
29
31
|
assert.doesNotMatch(content, /\$\\/);
|
|
30
32
|
assert.doesNotMatch(content, /<br\s*\/?>/i);
|
|
@@ -35,6 +37,10 @@ test('Claude Code skill is Kiro-safe: no mermaid, latex, HTML breaks, or Grok to
|
|
|
35
37
|
assert.match(content, /subagent_type/);
|
|
36
38
|
assert.match(content, /devil-advocate/);
|
|
37
39
|
assert.match(content, /\bjudge\b/);
|
|
40
|
+
assert.match(content, /cannot determine the safety/);
|
|
41
|
+
assert.match(content, /run_in_background/);
|
|
42
|
+
assert.match(content, /current\.diff/);
|
|
43
|
+
assert.match(content, /8 tool calls/);
|
|
38
44
|
});
|
|
39
45
|
|
|
40
46
|
test('Claude Code agents exist with Claude tool names and Finding Ledger / verdict contracts', () => {
|
|
@@ -48,14 +54,20 @@ test('Claude Code agents exist with Claude tool names and Finding Ledger / verdi
|
|
|
48
54
|
assert.doesNotMatch(da, /spawn_subagent|capability_mode|resume_from/);
|
|
49
55
|
assert.doesNotMatch(judge, /spawn_subagent|capability_mode|resume_from/);
|
|
50
56
|
assert.match(da, /Finding Ledger/);
|
|
57
|
+
assert.match(da, /8 tool calls/);
|
|
58
|
+
assert.match(da, /Skip: `\*\.css`/);
|
|
59
|
+
assert.match(da, /Do not run git log/);
|
|
51
60
|
assert.match(judge, /PASS/);
|
|
52
61
|
assert.match(judge, /ITERATE/);
|
|
53
62
|
assert.match(judge, /ESCALATE/);
|
|
63
|
+
assert.match(judge, /4 tool calls/);
|
|
54
64
|
});
|
|
55
65
|
|
|
56
66
|
test('Claude Code slash command does not embed Grok spawn keys', () => {
|
|
57
67
|
const cmd = readRepo('.claude/commands/ai-engineering-loop.md');
|
|
58
|
-
parseFrontmatter(cmd, 'claude command');
|
|
68
|
+
const { fm } = parseFrontmatter(cmd, 'claude command');
|
|
69
|
+
assert.match(fm, /^allowed-tools:/m);
|
|
70
|
+
assert.match(fm, /Bash\(npm run \*\)/);
|
|
59
71
|
assert.doesNotMatch(cmd, /spawn_subagent|capability_mode|resume_from/);
|
|
60
72
|
assert.match(cmd, /ai-engineering-loop/);
|
|
61
73
|
});
|