@xn-intenton-z2a/agentic-lib 7.4.22 → 7.4.24
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/agents/agent-issue-resolution.md +2 -0
- package/.github/agents/agent-supervisor.md +2 -2
- package/.github/workflows/agentic-lib-flow.yml +331 -25
- package/.github/workflows/agentic-lib-init.yml +1 -1
- package/.github/workflows/agentic-lib-schedule.yml +1 -1
- package/.github/workflows/agentic-lib-workflow.yml +234 -32
- package/agentic-lib.toml +37 -4
- package/package.json +1 -1
- package/src/actions/agentic-step/tasks/direct.js +52 -0
- package/src/actions/agentic-step/tasks/fix-code.js +7 -6
- package/src/actions/agentic-step/tasks/maintain-features.js +5 -4
- package/src/actions/agentic-step/tasks/maintain-library.js +5 -4
- package/src/actions/agentic-step/tasks/supervise.js +25 -0
- package/src/actions/agentic-step/tasks/transform.js +152 -27
- package/src/copilot/config.js +23 -1
- package/src/copilot/copilot-session.js +10 -5
- package/src/iterate.js +1 -1
- package/src/seeds/zero-package.json +1 -1
|
@@ -68,7 +68,7 @@ on:
|
|
|
68
68
|
options:
|
|
69
69
|
- ""
|
|
70
70
|
- min
|
|
71
|
-
-
|
|
71
|
+
- med
|
|
72
72
|
- max
|
|
73
73
|
mode:
|
|
74
74
|
description: "Run mode"
|
|
@@ -140,7 +140,10 @@ jobs:
|
|
|
140
140
|
- uses: actions/checkout@v6
|
|
141
141
|
with:
|
|
142
142
|
ref: ${{ inputs.ref || github.sha }}
|
|
143
|
-
sparse-checkout:
|
|
143
|
+
sparse-checkout: |
|
|
144
|
+
${{ env.configPath }}
|
|
145
|
+
MISSION_COMPLETE.md
|
|
146
|
+
MISSION_FAILED.md
|
|
144
147
|
sparse-checkout-cone-mode: false
|
|
145
148
|
- name: Normalise params
|
|
146
149
|
id: normalise
|
|
@@ -190,6 +193,23 @@ jobs:
|
|
|
190
193
|
echo "log-prefix=${LOG_PREFIX:-agent-log-}" >> $GITHUB_OUTPUT
|
|
191
194
|
echo "log-branch=${LOG_BRANCH:-agentic-lib-logs}" >> $GITHUB_OUTPUT
|
|
192
195
|
echo "screenshot-file=${SCREENSHOT:-SCREENSHOT_INDEX.png}" >> $GITHUB_OUTPUT
|
|
196
|
+
- name: Check mission-complete signal (W4)
|
|
197
|
+
id: mission-check
|
|
198
|
+
shell: bash
|
|
199
|
+
run: |
|
|
200
|
+
SUPERVISOR=""
|
|
201
|
+
if [ -f "${{ env.configPath }}" ]; then
|
|
202
|
+
SUPERVISOR=$(grep '^\s*supervisor\s*=' "${{ env.configPath }}" 2>/dev/null | head -1 | sed 's/.*=\s*"\([^"]*\)".*/\1/' || true)
|
|
203
|
+
fi
|
|
204
|
+
if [ -f MISSION_COMPLETE.md ] && [ "$SUPERVISOR" != "maintenance" ]; then
|
|
205
|
+
echo "mission-complete=true" >> $GITHUB_OUTPUT
|
|
206
|
+
echo "::notice::Mission is complete — most jobs will be skipped"
|
|
207
|
+
elif [ -f MISSION_FAILED.md ]; then
|
|
208
|
+
echo "mission-complete=true" >> $GITHUB_OUTPUT
|
|
209
|
+
echo "::notice::Mission has failed — most jobs will be skipped"
|
|
210
|
+
else
|
|
211
|
+
echo "mission-complete=false" >> $GITHUB_OUTPUT
|
|
212
|
+
fi
|
|
193
213
|
outputs:
|
|
194
214
|
model: ${{ steps.normalise.outputs.model }}
|
|
195
215
|
profile: ${{ steps.normalise.outputs.profile }}
|
|
@@ -203,6 +223,7 @@ jobs:
|
|
|
203
223
|
log-prefix: ${{ steps.normalise.outputs.log-prefix }}
|
|
204
224
|
log-branch: ${{ steps.normalise.outputs.log-branch }}
|
|
205
225
|
screenshot-file: ${{ steps.normalise.outputs.screenshot-file }}
|
|
226
|
+
mission-complete: ${{ steps.mission-check.outputs.mission-complete }}
|
|
206
227
|
|
|
207
228
|
# ─── PR Cleanup: merge/close/delete stale PRs and branches ─────────
|
|
208
229
|
pr-cleanup:
|
|
@@ -280,7 +301,8 @@ jobs:
|
|
|
280
301
|
behaviour-telemetry:
|
|
281
302
|
needs: params
|
|
282
303
|
if: |
|
|
283
|
-
needs.params.outputs.
|
|
304
|
+
needs.params.outputs.mission-complete != 'true' &&
|
|
305
|
+
(needs.params.outputs.mode == 'full' || needs.params.outputs.mode == 'dev-only' || needs.params.outputs.mode == 'review-only')
|
|
284
306
|
runs-on: ubuntu-latest
|
|
285
307
|
container: mcr.microsoft.com/playwright:v1.58.2-noble
|
|
286
308
|
steps:
|
|
@@ -323,6 +345,7 @@ jobs:
|
|
|
323
345
|
needs: [params, behaviour-telemetry]
|
|
324
346
|
if: |
|
|
325
347
|
!cancelled() &&
|
|
348
|
+
needs.params.outputs.mission-complete != 'true' &&
|
|
326
349
|
(needs.params.outputs.mode == 'full' || needs.params.outputs.mode == 'dev-only' || needs.params.outputs.mode == 'review-only')
|
|
327
350
|
runs-on: ubuntu-latest
|
|
328
351
|
steps:
|
|
@@ -550,22 +573,38 @@ jobs:
|
|
|
550
573
|
if (fs.existsSync('agentic-lib.toml')) {
|
|
551
574
|
const toml = fs.readFileSync('agentic-lib.toml', 'utf8');
|
|
552
575
|
const profileMatch = toml.match(/^\s*profile\s*=\s*"(\w+)"/m);
|
|
553
|
-
const profile = profileMatch ? profileMatch[1] : '
|
|
554
|
-
const PROFILE_LIMITS = { min: 10000,
|
|
576
|
+
const profile = profileMatch ? profileMatch[1] : 'med';
|
|
577
|
+
const PROFILE_LIMITS = { min: 10000, med: 30000, max: 60000 };
|
|
555
578
|
maxTelemetryChars = PROFILE_LIMITS[profile] || 30000;
|
|
556
579
|
}
|
|
557
580
|
} catch (e) {}
|
|
558
581
|
const summary = JSON.stringify(telemetry);
|
|
559
582
|
core.setOutput('telemetry', summary.slice(0, maxTelemetryChars));
|
|
560
583
|
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
584
|
+
// W15: Output counts for downstream job gating
|
|
585
|
+
core.setOutput('open-issue-count', String(issuesSummary.length));
|
|
586
|
+
core.setOutput('open-pr-count', String(prsSummary.length));
|
|
587
|
+
|
|
588
|
+
// W19: Output unit test summary for transform prompt
|
|
589
|
+
const unitSummary = `exit=${telemetry.liveTests.unit.exitCode} pass=${telemetry.liveTests.unit.passCount} fail=${telemetry.liveTests.unit.failCount}`;
|
|
590
|
+
core.setOutput('unit-test-summary', unitSummary);
|
|
591
|
+
// Truncated unit test output for transform (first 4000 chars)
|
|
592
|
+
const unitOutputForTransform = (telemetry.liveTests?.unit?.output || '').substring(0, 4000);
|
|
593
|
+
core.setOutput('unit-test-output', unitOutputForTransform);
|
|
594
|
+
|
|
595
|
+
- name: Output telemetry summary
|
|
596
|
+
shell: bash
|
|
597
|
+
run: |
|
|
598
|
+
echo "=== Telemetry Summary ==="
|
|
599
|
+
cat /tmp/telemetry.json 2>/dev/null || echo "No telemetry file"
|
|
600
|
+
echo "=== End Telemetry ==="
|
|
566
601
|
|
|
567
602
|
outputs:
|
|
568
603
|
telemetry: ${{ steps.gather.outputs.telemetry }}
|
|
604
|
+
open-issue-count: ${{ steps.gather.outputs.open-issue-count }}
|
|
605
|
+
open-pr-count: ${{ steps.gather.outputs.open-pr-count }}
|
|
606
|
+
unit-test-summary: ${{ steps.gather.outputs.unit-test-summary }}
|
|
607
|
+
unit-test-output: ${{ steps.gather.outputs.unit-test-output }}
|
|
569
608
|
|
|
570
609
|
# ─── Maintain: features + library (push to main) ───────────────────
|
|
571
610
|
# Runs early (parallel with pr-cleanup/telemetry) so supervisor sees features.
|
|
@@ -573,6 +612,7 @@ jobs:
|
|
|
573
612
|
needs: [params]
|
|
574
613
|
if: |
|
|
575
614
|
!cancelled() &&
|
|
615
|
+
needs.params.outputs.mission-complete != 'true' &&
|
|
576
616
|
(needs.params.outputs.mode == 'full' || needs.params.outputs.mode == 'maintain-only') &&
|
|
577
617
|
needs.params.result == 'success' &&
|
|
578
618
|
inputs.skipMaintain != 'true' && inputs.skipMaintain != true
|
|
@@ -655,6 +695,7 @@ jobs:
|
|
|
655
695
|
- name: Maintain library
|
|
656
696
|
id: maintain-library
|
|
657
697
|
if: steps.mission-check.outputs.mission-complete != 'true'
|
|
698
|
+
timeout-minutes: 10
|
|
658
699
|
uses: ./.github/agentic-lib/actions/agentic-step
|
|
659
700
|
env:
|
|
660
701
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -669,6 +710,7 @@ jobs:
|
|
|
669
710
|
- name: Maintain features
|
|
670
711
|
id: maintain-features
|
|
671
712
|
if: steps.mission-check.outputs.mission-complete != 'true'
|
|
713
|
+
timeout-minutes: 10
|
|
672
714
|
uses: ./.github/agentic-lib/actions/agentic-step
|
|
673
715
|
env:
|
|
674
716
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -709,6 +751,7 @@ jobs:
|
|
|
709
751
|
needs: [params]
|
|
710
752
|
if: |
|
|
711
753
|
!cancelled() &&
|
|
754
|
+
needs.params.outputs.mission-complete != 'true' &&
|
|
712
755
|
(needs.params.outputs.mode == 'full' || needs.params.outputs.mode == 'maintain-only') &&
|
|
713
756
|
needs.params.result == 'success'
|
|
714
757
|
runs-on: ubuntu-latest
|
|
@@ -754,6 +797,7 @@ jobs:
|
|
|
754
797
|
- name: Run implementation review
|
|
755
798
|
id: review
|
|
756
799
|
if: github.repository != 'xn-intenton-z2a/agentic-lib'
|
|
800
|
+
timeout-minutes: 10
|
|
757
801
|
uses: ./.github/agentic-lib/actions/agentic-step
|
|
758
802
|
env:
|
|
759
803
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -775,6 +819,7 @@ jobs:
|
|
|
775
819
|
needs: [params, telemetry, maintain, implementation-review]
|
|
776
820
|
if: |
|
|
777
821
|
!cancelled() &&
|
|
822
|
+
needs.params.outputs.mission-complete != 'true' &&
|
|
778
823
|
(needs.params.outputs.mode == 'full' || needs.params.outputs.mode == 'dev-only') &&
|
|
779
824
|
needs.params.result == 'success'
|
|
780
825
|
runs-on: ubuntu-latest
|
|
@@ -815,6 +860,7 @@ jobs:
|
|
|
815
860
|
- name: Run director
|
|
816
861
|
id: director
|
|
817
862
|
if: github.repository != 'xn-intenton-z2a/agentic-lib'
|
|
863
|
+
timeout-minutes: 10
|
|
818
864
|
uses: ./.github/agentic-lib/actions/agentic-step
|
|
819
865
|
env:
|
|
820
866
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -902,6 +948,7 @@ jobs:
|
|
|
902
948
|
|
|
903
949
|
- name: Run supervisor
|
|
904
950
|
if: github.repository != 'xn-intenton-z2a/agentic-lib'
|
|
951
|
+
timeout-minutes: 10
|
|
905
952
|
uses: ./.github/agentic-lib/actions/agentic-step
|
|
906
953
|
env:
|
|
907
954
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -1178,6 +1225,7 @@ jobs:
|
|
|
1178
1225
|
env.FIX_PR_NUMBER != '' &&
|
|
1179
1226
|
steps.fix-mission-check.outputs.mission-complete != 'true' &&
|
|
1180
1227
|
env.FIX_REASON == 'requested'
|
|
1228
|
+
timeout-minutes: 10
|
|
1181
1229
|
uses: ./.github/agentic-lib/actions/agentic-step
|
|
1182
1230
|
env:
|
|
1183
1231
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -1195,6 +1243,7 @@ jobs:
|
|
|
1195
1243
|
if: |
|
|
1196
1244
|
env.FIX_MAIN_BUILD == 'true' &&
|
|
1197
1245
|
steps.fix-mission-check.outputs.mission-complete != 'true'
|
|
1246
|
+
timeout-minutes: 10
|
|
1198
1247
|
uses: ./.github/agentic-lib/actions/agentic-step
|
|
1199
1248
|
env:
|
|
1200
1249
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -1228,6 +1277,63 @@ jobs:
|
|
|
1228
1277
|
echo "No additional changes to push"
|
|
1229
1278
|
fi
|
|
1230
1279
|
|
|
1280
|
+
# W20: Immediately attempt merge after fix-stuck resolves conflicts
|
|
1281
|
+
- name: "W20: Immediate merge attempt after fix"
|
|
1282
|
+
if: |
|
|
1283
|
+
github.repository != 'xn-intenton-z2a/agentic-lib' &&
|
|
1284
|
+
env.FIX_PR_NUMBER != '' &&
|
|
1285
|
+
steps.fix-mission-check.outputs.mission-complete != 'true' &&
|
|
1286
|
+
needs.params.outputs.dry-run != 'true'
|
|
1287
|
+
uses: actions/github-script@v8
|
|
1288
|
+
with:
|
|
1289
|
+
script: |
|
|
1290
|
+
const owner = context.repo.owner;
|
|
1291
|
+
const repo = context.repo.repo;
|
|
1292
|
+
const prNumber = parseInt('${{ env.FIX_PR_NUMBER }}');
|
|
1293
|
+
if (!prNumber) return;
|
|
1294
|
+
|
|
1295
|
+
// Wait for checks to register
|
|
1296
|
+
await new Promise(r => setTimeout(r, 15000));
|
|
1297
|
+
|
|
1298
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
1299
|
+
const { data: pr } = await github.rest.pulls.get({
|
|
1300
|
+
owner, repo, pull_number: prNumber,
|
|
1301
|
+
});
|
|
1302
|
+
|
|
1303
|
+
if (pr.mergeable && pr.mergeable_state === 'clean') {
|
|
1304
|
+
try {
|
|
1305
|
+
await github.rest.pulls.merge({
|
|
1306
|
+
owner, repo, pull_number: prNumber, merge_method: 'squash',
|
|
1307
|
+
});
|
|
1308
|
+
core.info(`W20: Merged PR #${prNumber} immediately after fix`);
|
|
1309
|
+
try {
|
|
1310
|
+
await github.rest.git.deleteRef({ owner, repo, ref: `heads/${pr.head.ref}` });
|
|
1311
|
+
} catch (e) { /* branch may already be deleted */ }
|
|
1312
|
+
// Label associated issue
|
|
1313
|
+
const branchPrefix = 'agentic-lib-issue-';
|
|
1314
|
+
if (pr.head.ref.startsWith(branchPrefix)) {
|
|
1315
|
+
const issueNum = parseInt(pr.head.ref.replace(branchPrefix, ''));
|
|
1316
|
+
if (issueNum) {
|
|
1317
|
+
try {
|
|
1318
|
+
await github.rest.issues.addLabels({ owner, repo, issue_number: issueNum, labels: ['merged'] });
|
|
1319
|
+
await github.rest.issues.removeLabel({ owner, repo, issue_number: issueNum, name: 'in-progress' });
|
|
1320
|
+
} catch (e) { /* label may not exist */ }
|
|
1321
|
+
}
|
|
1322
|
+
}
|
|
1323
|
+
return;
|
|
1324
|
+
} catch (e) {
|
|
1325
|
+
core.info(`W20: Merge attempt ${attempt + 1} failed: ${e.message}`);
|
|
1326
|
+
}
|
|
1327
|
+
} else if (pr.mergeable_state === 'unstable' || pr.mergeable === null) {
|
|
1328
|
+
core.info(`W20: PR not ready yet (${pr.mergeable_state}), waiting...`);
|
|
1329
|
+
await new Promise(r => setTimeout(r, 15000));
|
|
1330
|
+
} else {
|
|
1331
|
+
core.info(`W20: PR not mergeable (${pr.mergeable_state}), leaving for pr-cleanup`);
|
|
1332
|
+
break;
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
core.info(`W20: PR #${prNumber} left open for next cycle`);
|
|
1336
|
+
|
|
1231
1337
|
- name: Commit, push, and open PR for main build fix
|
|
1232
1338
|
if: github.repository != 'xn-intenton-z2a/agentic-lib' && env.FIX_MAIN_BUILD == 'true' && steps.fix-mission-check.outputs.mission-complete != 'true'
|
|
1233
1339
|
env:
|
|
@@ -1248,12 +1354,14 @@ jobs:
|
|
|
1248
1354
|
--label automerge
|
|
1249
1355
|
|
|
1250
1356
|
# ─── Review: close resolved issues, enhance with criteria ──────────
|
|
1357
|
+
# W15: Skip review when there are no open issues to review
|
|
1251
1358
|
review-features:
|
|
1252
|
-
needs: [params, maintain, supervisor]
|
|
1359
|
+
needs: [params, maintain, supervisor, telemetry]
|
|
1253
1360
|
if: |
|
|
1254
1361
|
!cancelled() &&
|
|
1255
1362
|
(needs.params.outputs.mode == 'full' || needs.params.outputs.mode == 'review-only') &&
|
|
1256
|
-
needs.params.result == 'success'
|
|
1363
|
+
needs.params.result == 'success' &&
|
|
1364
|
+
needs.telemetry.outputs.open-issue-count != '0'
|
|
1257
1365
|
runs-on: ubuntu-latest
|
|
1258
1366
|
steps:
|
|
1259
1367
|
- uses: actions/checkout@v6
|
|
@@ -1277,6 +1385,7 @@ jobs:
|
|
|
1277
1385
|
fi
|
|
1278
1386
|
|
|
1279
1387
|
- name: Review issues
|
|
1388
|
+
timeout-minutes: 10
|
|
1280
1389
|
uses: ./.github/agentic-lib/actions/agentic-step
|
|
1281
1390
|
env:
|
|
1282
1391
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -1288,6 +1397,7 @@ jobs:
|
|
|
1288
1397
|
model: ${{ needs.params.outputs.model }}
|
|
1289
1398
|
|
|
1290
1399
|
- name: Enhance issues
|
|
1400
|
+
timeout-minutes: 10
|
|
1291
1401
|
uses: ./.github/agentic-lib/actions/agentic-step
|
|
1292
1402
|
env:
|
|
1293
1403
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -1298,9 +1408,9 @@ jobs:
|
|
|
1298
1408
|
instructions: ".github/agents/agent-ready-issue.md"
|
|
1299
1409
|
model: ${{ needs.params.outputs.model }}
|
|
1300
1410
|
|
|
1301
|
-
# ─── Dev:
|
|
1411
|
+
# ─── Dev: issue resolution (W7: multiple issues per session) ──────
|
|
1302
1412
|
dev:
|
|
1303
|
-
needs: [params, maintain, review-features]
|
|
1413
|
+
needs: [params, maintain, review-features, telemetry, implementation-review]
|
|
1304
1414
|
if: |
|
|
1305
1415
|
!cancelled() &&
|
|
1306
1416
|
(needs.params.outputs.mode == 'full' || needs.params.outputs.mode == 'dev-only') &&
|
|
@@ -1382,25 +1492,32 @@ jobs:
|
|
|
1382
1492
|
core.setOutput('issue-number', specificIssue);
|
|
1383
1493
|
return;
|
|
1384
1494
|
}
|
|
1385
|
-
// W7:
|
|
1386
|
-
|
|
1495
|
+
// W7: Collect ALL ready issues for concurrent resolution in one session
|
|
1496
|
+
const collected = [];
|
|
1497
|
+
// Instability issues first (mechanical priority override)
|
|
1387
1498
|
const { data: instabilityIssues } = await github.rest.issues.listForRepo({
|
|
1388
1499
|
...context.repo, state: 'open', labels: 'instability',
|
|
1389
|
-
sort: 'created', direction: 'asc', per_page:
|
|
1500
|
+
sort: 'created', direction: 'asc', per_page: 10,
|
|
1390
1501
|
});
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
core.info(`Instability
|
|
1394
|
-
return;
|
|
1502
|
+
for (const i of instabilityIssues) {
|
|
1503
|
+
collected.push(i.number);
|
|
1504
|
+
core.info(`Instability issue: #${i.number}: ${i.title}`);
|
|
1395
1505
|
}
|
|
1396
|
-
//
|
|
1397
|
-
const { data:
|
|
1506
|
+
// Then ready issues
|
|
1507
|
+
const { data: readyIssues } = await github.rest.issues.listForRepo({
|
|
1398
1508
|
...context.repo, state: 'open', labels: 'ready',
|
|
1399
|
-
sort: 'created', direction: 'asc', per_page:
|
|
1509
|
+
sort: 'created', direction: 'asc', per_page: 10,
|
|
1400
1510
|
});
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1511
|
+
for (const i of readyIssues) {
|
|
1512
|
+
if (!collected.includes(i.number)) {
|
|
1513
|
+
collected.push(i.number);
|
|
1514
|
+
core.info(`Ready issue: #${i.number}: ${i.title}`);
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
if (collected.length > 0) {
|
|
1518
|
+
// W7: Pass all issues as comma-separated list
|
|
1519
|
+
core.setOutput('issue-number', collected.join(','));
|
|
1520
|
+
core.info(`Targeting ${collected.length} issue(s): ${collected.join(', ')}`);
|
|
1404
1521
|
} else {
|
|
1405
1522
|
core.setOutput('issue-number', '');
|
|
1406
1523
|
core.info('No ready issues found');
|
|
@@ -1410,17 +1527,24 @@ jobs:
|
|
|
1410
1527
|
if: steps.issue.outputs.issue-number != ''
|
|
1411
1528
|
id: branch
|
|
1412
1529
|
run: |
|
|
1413
|
-
|
|
1530
|
+
# W7: Use first issue number for branch name (may be comma-separated list)
|
|
1531
|
+
ISSUE_LIST="${{ steps.issue.outputs.issue-number }}"
|
|
1532
|
+
ISSUE_NUMBER="${ISSUE_LIST%%,*}"
|
|
1414
1533
|
BRANCH="agentic-lib-issue-${ISSUE_NUMBER}"
|
|
1415
1534
|
git checkout -b "${BRANCH}" 2>/dev/null || git checkout "${BRANCH}"
|
|
1416
1535
|
echo "branchName=${BRANCH}" >> $GITHUB_OUTPUT
|
|
1417
1536
|
|
|
1418
1537
|
- name: Run transformation
|
|
1419
1538
|
if: steps.issue.outputs.issue-number != ''
|
|
1539
|
+
timeout-minutes: 10
|
|
1420
1540
|
uses: ./.github/agentic-lib/actions/agentic-step
|
|
1421
1541
|
env:
|
|
1422
1542
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
1423
1543
|
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
|
|
1544
|
+
REVIEW_ADVICE: ${{ needs.implementation-review.outputs.review-advice }}
|
|
1545
|
+
REVIEW_GAPS: ${{ needs.implementation-review.outputs.review-gaps }}
|
|
1546
|
+
TELEMETRY_UNIT_TEST_SUMMARY: ${{ needs.telemetry.outputs.unit-test-summary }}
|
|
1547
|
+
TELEMETRY_UNIT_TEST_OUTPUT: ${{ needs.telemetry.outputs.unit-test-output }}
|
|
1424
1548
|
with:
|
|
1425
1549
|
task: "transform"
|
|
1426
1550
|
config: ${{ needs.params.outputs.config-path }}
|
|
@@ -1500,7 +1624,10 @@ jobs:
|
|
|
1500
1624
|
const owner = context.repo.owner;
|
|
1501
1625
|
const repo = context.repo.repo;
|
|
1502
1626
|
const branchName = '${{ steps.branch.outputs.branchName }}';
|
|
1503
|
-
const
|
|
1627
|
+
const issueList = '${{ steps.issue.outputs.issue-number }}';
|
|
1628
|
+
// W7: issueNumber may be comma-separated list
|
|
1629
|
+
const issueNumbers = issueList.split(',').map(n => n.trim()).filter(Boolean);
|
|
1630
|
+
const issueNumber = issueNumbers[0] || '';
|
|
1504
1631
|
|
|
1505
1632
|
if (!branchName) return;
|
|
1506
1633
|
|
|
@@ -1524,6 +1651,12 @@ jobs:
|
|
|
1524
1651
|
head: `${owner}:${branchName}`, per_page: 1,
|
|
1525
1652
|
});
|
|
1526
1653
|
|
|
1654
|
+
// W7: Build PR body with Closes for all issues
|
|
1655
|
+
const closesLines = issueNumbers.map(n => `Closes #${n}`).join('\n');
|
|
1656
|
+
const prTitle = issueNumbers.length > 1
|
|
1657
|
+
? `fix: resolve issues ${issueNumbers.map(n => '#' + n).join(', ')}`
|
|
1658
|
+
: `fix: resolve issue #${issueNumber}`;
|
|
1659
|
+
|
|
1527
1660
|
let prNumber;
|
|
1528
1661
|
if (existingPRs.length > 0) {
|
|
1529
1662
|
prNumber = existingPRs[0].number;
|
|
@@ -1531,8 +1664,8 @@ jobs:
|
|
|
1531
1664
|
} else {
|
|
1532
1665
|
const { data: pr } = await github.rest.pulls.create({
|
|
1533
1666
|
owner, repo,
|
|
1534
|
-
title:
|
|
1535
|
-
body:
|
|
1667
|
+
title: prTitle,
|
|
1668
|
+
body: `${closesLines}\n\nAutomated transformation.`,
|
|
1536
1669
|
head: branchName, base: 'main',
|
|
1537
1670
|
});
|
|
1538
1671
|
prNumber = pr.number;
|
|
@@ -1582,7 +1715,7 @@ jobs:
|
|
|
1582
1715
|
|
|
1583
1716
|
# ─── Post-merge: stats, schedule, mission check ────────────────────
|
|
1584
1717
|
post-merge:
|
|
1585
|
-
needs: [params, maintain, dev, pr-cleanup]
|
|
1718
|
+
needs: [params, maintain, dev, pr-cleanup, implementation-review]
|
|
1586
1719
|
if: ${{ !cancelled() && needs.params.result == 'success' }}
|
|
1587
1720
|
runs-on: ubuntu-latest
|
|
1588
1721
|
steps:
|
|
@@ -1604,6 +1737,75 @@ jobs:
|
|
|
1604
1737
|
echo "- Dry-run: ${{ needs.params.outputs.dry-run }}" >> $GITHUB_STEP_SUMMARY
|
|
1605
1738
|
echo "- Website: [${SITE_URL}](${SITE_URL})" >> $GITHUB_STEP_SUMMARY
|
|
1606
1739
|
|
|
1740
|
+
# W14: Post-merge director check — re-evaluate mission status after dev/PR merges
|
|
1741
|
+
- name: Fetch log and screenshot from log branch (post-merge director)
|
|
1742
|
+
if: |
|
|
1743
|
+
needs.params.outputs.mission-complete != 'true' &&
|
|
1744
|
+
needs.params.outputs.dry-run != 'true' &&
|
|
1745
|
+
github.repository != 'xn-intenton-z2a/agentic-lib'
|
|
1746
|
+
env:
|
|
1747
|
+
LOG_BRANCH: ${{ needs.params.outputs.log-branch }}
|
|
1748
|
+
SCREENSHOT_FILE: ${{ needs.params.outputs.screenshot-file }}
|
|
1749
|
+
run: |
|
|
1750
|
+
git fetch origin "${LOG_BRANCH}" 2>/dev/null || true
|
|
1751
|
+
git show "origin/${LOG_BRANCH}:${SCREENSHOT_FILE}" > "${SCREENSHOT_FILE}" 2>/dev/null || true
|
|
1752
|
+
git show "origin/${LOG_BRANCH}:agentic-lib-state.toml" > "agentic-lib-state.toml" 2>/dev/null || true
|
|
1753
|
+
|
|
1754
|
+
- uses: actions/setup-node@v6
|
|
1755
|
+
if: |
|
|
1756
|
+
needs.params.outputs.mission-complete != 'true' &&
|
|
1757
|
+
needs.params.outputs.dry-run != 'true' &&
|
|
1758
|
+
github.repository != 'xn-intenton-z2a/agentic-lib'
|
|
1759
|
+
with:
|
|
1760
|
+
node-version: "24"
|
|
1761
|
+
|
|
1762
|
+
- name: Self-init (agentic-lib dev only)
|
|
1763
|
+
if: |
|
|
1764
|
+
needs.params.outputs.mission-complete != 'true' &&
|
|
1765
|
+
needs.params.outputs.dry-run != 'true' &&
|
|
1766
|
+
hashFiles('scripts/self-init.sh') != '' && hashFiles('.github/agentic-lib/actions/agentic-step/package.json') == ''
|
|
1767
|
+
run: bash scripts/self-init.sh
|
|
1768
|
+
|
|
1769
|
+
- name: Install agentic-step dependencies (post-merge director)
|
|
1770
|
+
if: |
|
|
1771
|
+
needs.params.outputs.mission-complete != 'true' &&
|
|
1772
|
+
needs.params.outputs.dry-run != 'true' &&
|
|
1773
|
+
github.repository != 'xn-intenton-z2a/agentic-lib'
|
|
1774
|
+
working-directory: .github/agentic-lib/actions/agentic-step
|
|
1775
|
+
run: |
|
|
1776
|
+
npm ci
|
|
1777
|
+
if [ -d "../../copilot" ]; then
|
|
1778
|
+
ln -sf "$(pwd)/node_modules" ../../copilot/node_modules
|
|
1779
|
+
fi
|
|
1780
|
+
|
|
1781
|
+
- name: "W14: Post-merge director evaluation"
|
|
1782
|
+
id: post-merge-director
|
|
1783
|
+
if: |
|
|
1784
|
+
needs.params.outputs.mission-complete != 'true' &&
|
|
1785
|
+
needs.params.outputs.dry-run != 'true' &&
|
|
1786
|
+
github.repository != 'xn-intenton-z2a/agentic-lib'
|
|
1787
|
+
timeout-minutes: 10
|
|
1788
|
+
uses: ./.github/agentic-lib/actions/agentic-step
|
|
1789
|
+
env:
|
|
1790
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
1791
|
+
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
|
|
1792
|
+
REVIEW_ADVICE: ${{ needs.implementation-review.outputs.review-advice }}
|
|
1793
|
+
REVIEW_GAPS: ${{ needs.implementation-review.outputs.review-gaps }}
|
|
1794
|
+
with:
|
|
1795
|
+
task: "direct"
|
|
1796
|
+
config: ${{ needs.params.outputs.config-path }}
|
|
1797
|
+
instructions: ".github/agents/agent-director.md"
|
|
1798
|
+
model: ${{ needs.params.outputs.model }}
|
|
1799
|
+
|
|
1800
|
+
- name: Push log to log branch (post-merge director)
|
|
1801
|
+
if: |
|
|
1802
|
+
needs.params.outputs.mission-complete != 'true' &&
|
|
1803
|
+
needs.params.outputs.dry-run != 'true' &&
|
|
1804
|
+
github.repository != 'xn-intenton-z2a/agentic-lib'
|
|
1805
|
+
env:
|
|
1806
|
+
LOG_BRANCH: ${{ needs.params.outputs.log-branch }}
|
|
1807
|
+
run: bash .github/agentic-lib/scripts/push-to-logs.sh agent-log-*.md agentic-lib-state.toml
|
|
1808
|
+
|
|
1607
1809
|
# ─── Post-commit validation: call test workflow to verify branch health ───
|
|
1608
1810
|
post-commit-test:
|
|
1609
1811
|
needs: [params, maintain, dev, fix-stuck, post-merge]
|
package/agentic-lib.toml
CHANGED
|
@@ -36,9 +36,9 @@ test = "npm ci && npm test"
|
|
|
36
36
|
# library-limit = 32
|
|
37
37
|
|
|
38
38
|
[tuning]
|
|
39
|
-
# Profile sets defaults for all tuning and limit knobs: min |
|
|
39
|
+
# Profile sets defaults for all tuning and limit knobs: min | med | max
|
|
40
40
|
# Profile definitions live in [profiles.*] sections below.
|
|
41
|
-
profile = "min" #@dist "
|
|
41
|
+
profile = "min" #@dist "max"
|
|
42
42
|
#
|
|
43
43
|
# Model selection — each has different strengths:
|
|
44
44
|
# gpt-5-mini — Fast, cheap, supports reasoning-effort. Best for CI and iteration.
|
|
@@ -55,6 +55,13 @@ infinite-sessions = false # set to true for long sessions with compaction
|
|
|
55
55
|
# max-issues = 5
|
|
56
56
|
# stale-days = 14
|
|
57
57
|
# max-discussion-comments = 5
|
|
58
|
+
# session-timeout-ms = 480000 # LLM session timeout in ms (should be < workflow step timeout)
|
|
59
|
+
# max-tokens = 200000 # token budget — controls max tool calls (tokens / 5000)
|
|
60
|
+
# max-read-chars = 20000 # max chars per read_file result
|
|
61
|
+
# max-test-output = 4000 # max chars of test output in prompts
|
|
62
|
+
# max-file-listing = 30 # max files in directory listings (0 = unlimited)
|
|
63
|
+
# max-library-index = 2000 # max chars for library index summary
|
|
64
|
+
# max-fix-test-output = 8000 # max chars of failed run log in fix-code
|
|
58
65
|
|
|
59
66
|
# ─── Profile Definitions ────────────────────────────────────────────
|
|
60
67
|
# Each profile defines tuning and limits defaults. The active profile
|
|
@@ -75,9 +82,16 @@ max-attempts-per-branch = 2 # max transform attempts before abando
|
|
|
75
82
|
max-attempts-per-issue = 1 # max transform attempts before abandoning an issue
|
|
76
83
|
features-limit = 2 # max feature files in features/ directory
|
|
77
84
|
library-limit = 8 # max library entries in library/ directory
|
|
85
|
+
session-timeout-ms = 480000 # LLM session timeout in ms (8 min, below 10-min workflow step)
|
|
86
|
+
max-tokens = 200000 # token budget for tool-call cap calculation
|
|
87
|
+
max-read-chars = 20000 # max chars returned from read_file tool
|
|
88
|
+
max-test-output = 4000 # max chars of test output in prompts
|
|
89
|
+
max-file-listing = 30 # max files in directory listings (0 = unlimited)
|
|
90
|
+
max-library-index = 2000 # max chars for library index in prompts
|
|
91
|
+
max-fix-test-output = 8000 # max chars of failed run log in fix-code
|
|
78
92
|
|
|
79
|
-
[profiles.
|
|
80
|
-
# Balanced — good results,
|
|
93
|
+
[profiles.med]
|
|
94
|
+
# Balanced — good results, middle ground.
|
|
81
95
|
reasoning-effort = "medium" # low | medium | high | none
|
|
82
96
|
infinite-sessions = true # enable session compaction for long runs
|
|
83
97
|
transformation-budget = 32 # max code-changing cycles per run
|
|
@@ -90,6 +104,13 @@ max-attempts-per-branch = 3 # max transform attempts before abando
|
|
|
90
104
|
max-attempts-per-issue = 2 # max transform attempts before abandoning an issue
|
|
91
105
|
features-limit = 4 # max feature files in features/ directory
|
|
92
106
|
library-limit = 32 # max library entries in library/ directory
|
|
107
|
+
session-timeout-ms = 480000 # LLM session timeout in ms (8 min, below 10-min workflow step)
|
|
108
|
+
max-tokens = 200000 # token budget for tool-call cap calculation
|
|
109
|
+
max-read-chars = 50000 # max chars returned from read_file tool
|
|
110
|
+
max-test-output = 10000 # max chars of test output in prompts
|
|
111
|
+
max-file-listing = 100 # max files in directory listings (0 = unlimited)
|
|
112
|
+
max-library-index = 5000 # max chars for library index in prompts
|
|
113
|
+
max-fix-test-output = 15000 # max chars of failed run log in fix-code
|
|
93
114
|
|
|
94
115
|
[profiles.max]
|
|
95
116
|
# Thorough — maximum context for complex missions.
|
|
@@ -105,6 +126,18 @@ max-attempts-per-branch = 5 # max transform attempts before abando
|
|
|
105
126
|
max-attempts-per-issue = 4 # max transform attempts before abandoning an issue
|
|
106
127
|
features-limit = 8 # max feature files in features/ directory
|
|
107
128
|
library-limit = 64 # max library entries in library/ directory
|
|
129
|
+
session-timeout-ms = 480000 # LLM session timeout in ms (8 min, below 10-min workflow step)
|
|
130
|
+
max-tokens = 500000 # token budget for tool-call cap calculation
|
|
131
|
+
max-read-chars = 100000 # max chars returned from read_file tool
|
|
132
|
+
max-test-output = 20000 # max chars of test output in prompts
|
|
133
|
+
max-file-listing = 0 # max files in directory listings (0 = unlimited)
|
|
134
|
+
max-library-index = 10000 # max chars for library index in prompts
|
|
135
|
+
max-fix-test-output = 30000 # max chars of failed run log in fix-code
|
|
136
|
+
|
|
137
|
+
[goals]
|
|
138
|
+
# W12/W13: Code coverage thresholds — stated in all code-changing prompts
|
|
139
|
+
min-line-coverage = 50 # minimum % line coverage required
|
|
140
|
+
min-branch-coverage = 30 # minimum % branch coverage required
|
|
108
141
|
|
|
109
142
|
[mission-complete]
|
|
110
143
|
# Thresholds for deterministic mission-complete declaration.
|
package/package.json
CHANGED
|
@@ -213,6 +213,45 @@ async function executeMissionComplete(octokit, repo, reason) {
|
|
|
213
213
|
} catch (err) {
|
|
214
214
|
core.warning(`Could not commit MISSION_COMPLETE.md: ${err.message}`);
|
|
215
215
|
}
|
|
216
|
+
|
|
217
|
+
// W2: Update persistent state (Benchmark 011 FINDING-3)
|
|
218
|
+
try {
|
|
219
|
+
const { readState, writeState } = await import("../../../copilot/state.js");
|
|
220
|
+
const state = readState(".");
|
|
221
|
+
state.status["mission-complete"] = true;
|
|
222
|
+
state.schedule["auto-disabled"] = true;
|
|
223
|
+
state.schedule["auto-disabled-reason"] = "mission-complete";
|
|
224
|
+
writeState(".", state);
|
|
225
|
+
core.info("State updated: mission-complete, schedule auto-disabled");
|
|
226
|
+
} catch (err) {
|
|
227
|
+
core.warning(`Could not update state for mission-complete: ${err.message}`);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// W3: Disable schedule on mission-complete (Benchmark 011 FINDING-4)
|
|
231
|
+
try {
|
|
232
|
+
await octokit.rest.actions.createWorkflowDispatch({
|
|
233
|
+
...repo,
|
|
234
|
+
workflow_id: "agentic-lib-schedule.yml",
|
|
235
|
+
ref: "main",
|
|
236
|
+
inputs: { frequency: "off" },
|
|
237
|
+
});
|
|
238
|
+
core.info("Dispatched schedule change to off after mission-complete");
|
|
239
|
+
} catch (err) {
|
|
240
|
+
core.warning(`Could not dispatch schedule change: ${err.message}`);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// W16: Notify bot about mission-complete
|
|
244
|
+
try {
|
|
245
|
+
await octokit.rest.actions.createWorkflowDispatch({
|
|
246
|
+
...repo,
|
|
247
|
+
workflow_id: "agentic-lib-bot.yml",
|
|
248
|
+
ref: "main",
|
|
249
|
+
inputs: { message: `Mission complete: ${reason.substring(0, 200)}` },
|
|
250
|
+
});
|
|
251
|
+
core.info("Dispatched bot notification for mission-complete");
|
|
252
|
+
} catch (err) {
|
|
253
|
+
core.warning(`Could not dispatch bot notification: ${err.message}`);
|
|
254
|
+
}
|
|
216
255
|
}
|
|
217
256
|
|
|
218
257
|
/**
|
|
@@ -287,6 +326,19 @@ async function executeMissionFailed(octokit, repo, reason, metricAssessment) {
|
|
|
287
326
|
} catch (err) {
|
|
288
327
|
core.warning(`Could not dispatch schedule change: ${err.message}`);
|
|
289
328
|
}
|
|
329
|
+
|
|
330
|
+
// W16: Notify bot about mission-failed
|
|
331
|
+
try {
|
|
332
|
+
await octokit.rest.actions.createWorkflowDispatch({
|
|
333
|
+
...repo,
|
|
334
|
+
workflow_id: "agentic-lib-bot.yml",
|
|
335
|
+
ref: "main",
|
|
336
|
+
inputs: { message: `Mission failed: ${metricDetail.substring(0, 200)}` },
|
|
337
|
+
});
|
|
338
|
+
core.info("Dispatched bot notification for mission-failed");
|
|
339
|
+
} catch (err) {
|
|
340
|
+
core.warning(`Could not dispatch bot notification: ${err.message}`);
|
|
341
|
+
}
|
|
290
342
|
}
|
|
291
343
|
|
|
292
344
|
/**
|