@xn-intenton-z2a/agentic-lib 7.2.15 → 7.2.17

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.
@@ -122,29 +122,12 @@ jobs:
122
122
  path: SCREENSHOT_INDEX.png
123
123
  if-no-files-found: ignore
124
124
 
125
- - name: Push screenshot on main
125
+ - name: Push screenshot to .logs branch
126
126
  if: |
127
127
  github.ref == 'refs/heads/main' &&
128
+ github.repository != 'xn-intenton-z2a/agentic-lib' &&
128
129
  (github.event_name == 'schedule' || inputs.push-screenshot == 'true' || inputs.push-screenshot == true)
129
- run: |
130
- git config --global --add safe.directory "$GITHUB_WORKSPACE"
131
- git config user.name "github-actions[bot]"
132
- git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
133
- git add SCREENSHOT_INDEX.png
134
- git diff --cached --quiet && echo "No screenshot changes" && exit 0
135
- git commit -m "test: update SCREENSHOT_INDEX.png [skip ci]"
136
- for attempt in 1 2 3; do
137
- git push origin HEAD:main && break
138
- echo "Push failed (attempt $attempt) — pulling and retrying"
139
- git pull --rebase origin main || {
140
- echo "Rebase conflict — aborting rebase and retrying"
141
- git rebase --abort 2>/dev/null || true
142
- }
143
- sleep $((attempt * 2))
144
- if [ "$attempt" -eq 3 ]; then
145
- echo "::warning::Failed to push screenshot after 3 attempts"
146
- fi
147
- done
130
+ run: bash .github/agentic-lib/scripts/push-to-logs.sh SCREENSHOT_INDEX.png
148
131
 
149
132
  # ─── Dispatch fix workflow when unit tests fail on main ─────────────
150
133
  dispatch-fix:
@@ -428,12 +428,26 @@ jobs:
428
428
  const missionComplete = fs.existsSync('MISSION_COMPLETE.md');
429
429
  const missionFailed = fs.existsSync('MISSION_FAILED.md');
430
430
 
431
- // Activity log stats
431
+ // Activity log stats (fetched from .logs branch)
432
432
  let activityStats = null;
