ai-engineering-loop 1.0.5 → 1.0.6

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.
@@ -0,0 +1,60 @@
1
+ ---
2
+ name: devil-advocate
3
+ description: Use this agent after deterministic tests pass, to adversarially review a git diff against a Goal Contract. Returns a Finding Ledger. Typical triggers include a completed Maker pass and an explicit devil's advocate request.
4
+ tools: Read, Grep, Glob, Bash
5
+ model: inherit
6
+ ---
7
+
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
+
10
+ ## When to invoke
11
+
12
+ - **After Maker verification.** Tests passed. Review the diff against the Goal Contract.
13
+ - **Explicit review request.** The user or orchestrator asks for a devil's advocate pass.
14
+
15
+ ## Input barrier
16
+
17
+ Use only the spawn prompt plus:
18
+
19
+ - Goal Contract
20
+ - `.ai-engineering-loop/` (`architecture.md`, `conventions.md`, `verification.md`)
21
+ - The git diff (path in the prompt, or `git diff <base>...HEAD`)
22
+ - Verification logs (exit code, stdout, test counts)
23
+
24
+ Do not ask for Maker rationale. Do not treat parent narration as evidence.
25
+
26
+ ## Output
27
+
28
+ Return a Finding Ledger as a fenced JSON block:
29
+
30
+ ```json
31
+ {
32
+ "iteration": 1,
33
+ "executionMode": "TRUE_INDEPENDENT_AGENT",
34
+ "findings": [
35
+ {
36
+ "id": "DA-01",
37
+ "topic": "correctness",
38
+ "validity": "VALID",
39
+ "severity": "BLOCKER",
40
+ "disposition": "STRONG",
41
+ "location": "path/to/file.ext#L12-L20",
42
+ "acceptanceCriteria": "AC-1",
43
+ "failureScenario": "Concrete failing case",
44
+ "reproduction": "Steps to reproduce",
45
+ "evidence": "What you read in the diff or source",
46
+ "concreteAlternativeDiff": "diff snippet"
47
+ }
48
+ ]
49
+ }
50
+ ```
51
+
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.
@@ -0,0 +1,49 @@
1
+ ---
2
+ name: judge
3
+ description: Use this agent after Devil's Advocate returns a Finding Ledger. Issues PASS, ITERATE, or ESCALATE from Validity plus Severity. Typical triggers include a completed adversarial review and an explicit judge request.
4
+ tools: Read, Grep, Glob, Bash
5
+ model: inherit
6
+ ---
7
+
8
+ You are the Judge for the AI Engineering Loop. You do not write application code. You issue one verdict: PASS, ITERATE, or ESCALATE.
9
+
10
+ ## When to invoke
11
+
12
+ - **After Devil's Advocate.** A Finding Ledger exists. Evaluate it against the Goal Contract and verification evidence.
13
+ - **Explicit judge request.** The orchestrator asks for a verdict.
14
+
15
+ ## Inputs
16
+
17
+ - Goal Contract
18
+ - Verification evidence (command, exit code 0, stdout, test counts)
19
+ - Devil's Advocate Finding Ledger
20
+ - Git diff only to fact-check a finding
21
+
22
+ Ignore Maker optimism and reviewer tone. Disposition never overrides Validity plus Severity.
23
+
24
+ ## Decision matrix
25
+
26
+ - Verification missing, vague, or non-zero exit: ITERATE
27
+ - Any VALID BLOCKER or HIGH still open: ITERATE (ESCALATE if iteration is 3 or more)
28
+ - INVALID findings: DISMISS, cannot block delivery
29
+ - VALID MEDIUM or LOW: ACCEPT as tradeoff; may still PASS
30
+ - All acceptance criteria proven, verification green, zero open blockers: PASS
31
+
32
+ ## Output
33
+
34
+ Return a fenced JSON block:
35
+
36
+ ```json
37
+ {
38
+ "verdict": "PASS",
39
+ "reason": "All acceptance criteria verified; 0 open blocking findings",
40
+ "action": "Proceed to context impact assessment and delivery adapter",
41
+ "blockingFindings": [],
42
+ "acceptableTradeoffs": [],
43
+ "dismissedFindings": []
44
+ }
45
+ ```
46
+
47
+ `verdict` must be exactly PASS, ITERATE, or ESCALATE.
48
+
49
+ Use Read and read-only git. Do not edit source.
@@ -0,0 +1,10 @@
1
+ ---
2
+ name: ai-engineering-loop
3
+ description: Run the AI Engineering Loop (init, status, refresh, or full Maker then Devil's Advocate then Judge).
4
+ ---
5
+
6
+ Follow `.claude/skills/ai-engineering-loop/SKILL.md`.
7
+
8
+ Use the Task tool for Devil's Advocate and Judge. Pass only subagent_type, description, and prompt.
9
+
10
+ Arguments: init, status, refresh, or a task description.
@@ -0,0 +1,9 @@
1
+ {
2
+ "enabledMcpjsonServers": [
3
+ "browsermcp"
4
+ ],
5
+ "disabledMcpjsonServers": [
6
+ "Figma-20182",
7
+ "Figma-i5xgii"
8
+ ]
9
+ }
@@ -0,0 +1,59 @@
1
+ ---
2
+ name: ai-engineering-loop
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
+ ---
5
+
6
+ # AI Engineering Loop (Claude Code)
7
+
8
+ Canonical specs: `core/`, `agents/`, `policies/`. Read those files. Do not invent extra tool parameters.
9
+
10
+ ## Host rule (prevents 400 REQUEST_BODY_INVALID)
11
+
12
+ Claude Code talks to strict proxies (including Kiro). Follow this exactly:
13
+
14
+ 1. Use only tools that exist in this session.
15
+ 2. For subagents, call the host tool named **Task** (or **Agent** if that is the only subagent tool). Pass **only** these keys:
16
+ - `subagent_type`
17
+ - `description`
18
+ - `prompt`
19
+ 3. Do **not** add any other keys. Extra keys make Kiro return HTTP 400 `REQUEST_BODY_INVALID`.
20
+ 4. If no Task/Agent tool exists, review in this session and label it `CONTEXT_ISOLATION_ONLY`. Do not invent a tool name.
21
+
22
+ ## Commands
23
+
24
+ - `init` / `status` / `refresh`: run `npx ai-engineering-loop <command>` in the repo. Do not commit unless asked.
25
+ - Any other argument: full loop for that task.
26
+
27
+ ## Loop
28
+
29
+ Parent session is Maker plus orchestrator. Spawn Devil's Advocate and Judge as **siblings**, not nested.
30
+
31
+ 1. Stage 0: `npx ai-engineering-loop status` (init or refresh if missing or stale).
32
+ 2. Stage 1: write a Goal Contract. Schema: `core/goal-contract.md`.
33
+ 3. Stages 2-4: Maker work in the parent. Surgical diff plus tests.
34
+ 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 artifact paths (Goal Contract, diff, verification log). Put those paths in child prompts. Do not paste Maker rationale.
36
+ 6. Stage 6: Task `subagent_type: devil-advocate` (fallback `general-purpose`). Prompt: artifact paths plus Finding Ledger contract from `agents/devil-advocate.md`.
37
+ 7. Stage 7: Task `subagent_type: judge` (fallback `general-purpose`). Prompt: Goal Contract, verification evidence, Finding Ledger. Verdict is PASS, ITERATE, or ESCALATE.
38
+ 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
+ 9. Stage 8: delivery from `.ai-engineering-loop/adapter.md`.
40
+
41
+ ## Report header
42
+
43
+ When Task/Agent actually returned a child result:
44
+
45
+ ```
46
+ Execution Mode: TRUE_INDEPENDENT_AGENT
47
+ Independent LLM Execution: PROVEN
48
+ Native Subagent Invocation: AVAILABLE
49
+ Review Method: True Independent Agent
50
+ ```
51
+
52
+ When no subagent tool exists:
53
+
54
+ ```
55
+ Execution Mode: CONTEXT_ISOLATION_ONLY
56
+ Independent LLM Execution: NOT PROVEN
57
+ Native Subagent Invocation: UNAVAILABLE
58
+ Review Method: Clean-Slate Artifact Isolation Barrier
59
+ ```
package/README.md CHANGED
@@ -6,13 +6,13 @@
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
7
7
  [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/egagofur/ai-engineering-loop/pulls)
8
8
  [![AI Engineering](https://img.shields.io/badge/AI-Engineering%20Loop-orange.svg)](https://github.com/egagofur/ai-engineering-loop)
9
- [![Release](https://img.shields.io/badge/release-v1.0.5-purple.svg)](https://github.com/egagofur/ai-engineering-loop/releases)
9
+ [![Release](https://img.shields.io/badge/release-v1.0.6-purple.svg)](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
 
13
13
  *Featuring living project context, strict verification evidence contracts, 3-stage capability lifecycle registry, and dual-axis Judge evaluation.*
14
14
 
15
- [Overview](#overview--philosophy) • [Runtime Capability Registry](#runtime-capability-registry--execution-modes) • [Verification Evidence](#verification-evidence-contract) • [CLI Commands](#cli-interface--commands) • [Grok CLI](#grok-cli-integration) • [Antigravity](#antigravity-agent-integration) • [Lifecycle](#lifecycle-stages) • [Architecture](#architecture--5-layer-configuration) • [Project Profiles](#project-profiles) • [Repository Structure](#repository-structure) • [Reference Examples](#reference-examples) • [Contributing](#contributing)
15
+ [Overview](#overview--philosophy) • [Runtime Capability Registry](#runtime-capability-registry--execution-modes) • [Verification Evidence](#verification-evidence-contract) • [CLI Commands](#cli-interface--commands) • [Grok CLI](#grok-cli-integration) • [Claude Code](#claude-code-integration) • [Antigravity](#antigravity-agent-integration) • [Lifecycle](#lifecycle-stages) • [Architecture](#architecture--5-layer-configuration) • [Project Profiles](#project-profiles) • [Repository Structure](#repository-structure) • [Reference Examples](#reference-examples) • [Contributing](#contributing)
16
16
 
17
17
  </div>
18
18
 
@@ -188,6 +188,32 @@ See [docs/grok-cli-feasibility.md](docs/grok-cli-feasibility.md).
188
188
 
189
189
  ---
190
190
 
191
+ ## Claude Code Integration
192
+
193
+ Claude Code is a first-class host. Use the **Task** (or **Agent**) tool with **only** `subagent_type`, `description`, and `prompt`.
194
+
195
+ Do **not** pass Grok keys (`spawn_subagent`, `capability_mode`, `isolation`, `resume_from`). Extra keys are the usual cause of:
196
+
197
+ ```
198
+ API Error: 400 [kiro/claude-sonnet-5] REQUEST_BODY_INVALID
199
+ ```
200
+
201
+ | Loop role | Claude Code `subagent_type` | Task keys |
202
+ |---|---|---|
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`) | `subagent_type`, `description`, `prompt` |
206
+
207
+ Repo-local Claude Code files:
208
+
209
+ - `.claude/agents/devil-advocate.md` / `.claude/agents/judge.md`
210
+ - `.claude/skills/ai-engineering-loop/SKILL.md`
211
+ - `.claude/commands/ai-engineering-loop.md` → `/ai-engineering-loop`
212
+
213
+ See [docs/claude-code-feasibility.md](docs/claude-code-feasibility.md).
214
+
215
+ ---
216
+
191
217
  ## Antigravity Agent Integration
192
218
 
193
219
  When working inside the Antigravity IDE or compatible agentic platforms, you can invoke the loop via slash commands:
@@ -227,6 +253,12 @@ ai-engineering-loop/
227
253
  │ ├── skills/ai-engineering-loop/ # Grok skill (spawn protocol)
228
254
  │ └── commands/ai-engineering-loop.md # /ai-engineering-loop slash command
229
255
 
256
+ ├── .claude/ # Claude Code host adapter (Kiro-safe)
257
+ │ ├── agents/devil-advocate.md # Task subagent type
258
+ │ ├── agents/judge.md # Task subagent type
259
+ │ ├── skills/ai-engineering-loop/ # Claude skill (Task keys only)
260
+ │ └── commands/ai-engineering-loop.md # /ai-engineering-loop slash command
261
+
230
262
  ├── core/ # Generic engineering loop specifications
231
263
  │ ├── orchestration-model.md # 3-stage capability lifecycle & execution priority
232
264
  │ ├── project-initialization.md # Auto-discovery & initialization lifecycle
package/README.npm.md CHANGED
@@ -44,6 +44,10 @@ npx ai-engineering-loop run
44
44
 
45
45
  Inside a Grok TUI session, `/ai-engineering-loop` uses repo-local `.grok/agents/` types. Devil's Advocate and Judge spawn as sibling children (`capability_mode: execute`, no `resume_from`). Do not use `caveman:cavecrew-reviewer` as the loop reviewer.
46
46
 
47
+ ## Claude Code
48
+
49
+ Inside Claude Code, `/ai-engineering-loop` uses `.claude/agents/` types via the **Task** tool. Pass only `subagent_type`, `description`, and `prompt`. Do not pass Grok keys (`spawn_subagent`, `capability_mode`, `resume_from`) — extra keys cause Kiro `REQUEST_BODY_INVALID`.
50
+
47
51
  ---
48
52
 
49
53
  ## Antigravity IDE Integration
@@ -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.5';
18
+ const VERSION = '1.0.6';
19
19
  const CWD = process.cwd();
20
20
  const CONTEXT_DIR = path.join(CWD, '.ai-engineering-loop');
21
21
 
@@ -601,6 +601,18 @@ function handleRun() {
601
601
  }
602
602
  console.log('- Skill: .grok/skills/ai-engineering-loop/SKILL.md');
603
603
  }
604
+
605
+ const claudeSkill = path.join(CWD, '.claude', 'skills', 'ai-engineering-loop', 'SKILL.md');
606
+ const claudeAgent = path.join(CWD, '.claude', 'agents', 'devil-advocate.md');
607
+ if (fs.existsSync(claudeSkill) || fs.existsSync(claudeAgent)) {
608
+ console.log('------------------------------------------------------------');
609
+ log.bold('Claude Code host:');
610
+ console.log('- Subagent tool: Task (or Agent). Keys allowed: subagent_type, description, prompt');
611
+ console.log('- Devil\'s Advocate: Task subagent_type=devil-advocate');
612
+ console.log('- Judge: Task subagent_type=judge (sibling, not nested)');
613
+ console.log('- Do not pass spawn_subagent, capability_mode, isolation, resume_from (Kiro 400 REQUEST_BODY_INVALID)');
614
+ console.log('- Skill: .claude/skills/ai-engineering-loop/SKILL.md');
615
+ }
604
616
  console.log('------------------------------------------------------------\n');
605
617
  }
606
618
 
@@ -0,0 +1,45 @@
1
+ # Claude Code Feasibility and Kiro Request Safety
2
+
3
+ ## 1. Problem
4
+
5
+ Claude Code users (including Kiro-backed models such as `kiro/claude-sonnet-5`) hit:
6
+
7
+ ```
8
+ API Error: 400 [kiro/claude-sonnet-5] [400]:
9
+ {"message":"Improperly formed request.","reason":"REQUEST_BODY_INVALID"}
10
+ ```
11
+
12
+ Kiro's `generateAssistantResponse` rejects request bodies that Claude Code will happily send. Two skill-side causes were confirmed:
13
+
14
+ 1. **Extra tool keys.** The shared skill told the model to call `spawn_subagent` with `capability_mode`, `isolation`, and `resume_from`. Claude Code's Task/Agent schema does not have those fields. Proxies that validate additionalProperties fail with `REQUEST_BODY_INVALID`.
15
+ 2. **Hostile markup in the injected skill.** Mermaid (`<br>`, nested `{braces}`), LaTeX (`$\rightarrow$`), and folded YAML descriptions inflate and corrupt the system/skill payload Kiro receives.
16
+
17
+ This is separate from 9router bugs that reject any Anthropic `system` field. Those need a router fix. The skill must still not add extra invalid keys or markup.
18
+
19
+ ## 2. Claude Code mapping
20
+
21
+ | Loop role | Claude Code type | Task keys allowed |
22
+ |---|---|---|
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`) | `subagent_type`, `description`, `prompt` |
26
+
27
+ Do not pass Grok keys (`spawn_subagent`, `capability_mode`, `resume_from`, `isolation`, `background`) on Claude Code.
28
+
29
+ Repo files:
30
+
31
+ - `.claude/skills/ai-engineering-loop/SKILL.md`
32
+ - `.claude/agents/devil-advocate.md`
33
+ - `.claude/agents/judge.md`
34
+ - `.claude/commands/ai-engineering-loop.md`
35
+
36
+ ## 3. Mode selection
37
+
38
+ | Condition | Mode |
39
+ |---|---|
40
+ | Task/Agent tool present, child result returned | `TRUE_INDEPENDENT_AGENT` |
41
+ | No subagent tool | `CONTEXT_ISOLATION_ONLY` |
42
+
43
+ ## 4. What stays in Grok-only files
44
+
45
+ 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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-engineering-loop",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "description": "A reusable, framework-agnostic AI Engineering Operating System for autonomous coding agents.",
5
5
  "main": "bin/ai-engineering-loop.js",
6
6
  "bin": {
@@ -20,6 +20,7 @@
20
20
  "tests/",
21
21
  "scripts/",
22
22
  ".grok/",
23
+ ".claude/",
23
24
  "LICENSE",
24
25
  "README.md",
25
26
  "README.npm.md"
@@ -41,6 +42,7 @@
41
42
  "autonomous-agents",
42
43
  "antigravity",
43
44
  "grok",
45
+ "claude-code",
44
46
  "subagents"
45
47
  ],
46
48
  "author": "Ega Gofur",
@@ -0,0 +1,68 @@
1
+ const test = require('node:test');
2
+ const assert = require('node:assert');
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+
6
+ const ROOT = path.join(__dirname, '..');
7
+
8
+ function readRepo(rel) {
9
+ return fs.readFileSync(path.join(ROOT, rel), 'utf8');
10
+ }
11
+
12
+ function parseFrontmatter(content, label) {
13
+ const match = content.match(/^---\n([\s\S]*?)\n---\n/);
14
+ assert.ok(match, `${label} is missing YAML frontmatter`);
15
+ const fm = match[1];
16
+ assert.match(fm, /^name:\s*[a-z0-9-]+$/m, `${label} name must be kebab-case`);
17
+ assert.match(fm, /^description:\s+\S/m, `${label} description must be a single-line value`);
18
+ assert.doesNotMatch(fm, /^description:\s*>-?/m, `${label} must not use folded YAML description`);
19
+ const desc = fm.split('\n').find((line) => line.startsWith('description:'));
20
+ assert.ok(desc.length <= 500, `${label} description exceeds 500 chars (${desc.length})`);
21
+ return { fm, body: content.slice(match[0].length) };
22
+ }
23
+
24
+ test('Claude Code skill is Kiro-safe: no mermaid, latex, HTML breaks, or Grok tool keys', () => {
25
+ const content = readRepo('.claude/skills/ai-engineering-loop/SKILL.md');
26
+ parseFrontmatter(content, 'claude skill');
27
+
28
+ assert.doesNotMatch(content, /```mermaid/);
29
+ assert.doesNotMatch(content, /\$\\/);
30
+ assert.doesNotMatch(content, /<br\s*\/?>/i);
31
+ assert.doesNotMatch(content, /spawn_subagent/);
32
+ assert.doesNotMatch(content, /capability_mode/);
33
+ assert.doesNotMatch(content, /resume_from/);
34
+ assert.match(content, /\bTask\b/);
35
+ assert.match(content, /subagent_type/);
36
+ assert.match(content, /devil-advocate/);
37
+ assert.match(content, /\bjudge\b/);
38
+ });
39
+
40
+ test('Claude Code agents exist with Claude tool names and Finding Ledger / verdict contracts', () => {
41
+ const da = readRepo('.claude/agents/devil-advocate.md');
42
+ const judge = readRepo('.claude/agents/judge.md');
43
+ parseFrontmatter(da, 'devil-advocate agent');
44
+ parseFrontmatter(judge, 'judge agent');
45
+
46
+ assert.match(da, /^tools:\s*Read, Grep, Glob, Bash$/m);
47
+ assert.match(judge, /^tools:\s*Read, Grep, Glob, Bash$/m);
48
+ assert.doesNotMatch(da, /spawn_subagent|capability_mode|resume_from/);
49
+ assert.doesNotMatch(judge, /spawn_subagent|capability_mode|resume_from/);
50
+ assert.match(da, /Finding Ledger/);
51
+ assert.match(judge, /PASS/);
52
+ assert.match(judge, /ITERATE/);
53
+ assert.match(judge, /ESCALATE/);
54
+ });
55
+
56
+ test('Claude Code slash command does not embed Grok spawn keys', () => {
57
+ const cmd = readRepo('.claude/commands/ai-engineering-loop.md');
58
+ parseFrontmatter(cmd, 'claude command');
59
+ assert.doesNotMatch(cmd, /spawn_subagent|capability_mode|resume_from/);
60
+ assert.match(cmd, /ai-engineering-loop/);
61
+ });
62
+
63
+ test('Grok skill may use spawn_subagent; Claude skill must not', () => {
64
+ const grok = readRepo('.grok/skills/ai-engineering-loop/SKILL.md');
65
+ const claude = readRepo('.claude/skills/ai-engineering-loop/SKILL.md');
66
+ assert.match(grok, /spawn_subagent/);
67
+ assert.doesNotMatch(claude, /spawn_subagent/);
68
+ });