ai-engineering-loop 1.0.4 → 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.
- package/.claude/agents/devil-advocate.md +60 -0
- package/.claude/agents/judge.md +49 -0
- package/.claude/commands/ai-engineering-loop.md +10 -0
- package/.claude/settings.local.json +9 -0
- package/.claude/skills/ai-engineering-loop/SKILL.md +59 -0
- package/.grok/agents/devil-advocate.md +67 -0
- package/.grok/agents/judge.md +53 -0
- package/.grok/commands/ai-engineering-loop.md +11 -0
- package/.grok/skills/ai-engineering-loop/SKILL.md +79 -0
- package/README.md +279 -19
- package/README.npm.md +11 -0
- package/agents/devil-advocate.md +9 -5
- package/agents/judge.md +2 -0
- package/bin/ai-engineering-loop.js +40 -1
- package/core/orchestration-model.md +20 -0
- package/docs/claude-code-feasibility.md +45 -0
- package/docs/grok-cli-feasibility.md +99 -0
- package/lib/orchestration.js +182 -2
- package/package.json +24 -2
- package/tests/grok-runtime.test.js +201 -0
- package/tests/skill-host-compat.test.js +68 -0
- package/README.full.md +0 -251
package/lib/orchestration.js
CHANGED
|
@@ -11,9 +11,15 @@
|
|
|
11
11
|
* 3. Artifact isolation is strictly reported as CONTEXT_ISOLATION_ONLY (Independent LLM execution: NOT PROVEN).
|
|
12
12
|
* 4. browser_subagent is browser automation and must NOT be classified as an LLM subagent.
|
|
13
13
|
* 5. agentapi send-message is an IPC communication capability and must NEVER activate agent execution.
|
|
14
|
+
* 6. grok spawn_subagent is a true independent child session (own context, no parent transcript)
|
|
15
|
+
* when a child id and model response are captured. GROK_SUBAGENTS=0 disables invocation.
|
|
16
|
+
* 7. caveman:cavecrew-reviewer is a compressed code-review preset with a different output schema
|
|
17
|
+
* and must NEVER be used as the Devil's Advocate or Judge.
|
|
14
18
|
*/
|
|
15
19
|
|
|
16
20
|
const crypto = require('crypto');
|
|
21
|
+
const fs = require('fs');
|
|
22
|
+
const path = require('path');
|
|
17
23
|
|
|
18
24
|
// 1. Standard 5 Execution Modes
|
|
19
25
|
const EXECUTION_MODES = {
|
|
@@ -49,6 +55,30 @@ const EXECUTION_MODES = {
|
|
|
49
55
|
}
|
|
50
56
|
};
|
|
51
57
|
|
|
58
|
+
/**
|
|
59
|
+
* Skill / agent-spec aliases. The skill historically used NATIVE_SUBAGENT etc.
|
|
60
|
+
* Canonical runtime IDs remain the 5 EXECUTION_MODES keys.
|
|
61
|
+
*/
|
|
62
|
+
const EXECUTION_MODE_ALIASES = {
|
|
63
|
+
NATIVE_SUBAGENT: 'TRUE_INDEPENDENT_AGENT',
|
|
64
|
+
SDK_AGENT: 'ISOLATED_AGENT_INSTANCE',
|
|
65
|
+
HEADLESS_SUBPROCESS: 'FRESH_PROCESS_AGENT',
|
|
66
|
+
ARTIFACT_ISOLATED_REVIEW: 'CONTEXT_ISOLATION_ONLY'
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const GROK_FORBIDDEN_REVIEW_TYPES = [
|
|
70
|
+
'caveman:cavecrew-reviewer',
|
|
71
|
+
'caveman:cavecrew-builder',
|
|
72
|
+
'caveman:cavecrew-investigator',
|
|
73
|
+
'explore',
|
|
74
|
+
'plan'
|
|
75
|
+
];
|
|
76
|
+
|
|
77
|
+
function resolveExecutionModeId(modeId) {
|
|
78
|
+
if (!modeId) return 'UNAVAILABLE';
|
|
79
|
+
return EXECUTION_MODE_ALIASES[modeId] || modeId;
|
|
80
|
+
}
|
|
81
|
+
|
|
52
82
|
/**
|
|
53
83
|
* 2. Standardized Capability Evidence Factory with 3-Stage Lifecycle
|
|
54
84
|
*/
|
|
@@ -126,6 +156,15 @@ function isCapabilityProvenForMode(evidence, targetModeId) {
|
|
|
126
156
|
return false;
|
|
127
157
|
}
|
|
128
158
|
|
|
159
|
+
// Reject compressed review presets that do not emit the Finding Ledger schema
|
|
160
|
+
if (
|
|
161
|
+
evidence.classification === 'GROK_COMPRESSED_REVIEW_PRESET' ||
|
|
162
|
+
GROK_FORBIDDEN_REVIEW_TYPES.includes(evidence.mechanism) ||
|
|
163
|
+
GROK_FORBIDDEN_REVIEW_TYPES.includes(evidence.commandOrApi)
|
|
164
|
+
) {
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
|
|
129
168
|
// Reject documentation-only or configuration-only claims
|
|
130
169
|
if (evidence.isDocumentationOnly || (evidence.configurationSupported && !evidence.executionProven)) {
|
|
131
170
|
if (targetModeId !== 'CONTEXT_ISOLATION_ONLY') {
|
|
@@ -376,7 +415,142 @@ function computeJudgeVerdict({
|
|
|
376
415
|
}
|
|
377
416
|
|
|
378
417
|
/**
|
|
379
|
-
* 9.
|
|
418
|
+
* 9. Detect Grok CLI as a host runtime.
|
|
419
|
+
* Presence of the grok binary is CONFIGURATION_SUPPORTED.
|
|
420
|
+
* GROK_SUBAGENTS=0 means invocation is disabled even if grok is installed.
|
|
421
|
+
* Execution is never proven from detection alone.
|
|
422
|
+
*/
|
|
423
|
+
function detectGrokRuntime(env = process.env, fsApi = fs) {
|
|
424
|
+
const grokHome = env.GROK_HOME || path.join(env.HOME || env.USERPROFILE || '', '.grok');
|
|
425
|
+
const grokBinCandidates = [
|
|
426
|
+
env.GROK_BIN,
|
|
427
|
+
path.join(grokHome, 'bin', 'grok'),
|
|
428
|
+
path.join(grokHome, 'bin', 'agent')
|
|
429
|
+
].filter(Boolean);
|
|
430
|
+
|
|
431
|
+
const grokBin = grokBinCandidates.find((candidate) => {
|
|
432
|
+
try {
|
|
433
|
+
return fsApi.existsSync(candidate);
|
|
434
|
+
} catch (e) {
|
|
435
|
+
return false;
|
|
436
|
+
}
|
|
437
|
+
}) || null;
|
|
438
|
+
|
|
439
|
+
const grokPresent = Boolean(grokBin);
|
|
440
|
+
const subagentsDisabled = env.GROK_SUBAGENTS === '0';
|
|
441
|
+
const invocationAvailable = grokPresent && !subagentsDisabled;
|
|
442
|
+
|
|
443
|
+
let reason;
|
|
444
|
+
if (!grokPresent) {
|
|
445
|
+
reason = 'Grok CLI binary not found under GROK_HOME/bin';
|
|
446
|
+
} else if (subagentsDisabled) {
|
|
447
|
+
reason = 'GROK_SUBAGENTS=0 disables spawn_subagent; fall back to CONTEXT_ISOLATION_ONLY or grok -p';
|
|
448
|
+
} else {
|
|
449
|
+
reason = 'Grok CLI present; spawn_subagent is the native independent-agent tool (enabled by default)';
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
return {
|
|
453
|
+
host: grokPresent ? 'grok-cli' : 'unknown',
|
|
454
|
+
grokHome,
|
|
455
|
+
grokBin,
|
|
456
|
+
configurationSupported: grokPresent,
|
|
457
|
+
invocationAvailable,
|
|
458
|
+
executionProven: false,
|
|
459
|
+
subagentsDisabled,
|
|
460
|
+
commandOrApi: 'spawn_subagent',
|
|
461
|
+
headlessCommand: 'grok -p',
|
|
462
|
+
reason
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* 10. Build capability evidence for Grok spawn_subagent.
|
|
468
|
+
* Independent context is proven only when the child did not resume a Maker transcript.
|
|
469
|
+
*/
|
|
470
|
+
function createGrokCapabilityEvidence({
|
|
471
|
+
invocationAvailable = false,
|
|
472
|
+
executionProven = false,
|
|
473
|
+
childConversationId = null,
|
|
474
|
+
childModelResponse = null,
|
|
475
|
+
executionIdentity = null,
|
|
476
|
+
independentContextProven = false,
|
|
477
|
+
historyInherited = null,
|
|
478
|
+
resumeFrom = null,
|
|
479
|
+
reason = null
|
|
480
|
+
} = {}) {
|
|
481
|
+
const resumedMaker = Boolean(resumeFrom);
|
|
482
|
+
const inherited = historyInherited === true || resumedMaker;
|
|
483
|
+
const modelExecuted = Boolean(executionProven || childModelResponse);
|
|
484
|
+
const fullyProven = Boolean(
|
|
485
|
+
modelExecuted &&
|
|
486
|
+
childConversationId &&
|
|
487
|
+
executionIdentity &&
|
|
488
|
+
independentContextProven &&
|
|
489
|
+
!inherited
|
|
490
|
+
);
|
|
491
|
+
|
|
492
|
+
return createCapabilityEvidence({
|
|
493
|
+
mechanism: 'grok-spawn_subagent',
|
|
494
|
+
classification: fullyProven
|
|
495
|
+
? 'TRUE_INDEPENDENT_AGENT'
|
|
496
|
+
: invocationAvailable
|
|
497
|
+
? 'INVOCATION_AVAILABLE'
|
|
498
|
+
: 'CONFIGURATION_SUPPORTED_WITHOUT_INVOCATION_TOOL',
|
|
499
|
+
configurationSupported: true,
|
|
500
|
+
invocationAvailable: Boolean(invocationAvailable),
|
|
501
|
+
executionProven: fullyProven,
|
|
502
|
+
available: Boolean(invocationAvailable || fullyProven),
|
|
503
|
+
commandOrApi: 'spawn_subagent',
|
|
504
|
+
childConversationId,
|
|
505
|
+
childModelResponse,
|
|
506
|
+
executionIdentity,
|
|
507
|
+
modelExecutionProven: modelExecuted,
|
|
508
|
+
independentContextProven: Boolean(independentContextProven && !inherited),
|
|
509
|
+
historyInherited: inherited ? true : historyInherited,
|
|
510
|
+
reason: reason || (resumedMaker
|
|
511
|
+
? 'resume_from inherits the source transcript; Devil\'s Advocate and Judge must spawn fresh'
|
|
512
|
+
: null)
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
/**
|
|
517
|
+
* 11. Grok spawn plan for Devil's Advocate / Judge.
|
|
518
|
+
* Parent orchestrator spawns children; children must not spawn children (depth 1).
|
|
519
|
+
* Never pass resume_from. Never use cavecrew-reviewer (wrong output schema).
|
|
520
|
+
*/
|
|
521
|
+
function buildGrokReviewSpawnPlan({
|
|
522
|
+
role,
|
|
523
|
+
iteration = 1,
|
|
524
|
+
artifactPaths = {}
|
|
525
|
+
} = {}) {
|
|
526
|
+
if (role !== 'devil-advocate' && role !== 'judge') {
|
|
527
|
+
throw new Error('Grok review spawn role must be devil-advocate or judge');
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
return {
|
|
531
|
+
tool: 'spawn_subagent',
|
|
532
|
+
subagent_type: role,
|
|
533
|
+
fallback_subagent_type: 'general-purpose',
|
|
534
|
+
description: role === 'judge'
|
|
535
|
+
? `[judge] evaluate iteration ${iteration}`
|
|
536
|
+
: `[devil-advocate] review iteration ${iteration}`,
|
|
537
|
+
background: false,
|
|
538
|
+
capability_mode: 'execute',
|
|
539
|
+
isolation: 'none',
|
|
540
|
+
resume_from: null,
|
|
541
|
+
forbidden_types: [...GROK_FORBIDDEN_REVIEW_TYPES],
|
|
542
|
+
artifactPaths: {
|
|
543
|
+
goalContract: artifactPaths.goalContract || null,
|
|
544
|
+
gitDiff: artifactPaths.gitDiff || null,
|
|
545
|
+
verificationLogs: artifactPaths.verificationLogs || null,
|
|
546
|
+
projectContext: artifactPaths.projectContext || '.ai-engineering-loop/',
|
|
547
|
+
findingLedger: artifactPaths.findingLedger || null
|
|
548
|
+
}
|
|
549
|
+
};
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* 12. Truthful Review Report Generator
|
|
380
554
|
* Enforces mandatory reporting headers and strictly prevents misleading phrasing.
|
|
381
555
|
*/
|
|
382
556
|
function formatExecutionReport({ selectedMode, capabilityRegistry = {} }) {
|
|
@@ -398,6 +572,9 @@ function formatExecutionReport({ selectedMode, capabilityRegistry = {} }) {
|
|
|
398
572
|
|
|
399
573
|
module.exports = {
|
|
400
574
|
EXECUTION_MODES,
|
|
575
|
+
EXECUTION_MODE_ALIASES,
|
|
576
|
+
GROK_FORBIDDEN_REVIEW_TYPES,
|
|
577
|
+
resolveExecutionModeId,
|
|
401
578
|
createCapabilityEvidence,
|
|
402
579
|
isCapabilityProvenForMode,
|
|
403
580
|
selectExecutionMode,
|
|
@@ -405,5 +582,8 @@ module.exports = {
|
|
|
405
582
|
validateVerificationEvidence,
|
|
406
583
|
validateFindingLedger,
|
|
407
584
|
computeJudgeVerdict,
|
|
408
|
-
formatExecutionReport
|
|
585
|
+
formatExecutionReport,
|
|
586
|
+
detectGrokRuntime,
|
|
587
|
+
createGrokCapabilityEvidence,
|
|
588
|
+
buildGrokReviewSpawnPlan
|
|
409
589
|
};
|
package/package.json
CHANGED
|
@@ -1,11 +1,30 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai-engineering-loop",
|
|
3
|
-
"version": "1.0.
|
|
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": {
|
|
7
7
|
"ai-engineering-loop": "bin/ai-engineering-loop.js"
|
|
8
8
|
},
|
|
9
|
+
"files": [
|
|
10
|
+
"bin/",
|
|
11
|
+
"lib/",
|
|
12
|
+
"core/",
|
|
13
|
+
"agents/",
|
|
14
|
+
"policies/",
|
|
15
|
+
"profiles/",
|
|
16
|
+
"adapters/",
|
|
17
|
+
"templates/",
|
|
18
|
+
"examples/",
|
|
19
|
+
"docs/",
|
|
20
|
+
"tests/",
|
|
21
|
+
"scripts/",
|
|
22
|
+
".grok/",
|
|
23
|
+
".claude/",
|
|
24
|
+
"LICENSE",
|
|
25
|
+
"README.md",
|
|
26
|
+
"README.npm.md"
|
|
27
|
+
],
|
|
9
28
|
"scripts": {
|
|
10
29
|
"init": "node bin/ai-engineering-loop.js",
|
|
11
30
|
"test": "node --test tests/*.test.js"
|
|
@@ -21,7 +40,10 @@
|
|
|
21
40
|
"devils-advocate",
|
|
22
41
|
"verification",
|
|
23
42
|
"autonomous-agents",
|
|
24
|
-
"antigravity"
|
|
43
|
+
"antigravity",
|
|
44
|
+
"grok",
|
|
45
|
+
"claude-code",
|
|
46
|
+
"subagents"
|
|
25
47
|
],
|
|
26
48
|
"author": "Ega Gofur",
|
|
27
49
|
"license": "MIT",
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
const test = require('node:test');
|
|
2
|
+
const assert = require('node:assert');
|
|
3
|
+
const {
|
|
4
|
+
EXECUTION_MODES,
|
|
5
|
+
EXECUTION_MODE_ALIASES,
|
|
6
|
+
GROK_FORBIDDEN_REVIEW_TYPES,
|
|
7
|
+
resolveExecutionModeId,
|
|
8
|
+
createCapabilityEvidence,
|
|
9
|
+
selectExecutionMode,
|
|
10
|
+
detectGrokRuntime,
|
|
11
|
+
createGrokCapabilityEvidence,
|
|
12
|
+
buildGrokReviewSpawnPlan,
|
|
13
|
+
formatExecutionReport
|
|
14
|
+
} = require('../lib/orchestration.js');
|
|
15
|
+
|
|
16
|
+
function fakeFs(existingPaths) {
|
|
17
|
+
return {
|
|
18
|
+
existsSync: (p) => existingPaths.includes(p)
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
test('Grok spawn_subagent with full execution proof selects TRUE_INDEPENDENT_AGENT', () => {
|
|
23
|
+
const nativeSubagent = createGrokCapabilityEvidence({
|
|
24
|
+
invocationAvailable: true,
|
|
25
|
+
childConversationId: 'grok-child-da-01',
|
|
26
|
+
childModelResponse: 'Finding ledger JSON emitted',
|
|
27
|
+
executionIdentity: 'spawn_subagent:grok-child-da-01',
|
|
28
|
+
independentContextProven: true,
|
|
29
|
+
historyInherited: false
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const selected = selectExecutionMode({
|
|
33
|
+
nativeSubagent,
|
|
34
|
+
artifactIsolation: createCapabilityEvidence({
|
|
35
|
+
mechanism: 'clean-slate-artifact-barrier',
|
|
36
|
+
classification: 'CONTEXT_ISOLATION_ONLY',
|
|
37
|
+
available: true
|
|
38
|
+
})
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
assert.strictEqual(selected.id, EXECUTION_MODES.TRUE_INDEPENDENT_AGENT.id);
|
|
42
|
+
assert.strictEqual(selected.isIndependentExecutionProven, true);
|
|
43
|
+
assert.strictEqual(nativeSubagent.commandOrApi, 'spawn_subagent');
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test('GROK_SUBAGENTS=0 disables invocation even when grok binary exists', () => {
|
|
47
|
+
const grokBin = '/tmp/fake-grok-home/bin/grok';
|
|
48
|
+
const runtime = detectGrokRuntime(
|
|
49
|
+
{ GROK_HOME: '/tmp/fake-grok-home', GROK_SUBAGENTS: '0', HOME: '/tmp' },
|
|
50
|
+
fakeFs([grokBin])
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
assert.strictEqual(runtime.host, 'grok-cli');
|
|
54
|
+
assert.strictEqual(runtime.configurationSupported, true);
|
|
55
|
+
assert.strictEqual(runtime.invocationAvailable, false);
|
|
56
|
+
assert.strictEqual(runtime.executionProven, false);
|
|
57
|
+
assert.match(runtime.reason, /GROK_SUBAGENTS=0/);
|
|
58
|
+
|
|
59
|
+
const selected = selectExecutionMode({
|
|
60
|
+
nativeSubagent: createGrokCapabilityEvidence({
|
|
61
|
+
invocationAvailable: runtime.invocationAvailable,
|
|
62
|
+
reason: runtime.reason
|
|
63
|
+
}),
|
|
64
|
+
artifactIsolation: createCapabilityEvidence({
|
|
65
|
+
mechanism: 'clean-slate-artifact-barrier',
|
|
66
|
+
classification: 'CONTEXT_ISOLATION_ONLY',
|
|
67
|
+
available: true
|
|
68
|
+
})
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
assert.strictEqual(selected.id, EXECUTION_MODES.CONTEXT_ISOLATION_ONLY.id);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
test('Grok binary present with default subagents maps to INVOCATION_AVAILABLE, not execution proven', () => {
|
|
75
|
+
const grokBin = '/tmp/fake-grok-home/bin/grok';
|
|
76
|
+
const runtime = detectGrokRuntime(
|
|
77
|
+
{ GROK_HOME: '/tmp/fake-grok-home', HOME: '/tmp' },
|
|
78
|
+
fakeFs([grokBin])
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
assert.strictEqual(runtime.invocationAvailable, true);
|
|
82
|
+
assert.strictEqual(runtime.executionProven, false);
|
|
83
|
+
|
|
84
|
+
const evidence = createGrokCapabilityEvidence({
|
|
85
|
+
invocationAvailable: true
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
const selected = selectExecutionMode({
|
|
89
|
+
nativeSubagent: evidence,
|
|
90
|
+
artifactIsolation: createCapabilityEvidence({
|
|
91
|
+
mechanism: 'clean-slate-artifact-barrier',
|
|
92
|
+
classification: 'CONTEXT_ISOLATION_ONLY',
|
|
93
|
+
available: true
|
|
94
|
+
})
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
assert.strictEqual(evidence.classification, 'INVOCATION_AVAILABLE');
|
|
98
|
+
assert.strictEqual(selected.id, EXECUTION_MODES.CONTEXT_ISOLATION_ONLY.id);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
test('resume_from Maker transcript cannot activate TRUE_INDEPENDENT_AGENT', () => {
|
|
102
|
+
const tainted = createGrokCapabilityEvidence({
|
|
103
|
+
invocationAvailable: true,
|
|
104
|
+
childConversationId: 'grok-child-resume',
|
|
105
|
+
childModelResponse: 'I remember the Maker rationale',
|
|
106
|
+
executionIdentity: 'spawn_subagent:resume',
|
|
107
|
+
independentContextProven: true,
|
|
108
|
+
resumeFrom: 'maker-subagent-id'
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
const selected = selectExecutionMode({
|
|
112
|
+
nativeSubagent: tainted,
|
|
113
|
+
artifactIsolation: createCapabilityEvidence({
|
|
114
|
+
mechanism: 'clean-slate-artifact-barrier',
|
|
115
|
+
classification: 'CONTEXT_ISOLATION_ONLY',
|
|
116
|
+
available: true
|
|
117
|
+
})
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
assert.strictEqual(tainted.historyInherited, true);
|
|
121
|
+
assert.strictEqual(selected.id, EXECUTION_MODES.CONTEXT_ISOLATION_ONLY.id);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
test('caveman:cavecrew-reviewer cannot serve as Devil\'s Advocate', () => {
|
|
125
|
+
const compressed = createCapabilityEvidence({
|
|
126
|
+
mechanism: 'caveman:cavecrew-reviewer',
|
|
127
|
+
classification: 'GROK_COMPRESSED_REVIEW_PRESET',
|
|
128
|
+
available: true,
|
|
129
|
+
invocationAvailable: true,
|
|
130
|
+
executionProven: true,
|
|
131
|
+
childConversationId: 'cave-1',
|
|
132
|
+
executionIdentity: 'cave-1',
|
|
133
|
+
childModelResponse: 'path:line: 🔴 BLOCKER: bug. fix it.',
|
|
134
|
+
modelExecutionProven: true,
|
|
135
|
+
independentContextProven: true
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
const selected = selectExecutionMode({
|
|
139
|
+
nativeSubagent: compressed,
|
|
140
|
+
artifactIsolation: createCapabilityEvidence({
|
|
141
|
+
mechanism: 'clean-slate-artifact-barrier',
|
|
142
|
+
classification: 'CONTEXT_ISOLATION_ONLY',
|
|
143
|
+
available: true
|
|
144
|
+
})
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
assert.strictEqual(selected.id, EXECUTION_MODES.CONTEXT_ISOLATION_ONLY.id);
|
|
148
|
+
assert.ok(GROK_FORBIDDEN_REVIEW_TYPES.includes('caveman:cavecrew-reviewer'));
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
test('Skill aliases resolve to canonical execution mode ids', () => {
|
|
152
|
+
assert.strictEqual(resolveExecutionModeId('NATIVE_SUBAGENT'), 'TRUE_INDEPENDENT_AGENT');
|
|
153
|
+
assert.strictEqual(resolveExecutionModeId('SDK_AGENT'), 'ISOLATED_AGENT_INSTANCE');
|
|
154
|
+
assert.strictEqual(resolveExecutionModeId('HEADLESS_SUBPROCESS'), 'FRESH_PROCESS_AGENT');
|
|
155
|
+
assert.strictEqual(resolveExecutionModeId('ARTIFACT_ISOLATED_REVIEW'), 'CONTEXT_ISOLATION_ONLY');
|
|
156
|
+
assert.strictEqual(EXECUTION_MODE_ALIASES.NATIVE_SUBAGENT, EXECUTION_MODES.TRUE_INDEPENDENT_AGENT.id);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
test('Grok DA/Judge spawn plan is fresh, execute-only, and forbids compressed review types', () => {
|
|
160
|
+
const da = buildGrokReviewSpawnPlan({
|
|
161
|
+
role: 'devil-advocate',
|
|
162
|
+
iteration: 2,
|
|
163
|
+
artifactPaths: { goalContract: 'goal.md', gitDiff: 'diff.patch' }
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
assert.strictEqual(da.tool, 'spawn_subagent');
|
|
167
|
+
assert.strictEqual(da.subagent_type, 'devil-advocate');
|
|
168
|
+
assert.strictEqual(da.fallback_subagent_type, 'general-purpose');
|
|
169
|
+
assert.strictEqual(da.description, '[devil-advocate] review iteration 2');
|
|
170
|
+
assert.strictEqual(da.background, false);
|
|
171
|
+
assert.strictEqual(da.capability_mode, 'execute');
|
|
172
|
+
assert.strictEqual(da.isolation, 'none');
|
|
173
|
+
assert.strictEqual(da.resume_from, null);
|
|
174
|
+
assert.ok(da.forbidden_types.includes('caveman:cavecrew-reviewer'));
|
|
175
|
+
assert.strictEqual(da.artifactPaths.goalContract, 'goal.md');
|
|
176
|
+
|
|
177
|
+
const judge = buildGrokReviewSpawnPlan({ role: 'judge', iteration: 2 });
|
|
178
|
+
assert.strictEqual(judge.subagent_type, 'judge');
|
|
179
|
+
assert.strictEqual(judge.description, '[judge] evaluate iteration 2');
|
|
180
|
+
assert.strictEqual(judge.resume_from, null);
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
test('buildGrokReviewSpawnPlan rejects unknown roles', () => {
|
|
184
|
+
assert.throws(
|
|
185
|
+
() => buildGrokReviewSpawnPlan({ role: 'caveman:cavecrew-reviewer' }),
|
|
186
|
+
/must be devil-advocate or judge/
|
|
187
|
+
);
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
test('Grok proven spawn report discloses independent execution', () => {
|
|
191
|
+
const report = formatExecutionReport({
|
|
192
|
+
selectedMode: EXECUTION_MODES.TRUE_INDEPENDENT_AGENT,
|
|
193
|
+
capabilityRegistry: {
|
|
194
|
+
nativeSubagent: { invocationAvailable: true }
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
assert.match(report, /Execution Mode: TRUE_INDEPENDENT_AGENT/);
|
|
199
|
+
assert.match(report, /Independent LLM Execution: PROVEN/);
|
|
200
|
+
assert.match(report, /Native Subagent Invocation: AVAILABLE/);
|
|
201
|
+
});
|
|
@@ -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
|
+
});
|