433
433
  try {
434
- const logPath = fs.existsSync('intenti\u00F6n.md') ? 'intenti\u00F6n.md' : (fs.existsSync('intention.md') ? 'intention.md' : null);
435
- if (logPath) {
436
- const log = fs.readFileSync(logPath, 'utf8');
434
+ // Try .logs branch first (new location), fall back to local file (legacy)
435
+ let log = null;
436
+ for (const logFile of ['intenti\u00F6n.md', 'intention.md']) {
437
+ try {
438
+ const { data } = await github.rest.repos.getContent({
439
+ owner, repo, path: logFile, ref: '.logs',
440
+ });
441
+ log = Buffer.from(data.content, 'base64').toString('utf8');
442
+ break;
443
+ } catch { /* try next */ }
444
+ }
445
+ // Fall back to local file (for repos not yet using .logs branch)
446
+ if (!log) {
447
+ const logPath = fs.existsSync('intenti\u00F6n.md') ? 'intenti\u00F6n.md' : (fs.existsSync('intention.md') ? 'intention.md' : null);
448
+ if (logPath) log = fs.readFileSync(logPath, 'utf8');
449
+ }
450
+ if (log) {
437
451
  const entries = log.split('\n## ').length - 1;
438
452
  const costMatches = [...log.matchAll(/\*\*agentic-lib transformation cost:\*\* (\d+)/g)];
439
453
  const totalCost = costMatches.reduce((sum, m) => sum + parseInt(m[1], 10), 0);
@@ -526,6 +540,12 @@ jobs:
526
540
  with:
527
541
  fetch-depth: 0
528
542
 
543
+ - name: Fetch log from .logs branch
544
+ run: |
545
+ for f in "intentïon.md" "intention.md"; do
546
+ git show "origin/.logs:${f}" > "$f" 2>/dev/null || true
547
+ done
548
+
529
549
  - name: Check mission-complete signal
530
550
  id: mission-check
531
551
  run: |
@@ -622,6 +642,10 @@ jobs:
622
642
  commit-message: "agentic-step: maintain features and library"
623
643
  push-ref: ${{ github.ref_name }}
624
644
 
645
+ - name: Push log to .logs branch
646
+ if: github.repository != 'xn-intenton-z2a/agentic-lib' && needs.params.outputs.dry-run != 'true'
647
+ run: bash .github/agentic-lib/scripts/push-to-logs.sh "intentïon.md" "intention.md"
648
+
625
649
  # ─── Director: LLM evaluates mission status (complete/failed/in-progress) ──
626
650
  director:
627
651
  needs: [params, telemetry, maintain]
@@ -635,6 +659,14 @@ jobs:
635
659
  analysis: ${{ steps.director.outputs.director-analysis }}
636
660
  steps:
637
661
  - uses: actions/checkout@v6
662
+ with:
663
+ fetch-depth: 0
664
+
665
+ - name: Fetch log from .logs branch
666
+ run: |
667
+ for f in "intentïon.md" "intention.md"; do
668
+ git show "origin/.logs:${f}" > "$f" 2>/dev/null || true
669
+ done
638
670
 
639
671
  - uses: actions/setup-node@v6
640
672
  with:
@@ -661,6 +693,10 @@ jobs:
661
693
  instructions: ".github/agentic-lib/agents/agent-director.md"
662
694
  model: ${{ needs.params.outputs.model }}
663
695
 
696
+ - name: Push log to .logs branch
697
+ if: github.repository != 'xn-intenton-z2a/agentic-lib' && needs.params.outputs.dry-run != 'true'
698
+ run: bash .github/agentic-lib/scripts/push-to-logs.sh "intentïon.md" "intention.md"
699
+
664
700
  # ─── Supervisor: LLM decides what to do (after director evaluates) ──
665
701
  supervisor:
666
702
  needs: [params, pr-cleanup, telemetry, maintain, director]
@@ -673,6 +709,14 @@ jobs:
673
709
  runs-on: ubuntu-latest
674
710
  steps:
675
711
  - uses: actions/checkout@v6
712
+ with:
713
+ fetch-depth: 0
714
+
715
+ - name: Fetch log from .logs branch
716
+ run: |
717
+ for f in "intentïon.md" "intention.md"; do
718
+ git show "origin/.logs:${f}" > "$f" 2>/dev/null || true
719
+ done
676
720
 
677
721
  - uses: actions/setup-node@v6
678
722
  with:
@@ -699,6 +743,10 @@ jobs:
699
743
  instructions: ".github/agentic-lib/agents/agent-supervisor.md"
700
744
  model: ${{ needs.params.outputs.model }}
701
745
 
746
+ - name: Push log to .logs branch
747
+ if: github.repository != 'xn-intenton-z2a/agentic-lib' && needs.params.outputs.dry-run != 'true'
748
+ run: bash .github/agentic-lib/scripts/push-to-logs.sh "intentïon.md" "intention.md"
749
+
702
750
  # ─── Fix stuck PRs with failing checks ─────────────────────────────
703
751
  fix-stuck:
704
752
  needs: [params, supervisor]
@@ -1079,6 +1127,12 @@ jobs:
1079
1127
  fetch-depth: 0
1080
1128
  token: ${{ secrets.GITHUB_TOKEN }}
1081
1129
 
1130
+ - name: Fetch log from .logs branch
1131
+ run: |
1132
+ for f in "intentïon.md" "intention.md"; do
1133
+ git show "origin/.logs:${f}" > "$f" 2>/dev/null || true
1134
+ done
1135
+
1082
1136
  - uses: actions/setup-node@v6
1083
1137
  with:
1084
1138
  node-version: "24"
@@ -1239,6 +1293,10 @@ jobs:
1239
1293
  commit-message: "agentic-step: transform issue #${{ steps.issue.outputs.issue-number }}"
1240
1294
  push-ref: ${{ steps.branch.outputs.branchName }}
1241
1295
 
1296
+ - name: Push log to .logs branch
1297
+ if: github.repository != 'xn-intenton-z2a/agentic-lib' && needs.params.outputs.dry-run != 'true'
1298
+ run: bash .github/agentic-lib/scripts/push-to-logs.sh "intentïon.md" "intention.md"
1299
+
1242
1300
  - name: Create PR and attempt merge
1243
1301
  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'
1244
1302
  uses: actions/github-script@v8
@@ -559,6 +559,7 @@ function initScripts(agenticDir) {
559
559
  "clean.sh",
560
560
  "initialise.sh",
561
561
  "md-to-html.js",
562
+ "push-to-logs.sh",
562
563
  "update.sh",
563
564
  ];
564
565
  if (!existsSync(scriptsDir)) return;
@@ -1133,6 +1134,32 @@ function initPurgeGitHub() {
1133
1134
  console.log(` SKIP: Could not create discussion (${err.message})`);
1134
1135
  }
1135
1136
 
1137
+ // ── Create/reset .logs orphan branch ─────────────────────────────
1138
+ console.log("\n--- .logs branch (activity log + screenshot) ---");
1139
+ try {
1140
+ if (!dryRun) {
1141
+ // Delete existing .logs branch if present
1142
+ try {
1143
+ ghExec(`gh api repos/${repoSlug}/git/refs/heads/.logs -X DELETE`);
1144
+ console.log(" DELETE: existing .logs branch");
1145
+ } catch { /* branch may not exist */ }
1146
+ // Create orphan .logs branch with an empty commit via the API
1147
+ // First get the empty tree SHA
1148
+ 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]="`));
1149
+ const commitData = JSON.parse(ghExec(
1150
+ `gh api repos/${repoSlug}/git/commits -X POST -f "message=init .logs branch" -f "tree=${emptyTree.sha}"`,
1151
+ ));
1152
+ ghExec(`gh api repos/${repoSlug}/git/refs -X POST -f "ref=refs/heads/.logs" -f "sha=${commitData.sha}"`);
1153
+ console.log(" CREATE: .logs orphan branch");
1154
+ initChanges++;
1155
+ } else {
1156
+ console.log(" CREATE: .logs orphan branch (dry run)");
1157
+ initChanges++;
1158
+ }
1159
+ } catch (err) {
1160
+ console.log(` SKIP: Could not create .logs branch (${err.message})`);
1161
+ }
1162
+
1136
1163
  // ── Enable GitHub Pages ───────────────────────────────────────────
1137
1164
  console.log("\n--- Enable GitHub Pages ---");
1138
1165
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xn-intenton-z2a/agentic-lib",
3
- "version": "7.2.15",
3
+ "version": "7.2.17",
4
4
  "description": "Agentic-lib Agentic Coding Systems SDK powering automated GitHub workflows.",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -304,6 +304,45 @@ async function run() {
304
304
  }
305
305
  } catch (_) { /* API not available */ }
306
306
 
307
+ // Count resolved issues (if not already provided by the task)
308
+ if (result.resolvedCount == null) {
309
+ let resolvedCount = 0;
310
+ try {
311
+ const initTimestamp = config.init?.timestamp;
312
+ const { data: closedIssuesRaw } = await context.octokit.rest.issues.listForRepo({
313
+ ...context.repo, state: "closed", labels: "automated", per_page: 10, sort: "updated", direction: "desc",
314
+ });
315
+ const initEpoch = initTimestamp ? new Date(initTimestamp).getTime() : 0;
316
+ const closedFiltered = closedIssuesRaw.filter((i) =>
317
+ !i.pull_request && (initEpoch <= 0 || new Date(i.created_at).getTime() >= initEpoch)
318
+ );
319
+ for (const ci of closedFiltered) {
320
+ let isResolved = false;
321
+ try {
322
+ const { data: comments } = await context.octokit.rest.issues.listComments({
323
+ ...context.repo, issue_number: ci.number, per_page: 5, sort: "created", direction: "desc",
324
+ });
325
+ if (comments.some((c) => c.body?.includes("Automated Review Result"))) {
326
+ isResolved = true;
327
+ } else {
328
+ const { data: events } = await context.octokit.rest.issues.listEvents({
329
+ ...context.repo, issue_number: ci.number, per_page: 10,
330
+ });
331
+ if (events.some((e) => e.event === "closed" && e.commit_id)) {
332
+ isResolved = true;
333
+ }
334
+ }
335
+ if (!isResolved) {
336
+ const issueLabels = ci.labels.map((l) => (typeof l === "string" ? l : l.name));
337
+ if (issueLabels.includes("merged")) isResolved = true;
338
+ }
339
+ } catch { /* ignore */ }
340
+ if (isResolved) resolvedCount++;
341
+ }
342
+ } catch (_) { /* API not available */ }
343
+ result.resolvedCount = resolvedCount;
344
+ }
345
+
307
346
  const budgetCap = config.transformationBudget || 0;
308
347
  const featCap = config.paths?.features?.limit || 4;
309
348
  const libCap = config.paths?.library?.limit || 32;
@@ -28,20 +28,10 @@ runs:
28
28
  git add -A
29
29
  # Unstage workflow files — GITHUB_TOKEN cannot push workflow changes
30
30
  git reset HEAD -- '.github/workflows/' 2>/dev/null || true
31
- # Unstage log files on non-default branches to avoid merge conflicts
32
- REF="${{ inputs.push-ref }}"
33
- if [ -n "$REF" ] && [ "$REF" != "main" ] && [ "$REF" != "master" ]; then
34
- git reset HEAD -- 'intentïon.md' 'intention.md' 2>/dev/null || true
35
- fi
31
+ # Unstage log/screenshot files these live on the .logs branch
32
+ git reset HEAD -- 'intentïon.md' 'intention.md' 'SCREENSHOT_INDEX.png' 2>/dev/null || true
36
33
  if git diff --cached --quiet; then
37
34
  echo "No changes to commit"
38
- elif git diff --cached --name-only | grep -qvE '(intentïon\.md|intention\.md)$'; then
39
- # At least one non-log file changed — proceed with commit
40
- true
41
- else
42
- echo "Only log files changed — skipping commit"
43
- git reset HEAD -- . > /dev/null 2>&1
44
- exit 0
45
35
  fi
46
36
  if ! git diff --cached --quiet; then
47
37
  git commit -m "${{ inputs.commit-message }}"
@@ -0,0 +1,86 @@
1
+ #!/usr/bin/env bash
2
+ # SPDX-License-Identifier: MIT
3
+ # Copyright (C) 2025-2026 Polycode Limited
4
+ # push-to-logs.sh — Push log/screenshot files to the .logs orphan branch.
5
+ #
6
+ # Usage: bash .github/agentic-lib/scripts/push-to-logs.sh [file ...]
7
+ # e.g. bash .github/agentic-lib/scripts/push-to-logs.sh "intentïon.md" SCREENSHOT_INDEX.png
8
+ #
9
+ # Creates the .logs branch if it doesn't exist. Uses rebase/retry for
10
+ # concurrent pushes (same strategy as commit-if-changed).
11
+
12
+ set -euo pipefail
13
+
14
+ BRANCH=".logs"
15
+ MAX_RETRIES=3
16
+
17
+ # Collect files that actually exist in the workspace
18
+ FILES=()
19
+ for arg in "$@"; do
20
+ if [ -f "$arg" ]; then
21
+ FILES+=("$arg")
22
+ fi
23
+ done
24
+
25
+ if [ ${#FILES[@]} -eq 0 ]; then
26
+ echo "push-to-logs: no files to push"
27
+ exit 0
28
+ fi
29
+
30
+ echo "push-to-logs: pushing ${FILES[*]} to ${BRANCH}"
31
+
32
+ # Configure git
33
+ git config --local user.email 'action@github.com'
34
+ git config --local user.name 'GitHub Actions[bot]'
35
+
36
+ # Save file contents to temp
37
+ TMPDIR=$(mktemp -d)
38
+ for f in "${FILES[@]}"; do
39
+ cp "$f" "${TMPDIR}/$(basename "$f")"
40
+ done
41
+
42
+ # Fetch the .logs branch (may not exist yet)
43
+ REMOTE_EXISTS=""
44
+ git fetch origin "${BRANCH}" 2>/dev/null && REMOTE_EXISTS="true" || true
45
+
46
+ if [ "$REMOTE_EXISTS" = "true" ]; then
47
+ # Check out existing .logs branch into a detached worktree-like state
48
+ git checkout "origin/${BRANCH}" -- . 2>/dev/null || true
49
+ git checkout -B "${BRANCH}" "origin/${BRANCH}"
50
+ else
51
+ # Create orphan branch
52
+ git checkout --orphan "${BRANCH}"
53
+ git rm -rf . 2>/dev/null || true
54
+ fi
55
+
56
+ # Copy files in
57
+ for f in "${FILES[@]}"; do
58
+ cp "${TMPDIR}/$(basename "$f")" "$f"
59
+ git add "$f"
60
+ done
61
+
62
+ # Commit if changed
63
+ if git diff --cached --quiet 2>/dev/null; then
64
+ echo "push-to-logs: no changes to commit"
65
+ else
66
+ git commit -m "logs: update ${FILES[*]} [skip ci]"
67
+
68
+ for attempt in $(seq 1 $MAX_RETRIES); do
69
+ git push origin "${BRANCH}" && break
70
+ echo "push-to-logs: push failed (attempt $attempt) — pulling and retrying"
71
+ git pull --rebase origin "${BRANCH}" || {
72
+ echo "push-to-logs: rebase conflict — aborting and retrying"
73
+ git rebase --abort 2>/dev/null || true
74
+ }
75
+ sleep $((attempt * 2))
76
+ if [ "$attempt" -eq "$MAX_RETRIES" ]; then
77
+ echo "::warning::push-to-logs: failed to push after $MAX_RETRIES attempts"
78
+ fi
79
+ done
80
+ fi
81
+
82
+ # Return to previous branch
83
+ git checkout - 2>/dev/null || git checkout main 2>/dev/null || true
84
+
85
+ # Clean up
86
+ rm -rf "$TMPDIR"
@@ -20,8 +20,12 @@ Thumbs.db
20
20
  *.swp
21
21
  *.swo
22
22
 
23
+ # Activity log and screenshot (live on .logs branch, not main)
24
+ /intentïon.md
25
+ /intention.md
26
+ /SCREENSHOT_INDEX.png
27
+
23
28
  # Generated files at repo root (agents should use examples/ instead)
24
- /*.png
25
29
  /*.svg
26
30
  /*.pdf
27
31
  /*.csv
@@ -17,7 +17,7 @@
17
17
  "author": "",
18
18
  "license": "MIT",
19
19
  "dependencies": {
20
- "@xn-intenton-z2a/agentic-lib": "^7.2.15"
20
+ "@xn-intenton-z2a/agentic-lib": "^7.2.17"
21
21
  },
22
22
  "devDependencies": {
23
23
  "@playwright/test": "^1.58.0",