@xn-intenton-z2a/agentic-lib 7.4.13 → 7.4.15

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.
Files changed (55) hide show
  1. package/.github/agents/agent-apply-fix.md +30 -1
  2. package/.github/agents/agent-director.md +28 -7
  3. package/.github/agents/agent-discussion-bot.md +28 -0
  4. package/.github/agents/agent-implementation-review.md +21 -0
  5. package/.github/agents/agent-issue-resolution.md +32 -0
  6. package/.github/agents/agent-iterate.md +33 -0
  7. package/.github/agents/agent-maintain-features.md +34 -0
  8. package/.github/agents/agent-maintain-library.md +39 -0
  9. package/.github/agents/agent-ready-issue.md +21 -0
  10. package/.github/agents/agent-review-issue.md +16 -0
  11. package/.github/agents/agent-supervisor.md +60 -0
  12. package/.github/workflows/agentic-lib-init.yml +76 -11
  13. package/.github/workflows/agentic-lib-schedule.yml +58 -6
  14. package/.github/workflows/agentic-lib-test.yml +31 -3
  15. package/.github/workflows/agentic-lib-update.yml +20 -0
  16. package/.github/workflows/agentic-lib-workflow.yml +63 -52
  17. package/README.md +23 -12
  18. package/agentic-lib.toml +3 -3
  19. package/bin/agentic-lib.js +34 -4
  20. package/package.json +1 -1
  21. package/src/actions/agentic-step/index.js +51 -34
  22. package/src/actions/agentic-step/logging.js +7 -14
  23. package/src/actions/agentic-step/tasks/direct.js +52 -11
  24. package/src/actions/agentic-step/tasks/maintain-features.js +7 -0
  25. package/src/actions/agentic-step/tasks/maintain-library.js +10 -0
  26. package/src/actions/agentic-step/tasks/supervise.js +14 -6
  27. package/src/actions/agentic-step/tasks/transform.js +37 -1
  28. package/src/actions/commit-if-changed/action.yml +2 -1
  29. package/src/copilot/config.js +3 -3
  30. package/src/copilot/guards.js +5 -5
  31. package/src/copilot/state.js +211 -0
  32. package/src/copilot/telemetry.js +88 -10
  33. package/src/seeds/missions/1-dan-create-c64-emulator.md +13 -13
  34. package/src/seeds/missions/1-dan-create-planning-engine.md +82 -0
  35. package/src/seeds/missions/1-kyu-create-ray-tracer.md +31 -8
  36. package/src/seeds/missions/2-dan-create-self-hosted.md +67 -0
  37. package/src/seeds/missions/2-kyu-create-markdown-compiler.md +48 -0
  38. package/src/seeds/missions/2-kyu-create-plot-code-lib.md +35 -16
  39. package/src/seeds/missions/3-kyu-analyze-lunar-lander.md +13 -14
  40. package/src/seeds/missions/3-kyu-evaluate-time-series-lab.md +22 -28
  41. package/src/seeds/missions/4-kyu-analyze-json-schema-diff.md +46 -2
  42. package/src/seeds/missions/4-kyu-apply-cron-engine.md +16 -18
  43. package/src/seeds/missions/4-kyu-apply-dense-encoding.md +14 -11
  44. package/src/seeds/missions/4-kyu-apply-owl-ontology.md +47 -0
  45. package/src/seeds/missions/5-kyu-apply-ascii-face.md +40 -0
  46. package/src/seeds/missions/5-kyu-apply-string-utils.md +17 -17
  47. package/src/seeds/missions/6-kyu-understand-hamming-distance.md +12 -12
  48. package/src/seeds/missions/6-kyu-understand-roman-numerals.md +12 -12
  49. package/src/seeds/missions/8-kyu-remember-hello-world.md +10 -0
  50. package/src/seeds/zero-MISSION.md +12 -12
  51. package/src/seeds/zero-package.json +1 -1
  52. package/src/seeds/missions/2-dan-create-agi.md +0 -22
  53. package/src/seeds/missions/2-kyu-evaluate-markdown-compiler.md +0 -33
  54. package/src/seeds/missions/3-kyu-evaluate-owl-ontology.md +0 -34
  55. package/src/seeds/missions/5-kyu-create-ascii-face.md +0 -4
@@ -79,7 +79,26 @@ permissions:
79
79
  contents: write
80
80
 
81
81
  jobs:
82
+ params:
83
+ runs-on: ubuntu-latest
84
+ outputs:
85
+ frequency: ${{ steps.resolve.outputs.frequency }}
86
+ model: ${{ steps.resolve.outputs.model }}
87
+ profile: ${{ steps.resolve.outputs.profile }}
88
+ maintenance: ${{ steps.resolve.outputs.maintenance }}
89
+ steps:
90
+ - id: resolve
91
+ uses: actions/github-script@v7
92
+ with:
93
+ script: |
94
+ const frequency = context.payload.inputs?.['frequency'] || 'off';
95
+ core.setOutput('frequency', frequency);
96
+ core.setOutput('model', context.payload.inputs?.['model'] || '');
97
+ core.setOutput('profile', context.payload.inputs?.['profile'] || '');
98
+ core.setOutput('maintenance', frequency === 'maintenance' ? 'true' : 'false');
99
+
82
100
  update-schedule:
