@yemi33/minions 0.1.225 → 0.1.226
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 +6 -1
- package/dashboard/js/render-pipelines.js +50 -51
- package/engine/cooldown.js +51 -1
- package/engine/playbook.js +1 -1
- package/package.json +1 -1
- package/playbooks/evaluate.md +149 -0
- package/routing.md +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.1.
|
|
3
|
+
## 0.1.226 (2026-04-03)
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
- add evaluate type to routing and playbooks (#70)
|
|
7
|
+
- fix cooldown context accumulation bloat (#71)
|
|
8
|
+
- wire dead test and extract progress bar helper (#64)
|
|
4
9
|
|
|
5
10
|
### Fixes
|
|
6
11
|
- silence git stderr noise during repo scan
|
|
@@ -64,6 +64,54 @@ function _collectRunArtifacts(run) {
|
|
|
64
64
|
return { merged: merged, total: total };
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
+
/**
|
|
68
|
+
* Build a segmented progress bar from pipeline stages and a run.
|
|
69
|
+
* @param {Array} stages - pipeline stage definitions
|
|
70
|
+
* @param {Object} run - the run object containing stages status map
|
|
71
|
+
* @param {Object} [options] - optional config: { height: '8px', detailLabel: true }
|
|
72
|
+
* @returns {string} HTML string for the progress bar
|
|
73
|
+
*/
|
|
74
|
+
function _buildProgressBar(stages, run, options) {
|
|
75
|
+
var totalStages = stages.length;
|
|
76
|
+
var completedCount = 0;
|
|
77
|
+
var runningCount = 0;
|
|
78
|
+
var failedCount = 0;
|
|
79
|
+
stages.forEach(function(s) {
|
|
80
|
+
var st = run.stages?.[s.id]?.status;
|
|
81
|
+
if (st === 'completed') completedCount++;
|
|
82
|
+
else if (st === 'running') runningCount++;
|
|
83
|
+
else if (st === 'failed') failedCount++;
|
|
84
|
+
});
|
|
85
|
+
var pct = Math.round((completedCount / totalStages) * 100);
|
|
86
|
+
|
|
87
|
+
var segments = stages.map(function(s) {
|
|
88
|
+
var st = run.stages?.[s.id]?.status || 'pending';
|
|
89
|
+
var cls = st === 'completed' ? 'complete' : st === 'running' ? 'running' : st === 'failed' ? 'failed' : st === 'waiting-human' ? 'waiting' : 'pending';
|
|
90
|
+
return '<div class="pl-prog-seg ' + cls + '" style="width:' + (100 / totalStages) + '%" title="' + escHtml(s.id) + ': ' + st + '"></div>';
|
|
91
|
+
}).join('');
|
|
92
|
+
|
|
93
|
+
var barStyle = options && options.height ? ' style="height:' + options.height + '"' : '';
|
|
94
|
+
|
|
95
|
+
var label;
|
|
96
|
+
if (options && options.detailLabel) {
|
|
97
|
+
label = '<span style="font-weight:600;color:' + (pct === 100 ? 'var(--green)' : failedCount ? 'var(--red)' : 'var(--blue)') + '">' + pct + '% complete</span> <span style="color:var(--muted)">(' + completedCount + '/' + totalStages + ' stages)</span>';
|
|
98
|
+
} else {
|
|
99
|
+
var statusParts = [];
|
|
100
|
+
if (completedCount) statusParts.push(completedCount + ' done');
|
|
101
|
+
if (runningCount) statusParts.push(runningCount + ' running');
|
|
102
|
+
if (failedCount) statusParts.push(failedCount + ' failed');
|
|
103
|
+
var remaining = totalStages - completedCount - runningCount - failedCount;
|
|
104
|
+
if (remaining > 0) statusParts.push(remaining + ' pending');
|
|
105
|
+
label = '<span style="font-weight:600;color:' + (pct === 100 ? 'var(--green)' : failedCount ? 'var(--red)' : 'var(--blue)') + '">' + pct + '%</span>' +
|
|
106
|
+
'<span style="color:var(--muted)">' + statusParts.join(' \u00b7 ') + '</span>';
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return '<div class="pl-progress-wrap">' +
|
|
110
|
+
'<div class="pl-progress-bar"' + barStyle + '>' + segments + '</div>' +
|
|
111
|
+
'<div class="pl-progress-label">' + label + '</div>' +
|
|
112
|
+
'</div>';
|
|
113
|
+
}
|
|
114
|
+
|
|
67
115
|
function renderPipelines(pipelines) {
|
|
68
116
|
_pipelinesData = pipelines || [];
|
|
69
117
|
const el = document.getElementById('pipelines-content');
|
|
@@ -95,39 +143,7 @@ function renderPipelines(pipelines) {
|
|
|
95
143
|
var progressHtml = '';
|
|
96
144
|
var displayRun = activeRun || lastRun;
|
|
97
145
|
if (displayRun && (p.stages || []).length > 0) {
|
|
98
|
-
|
|
99
|
-
var completedCount = 0;
|
|
100
|
-
var runningCount = 0;
|
|
101
|
-
var failedCount = 0;
|
|
102
|
-
(p.stages || []).forEach(function(s) {
|
|
103
|
-
var st = displayRun.stages?.[s.id]?.status;
|
|
104
|
-
if (st === 'completed') completedCount++;
|
|
105
|
-
else if (st === 'running') runningCount++;
|
|
106
|
-
else if (st === 'failed') failedCount++;
|
|
107
|
-
});
|
|
108
|
-
var pct = Math.round((completedCount / totalStages) * 100);
|
|
109
|
-
|
|
110
|
-
// Segmented progress bar — one segment per stage
|
|
111
|
-
var segments = (p.stages || []).map(function(s) {
|
|
112
|
-
var st = displayRun.stages?.[s.id]?.status || 'pending';
|
|
113
|
-
var cls = st === 'completed' ? 'complete' : st === 'running' ? 'running' : st === 'failed' ? 'failed' : st === 'waiting-human' ? 'waiting' : 'pending';
|
|
114
|
-
return '<div class="pl-prog-seg ' + cls + '" style="width:' + (100 / totalStages) + '%" title="' + escHtml(s.id) + ': ' + st + '"></div>';
|
|
115
|
-
}).join('');
|
|
116
|
-
|
|
117
|
-
var statusParts = [];
|
|
118
|
-
if (completedCount) statusParts.push(completedCount + ' done');
|
|
119
|
-
if (runningCount) statusParts.push(runningCount + ' running');
|
|
120
|
-
if (failedCount) statusParts.push(failedCount + ' failed');
|
|
121
|
-
var remaining = totalStages - completedCount - runningCount - failedCount;
|
|
122
|
-
if (remaining > 0) statusParts.push(remaining + ' pending');
|
|
123
|
-
|
|
124
|
-
progressHtml = '<div class="pl-progress-wrap">' +
|
|
125
|
-
'<div class="pl-progress-bar">' + segments + '</div>' +
|
|
126
|
-
'<div class="pl-progress-label">' +
|
|
127
|
-
'<span style="font-weight:600;color:' + (pct === 100 ? 'var(--green)' : failedCount ? 'var(--red)' : 'var(--blue)') + '">' + pct + '%</span>' +
|
|
128
|
-
'<span style="color:var(--muted)">' + statusParts.join(' \u00b7 ') + '</span>' +
|
|
129
|
-
'</div>' +
|
|
130
|
-
'</div>';
|
|
146
|
+
progressHtml = _buildProgressBar(p.stages || [], displayRun);
|
|
131
147
|
}
|
|
132
148
|
|
|
133
149
|
return '<div style="background:var(--surface);border:1px solid var(--border);border-radius:8px;padding:12px 16px;margin-bottom:8px;cursor:pointer" onclick="openPipelineDetail(\'' + escHtml(p.id) + '\')">' +
|
|
@@ -166,24 +182,7 @@ function openPipelineDetail(id) {
|
|
|
166
182
|
// Stage detail with progress bar
|
|
167
183
|
var detailRun = activeRun || (p.runs || []).slice(-1)[0];
|
|
168
184
|
if (detailRun && (p.stages || []).length > 0) {
|
|
169
|
-
|
|
170
|
-
var ddone = 0, drun = 0, dfail = 0;
|
|
171
|
-
(p.stages || []).forEach(function(s) {
|
|
172
|
-
var st = detailRun.stages?.[s.id]?.status;
|
|
173
|
-
if (st === 'completed') ddone++;
|
|
174
|
-
else if (st === 'running') drun++;
|
|
175
|
-
else if (st === 'failed') dfail++;
|
|
176
|
-
});
|
|
177
|
-
var dpct = Math.round((ddone / dtotal) * 100);
|
|
178
|
-
var dsegs = (p.stages || []).map(function(s) {
|
|
179
|
-
var st = detailRun.stages?.[s.id]?.status || 'pending';
|
|
180
|
-
var cls = st === 'completed' ? 'complete' : st === 'running' ? 'running' : st === 'failed' ? 'failed' : st === 'waiting-human' ? 'waiting' : 'pending';
|
|
181
|
-
return '<div class="pl-prog-seg ' + cls + '" style="width:' + (100 / dtotal) + '%" title="' + escHtml(s.id) + ': ' + st + '"></div>';
|
|
182
|
-
}).join('');
|
|
183
|
-
html += '<div class="pl-progress-wrap">' +
|
|
184
|
-
'<div class="pl-progress-bar" style="height:8px">' + dsegs + '</div>' +
|
|
185
|
-
'<div class="pl-progress-label"><span style="font-weight:600;color:' + (dpct === 100 ? 'var(--green)' : dfail ? 'var(--red)' : 'var(--blue)') + '">' + dpct + '% complete</span> <span style="color:var(--muted)">(' + ddone + '/' + dtotal + ' stages)</span></div>' +
|
|
186
|
-
'</div>';
|
|
185
|
+
html += _buildProgressBar(p.stages || [], detailRun, { height: '8px', detailLabel: true });
|
|
187
186
|
}
|
|
188
187
|
html += '<h4 style="font-size:12px;color:var(--blue);margin:0">Stages</h4>';
|
|
189
188
|
(p.stages || []).forEach(function(s, i) {
|
package/engine/cooldown.js
CHANGED
|
@@ -7,10 +7,12 @@ const path = require('path');
|
|
|
7
7
|
const shared = require('./shared');
|
|
8
8
|
const queries = require('./queries');
|
|
9
9
|
|
|
10
|
+
const { createHash } = require('crypto');
|
|
10
11
|
const { safeJson, safeWrite, log } = shared;
|
|
11
12
|
const { ENGINE_DIR } = queries;
|
|
12
13
|
|
|
13
14
|
const COOLDOWN_PATH = path.join(ENGINE_DIR, 'cooldowns.json');
|
|
15
|
+
const PENDING_CONTEXTS_CAP = 10;
|
|
14
16
|
const dispatchCooldowns = new Map(); // key → { timestamp, failures }
|
|
15
17
|
|
|
16
18
|
function loadCooldowns() {
|
|
@@ -24,6 +26,35 @@ function loadCooldowns() {
|
|
|
24
26
|
}
|
|
25
27
|
}
|
|
26
28
|
log('info', `Loaded ${dispatchCooldowns.size} cooldowns from disk`);
|
|
29
|
+
// One-time purge of bloated pendingContexts on startup
|
|
30
|
+
purgeBloatedCooldowns();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Deduplicate and cap pendingContexts in all loaded cooldown entries. */
|
|
34
|
+
function purgeBloatedCooldowns() {
|
|
35
|
+
let totalRemoved = 0;
|
|
36
|
+
for (const [k, v] of dispatchCooldowns) {
|
|
37
|
+
if (!Array.isArray(v.pendingContexts) || v.pendingContexts.length <= 1) continue;
|
|
38
|
+
const seen = new Set();
|
|
39
|
+
const deduped = [];
|
|
40
|
+
for (const ctx of v.pendingContexts) {
|
|
41
|
+
const hash = _contentHash(ctx);
|
|
42
|
+
if (!seen.has(hash)) {
|
|
43
|
+
seen.add(hash);
|
|
44
|
+
deduped.push(ctx);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const before = v.pendingContexts.length;
|
|
48
|
+
// Apply FIFO cap after dedup — keep the most recent entries
|
|
49
|
+
v.pendingContexts = deduped.length > PENDING_CONTEXTS_CAP
|
|
50
|
+
? deduped.slice(deduped.length - PENDING_CONTEXTS_CAP)
|
|
51
|
+
: deduped;
|
|
52
|
+
totalRemoved += before - v.pendingContexts.length;
|
|
53
|
+
}
|
|
54
|
+
if (totalRemoved > 0) {
|
|
55
|
+
log('info', `Purged ${totalRemoved} duplicate/excess pendingContexts entries from cooldowns`);
|
|
56
|
+
saveCooldowns();
|
|
57
|
+
}
|
|
27
58
|
}
|
|
28
59
|
|
|
29
60
|
let _cooldownWriteTimer = null;
|
|
@@ -55,10 +86,26 @@ function setCooldown(key) {
|
|
|
55
86
|
saveCooldowns();
|
|
56
87
|
}
|
|
57
88
|
|
|
89
|
+
function _contentHash(content) {
|
|
90
|
+
const str = typeof content === 'string' ? content : JSON.stringify(content);
|
|
91
|
+
return createHash('sha256').update(str).digest('hex');
|
|
92
|
+
}
|
|
93
|
+
|
|
58
94
|
function setCooldownWithContext(key, context) {
|
|
59
95
|
const existing = dispatchCooldowns.get(key);
|
|
60
96
|
const pendingContexts = existing?.pendingContexts || [];
|
|
61
|
-
if (context)
|
|
97
|
+
if (context) {
|
|
98
|
+
// Dedup: only append if content differs from all existing entries
|
|
99
|
+
const newHash = _contentHash(context);
|
|
100
|
+
const isDuplicate = pendingContexts.some(c => _contentHash(c) === newHash);
|
|
101
|
+
if (!isDuplicate) {
|
|
102
|
+
pendingContexts.push(context);
|
|
103
|
+
// FIFO cap: drop oldest entries when exceeding cap
|
|
104
|
+
while (pendingContexts.length > PENDING_CONTEXTS_CAP) {
|
|
105
|
+
pendingContexts.shift();
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
62
109
|
dispatchCooldowns.set(key, {
|
|
63
110
|
timestamp: Date.now(),
|
|
64
111
|
failures: existing?.failures || 0,
|
|
@@ -101,13 +148,16 @@ function isAlreadyDispatched(key) {
|
|
|
101
148
|
|
|
102
149
|
module.exports = {
|
|
103
150
|
COOLDOWN_PATH,
|
|
151
|
+
PENDING_CONTEXTS_CAP,
|
|
104
152
|
dispatchCooldowns,
|
|
105
153
|
loadCooldowns,
|
|
106
154
|
saveCooldowns,
|
|
155
|
+
purgeBloatedCooldowns,
|
|
107
156
|
isOnCooldown,
|
|
108
157
|
setCooldown,
|
|
109
158
|
setCooldownWithContext,
|
|
110
159
|
getCoalescedContexts,
|
|
111
160
|
setCooldownFailure,
|
|
112
161
|
isAlreadyDispatched,
|
|
162
|
+
_contentHash,
|
|
113
163
|
};
|
package/engine/playbook.js
CHANGED
|
@@ -481,7 +481,7 @@ function selectPlaybook(workType, item) {
|
|
|
481
481
|
if (workType === 'review' && !item?._pr && !item?.pr_id) {
|
|
482
482
|
return 'work-item';
|
|
483
483
|
}
|
|
484
|
-
const typeSpecificPlaybooks = ['explore', 'review', 'test', 'plan-to-prd', 'plan', 'ask', 'verify', 'decompose', 'meeting-investigate', 'meeting-debate', 'meeting-conclude'];
|
|
484
|
+
const typeSpecificPlaybooks = ['explore', 'review', 'test', 'plan-to-prd', 'plan', 'ask', 'verify', 'decompose', 'evaluate', 'meeting-investigate', 'meeting-debate', 'meeting-conclude'];
|
|
485
485
|
return typeSpecificPlaybooks.includes(workType) ? workType : 'work-item';
|
|
486
486
|
}
|
|
487
487
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.226",
|
|
4
4
|
"description": "Multi-agent AI dev team that runs from ~/.minions/ — five autonomous agents share a single engine, dashboard, and knowledge base",
|
|
5
5
|
"bin": {
|
|
6
6
|
"minions": "bin/minions.js"
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# Playbook: Evaluate
|
|
2
|
+
|
|
3
|
+
You are {{agent_name}}, the {{agent_role}} on the {{project_name}} project.
|
|
4
|
+
TEAM ROOT: {{team_root}}
|
|
5
|
+
|
|
6
|
+
## Your Task
|
|
7
|
+
|
|
8
|
+
Evaluate the implementation quality of a completed work item against its acceptance criteria and code quality standards.
|
|
9
|
+
|
|
10
|
+
## Work Item Under Evaluation
|
|
11
|
+
|
|
12
|
+
- **ID:** {{item_id}}
|
|
13
|
+
- **Title:** {{item_title}}
|
|
14
|
+
- **Description:** {{item_description}}
|
|
15
|
+
- **Branch:** `{{branch_name}}`
|
|
16
|
+
- **Project:** {{project_name}} (`{{project_path}}`)
|
|
17
|
+
|
|
18
|
+
{{#acceptance_criteria}}
|
|
19
|
+
## Acceptance Criteria
|
|
20
|
+
|
|
21
|
+
{{acceptance_criteria}}
|
|
22
|
+
{{/acceptance_criteria}}
|
|
23
|
+
|
|
24
|
+
{{#references}}
|
|
25
|
+
## References
|
|
26
|
+
|
|
27
|
+
{{references}}
|
|
28
|
+
{{/references}}
|
|
29
|
+
|
|
30
|
+
## Evaluation Rubric
|
|
31
|
+
|
|
32
|
+
Score each category on a 1-5 scale. A category **passes** at 3 or above.
|
|
33
|
+
|
|
34
|
+
### 1. Correctness (weight: 30%)
|
|
35
|
+
|
|
36
|
+
Does the implementation do what the task description and acceptance criteria require?
|
|
37
|
+
|
|
38
|
+
- **5 — Excellent:** All acceptance criteria met, edge cases handled, no functional gaps
|
|
39
|
+
- **4 — Good:** All core criteria met, minor edge cases not handled
|
|
40
|
+
- **3 — Adequate:** Most criteria met, one minor gap that doesn't block usage
|
|
41
|
+
- **2 — Deficient:** One or more acceptance criteria not met
|
|
42
|
+
- **1 — Failing:** Core functionality missing or broken
|
|
43
|
+
|
|
44
|
+
**Pass threshold:** 3
|
|
45
|
+
|
|
46
|
+
### 2. Completeness (weight: 25%)
|
|
47
|
+
|
|
48
|
+
Is the implementation finished end-to-end? No TODO stubs, no half-wired features, no missing integration points.
|
|
49
|
+
|
|
50
|
+
- **5 — Excellent:** Fully integrated, no loose ends, documentation updated if applicable
|
|
51
|
+
- **4 — Good:** Feature complete, minor polish items remain (comments, naming)
|
|
52
|
+
- **3 — Adequate:** Core feature works, one non-critical integration point incomplete
|
|
53
|
+
- **2 — Deficient:** Significant pieces missing or stubbed out
|
|
54
|
+
- **1 — Failing:** Skeleton or partial implementation only
|
|
55
|
+
|
|
56
|
+
**Pass threshold:** 3
|
|
57
|
+
|
|
58
|
+
### 3. Code Quality (weight: 25%)
|
|
59
|
+
|
|
60
|
+
Does the code follow existing project patterns, naming conventions, and architectural decisions?
|
|
61
|
+
|
|
62
|
+
- **5 — Excellent:** Clean, idiomatic, follows all project conventions, well-structured
|
|
63
|
+
- **4 — Good:** Follows conventions, minor style inconsistencies
|
|
64
|
+
- **3 — Adequate:** Generally follows patterns, one area deviates without justification
|
|
65
|
+
- **2 — Deficient:** Multiple convention violations, poor structure
|
|
66
|
+
- **1 — Failing:** Ignores project patterns, introduces anti-patterns
|
|
67
|
+
|
|
68
|
+
**Pass threshold:** 3
|
|
69
|
+
|
|
70
|
+
### 4. Test Coverage (weight: 20%)
|
|
71
|
+
|
|
72
|
+
Are there tests for the new functionality? Do existing tests still pass?
|
|
73
|
+
|
|
74
|
+
- **5 — Excellent:** Comprehensive tests for happy path and edge cases, all passing
|
|
75
|
+
- **4 — Good:** Tests cover core functionality, existing tests pass
|
|
76
|
+
- **3 — Adequate:** At least one test for the main feature, no regressions
|
|
77
|
+
- **2 — Deficient:** No new tests, but existing tests pass
|
|
78
|
+
- **1 — Failing:** No tests, or existing tests broken
|
|
79
|
+
|
|
80
|
+
**Pass threshold:** 3
|
|
81
|
+
|
|
82
|
+
## Evaluation Steps
|
|
83
|
+
|
|
84
|
+
1. **Fetch and review the diff:**
|
|
85
|
+
```bash
|
|
86
|
+
git fetch origin
|
|
87
|
+
git diff {{main_branch}}...origin/{{branch_name}}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
2. **Check acceptance criteria** one by one — mark each as MET or NOT MET with evidence
|
|
91
|
+
|
|
92
|
+
3. **Review code quality** — check for pattern adherence, naming, structure
|
|
93
|
+
|
|
94
|
+
4. **Verify tests:**
|
|
95
|
+
```bash
|
|
96
|
+
cd {{project_path}}
|
|
97
|
+
npm test
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
5. **Calculate scores** using the rubric above
|
|
101
|
+
|
|
102
|
+
6. **Determine verdict:**
|
|
103
|
+
- **PASS** — all four categories score 3 or above
|
|
104
|
+
- **FAIL** — any category scores below 3
|
|
105
|
+
|
|
106
|
+
## Output Format
|
|
107
|
+
|
|
108
|
+
Structure your evaluation result as follows:
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
## Evaluation Result
|
|
112
|
+
|
|
113
|
+
**Item:** {{item_id}} — {{item_title}}
|
|
114
|
+
**Verdict:** PASS | FAIL
|
|
115
|
+
**Weighted Score:** X.X / 5.0
|
|
116
|
+
|
|
117
|
+
### Scores
|
|
118
|
+
|
|
119
|
+
| Category | Score | Pass | Notes |
|
|
120
|
+
|----------|-------|------|-------|
|
|
121
|
+
| Correctness | X/5 | YES/NO | ... |
|
|
122
|
+
| Completeness | X/5 | YES/NO | ... |
|
|
123
|
+
| Code Quality | X/5 | YES/NO | ... |
|
|
124
|
+
| Test Coverage | X/5 | YES/NO | ... |
|
|
125
|
+
|
|
126
|
+
### Acceptance Criteria Checklist
|
|
127
|
+
|
|
128
|
+
- [x] Criterion 1 — evidence
|
|
129
|
+
- [ ] Criterion 2 — what's missing
|
|
130
|
+
|
|
131
|
+
### Issues Found
|
|
132
|
+
|
|
133
|
+
1. **[severity]** Description (file:line)
|
|
134
|
+
|
|
135
|
+
### Recommendations
|
|
136
|
+
|
|
137
|
+
- What to fix before merging (if FAIL)
|
|
138
|
+
- Suggestions for improvement (if PASS)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Rules
|
|
142
|
+
|
|
143
|
+
- Base your evaluation on **evidence from the diff and test output** — not assumptions
|
|
144
|
+
- If acceptance criteria are missing, evaluate against the task description
|
|
145
|
+
- A FAIL verdict should include actionable feedback — what specifically needs to change
|
|
146
|
+
- Do NOT modify any code — this is a read-only evaluation
|
|
147
|
+
- NEVER checkout branches in the main working tree — use `git diff` and `git show` only
|
|
148
|
+
|
|
149
|
+
**Note:** Do NOT write to `agents/*/status.json` — the engine manages your status automatically.
|
package/routing.md
CHANGED
|
@@ -17,6 +17,7 @@ How the engine decides who handles what. Parsed by engine.js — keep the table
|
|
|
17
17
|
| test | dallas | ralph |
|
|
18
18
|
| ask | ripley | rebecca |
|
|
19
19
|
| verify | dallas | ralph |
|
|
20
|
+
| evaluate | ripley | rebecca |
|
|
20
21
|
| decompose | ripley | rebecca |
|
|
21
22
|
| meeting | ripley | rebecca |
|
|
22
23
|
|