@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.
@@ -68,7 +68,7 @@ on:
68
68
  options:
69
69
  - ""
70
70
  - min
71
- - recommended
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: ${{ env.configPath }}
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.mode == 'full' || needs.params.outputs.mode == 'dev-only' || needs.params.outputs.mode == 'review-only'
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] : 'recommended';
554
- const PROFILE_LIMITS = { min: 10000, recommended: 30000, max: 60000 };
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
- #- name: Output telemetry
562
- # shell: bash
563
- # run: |
564
- # echo "Telemetry data:"
565
- # echo '${{ steps.gather.outputs.telemetry }}'
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: sequential issue resolution ──────────────────────────────
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: Mechanical instability override prioritise instability issues
1386
- // before any other ready issues, regardless of supervisor decisions
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: 1,
1500
+ sort: 'created', direction: 'asc', per_page: 10,
1390
1501
  });
1391
- if (instabilityIssues.length > 0) {
1392
- core.setOutput('issue-number', String(instabilityIssues[0].number));
1393
- core.info(`Instability override: targeting issue #${instabilityIssues[0].number}: ${instabilityIssues[0].title}`);
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
- // Find oldest open issue with 'ready' label
1397
- const { data: issues } = await github.rest.issues.listForRepo({
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: 1,
1509
+ sort: 'created', direction: 'asc', per_page: 10,
1400
1510
  });
1401
- if (issues.length > 0) {
1402
- core.setOutput('issue-number', String(issues[0].number));
1403
- core.info(`Targeting issue #${issues[0].number}: ${issues[0].title}`);
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
- ISSUE_NUMBER="${{ steps.issue.outputs.issue-number }}"
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 issueNumber = '${{ steps.issue.outputs.issue-number }}';
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: `fix: resolve issue #${issueNumber}`,
1535
- body: `Closes #${issueNumber}\n\nAutomated transformation.`,
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 | recommended | max
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 "recommended"
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.recommended]
80
- # Balanced — good results, default for consumer repos.
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xn-intenton-z2a/agentic-lib",
3
- "version": "7.4.22",
3
+ "version": "7.4.24",
4
4
  "description": "Agentic-lib Agentic Coding Systems SDK powering automated GitHub workflows.",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -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
  /**