101
+ needs: [params]
83
102
  runs-on: ubuntu-latest
84
103
  steps:
85
104
  - uses: actions/checkout@v6
@@ -112,8 +131,10 @@ jobs:
112
131
  const isMaintenance = frequency === 'maintenance';
113
132
  const effectiveFrequency = isMaintenance ? 'weekly' : frequency;
114
133
 
134
+ // Problem 4 fix: Use a "never fires" cron for off instead of removing the block.
135
+ // Keeping the schedule: block permanently avoids GitHub cron de-registration issues.
115
136
  const SCHEDULE_MAP = {
116
- off: null,
137
+ off: '0 0 31 2 *',
117
138
  weekly: '25 6 * * 1',
118
139
  daily: '25 6 * * *',
119
140
  hourly: '25 * * * *',
@@ -147,11 +168,12 @@ jobs:
147
168
  }
148
169
  }
149
170
 
150
- // Remove any existing schedule block
151
- content = content.replace(/\n schedule:\n - cron: "[^"]*"\n/g, '\n');
152
-
153
- if (cron) {
154
- // Insert schedule block after the 'on:' line
171
+ // Replace existing schedule cron or insert a new block
172
+ const cronRegexReplace = /- cron: "[^"]*"/;
173
+ if (cronRegexReplace.test(content)) {
174
+ content = content.replace(cronRegexReplace, `- cron: "${cron}"`);
175
+ } else {
176
+ // No schedule block exists — insert one after 'on:'
155
177
  const scheduleBlock = `\n schedule:\n - cron: "${cron}"\n`;
156
178
  content = content.replace(
157
179
  /\non:\n/,
@@ -261,3 +283,33 @@ jobs:
261
283
  exit 1
262
284
  fi
263
285
  done
286
+
287
+ - name: "Problem 2 fix: Verify schedule registered with GitHub"
288
+ if: github.repository != 'xn-intenton-z2a/agentic-lib' && inputs.dry-run != 'true' && inputs.dry-run != true
289
+ env:
290
+ GH_TOKEN: ${{ secrets.WORKFLOW_TOKEN }}
291
+ run: |
292
+ echo "Waiting 10s for GitHub to process the push..."
293
+ sleep 10
294
+ WORKFLOW_STATE=$(gh api "repos/${{ github.repository }}/actions/workflows/agentic-lib-workflow.yml" --jq '.state' 2>/dev/null || echo "unknown")
295
+ echo "Workflow state: ${WORKFLOW_STATE}"
296
+ if [ "$WORKFLOW_STATE" != "active" ]; then
297
+ echo "::warning::Workflow state is '${WORKFLOW_STATE}', attempting to enable..."
298
+ gh api "repos/${{ github.repository }}/actions/workflows/agentic-lib-workflow.yml/enable" -X PUT 2>/dev/null || true
299
+ WORKFLOW_STATE=$(gh api "repos/${{ github.repository }}/actions/workflows/agentic-lib-workflow.yml" --jq '.state' 2>/dev/null || echo "unknown")
300
+ echo "Workflow state after enable: ${WORKFLOW_STATE}"
301
+ fi
302
+ # Verify the cron was registered by checking the workflow definition
303
+ FREQUENCY="${{ inputs.frequency }}"
304
+ if [ "$FREQUENCY" != "off" ]; then
305
+ echo "Verifying cron schedule is active..."
306
+ gh api "repos/${{ github.repository }}/actions/workflows" --jq '.workflows[] | select(.name == "agentic-lib-workflow") | "state=\(.state)"' 2>/dev/null || true
307
+ fi
308
+
309
+ - name: Job Summary
310
+ if: always()
311
+ uses: actions/github-script@v7
312
+ with:
313
+ script: |
314
+ const summary = `## Job: update-schedule\n| Key | Value |\n|-----|-------|\n| Status | ${context.job.status || 'completed'} |\n| Frequency | ${{ inputs.frequency }} |\n| Model | ${{ inputs.model || 'default' }} |\n| Profile | ${{ inputs.profile || 'default' }} |`;
315
+ core.summary.addRaw(summary).write();
@@ -58,7 +58,19 @@ permissions:
58
58
  issues: write
59
59
 
60
60
  jobs:
61
+ params:
62
+ runs-on: ubuntu-latest
63
+ outputs:
64
+ dry-run: ${{ steps.resolve.outputs.dry-run }}
65
+ steps:
66
+ - id: resolve
67
+ uses: actions/github-script@v7
68
+ with:
69
+ script: |
70
+ core.setOutput('dry-run', context.payload.inputs?.['dry-run'] || 'false');
71
+
61
72
  test:
73
+ needs: [params]
62
74
  runs-on: ubuntu-latest
63
75
  steps:
64
76
  - uses: actions/checkout@v6
@@ -86,6 +98,14 @@ jobs:
86
98
  - name: Run tests
87
99
  run: ${{ steps.config.outputs.test-command }}
88
100
 
101
+ - name: Job Summary
102
+ if: always()
103
+ uses: actions/github-script@v7
104
+ with:
105
+ script: |
106
+ const summary = `## Job: test\n| Key | Value |\n|-----|-------|\n| Status | ${context.job.status || 'completed'} |`;
107
+ core.summary.addRaw(summary).write();
108
+
89
109
  behaviour:
90
110
  if: github.repository != 'xn-intenton-z2a/agentic-lib'
91
111
  continue-on-error: true
@@ -139,9 +159,17 @@ jobs:
139
159
  LOG_BRANCH: ${{ inputs.log-branch || 'agentic-lib-logs' }}
140
160
  run: bash .github/agentic-lib/scripts/push-to-logs.sh "${SCREENSHOT_FILE:-SCREENSHOT_INDEX.png}"
141
161
 
162
+ - name: Job Summary
163
+ if: always()
164
+ uses: actions/github-script@v7
165
+ with:
166
+ script: |
167
+ const summary = `## Job: behaviour\n| Key | Value |\n|-----|-------|\n| Status | ${context.job.status || 'completed'} |\n| Tests Failed | ${{ steps.result.outputs.tests-failed }} |`;
168
+ core.summary.addRaw(summary).write();
169
+
142
170
  # ─── Dispatch fix workflow when unit tests fail on main ─────────────
143
171
  dispatch-fix:
144
- needs: [test]
172
+ needs: [params, test]
145
173
  if: >-
146
174
  !cancelled()
147
175
  && github.ref == 'refs/heads/main'
@@ -183,7 +211,7 @@ jobs:
183
211
 
184
212
  # ─── Report instability: install or unit test failure → automated + instability ──
185
213
  report-instability:
186
- needs: [test]
214
+ needs: [params, test]
187
215
  if: >-
188
216
  !cancelled()
189
217
  && github.ref == 'refs/heads/main'
@@ -293,7 +321,7 @@ jobs:
293
321
 
294
322
  # ─── Report behaviour failure: behaviour test failure → automated only ──
295
323
  report-behaviour:
296
- needs: [behaviour]
324
+ needs: [params, behaviour]
297
325
  if: >-
298
326
  !cancelled()
299
327
  && github.ref == 'refs/heads/main'
@@ -37,7 +37,19 @@ on:
37
37
  permissions: write-all
38
38
 
39
39
  jobs:
40
+ params:
41
+ runs-on: ubuntu-latest
42
+ outputs:
43
+ dry-run: ${{ steps.resolve.outputs.dry-run }}
44
+ steps:
45
+ - id: resolve
46
+ uses: actions/github-script@v7
47
+ with:
48
+ script: |
49
+ core.setOutput('dry-run', context.payload.inputs?.['dry-run'] || 'false');
50
+
40
51
  update:
52
+ needs: [params]
41
53
  runs-on: ubuntu-latest
42
54
  steps:
43
55
  - uses: actions/checkout@v6
@@ -109,3 +121,11 @@ jobs:
109
121
  exit 1
110
122
  fi
111
123
  done
124
+
125
+ - name: Job Summary
126
+ if: always()
127
+ uses: actions/github-script@v7
128
+ with:
129
+ script: |
130
+ const summary = `## Job: update\n| Key | Value |\n|-----|-------|\n| Status | ${context.job.status || 'completed'} |\n| Dry Run | ${{ inputs.dry-run }} |`;
131
+ core.summary.addRaw(summary).write();
@@ -178,16 +178,16 @@ jobs:
178
178
  echo "dry-run=${DRY_RUN}" >> $GITHUB_OUTPUT
179
179
  CONFIG='${{ inputs.config-path }}'
180
180
  echo "config-path=${CONFIG:-${{ env.configPath }}}" >> $GITHUB_OUTPUT
181
- # Bot config: log file, log branch, screenshot file
182
- LOG_FILE=""
181
+ # Bot config: log prefix, log branch, screenshot file
182
+ LOG_PREFIX=""
183
183
  LOG_BRANCH=""
184
184
  SCREENSHOT=""
185
185
  if [ -f "${{ env.configPath }}" ]; then
186
- LOG_FILE=$(grep '^\s*log-file' "${{ env.configPath }}" | head -1 | sed 's/.*= *"\([^"]*\)".*/\1/' || true)
186
+ LOG_PREFIX=$(grep '^\s*log-prefix' "${{ env.configPath }}" | head -1 | sed 's/.*= *"\([^"]*\)".*/\1/' || true)
187
187
  LOG_BRANCH=$(grep '^\s*log-branch' "${{ env.configPath }}" | head -1 | sed 's/.*= *"\([^"]*\)".*/\1/' || true)
188
188
  SCREENSHOT=$(grep '^\s*screenshot-file' "${{ env.configPath }}" | head -1 | sed 's/.*= *"\([^"]*\)".*/\1/' || true)
189
189
  fi
190
- echo "log-file=${LOG_FILE:-intentïon.md}" >> $GITHUB_OUTPUT
190
+ echo "log-prefix=${LOG_PREFIX:-agent-log-}" >> $GITHUB_OUTPUT
191
191
  echo "log-branch=${LOG_BRANCH:-agentic-lib-logs}" >> $GITHUB_OUTPUT
192
192
  echo "screenshot-file=${SCREENSHOT:-SCREENSHOT_INDEX.png}" >> $GITHUB_OUTPUT
193
193
  outputs:
@@ -200,7 +200,7 @@ jobs:
200
200
  pr-number: ${{ steps.normalise.outputs.pr-number }}
201
201
  dry-run: ${{ steps.normalise.outputs.dry-run }}
202
202
  config-path: ${{ steps.normalise.outputs.config-path }}
203
- log-file: ${{ steps.normalise.outputs.log-file }}
203
+ log-prefix: ${{ steps.normalise.outputs.log-prefix }}
204
204
  log-branch: ${{ steps.normalise.outputs.log-branch }}
205
205
  screenshot-file: ${{ steps.normalise.outputs.screenshot-file }}
206
206
 
@@ -373,7 +373,6 @@ jobs:
373
373
  id: gather
374
374
  uses: actions/github-script@v8
375
375
  env:
376
- LOG_FILE: ${{ needs.params.outputs.log-file }}
377
376
  LOG_BRANCH: ${{ needs.params.outputs.log-branch }}
378
377
  with:
379
378
  script: |
@@ -478,32 +477,28 @@ jobs:
478
477
  const missionComplete = fs.existsSync('MISSION_COMPLETE.md');
479
478
  const missionFailed = fs.existsSync('MISSION_FAILED.md');
480
479
 
481
- // Activity log stats (fetched from log branch)
482
- const logFile = process.env.LOG_FILE || 'intentïon.md';
480
+ // Activity log stats (from agent-log files on log branch)
483
481
  const logBranch = process.env.LOG_BRANCH || 'agentic-lib-logs';
484
482
  let activityStats = null;
485
483
  try {
486
- // Try log branch first, fall back to local file (legacy)
487
- let log = null;
488
- for (const lf of [logFile, 'intention.md']) {
484
+ const { data: tree } = await github.rest.git.getTree({
485
+ owner, repo, tree_sha: logBranch, recursive: false,
486
+ });
487
+ const logFiles = tree.tree
488
+ .filter(f => f.path.startsWith('agent-log-') && f.path.endsWith('.md'))
489
+ .sort((a, b) => a.path.localeCompare(b.path));
490
+ activityStats = { entries: logFiles.length, totalTransformCost: 0 };
491
+ // Sum costs from the most recent 10 log files
492
+ const recent = logFiles.slice(-10);
493
+ for (const lf of recent) {
489
494
  try {
490
495
  const { data } = await github.rest.repos.getContent({
491
- owner, repo, path: lf, ref: logBranch,
496
+ owner, repo, path: lf.path, ref: logBranch,
492
497
  });
493
- log = Buffer.from(data.content, 'base64').toString('utf8');
494
- break;
495
- } catch { /* try next */ }
496
- }
497
- // Fall back to local file
498
- if (!log) {
499
- const logPath = fs.existsSync(logFile) ? logFile : (fs.existsSync('intention.md') ? 'intention.md' : null);
500
- if (logPath) log = fs.readFileSync(logPath, 'utf8');
501
- }
502
- if (log) {
503
- const entries = log.split('\n## ').length - 1;
504
- const costMatches = [...log.matchAll(/\*\*agentic-lib transformation cost:\*\* (\d+)/g)];
505
- const totalCost = costMatches.reduce((sum, m) => sum + parseInt(m[1], 10), 0);
506
- activityStats = { entries, totalTransformCost: totalCost };
498
+ const content = Buffer.from(data.content, 'base64').toString('utf8');
499
+ const costMatches = [...content.matchAll(/\*\*agentic-lib transformation cost:\*\* (\d+)/g)];
500
+ activityStats.totalTransformCost += costMatches.reduce((sum, m) => sum + parseInt(m[1], 10), 0);
501
+ } catch { /* skip unreadable files */ }
507
502
  }
508
503
  } catch (e) {}
509
504
 
@@ -592,13 +587,11 @@ jobs:
592
587
 
593
588
  - name: Fetch log and screenshot from log branch
594
589
  env:
595
- LOG_FILE: ${{ needs.params.outputs.log-file }}
596
590
  LOG_BRANCH: ${{ needs.params.outputs.log-branch }}
597
591
  SCREENSHOT_FILE: ${{ needs.params.outputs.screenshot-file }}
598
592
  run: |
599
- for f in "${LOG_FILE}" "intention.md" "${SCREENSHOT_FILE}"; do
600
- git show "origin/${LOG_BRANCH}:${f}" > "$f" 2>/dev/null || true
601
- done
593
+ git show "origin/${LOG_BRANCH}:${SCREENSHOT_FILE}" > "${SCREENSHOT_FILE}" 2>/dev/null || true
594
+ git show "origin/${LOG_BRANCH}:agentic-lib-state.toml" > "agentic-lib-state.toml" 2>/dev/null || true
602
595
 
603
596
  - name: Check mission-complete signal
604
597
  id: mission-check
@@ -708,7 +701,7 @@ jobs:
708
701
  if: github.repository != 'xn-intenton-z2a/agentic-lib' && needs.params.outputs.dry-run != 'true'
709
702
  env:
710
703
  LOG_BRANCH: ${{ needs.params.outputs.log-branch }}
711
- run: bash .github/agentic-lib/scripts/push-to-logs.sh "${{ needs.params.outputs.log-file }}" "intention.md" agent-log-*.md
704
+ run: bash .github/agentic-lib/scripts/push-to-logs.sh agent-log-*.md
712
705
 
713
706
  # ─── Implementation Review: traces mission elements through code/tests/website ──
714
707
  implementation-review:
@@ -729,13 +722,11 @@ jobs:
729
722
 
730
723
  - name: Fetch log and agent logs from log branch
731
724
  env:
732
- LOG_FILE: ${{ needs.params.outputs.log-file }}
733
725
  LOG_BRANCH: ${{ needs.params.outputs.log-branch }}
734
726
  SCREENSHOT_FILE: ${{ needs.params.outputs.screenshot-file }}
735
727
  run: |
736
- for f in "${LOG_FILE}" "intention.md" "${SCREENSHOT_FILE}"; do
737
- git show "origin/${LOG_BRANCH}:${f}" > "$f" 2>/dev/null || true
738
- done
728
+ git show "origin/${LOG_BRANCH}:${SCREENSHOT_FILE}" > "${SCREENSHOT_FILE}" 2>/dev/null || true
729
+ git show "origin/${LOG_BRANCH}:agentic-lib-state.toml" > "agentic-lib-state.toml" 2>/dev/null || true
739
730
  mkdir -p .agent-logs
740
731
  git fetch origin "${LOG_BRANCH}" 2>/dev/null || true
741
732
  for f in $(git ls-tree --name-only "origin/${LOG_BRANCH}" 2>/dev/null | grep '^agent-log-' || true); do
@@ -776,7 +767,7 @@ jobs:
776
767
  if: github.repository != 'xn-intenton-z2a/agentic-lib' && needs.params.outputs.dry-run != 'true'
777
768
  env:
778
769
  LOG_BRANCH: ${{ needs.params.outputs.log-branch }}
779
- run: bash .github/agentic-lib/scripts/push-to-logs.sh "${{ needs.params.outputs.log-file }}" "intention.md" agent-log-*.md
770
+ run: bash .github/agentic-lib/scripts/push-to-logs.sh agent-log-*.md
780
771
 
781
772
  # ─── Director: LLM evaluates mission status (complete/failed/in-progress) ──
782
773
  director:
@@ -797,13 +788,11 @@ jobs:
797
788
 
798
789
  - name: Fetch log and screenshot from log branch
799
790
  env:
800
- LOG_FILE: ${{ needs.params.outputs.log-file }}
801
791
  LOG_BRANCH: ${{ needs.params.outputs.log-branch }}
802
792
  SCREENSHOT_FILE: ${{ needs.params.outputs.screenshot-file }}
803
793
  run: |
804
- for f in "${LOG_FILE}" "intention.md" "${SCREENSHOT_FILE}"; do
805
- git show "origin/${LOG_BRANCH}:${f}" > "$f" 2>/dev/null || true
806
- done
794
+ git show "origin/${LOG_BRANCH}:${SCREENSHOT_FILE}" > "${SCREENSHOT_FILE}" 2>/dev/null || true
795
+ git show "origin/${LOG_BRANCH}:agentic-lib-state.toml" > "agentic-lib-state.toml" 2>/dev/null || true
807
796
 
808
797
  - uses: actions/setup-node@v6
809
798
  with:
@@ -840,7 +829,7 @@ jobs:
840
829
  if: github.repository != 'xn-intenton-z2a/agentic-lib' && needs.params.outputs.dry-run != 'true'
841
830
  env:
842
831
  LOG_BRANCH: ${{ needs.params.outputs.log-branch }}
843
- run: bash .github/agentic-lib/scripts/push-to-logs.sh "${{ needs.params.outputs.log-file }}" "intention.md" agent-log-*.md
832
+ run: bash .github/agentic-lib/scripts/push-to-logs.sh agent-log-*.md
844
833
 
845
834
  # ─── Supervisor: LLM decides what to do (after director evaluates) ──
846
835
  supervisor:
@@ -852,23 +841,47 @@ jobs:
852
841
  needs.director.outputs.decision != 'mission-complete' &&
853
842
  needs.director.outputs.decision != 'mission-failed'
854
843
  runs-on: ubuntu-latest
844
+ outputs:
845
+ backoff-skip: ${{ steps.backoff.outputs.skip }}
855
846
  steps:
856
847
  - uses: actions/checkout@v6
857
848
  with:
858
849
  fetch-depth: 0
859
850
  ref: ${{ needs.maintain.outputs.commit-sha || github.sha }}
860
851
 
861
- - name: Fetch log and screenshot from log branch
852
+ - name: Fetch log, screenshot and state from log branch
862
853
  env:
863
- LOG_FILE: ${{ needs.params.outputs.log-file }}
864
854
  LOG_BRANCH: ${{ needs.params.outputs.log-branch }}
865
855
  SCREENSHOT_FILE: ${{ needs.params.outputs.screenshot-file }}
866
856
  run: |
867
- for f in "${LOG_FILE}" "intention.md" "${SCREENSHOT_FILE}"; do
868
- git show "origin/${LOG_BRANCH}:${f}" > "$f" 2>/dev/null || true
869
- done
857
+ git show "origin/${LOG_BRANCH}:${SCREENSHOT_FILE}" > "${SCREENSHOT_FILE}" 2>/dev/null || true
858
+ git show "origin/${LOG_BRANCH}:agentic-lib-state.toml" > "agentic-lib-state.toml" 2>/dev/null || true
859
+
860
+ - name: "C15: Check nop backoff"
861
+ id: backoff
862
+ uses: actions/github-script@v7
863
+ with:
864
+ script: |
865
+ const fs = require('fs');
866
+ let nopCount = 0;
867
+ try {
868
+ const content = fs.readFileSync('agentic-lib-state.toml', 'utf8');
869
+ const match = content.match(/cumulative-nop-cycles\s*=\s*(\d+)/);
870
+ if (match) nopCount = parseInt(match[1], 10);
871
+ } catch { /* no state file yet */ }
872
+ core.info(`Consecutive nop cycles: ${nopCount}`);
873
+ let shouldSkip = false;
874
+ if (nopCount > 3) {
875
+ const pow = Math.pow(2, Math.floor(Math.log2(nopCount)));
876
+ if (nopCount !== pow) {
877
+ shouldSkip = true;
878
+ core.info(`Backoff: skipping (nop count ${nopCount}, next run at ${pow * 2})`);
879
+ }
880
+ }
881
+ core.setOutput('skip', shouldSkip ? 'true' : 'false');
870
882
 
871
883
  - uses: actions/setup-node@v6
884
+ if: steps.backoff.outputs.skip != 'true'
872
885
  with:
873
886
  node-version: "24"
874
887
 
@@ -903,7 +916,7 @@ jobs:
903
916
  if: github.repository != 'xn-intenton-z2a/agentic-lib' && needs.params.outputs.dry-run != 'true'
904
917
  env:
905
918
  LOG_BRANCH: ${{ needs.params.outputs.log-branch }}
906
- run: bash .github/agentic-lib/scripts/push-to-logs.sh "${{ needs.params.outputs.log-file }}" "intention.md" agent-log-*.md
919
+ run: bash .github/agentic-lib/scripts/push-to-logs.sh agent-log-*.md
907
920
 
908
921
  # ─── Fix stuck PRs with failing checks ─────────────────────────────
909
922
  fix-stuck:
@@ -1299,13 +1312,11 @@ jobs:
1299
1312
 
1300
1313
  - name: Fetch log and screenshot from log branch
1301
1314
  env:
1302
- LOG_FILE: ${{ needs.params.outputs.log-file }}
1303
1315
  LOG_BRANCH: ${{ needs.params.outputs.log-branch }}
1304
1316
  SCREENSHOT_FILE: ${{ needs.params.outputs.screenshot-file }}
1305
1317
  run: |
1306
- for f in "${LOG_FILE}" "intention.md" "${SCREENSHOT_FILE}"; do
1307
- git show "origin/${LOG_BRANCH}:${f}" > "$f" 2>/dev/null || true
1308
- done
1318
+ git show "origin/${LOG_BRANCH}:${SCREENSHOT_FILE}" > "${SCREENSHOT_FILE}" 2>/dev/null || true
1319
+ git show "origin/${LOG_BRANCH}:agentic-lib-state.toml" > "agentic-lib-state.toml" 2>/dev/null || true
1309
1320
 
1310
1321
  - uses: actions/setup-node@v6
1311
1322
  with:
@@ -1475,7 +1486,7 @@ jobs:
1475
1486
  if: github.repository != 'xn-intenton-z2a/agentic-lib' && needs.params.outputs.dry-run != 'true'
1476
1487
  env:
1477
1488
  LOG_BRANCH: ${{ needs.params.outputs.log-branch }}
1478
- run: bash .github/agentic-lib/scripts/push-to-logs.sh "${{ needs.params.outputs.log-file }}" "intention.md" agent-log-*.md
1489
+ run: bash .github/agentic-lib/scripts/push-to-logs.sh agent-log-*.md
1479
1490
 
1480
1491
  - name: Create PR and attempt merge
1481
1492
  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'
package/README.md CHANGED
@@ -62,13 +62,12 @@ your-repo/
62
62
 
63
63
  ├── .github/
64
64
  │ ├── workflows/ # [INIT] 8 workflow files (always overwritten)
65
- │ │ ├── agent-flow-transform.yml # Core: transform code toward the mission
66
- │ │ ├── agent-flow-maintain.yml # Core: maintain features and library
67
- │ │ ├── agent-flow-review.yml # Core: review and close resolved issues
68
- │ │ ├── agent-flow-fix-code.yml # Core: fix failing tests
69
- │ │ ├── agent-discussions-bot.yml # Bot: respond to GitHub Discussions
70
- │ │ ├── agent-supervisor.yml # Supervisor: orchestrate the pipeline
71
- │ │ ├── ci-automerge.yml # CI: auto-merge passing PRs
65
+ │ │ ├── agentic-lib-workflow.yml # Core: supervisor + transform + maintain + review + dev
66
+ │ │ ├── agentic-lib-bot.yml # Bot: respond to GitHub Discussions
67
+ │ │ ├── agentic-lib-test.yml # CI: run unit + behaviour tests, dispatch fixes
68
+ │ │ ├── agentic-lib-init.yml # Infra: init/purge, optional seed issues
69
+ │ │ ├── agentic-lib-update.yml # Infra: update agentic-lib version
70
+ │ │ ├── agentic-lib-schedule.yml # Infra: change supervisor schedule
72
71
  │ │ └── test.yml # CI: run tests
73
72
  │ │
74
73
  │ └── agentic-lib/ # [INIT] Internal infrastructure (always overwritten)
@@ -187,10 +186,20 @@ profile = "recommended" # min | recommended | max
187
186
  # model = "gpt-5-mini" # override model per-profile
188
187
  # transformation-budget = 8 # max code-changing cycles per run
189
188
 
189
+ [mission-complete]
190
+ min-resolved-issues = 2 # minimum closed-as-RESOLVED issues since init
191
+ max-source-todos = 0 # max TODO comments allowed in ./src (0 = none)
192
+
190
193
  [bot]
191
- log-file = "intentïon.md"
194
+ log-prefix = "agent-log-"
195
+ log-branch = "agentic-lib-logs"
196
+ screenshot-file = "SCREENSHOT_INDEX.png"
192
197
  ```
193
198
 
199
+ ### Persistent State
200
+
201
+ The system maintains `agentic-lib-state.toml` on the `agentic-lib-logs` branch to track counters, budget, and status across workflow runs. This file is automatically created on `init --purge` and updated after each `agentic-step` invocation. It tracks cumulative transforms, token usage, consecutive nop cycles (for backoff), and mission status.
202
+
194
203
  ### Tuning Profiles
195
204
 
196
205
  The `profile` setting controls all tuning defaults. Three profiles are built in:
@@ -219,6 +228,7 @@ The core of the system is a single GitHub Action that handles all autonomous tas
219
228
  | `enhance-issue` | Add detail and acceptance criteria to issues |
220
229
  | `review-issue` | Review and close resolved issues |
221
230
  | `discussions` | Respond to GitHub Discussions |
231
+ | `implementation-review` | Review implementation completeness against mission |
222
232
 
223
233
  Each task calls the GitHub Copilot SDK with context assembled from your repository (mission, code, tests, features) and writes changes back to the working tree. The supervisor can dispatch any of the other tasks via workflow dispatch.
224
234
 
@@ -321,19 +331,20 @@ The session uses SDK hooks for observability (tool call tracking, error recovery
321
331
  | `7-kyu-understand-fizz-buzz` | 7 kyu | Understand | Classic FizzBuzz |
322
332
  | `6-kyu-understand-hamming-distance` | 6 kyu | Understand | Hamming distance (strings + bits) |
323
333
  | `6-kyu-understand-roman-numerals` | 6 kyu | Understand | Roman numeral conversion |
324
- | `5-kyu-create-ascii-face` | 5 kyu | Create | ASCII face art |
334
+ | `5-kyu-apply-ascii-face` | 5 kyu | Apply | ASCII face art |
325
335
  | `5-kyu-apply-string-utils` | 5 kyu | Apply | 10 string utility functions |
326
336
  | `4-kyu-apply-cron-engine` | 4 kyu | Apply | Cron expression parser |
327
337
  | `4-kyu-apply-dense-encoding` | 4 kyu | Apply | Dense binary encoding |
328
338
  | `4-kyu-analyze-json-schema-diff` | 4 kyu | Analyze | JSON Schema diff |
339
+ | `4-kyu-apply-owl-ontology` | 4 kyu | Apply | OWL ontology processor |
329
340
  | `3-kyu-analyze-lunar-lander` | 3 kyu | Analyze | Lunar lander simulation |
330
341
  | `3-kyu-evaluate-time-series-lab` | 3 kyu | Evaluate | Time series analysis |
331
- | `3-kyu-evaluate-owl-ontology` | 3 kyu | Evaluate | OWL ontology processor |
332
- | `2-kyu-evaluate-markdown-compiler` | 2 kyu | Evaluate | Markdown compiler |
342
+ | `2-kyu-create-markdown-compiler` | 2 kyu | Create | Markdown compiler |
333
343
  | `2-kyu-create-plot-code-lib` | 2 kyu | Create | Code visualization library |
334
344
  | `1-kyu-create-ray-tracer` | 1 kyu | Create | Ray tracer |
335
345
  | `1-dan-create-c64-emulator` | 1 dan | Create | C64 emulator |
336
- | `2-dan-create-agi` | 2 dan | Create | AGI vision |
346
+ | `1-dan-create-planning-engine` | 1 dan | Create | Planning engine with POP and belief revision |
347
+ | `2-dan-create-self-hosted` | 2 dan | Create | Self-hosting bootstrap tests |
337
348
 
338
349
  ### Running Local Benchmarks
339
350
 
package/agentic-lib.toml CHANGED
@@ -110,10 +110,10 @@ library-limit = 64 # max library entries in library/ directo
110
110
  # Thresholds for deterministic mission-complete declaration.
111
111
  # All conditions must be met simultaneously.
112
112
  min-resolved-issues = 2 # minimum closed-as-RESOLVED issues since init
113
- min-dedicated-tests = 0 # minimum test files that import from src/lib/
114
113
  max-source-todos = 0 # max TODO comments allowed in ./src (0 = none)
114
+ # C6: Removed min-dedicated-tests (replaced by cumulative transforms and acceptance criteria)
115
115
 
116
116
  [bot]
117
- log-file = "test/intentïon.md" #@dist "intentïon.md"
118
- log-branch = "agentic-lib-logs"
117
+ log-prefix = "tmp/agent-log-" #@dist "agent-log-"
118
+ log-branch = "main" #@dist "agentic-lib-logs"
119
119
  screenshot-file = "SCREENSHOT_INDEX.png"
@@ -1186,14 +1186,44 @@ function initPurgeGitHub() {
1186
1186
  ghExec(`gh api repos/${repoSlug}/git/refs/heads/agentic-lib-logs -X DELETE`);
1187
1187
  console.log(" DELETE: existing agentic-lib-logs branch");
1188
1188
  } catch { /* branch may not exist */ }
1189
- // Create orphan agentic-lib-logs branch with an empty commit via the API
1190
- // First get the empty tree SHA
1191
- const emptyTree = JSON.parse(ghExec(`gh api repos/${repoSlug}/git/trees -X POST -f "tree[0][path]=.gitkeep" -f "tree[0][mode]=100644" -f "tree[0][type]=blob" -f "tree[0][content]="`));
1189
+ // Create orphan agentic-lib-logs branch with initial state file
1190
+ // C1: Include agentic-lib-state.toml with default state
1191
+ const stateContent = [
1192
+ "# agentic-lib-state.toml — Persistent state across workflow runs",
1193
+ "# Written to the agentic-lib-logs branch by each agentic-step invocation",
1194
+ "",
1195
+ "[counters]",
1196
+ "log-sequence = 0",
1197
+ "cumulative-transforms = 0",
1198
+ "cumulative-maintain-features = 0",
1199
+ "cumulative-maintain-library = 0",
1200
+ "cumulative-nop-cycles = 0",
1201
+ "total-tokens = 0",
1202
+ "",
1203
+ "[budget]",
1204
+ "transformation-budget-used = 0",
1205
+ "transformation-budget-cap = 0",
1206
+ "",
1207
+ "[status]",
1208
+ 'mission-complete = false',
1209
+ 'mission-failed = false',
1210
+ 'mission-failed-reason = ""',
1211
+ 'last-transform-at = ""',
1212
+ 'last-non-nop-at = ""',
1213
+ "",
1214
+ "[schedule]",
1215
+ 'current = ""',
1216
+ "auto-disabled = false",
1217
+ 'auto-disabled-reason = ""',
1218
+ "",
1219
+ ].join("\n");
1220
+ const stateBlob = JSON.parse(ghExec(`gh api repos/${repoSlug}/git/blobs -X POST -f "content=${stateContent.replace(/"/g, '\\"')}" -f "encoding=utf-8"`));
1221
+ const emptyTree = JSON.parse(ghExec(`gh api repos/${repoSlug}/git/trees -X POST -f "tree[0][path]=.gitkeep" -f "tree[0][mode]=100644" -f "tree[0][type]=blob" -f "tree[0][content]=" -f "tree[1][path]=agentic-lib-state.toml" -f "tree[1][mode]=100644" -f "tree[1][type]=blob" -f "tree[1][sha]=${stateBlob.sha}"`));
1192
1222
  const commitData = JSON.parse(ghExec(
1193
1223
  `gh api repos/${repoSlug}/git/commits -X POST -f "message=init agentic-lib-logs branch" -f "tree=${emptyTree.sha}"`,
1194
1224
  ));
1195
1225
  ghExec(`gh api repos/${repoSlug}/git/refs -X POST -f "ref=refs/heads/agentic-lib-logs" -f "sha=${commitData.sha}"`);
1196
- console.log(" CREATE: agentic-lib-logs orphan branch");
1226
+ console.log(" CREATE: agentic-lib-logs orphan branch (with agentic-lib-state.toml)");
1197
1227
  initChanges++;
1198
1228
  } else {
1199
1229
  console.log(" CREATE: agentic-lib-logs orphan branch (dry run)");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xn-intenton-z2a/agentic-lib",
3
- "version": "7.4.13",
3
+ "version": "7.4.15",
4
4
  "description": "Agentic-lib Agentic Coding Systems SDK powering automated GitHub workflows.",
5
5
  "type": "module",
6
6
  "scripts": {