@xn-intenton-z2a/agentic-lib 7.4.31 → 7.4.33
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/.github/workflows/agentic-lib-init.yml +12 -10
- package/.github/workflows/agentic-lib-schedule.yml +122 -56
- package/.github/workflows/agentic-lib-test.yml +5 -1
- package/.github/workflows/agentic-lib-workflow.yml +57 -2
- package/agentic-lib.toml +22 -2
- package/bin/agentic-lib.js +166 -19
- package/package.json +1 -1
- package/src/actions/agentic-step/tasks/direct.js +25 -7
- package/src/actions/agentic-step/tasks/implementation-review.js +89 -3
- package/src/actions/agentic-step/tasks/maintain-features.js +5 -0
- package/src/actions/agentic-step/tasks/review-issue.js +13 -2
- package/src/actions/agentic-step/tasks/transform.js +18 -0
- package/src/copilot/config.js +17 -3
- package/src/copilot/telemetry.js +18 -1
- package/src/scripts/push-to-logs.sh +25 -0
- package/src/seeds/zero-MISSION.md +14 -14
- package/src/seeds/zero-README.md +106 -65
- package/src/seeds/zero-package.json +1 -1
|
@@ -19,7 +19,7 @@ on:
|
|
|
19
19
|
mode:
|
|
20
20
|
type: string
|
|
21
21
|
required: false
|
|
22
|
-
default: "
|
|
22
|
+
default: "purge"
|
|
23
23
|
dry-run:
|
|
24
24
|
type: string
|
|
25
25
|
required: false
|
|
@@ -27,7 +27,7 @@ on:
|
|
|
27
27
|
mission-seed:
|
|
28
28
|
type: string
|
|
29
29
|
required: false
|
|
30
|
-
default: "
|
|
30
|
+
default: "7-kyu-understand-fizz-buzz"
|
|
31
31
|
mission-text:
|
|
32
32
|
type: string
|
|
33
33
|
required: false
|
|
@@ -58,11 +58,11 @@ on:
|
|
|
58
58
|
description: "Init mode"
|
|
59
59
|
type: choice
|
|
60
60
|
required: false
|
|
61
|
-
default: "
|
|
61
|
+
default: "purge"
|
|
62
62
|
options:
|
|
63
|
-
- update
|
|
64
|
-
- reseed
|
|
65
63
|
- purge
|
|
64
|
+
- reseed
|
|
65
|
+
- update
|
|
66
66
|
dry-run:
|
|
67
67
|
description: "Preview changes without writing files"
|
|
68
68
|
type: boolean
|
|
@@ -72,8 +72,10 @@ on:
|
|
|
72
72
|
description: "Mission seed name (purge only)"
|
|
73
73
|
type: choice
|
|
74
74
|
required: false
|
|
75
|
-
default: "
|
|
75
|
+
default: "7-kyu-understand-fizz-buzz"
|
|
76
76
|
options:
|
|
77
|
+
- random
|
|
78
|
+
- generate
|
|
77
79
|
- 8-kyu-remember-empty
|
|
78
80
|
- 8-kyu-remember-hello-world
|
|
79
81
|
- 7-kyu-understand-fizz-buzz
|
|
@@ -158,7 +160,7 @@ jobs:
|
|
|
158
160
|
with:
|
|
159
161
|
script: |
|
|
160
162
|
core.setOutput('dry-run', context.payload.inputs?.['dry-run'] || 'false');
|
|
161
|
-
core.setOutput('mission', context.payload.inputs?.['mission-seed'] || '
|
|
163
|
+
core.setOutput('mission', context.payload.inputs?.['mission-seed'] || '7-kyu-understand-fizz-buzz');
|
|
162
164
|
core.setOutput('profile', context.payload.inputs?.['profile'] || '');
|
|
163
165
|
core.setOutput('model', context.payload.inputs?.['model'] || '');
|
|
164
166
|
core.setOutput('create-seed-issues', context.payload.inputs?.['create-seed-issues'] || 'false');
|
|
@@ -171,18 +173,18 @@ jobs:
|
|
|
171
173
|
with:
|
|
172
174
|
ref: ${{ inputs.ref }}
|
|
173
175
|
dry-run: ${{ inputs.dry-run || 'false' }}
|
|
174
|
-
skip-tests: ${{ inputs.mode
|
|
176
|
+
skip-tests: ${{ inputs.mode != 'update' }}
|
|
175
177
|
secrets: inherit
|
|
176
178
|
|
|
177
179
|
# Step 2: Reseed/purge and configure (only if mode != update)
|
|
178
180
|
# Use !cancelled() so purge runs even if update's npm test failed
|
|
179
181
|
init:
|
|
180
182
|
needs: [params, update]
|
|
181
|
-
if: "!cancelled() &&
|
|
183
|
+
if: "!cancelled() && inputs.mode != 'update'"
|
|
182
184
|
runs-on: ubuntu-latest
|
|
183
185
|
env:
|
|
184
186
|
INIT_MODE: ${{ inputs.mode }}
|
|
185
|
-
INIT_MISSION_SEED: ${{ inputs.mission-seed || '
|
|
187
|
+
INIT_MISSION_SEED: ${{ inputs.mission-seed || '7-kyu-understand-fizz-buzz' }}
|
|
186
188
|
INIT_MISSION_TEXT: ${{ inputs.mission-text }}
|
|
187
189
|
steps:
|
|
188
190
|
- uses: actions/checkout@v6
|
|
@@ -18,9 +18,10 @@ on:
|
|
|
18
18
|
required: false
|
|
19
19
|
default: ""
|
|
20
20
|
frequency:
|
|
21
|
-
description: "How often the workflow should run"
|
|
22
|
-
required:
|
|
21
|
+
description: "How often the workflow should run (empty = read from agentic-lib.toml)"
|
|
22
|
+
required: false
|
|
23
23
|
type: string
|
|
24
|
+
default: ""
|
|
24
25
|
model:
|
|
25
26
|
description: "Copilot SDK model to use"
|
|
26
27
|
required: false
|
|
@@ -39,16 +40,27 @@ on:
|
|
|
39
40
|
workflow_dispatch:
|
|
40
41
|
inputs:
|
|
41
42
|
frequency:
|
|
42
|
-
description: "How often the workflow should run (maintenance = weekly + remove mission-complete + unlimited budget)"
|
|
43
|
-
required:
|
|
43
|
+
description: "How often the workflow should run (empty = read from agentic-lib.toml, maintenance = weekly + remove mission-complete + unlimited budget)"
|
|
44
|
+
required: false
|
|
44
45
|
type: choice
|
|
46
|
+
default: ""
|
|
45
47
|
options:
|
|
48
|
+
- ""
|
|
46
49
|
- "off"
|
|
47
50
|
- "maintenance"
|
|
48
51
|
- "weekly"
|
|
49
52
|
- "daily"
|
|
50
53
|
- "hourly"
|
|
51
54
|
- "continuous"
|
|
55
|
+
focus:
|
|
56
|
+
description: "Focus mode (empty = read from agentic-lib.toml)"
|
|
57
|
+
required: false
|
|
58
|
+
type: choice
|
|
59
|
+
default: ""
|
|
60
|
+
options:
|
|
61
|
+
- ""
|
|
62
|
+
- "mission"
|
|
63
|
+
- "maintenance"
|
|
52
64
|
model:
|
|
53
65
|
description: "Copilot SDK model to use (empty = read from agentic-lib.toml)"
|
|
54
66
|
required: false
|
|
@@ -85,16 +97,36 @@ jobs:
|
|
|
85
97
|
frequency: ${{ steps.resolve.outputs.frequency }}
|
|
86
98
|
model: ${{ steps.resolve.outputs.model }}
|
|
87
99
|
profile: ${{ steps.resolve.outputs.profile }}
|
|
100
|
+
focus: ${{ steps.resolve.outputs.focus }}
|
|
88
101
|
maintenance: ${{ steps.resolve.outputs.maintenance }}
|
|
89
102
|
steps:
|
|
103
|
+
- uses: actions/checkout@v6
|
|
104
|
+
with:
|
|
105
|
+
sparse-checkout: agentic-lib.toml
|
|
106
|
+
sparse-checkout-cone-mode: false
|
|
90
107
|
- id: resolve
|
|
91
108
|
uses: actions/github-script@v8
|
|
92
109
|
with:
|
|
93
110
|
script: |
|
|
94
|
-
const
|
|
111
|
+
const fs = require('fs');
|
|
112
|
+
const tomlPath = 'agentic-lib.toml';
|
|
113
|
+
let tomlContent = '';
|
|
114
|
+
if (fs.existsSync(tomlPath)) tomlContent = fs.readFileSync(tomlPath, 'utf8');
|
|
115
|
+
const readToml = (key) => {
|
|
116
|
+
const m = tomlContent.match(new RegExp(`^\\s*${key}\\s*=\\s*"([^"]*)"`, 'm'));
|
|
117
|
+
return m ? m[1] : '';
|
|
118
|
+
};
|
|
119
|
+
let frequency = context.payload.inputs?.['frequency'] || '';
|
|
120
|
+
if (!frequency) frequency = readToml('supervisor') || 'off';
|
|
121
|
+
const model = context.payload.inputs?.['model'] || '';
|
|
122
|
+
const profile = context.payload.inputs?.['profile'] || '';
|
|
123
|
+
let focus = context.payload.inputs?.['focus'] || '';
|
|
124
|
+
if (!focus) focus = readToml('focus') || 'mission';
|
|
125
|
+
if (frequency === 'maintenance') focus = 'maintenance';
|
|
95
126
|
core.setOutput('frequency', frequency);
|
|
96
|
-
core.setOutput('model',
|
|
97
|
-
core.setOutput('profile',
|
|
127
|
+
core.setOutput('model', model);
|
|
128
|
+
core.setOutput('profile', profile);
|
|
129
|
+
core.setOutput('focus', focus);
|
|
98
130
|
core.setOutput('maintenance', frequency === 'maintenance' ? 'true' : 'false');
|
|
99
131
|
|
|
100
132
|
update-schedule:
|
|
@@ -116,8 +148,8 @@ jobs:
|
|
|
116
148
|
with:
|
|
117
149
|
script: |
|
|
118
150
|
const fs = require('fs');
|
|
119
|
-
const frequency = '${{
|
|
120
|
-
const
|
|
151
|
+
const frequency = '${{ needs.params.outputs.frequency }}';
|
|
152
|
+
const focus = '${{ needs.params.outputs.focus }}';
|
|
121
153
|
const tomlPath = 'agentic-lib.toml';
|
|
122
154
|
let model = '${{ inputs.model }}';
|
|
123
155
|
if (!model && fs.existsSync(tomlPath)) {
|
|
@@ -126,75 +158,101 @@ jobs:
|
|
|
126
158
|
if (m) model = m[1];
|
|
127
159
|
}
|
|
128
160
|
if (!model) model = 'gpt-5-mini';
|
|
129
|
-
|
|
161
|
+
let profile = '${{ inputs.profile }}';
|
|
162
|
+
if (!profile && fs.existsSync(tomlPath)) {
|
|
163
|
+
const toml = fs.readFileSync(tomlPath, 'utf8');
|
|
164
|
+
const m = toml.match(/^\s*profile\s*=\s*"([^"]*)"/m);
|
|
165
|
+
if (m) profile = m[1];
|
|
166
|
+
}
|
|
130
167
|
|
|
131
168
|
const isMaintenance = frequency === 'maintenance';
|
|
132
169
|
const effectiveFrequency = isMaintenance ? 'weekly' : frequency;
|
|
133
170
|
|
|
134
|
-
//
|
|
135
|
-
|
|
136
|
-
const SCHEDULE_MAP = {
|
|
171
|
+
// Proportional schedule maps for each workflow
|
|
172
|
+
const WORKFLOW_SCHEDULE_MAP = {
|
|
137
173
|
off: '0 0 31 2 *',
|
|
138
|
-
weekly: '25 6 * * 1',
|
|
139
|
-
daily: '25 6 * * *',
|
|
140
|
-
hourly: '25 * * * *',
|
|
141
|
-
continuous: '5,25,45 * * * *',
|
|
174
|
+
weekly: '25 6 * * 1', // Monday 6:25am
|
|
175
|
+
daily: '25 6 * * *', // Every day 6:25am
|
|
176
|
+
hourly: '25 * * * *', // Every hour at :25
|
|
177
|
+
continuous: '5,25,45 * * * *', // Every 20 min
|
|
142
178
|
};
|
|
179
|
+
const INIT_SCHEDULE_MAP = {
|
|
180
|
+
off: '0 0 31 2 *',
|
|
181
|
+
weekly: '0 4 1 * *', // 1st of month 4:00am
|
|
182
|
+
daily: '0 4 * * 1', // Monday 4:00am
|
|
183
|
+
hourly: '0 4 * * *', // Every day 4:00am
|
|
184
|
+
continuous: '0 1,5,9,13,17,21 * * *', // Every 4 hours
|
|
185
|
+
};
|
|
186
|
+
const TEST_SCHEDULE_MAP = {
|
|
187
|
+
off: '0 0 31 2 *',
|
|
188
|
+
weekly: '40 6 * * 1', // Monday 6:40am
|
|
189
|
+
daily: '40 6 * * *', // Every day 6:40am
|
|
190
|
+
hourly: '40 0,4,8,12,16,20 * * *', // Every 4 hours at :40
|
|
191
|
+
continuous: '40 * * * *', // Every hour at :40
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
// Helper: update cron in a workflow file
|
|
195
|
+
function updateWorkflowCron(path, cron, label) {
|
|
196
|
+
if (!fs.existsSync(path)) {
|
|
197
|
+
core.info(`${label}: file not found at ${path}, skipping`);
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
let content = fs.readFileSync(path, 'utf8');
|
|
201
|
+
const cronRegex = /- cron: "[^"]*"/;
|
|
202
|
+
if (cronRegex.test(content)) {
|
|
203
|
+
content = content.replace(cronRegex, `- cron: "${cron}"`);
|
|
204
|
+
} else {
|
|
205
|
+
const scheduleBlock = `\n schedule:\n - cron: "${cron}"\n`;
|
|
206
|
+
content = content.replace(/\non:\n/, `\non:${scheduleBlock}`);
|
|
207
|
+
}
|
|
208
|
+
fs.writeFileSync(path, content);
|
|
209
|
+
core.info(`${label}: set cron to "${cron}"`);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const workflowPath = '.github/workflows/agentic-lib-workflow.yml';
|
|
213
|
+
const initPath = '.github/workflows/agentic-lib-init.yml';
|
|
214
|
+
const testPath = '.github/workflows/agentic-lib-test.yml';
|
|
143
215
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
const
|
|
216
|
+
const workflowCron = WORKFLOW_SCHEDULE_MAP[effectiveFrequency];
|
|
217
|
+
const initCron = INIT_SCHEDULE_MAP[effectiveFrequency];
|
|
218
|
+
const testCron = TEST_SCHEDULE_MAP[effectiveFrequency];
|
|
147
219
|
|
|
148
220
|
// Check if the frequency is already set — skip if no-op (but never skip maintenance)
|
|
149
|
-
// Must check BOTH the config file AND the workflow file to avoid desynchronisation
|
|
150
221
|
const supervisorRegex2 = /^\s*supervisor\s*=\s*"([^"]*)"/m;
|
|
151
222
|
if (!isMaintenance && fs.existsSync(tomlPath)) {
|
|
152
223
|
const currentToml = fs.readFileSync(tomlPath, 'utf8');
|
|
153
224
|
const currentMatch = currentToml.match(supervisorRegex2);
|
|
154
225
|
const currentFreq = currentMatch ? currentMatch[1] : '';
|
|
155
|
-
|
|
226
|
+
const wfContent = fs.existsSync(workflowPath) ? fs.readFileSync(workflowPath, 'utf8') : '';
|
|
156
227
|
const cronRegex = /- cron: "([^"]*)"/;
|
|
157
|
-
const workflowCronMatch =
|
|
228
|
+
const workflowCronMatch = wfContent.match(cronRegex);
|
|
158
229
|
const currentCron = workflowCronMatch ? workflowCronMatch[1] : null;
|
|
159
|
-
const expectedCron = cron; // from SCHEDULE_MAP
|
|
160
230
|
const configMatches = currentFreq === frequency;
|
|
161
|
-
const workflowMatches = currentCron ===
|
|
231
|
+
const workflowMatches = currentCron === workflowCron;
|
|
162
232
|
if (configMatches && workflowMatches) {
|
|
163
233
|
core.info(`Schedule already set to ${frequency} — no change needed`);
|
|
164
234
|
return;
|
|
165
235
|
}
|
|
166
|
-
if (configMatches && !workflowMatches) {
|
|
167
|
-
core.info(`Config says ${frequency} but workflow cron is "${currentCron}" (expected "${expectedCron}") — updating workflow`);
|
|
168
|
-
}
|
|
169
236
|
}
|
|
170
237
|
|
|
171
|
-
//
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
} else {
|
|
176
|
-
// No schedule block exists — insert one after 'on:'
|
|
177
|
-
const scheduleBlock = `\n schedule:\n - cron: "${cron}"\n`;
|
|
178
|
-
content = content.replace(
|
|
179
|
-
/\non:\n/,
|
|
180
|
-
`\non:${scheduleBlock}`
|
|
181
|
-
);
|
|
182
|
-
}
|
|
238
|
+
// Update all three workflow files proportionally
|
|
239
|
+
updateWorkflowCron(workflowPath, workflowCron, 'workflow');
|
|
240
|
+
updateWorkflowCron(initPath, initCron, 'init');
|
|
241
|
+
updateWorkflowCron(testPath, testCron, 'test');
|
|
183
242
|
|
|
184
|
-
// Stamp the file with current date
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
(match) => match + dateStamp + '\n'
|
|
193
|
-
|
|
243
|
+
// Stamp the workflow file with current date
|
|
244
|
+
if (fs.existsSync(workflowPath)) {
|
|
245
|
+
let content = fs.readFileSync(workflowPath, 'utf8');
|
|
246
|
+
const dateStamp = `# Schedule updated: ${new Date().toISOString()}`;
|
|
247
|
+
const stampRegex = /^# Schedule updated: .*/m;
|
|
248
|
+
if (stampRegex.test(content)) {
|
|
249
|
+
content = content.replace(stampRegex, dateStamp);
|
|
250
|
+
} else {
|
|
251
|
+
content = content.replace(/^(# .*\n)+/m, (match) => match + dateStamp + '\n');
|
|
252
|
+
}
|
|
253
|
+
fs.writeFileSync(workflowPath, content);
|
|
194
254
|
}
|
|
195
|
-
|
|
196
|
-
fs.writeFileSync(workflowPath, content);
|
|
197
|
-
core.info(`Updated workflow schedule to: ${effectiveFrequency} (cron: ${cron || 'none'})`);
|
|
255
|
+
core.info(`Updated proportional schedules: workflow=${effectiveFrequency}, init=${effectiveFrequency}(proportional), test=${effectiveFrequency}(proportional)`);
|
|
198
256
|
|
|
199
257
|
// Maintenance mode: remove mission-complete/failed signals
|
|
200
258
|
if (isMaintenance) {
|
|
@@ -206,7 +264,7 @@ jobs:
|
|
|
206
264
|
}
|
|
207
265
|
}
|
|
208
266
|
|
|
209
|
-
// Update agentic-lib.toml with model and
|
|
267
|
+
// Update agentic-lib.toml with model, supervisor, focus, and profile settings
|
|
210
268
|
if (fs.existsSync(tomlPath)) {
|
|
211
269
|
let toml = fs.readFileSync(tomlPath, 'utf8');
|
|
212
270
|
|
|
@@ -227,6 +285,14 @@ jobs:
|
|
|
227
285
|
toml = toml.replace(scheduleSupervisorRegex, `$1supervisor = "${frequency}"`);
|
|
228
286
|
}
|
|
229
287
|
|
|
288
|
+
// Update focus
|
|
289
|
+
const focusRegex = /^(\s*focus\s*=\s*)"[^"]*"/m;
|
|
290
|
+
if (focusRegex.test(toml)) {
|
|
291
|
+
toml = toml.replace(focusRegex, `$1"${focus}"`);
|
|
292
|
+
} else if (toml.match(/^\[schedule\]/m)) {
|
|
293
|
+
toml = toml.replace(/^(\s*supervisor\s*=\s*"[^"]*".*$)/m, `$1\nfocus = "${focus}"`);
|
|
294
|
+
}
|
|
295
|
+
|
|
230
296
|
if (profile) {
|
|
231
297
|
const profileRegex = /(\[tuning\][^\[]*?)(^\s*profile\s*=\s*"[^"]*")/m;
|
|
232
298
|
if (profileRegex.test(toml)) {
|
|
@@ -244,7 +310,7 @@ jobs:
|
|
|
244
310
|
}
|
|
245
311
|
|
|
246
312
|
fs.writeFileSync(tomlPath, toml);
|
|
247
|
-
core.info(`Updated agentic-lib.toml: model=${model}, supervisor=${frequency}${profile ? ', profile=' + profile : ''}`);
|
|
313
|
+
core.info(`Updated agentic-lib.toml: model=${model}, supervisor=${frequency}, focus=${focus}${profile ? ', profile=' + profile : ''}`);
|
|
248
314
|
} else {
|
|
249
315
|
core.warning('agentic-lib.toml not found — skipping config update');
|
|
250
316
|
}
|
|
@@ -260,7 +326,7 @@ jobs:
|
|
|
260
326
|
git config user.email "${TOKEN_ID}+${TOKEN_USER}@users.noreply.github.com"
|
|
261
327
|
FREQUENCY="${{ inputs.frequency }}"
|
|
262
328
|
MODEL="${{ inputs.model }}"
|
|
263
|
-
git add .github/workflows/agentic-lib-workflow.yml agentic-lib.toml
|
|
329
|
+
git add .github/workflows/agentic-lib-workflow.yml .github/workflows/agentic-lib-init.yml .github/workflows/agentic-lib-test.yml agentic-lib.toml
|
|
264
330
|
# Stage removed mission files ONLY if maintenance mode deleted them
|
|
265
331
|
if [ "$FREQUENCY" = "maintenance" ]; then
|
|
266
332
|
git rm --ignore-unmatch MISSION_COMPLETE.md MISSION_FAILED.md 2>/dev/null || true
|
|
@@ -17,7 +17,7 @@ run-name: "agentic-lib-test [${{ github.ref_name }}]"
|
|
|
17
17
|
|
|
18
18
|
on:
|
|
19
19
|
#@dist schedule:
|
|
20
|
-
#@dist - cron: "
|
|
20
|
+
#@dist - cron: "0 0 31 2 *"
|
|
21
21
|
#@dist push:
|
|
22
22
|
#@dist branches: [main]
|
|
23
23
|
#@dist paths:
|
|
@@ -40,6 +40,10 @@ on:
|
|
|
40
40
|
type: string
|
|
41
41
|
required: false
|
|
42
42
|
default: "false"
|
|
43
|
+
log-branch:
|
|
44
|
+
type: string
|
|
45
|
+
required: false
|
|
46
|
+
default: "agentic-lib-logs"
|
|
43
47
|
ref:
|
|
44
48
|
type: string
|
|
45
49
|
required: false
|
|
@@ -17,7 +17,7 @@ run-name: "agentic-lib-workflow [${{ github.ref_name }}]"
|
|
|
17
17
|
|
|
18
18
|
on:
|
|
19
19
|
#@dist schedule:
|
|
20
|
-
#@dist - cron: "0
|
|
20
|
+
#@dist - cron: "0 0 31 2 *"
|
|
21
21
|
workflow_call:
|
|
22
22
|
inputs:
|
|
23
23
|
ref:
|
|
@@ -729,11 +729,30 @@ jobs:
|
|
|
729
729
|
echo "- **Features:** ${{ steps.maintain-features.outputs.narrative }}" >> $GITHUB_STEP_SUMMARY
|
|
730
730
|
echo "- **Library:** ${{ steps.maintain-library.outputs.narrative }}" >> $GITHUB_STEP_SUMMARY
|
|
731
731
|
|
|
732
|
+
- name: Check health for commit message
|
|
733
|
+
id: health
|
|
734
|
+
if: github.repository != 'xn-intenton-z2a/agentic-lib' && needs.params.outputs.dry-run != 'true'
|
|
735
|
+
run: |
|
|
736
|
+
if npm ci --ignore-scripts 2>/dev/null; then
|
|
737
|
+
TEST_OUTPUT=$(npm test 2>&1) || true
|
|
738
|
+
PASS_COUNT=$(echo "$TEST_OUTPUT" | grep -oP '\d+ passing' | head -1 || echo "")
|
|
739
|
+
FAIL_COUNT=$(echo "$TEST_OUTPUT" | grep -oP '\d+ failing' | head -1 || echo "")
|
|
740
|
+
if [ -n "$FAIL_COUNT" ]; then
|
|
741
|
+
echo "summary=maintain(features+library): ${PASS_COUNT:-0 passing}, ${FAIL_COUNT} [unstable]" >> $GITHUB_OUTPUT
|
|
742
|
+
elif [ -n "$PASS_COUNT" ]; then
|
|
743
|
+
echo "summary=maintain(features+library): ${PASS_COUNT} [healthy]" >> $GITHUB_OUTPUT
|
|
744
|
+
else
|
|
745
|
+
echo "summary=maintain(features+library): tests completed [healthy]" >> $GITHUB_OUTPUT
|
|
746
|
+
fi
|
|
747
|
+
else
|
|
748
|
+
echo "summary=maintain(features+library): [broken: npm ci failed]" >> $GITHUB_OUTPUT
|
|
749
|
+
fi
|
|
750
|
+
|
|
732
751
|
- name: Commit and push changes
|
|
733
752
|
if: github.repository != 'xn-intenton-z2a/agentic-lib' && needs.params.outputs.dry-run != 'true'
|
|
734
753
|
uses: ./.github/agentic-lib/actions/commit-if-changed
|
|
735
754
|
with:
|
|
736
|
-
commit-message: "agentic-step: maintain features and library"
|
|
755
|
+
commit-message: "${{ steps.health.outputs.summary || 'agentic-step: maintain features and library' }}"
|
|
737
756
|
push-ref: ${{ github.ref_name }}
|
|
738
757
|
fail-on-conflict: "false"
|
|
739
758
|
|
|
@@ -809,6 +828,21 @@ jobs:
|
|
|
809
828
|
instructions: ".github/agents/agent-implementation-review.md"
|
|
810
829
|
model: ${{ needs.params.outputs.model }}
|
|
811
830
|
|
|
831
|
+
# Commit MISSION.md checkbox updates (from Fix #6) so downstream jobs see them
|
|
832
|
+
- name: Commit acceptance criteria updates
|
|
833
|
+
if: github.repository != 'xn-intenton-z2a/agentic-lib' && needs.params.outputs.dry-run != 'true'
|
|
834
|
+
run: |
|
|
835
|
+
if git diff --quiet MISSION.md 2>/dev/null; then
|
|
836
|
+
echo "No MISSION.md changes to commit"
|
|
837
|
+
else
|
|
838
|
+
git config user.name "github-actions[bot]"
|
|
839
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
840
|
+
git add MISSION.md
|
|
841
|
+
git commit -m "agentic-step: update acceptance criteria checkboxes [skip ci]"
|
|
842
|
+
git pull --rebase origin main 2>/dev/null || true
|
|
843
|
+
git push origin HEAD:main || echo "::warning::Could not push MISSION.md updates"
|
|
844
|
+
fi
|
|
845
|
+
|
|
812
846
|
- name: Push log to log branch
|
|
813
847
|
if: github.repository != 'xn-intenton-z2a/agentic-lib' && needs.params.outputs.dry-run != 'true'
|
|
814
848
|
env:
|
|
@@ -1606,6 +1640,15 @@ jobs:
|
|
|
1606
1640
|
# echo "tests-passed=true" >> $GITHUB_OUTPUT
|
|
1607
1641
|
# echo "Behaviour tests passed"
|
|
1608
1642
|
|
|
1643
|
+
- name: Sync lockfile if package.json changed
|
|
1644
|
+
if: github.repository != 'xn-intenton-z2a/agentic-lib' && steps.issue.outputs.issue-number != '' && needs.params.outputs.dry-run != 'true'
|
|
1645
|
+
run: |
|
|
1646
|
+
if git diff --name-only | grep -q 'package.json'; then
|
|
1647
|
+
echo "package.json changed — syncing lockfile"
|
|
1648
|
+
npm install --package-lock-only || echo "::warning::Lockfile sync failed"
|
|
1649
|
+
git add package-lock.json 2>/dev/null || true
|
|
1650
|
+
fi
|
|
1651
|
+
|
|
1609
1652
|
- name: Commit and push
|
|
1610
1653
|
if: github.repository != 'xn-intenton-z2a/agentic-lib' && steps.issue.outputs.issue-number != '' && needs.params.outputs.dry-run != 'true' && steps.pre-commit-test.outputs.tests-passed == 'true' && steps.pre-commit-behaviour-test.outputs.tests-passed != 'false'
|
|
1611
1654
|
uses: ./.github/agentic-lib/actions/commit-if-changed
|
|
@@ -1741,6 +1784,16 @@ jobs:
|
|
|
1741
1784
|
echo "- Website: [${SITE_URL}](${SITE_URL})" >> $GITHUB_STEP_SUMMARY
|
|
1742
1785
|
|
|
1743
1786
|
# W14: Post-merge director check — re-evaluate mission status after dev/PR merges
|
|
1787
|
+
# Pull latest main to include dev merge (checkout was at maintain commit)
|
|
1788
|
+
- name: Pull latest main (include dev merge)
|
|
1789
|
+
if: |
|
|
1790
|
+
needs.params.outputs.mission-complete != 'true' &&
|
|
1791
|
+
needs.params.outputs.dry-run != 'true' &&
|
|
1792
|
+
needs.director.outputs.decision != 'mission-complete' &&
|
|
1793
|
+
needs.director.outputs.decision != 'mission-failed' &&
|
|
1794
|
+
github.repository != 'xn-intenton-z2a/agentic-lib'
|
|
1795
|
+
run: git pull origin main --ff-only 2>/dev/null || true
|
|
1796
|
+
|
|
1744
1797
|
- name: Fetch log and screenshot from log branch (post-merge director)
|
|
1745
1798
|
if: |
|
|
1746
1799
|
needs.params.outputs.mission-complete != 'true' &&
|
|
@@ -1831,6 +1884,8 @@ jobs:
|
|
|
1831
1884
|
uses: ./.github/workflows/agentic-lib-test.yml
|
|
1832
1885
|
with:
|
|
1833
1886
|
ref: ${{ needs.maintain.outputs.commit-sha || github.ref }}
|
|
1887
|
+
push-screenshot: "true"
|
|
1888
|
+
log-branch: ${{ needs.params.outputs.log-branch }}
|
|
1834
1889
|
secrets: inherit
|
|
1835
1890
|
|
|
1836
1891
|
# ─── Schedule change (if requested) ────────────────────────────────
|
package/agentic-lib.toml
CHANGED
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
# During init: #@dist transforms restore standard paths for consumer repos.
|
|
7
7
|
|
|
8
8
|
[schedule]
|
|
9
|
-
supervisor = "daily" # off | weekly | daily | hourly | continuous
|
|
9
|
+
supervisor = "daily" #@dist "off" # off | weekly | daily | hourly | continuous
|
|
10
|
+
focus = "mission" # mission | maintenance
|
|
10
11
|
|
|
11
12
|
[paths]
|
|
12
13
|
mission = "test/MISSION.md" #@dist "MISSION.md"
|
|
@@ -89,6 +90,11 @@ max-test-output = 4000 # max chars of test output in prompts
|
|
|
89
90
|
max-file-listing = 30 # max files in directory listings (0 = unlimited)
|
|
90
91
|
max-library-index = 2000 # max chars for library index in prompts
|
|
91
92
|
max-fix-test-output = 8000 # max chars of failed run log in fix-code
|
|
93
|
+
review-issues-cap = 2 # max issues reviewed per batch (conservative for 10 min timeout)
|
|
94
|
+
min-resolved-issues = 1 # mission-complete: minimum closed-as-RESOLVED issues
|
|
95
|
+
min-cumulative-transforms = 1 # mission-complete: minimum transform cycles
|
|
96
|
+
max-source-todos = 2 # mission-complete: max TODO comments in src
|
|
97
|
+
acceptance-criteria-threshold = 30 # mission-complete: % acceptance criteria required
|
|
92
98
|
|
|
93
99
|
[profiles.med]
|
|
94
100
|
# Balanced — good results, middle ground.
|
|
@@ -111,6 +117,11 @@ max-test-output = 10000 # max chars of test output in prompts
|
|
|
111
117
|
max-file-listing = 100 # max files in directory listings (0 = unlimited)
|
|
112
118
|
max-library-index = 5000 # max chars for library index in prompts
|
|
113
119
|
max-fix-test-output = 15000 # max chars of failed run log in fix-code
|
|
120
|
+
review-issues-cap = 3 # max issues reviewed per batch
|
|
121
|
+
min-resolved-issues = 2 # mission-complete: minimum closed-as-RESOLVED issues
|
|
122
|
+
min-cumulative-transforms = 1 # mission-complete: minimum transform cycles
|
|
123
|
+
max-source-todos = 1 # mission-complete: max TODO comments in src
|
|
124
|
+
acceptance-criteria-threshold = 50 # mission-complete: % acceptance criteria required
|
|
114
125
|
|
|
115
126
|
[profiles.max]
|
|
116
127
|
# Thorough — maximum context for complex missions.
|
|
@@ -133,6 +144,11 @@ max-test-output = 20000 # max chars of test output in prompts
|
|
|
133
144
|
max-file-listing = 0 # max files in directory listings (0 = unlimited)
|
|
134
145
|
max-library-index = 10000 # max chars for library index in prompts
|
|
135
146
|
max-fix-test-output = 30000 # max chars of failed run log in fix-code
|
|
147
|
+
review-issues-cap = 4 # max issues reviewed per batch (may need step timeout awareness)
|
|
148
|
+
min-resolved-issues = 3 # mission-complete: minimum closed-as-RESOLVED issues
|
|
149
|
+
min-cumulative-transforms = 2 # mission-complete: minimum transform cycles
|
|
150
|
+
max-source-todos = 0 # mission-complete: max TODO comments in src
|
|
151
|
+
acceptance-criteria-threshold = 75 # mission-complete: % acceptance criteria required
|
|
136
152
|
|
|
137
153
|
[goals]
|
|
138
154
|
# W12/W13: Code coverage thresholds — stated in all code-changing prompts
|
|
@@ -144,7 +160,11 @@ min-branch-coverage = 30 # minimum % branch coverage required
|
|
|
144
160
|
# All conditions must be met simultaneously.
|
|
145
161
|
min-resolved-issues = 1 # minimum closed-as-RESOLVED issues since init
|
|
146
162
|
max-source-todos = 0 # max TODO comments allowed in ./src (0 = none)
|
|
147
|
-
|
|
163
|
+
acceptance-criteria-threshold = 50 # percentage of acceptance criteria that must be met (0-100)
|
|
164
|
+
min-cumulative-transforms = 1 # minimum transform cycles completed
|
|
165
|
+
require-no-open-issues = true # all issues must be closed
|
|
166
|
+
require-no-open-prs = true # all PRs must be merged/closed
|
|
167
|
+
require-no-critical-gaps = true # no critical implementation gaps
|
|
148
168
|
|
|
149
169
|
[bot]
|
|
150
170
|
log-prefix = "tmp/agent-log-" #@dist "agent-log-"
|