@xn-intenton-z2a/agentic-lib 7.2.17 → 7.2.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/agentic-lib-test.yml +1 -1
- package/.github/workflows/agentic-lib-workflow.yml +16 -16
- package/agentic-lib.toml +1 -1
- package/bin/agentic-lib.js +11 -11
- package/package.json +1 -1
- package/src/actions/agentic-step/config-loader.js +1 -1
- package/src/actions/agentic-step/index.js +11 -14
- package/src/actions/agentic-step/tasks/direct.js +9 -11
- package/src/actions/agentic-step/tasks/supervise.js +8 -8
- package/src/actions/commit-if-changed/action.yml +1 -1
- package/src/scripts/push-to-logs.sh +5 -5
- package/src/seeds/zero-.gitignore +1 -1
- package/src/seeds/zero-package.json +1 -1
|
@@ -122,7 +122,7 @@ jobs:
|
|
|
122
122
|
path: SCREENSHOT_INDEX.png
|
|
123
123
|
if-no-files-found: ignore
|
|
124
124
|
|
|
125
|
-
- name: Push screenshot to
|
|
125
|
+
- name: Push screenshot to agentic-lib-logs branch
|
|
126
126
|
if: |
|
|
127
127
|
github.ref == 'refs/heads/main' &&
|
|
128
128
|
github.repository != 'xn-intenton-z2a/agentic-lib' &&
|
|
@@ -428,21 +428,21 @@ 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 (fetched from
|
|
431
|
+
// Activity log stats (fetched from agentic-lib-logs branch)
|
|
432
432
|
let activityStats = null;
|
|
433
433
|
try {
|
|
434
|
-
// Try
|
|
434
|
+
// Try agentic-lib-logs branch first (new location), fall back to local file (legacy)
|
|
435
435
|
let log = null;
|
|
436
436
|
for (const logFile of ['intenti\u00F6n.md', 'intention.md']) {
|
|
437
437
|
try {
|
|
438
438
|
const { data } = await github.rest.repos.getContent({
|
|
439
|
-
owner, repo, path: logFile, ref: '
|
|
439
|
+
owner, repo, path: logFile, ref: 'agentic-lib-logs',
|
|
440
440
|
});
|
|
441
441
|
log = Buffer.from(data.content, 'base64').toString('utf8');
|
|
442
442
|
break;
|
|
443
443
|
} catch { /* try next */ }
|
|
444
444
|
}
|
|
445
|
-
// Fall back to local file (for repos not yet using
|
|
445
|
+
// Fall back to local file (for repos not yet using agentic-lib-logs branch)
|
|
446
446
|
if (!log) {
|
|
447
447
|
const logPath = fs.existsSync('intenti\u00F6n.md') ? 'intenti\u00F6n.md' : (fs.existsSync('intention.md') ? 'intention.md' : null);
|
|
448
448
|
if (logPath) log = fs.readFileSync(logPath, 'utf8');
|
|
@@ -540,10 +540,10 @@ jobs:
|
|
|
540
540
|
with:
|
|
541
541
|
fetch-depth: 0
|
|
542
542
|
|
|
543
|
-
- name: Fetch log from
|
|
543
|
+
- name: Fetch log from agentic-lib-logs branch
|
|
544
544
|
run: |
|
|
545
545
|
for f in "intentïon.md" "intention.md"; do
|
|
546
|
-
git show "origin
|
|
546
|
+
git show "origin/agentic-lib-logs:${f}" > "$f" 2>/dev/null || true
|
|
547
547
|
done
|
|
548
548
|
|
|
549
549
|
- name: Check mission-complete signal
|
|
@@ -642,7 +642,7 @@ jobs:
|
|
|
642
642
|
commit-message: "agentic-step: maintain features and library"
|
|
643
643
|
push-ref: ${{ github.ref_name }}
|
|
644
644
|
|
|
645
|
-
- name: Push log to
|
|
645
|
+
- name: Push log to agentic-lib-logs branch
|
|
646
646
|
if: github.repository != 'xn-intenton-z2a/agentic-lib' && needs.params.outputs.dry-run != 'true'
|
|
647
647
|
run: bash .github/agentic-lib/scripts/push-to-logs.sh "intentïon.md" "intention.md"
|
|
648
648
|
|
|
@@ -662,10 +662,10 @@ jobs:
|
|
|
662
662
|
with:
|
|
663
663
|
fetch-depth: 0
|
|
664
664
|
|
|
665
|
-
- name: Fetch log from
|
|
665
|
+
- name: Fetch log from agentic-lib-logs branch
|
|
666
666
|
run: |
|
|
667
667
|
for f in "intentïon.md" "intention.md"; do
|
|
668
|
-
git show "origin
|
|
668
|
+
git show "origin/agentic-lib-logs:${f}" > "$f" 2>/dev/null || true
|
|
669
669
|
done
|
|
670
670
|
|
|
671
671
|
- uses: actions/setup-node@v6
|
|
@@ -693,7 +693,7 @@ jobs:
|
|
|
693
693
|
instructions: ".github/agentic-lib/agents/agent-director.md"
|
|
694
694
|
model: ${{ needs.params.outputs.model }}
|
|
695
695
|
|
|
696
|
-
- name: Push log to
|
|
696
|
+
- name: Push log to agentic-lib-logs branch
|
|
697
697
|
if: github.repository != 'xn-intenton-z2a/agentic-lib' && needs.params.outputs.dry-run != 'true'
|
|
698
698
|
run: bash .github/agentic-lib/scripts/push-to-logs.sh "intentïon.md" "intention.md"
|
|
699
699
|
|
|
@@ -712,10 +712,10 @@ jobs:
|
|
|
712
712
|
with:
|
|
713
713
|
fetch-depth: 0
|
|
714
714
|
|
|
715
|
-
- name: Fetch log from
|
|
715
|
+
- name: Fetch log from agentic-lib-logs branch
|
|
716
716
|
run: |
|
|
717
717
|
for f in "intentïon.md" "intention.md"; do
|
|
718
|
-
git show "origin
|
|
718
|
+
git show "origin/agentic-lib-logs:${f}" > "$f" 2>/dev/null || true
|
|
719
719
|
done
|
|
720
720
|
|
|
721
721
|
- uses: actions/setup-node@v6
|
|
@@ -743,7 +743,7 @@ jobs:
|
|
|
743
743
|
instructions: ".github/agentic-lib/agents/agent-supervisor.md"
|
|
744
744
|
model: ${{ needs.params.outputs.model }}
|
|
745
745
|
|
|
746
|
-
- name: Push log to
|
|
746
|
+
- name: Push log to agentic-lib-logs branch
|
|
747
747
|
if: github.repository != 'xn-intenton-z2a/agentic-lib' && needs.params.outputs.dry-run != 'true'
|
|
748
748
|
run: bash .github/agentic-lib/scripts/push-to-logs.sh "intentïon.md" "intention.md"
|
|
749
749
|
|
|
@@ -1127,10 +1127,10 @@ jobs:
|
|
|
1127
1127
|
fetch-depth: 0
|
|
1128
1128
|
token: ${{ secrets.GITHUB_TOKEN }}
|
|
1129
1129
|
|
|
1130
|
-
- name: Fetch log from
|
|
1130
|
+
- name: Fetch log from agentic-lib-logs branch
|
|
1131
1131
|
run: |
|
|
1132
1132
|
for f in "intentïon.md" "intention.md"; do
|
|
1133
|
-
git show "origin
|
|
1133
|
+
git show "origin/agentic-lib-logs:${f}" > "$f" 2>/dev/null || true
|
|
1134
1134
|
done
|
|
1135
1135
|
|
|
1136
1136
|
- uses: actions/setup-node@v6
|
|
@@ -1293,7 +1293,7 @@ jobs:
|
|
|
1293
1293
|
commit-message: "agentic-step: transform issue #${{ steps.issue.outputs.issue-number }}"
|
|
1294
1294
|
push-ref: ${{ steps.branch.outputs.branchName }}
|
|
1295
1295
|
|
|
1296
|
-
- name: Push log to
|
|
1296
|
+
- name: Push log to agentic-lib-logs branch
|
|
1297
1297
|
if: github.repository != 'xn-intenton-z2a/agentic-lib' && needs.params.outputs.dry-run != 'true'
|
|
1298
1298
|
run: bash .github/agentic-lib/scripts/push-to-logs.sh "intentïon.md" "intention.md"
|
|
1299
1299
|
|
package/agentic-lib.toml
CHANGED
|
@@ -134,7 +134,7 @@ library-limit = 64 # max library entries in library/ directo
|
|
|
134
134
|
# Thresholds for deterministic mission-complete declaration.
|
|
135
135
|
# All conditions must be met simultaneously.
|
|
136
136
|
min-resolved-issues = 3 # minimum closed-as-RESOLVED issues since init
|
|
137
|
-
|
|
137
|
+
min-dedicated-tests = 1 # minimum test files that import from src/lib/
|
|
138
138
|
max-source-todos = 0 # max TODO comments allowed in ./src (0 = none)
|
|
139
139
|
|
|
140
140
|
[bot]
|
package/bin/agentic-lib.js
CHANGED
|
@@ -1134,30 +1134,30 @@ function initPurgeGitHub() {
|
|
|
1134
1134
|
console.log(` SKIP: Could not create discussion (${err.message})`);
|
|
1135
1135
|
}
|
|
1136
1136
|
|
|
1137
|
-
// ── Create/reset
|
|
1138
|
-
console.log("\n---
|
|
1137
|
+
// ── Create/reset agentic-lib-logs orphan branch ─────────────────────────────
|
|
1138
|
+
console.log("\n--- agentic-lib-logs branch (activity log + screenshot) ---");
|
|
1139
1139
|
try {
|
|
1140
1140
|
if (!dryRun) {
|
|
1141
|
-
// Delete existing
|
|
1141
|
+
// Delete existing agentic-lib-logs branch if present
|
|
1142
1142
|
try {
|
|
1143
|
-
ghExec(`gh api repos/${repoSlug}/git/refs/heads
|
|
1144
|
-
console.log(" DELETE: existing
|
|
1143
|
+
ghExec(`gh api repos/${repoSlug}/git/refs/heads/agentic-lib-logs -X DELETE`);
|
|
1144
|
+
console.log(" DELETE: existing agentic-lib-logs branch");
|
|
1145
1145
|
} catch { /* branch may not exist */ }
|
|
1146
|
-
// Create orphan
|
|
1146
|
+
// Create orphan agentic-lib-logs branch with an empty commit via the API
|
|
1147
1147
|
// First get the empty tree SHA
|
|
1148
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
1149
|
const commitData = JSON.parse(ghExec(
|
|
1150
|
-
`gh api repos/${repoSlug}/git/commits -X POST -f "message=init
|
|
1150
|
+
`gh api repos/${repoSlug}/git/commits -X POST -f "message=init agentic-lib-logs branch" -f "tree=${emptyTree.sha}"`,
|
|
1151
1151
|
));
|
|
1152
|
-
ghExec(`gh api repos/${repoSlug}/git/refs -X POST -f "ref=refs/heads
|
|
1153
|
-
console.log(" CREATE:
|
|
1152
|
+
ghExec(`gh api repos/${repoSlug}/git/refs -X POST -f "ref=refs/heads/agentic-lib-logs" -f "sha=${commitData.sha}"`);
|
|
1153
|
+
console.log(" CREATE: agentic-lib-logs orphan branch");
|
|
1154
1154
|
initChanges++;
|
|
1155
1155
|
} else {
|
|
1156
|
-
console.log(" CREATE:
|
|
1156
|
+
console.log(" CREATE: agentic-lib-logs orphan branch (dry run)");
|
|
1157
1157
|
initChanges++;
|
|
1158
1158
|
}
|
|
1159
1159
|
} catch (err) {
|
|
1160
|
-
console.log(` SKIP: Could not create
|
|
1160
|
+
console.log(` SKIP: Could not create agentic-lib-logs branch (${err.message})`);
|
|
1161
1161
|
}
|
|
1162
1162
|
|
|
1163
1163
|
// ── Enable GitHub Pages ───────────────────────────────────────────
|
package/package.json
CHANGED
|
@@ -261,7 +261,7 @@ export function loadConfig(configPath) {
|
|
|
261
261
|
const mc = toml["mission-complete"] || {};
|
|
262
262
|
const missionCompleteThresholds = {
|
|
263
263
|
minResolvedIssues: mc["min-resolved-issues"] ?? 3,
|
|
264
|
-
|
|
264
|
+
minDedicatedTests: mc["min-dedicated-tests"] ?? (mc["require-dedicated-tests"] === false ? 0 : 1),
|
|
265
265
|
maxSourceTodos: mc["max-source-todos"] ?? 0,
|
|
266
266
|
};
|
|
267
267
|
|
|
@@ -86,20 +86,20 @@ function buildMissionMetrics(config, result, limitsStatus, cumulativeCost, featu
|
|
|
86
86
|
const srcRoot = sourceDir.includes("/") ? sourceDir.split("/").slice(0, -1).join("/") || "src" : "src";
|
|
87
87
|
const todoCount = countSourceTodos(srcRoot);
|
|
88
88
|
|
|
89
|
-
// W3:
|
|
90
|
-
const
|
|
89
|
+
// W3: Count dedicated test files
|
|
90
|
+
const dedicatedTestCount = result.dedicatedTestCount ?? 0;
|
|
91
91
|
|
|
92
92
|
// W11: Thresholds from config
|
|
93
93
|
const thresholds = config.missionCompleteThresholds || {};
|
|
94
94
|
const minResolved = thresholds.minResolvedIssues ?? 3;
|
|
95
|
-
const
|
|
95
|
+
const minTests = thresholds.minDedicatedTests ?? 1;
|
|
96
96
|
const maxTodos = thresholds.maxSourceTodos ?? 0;
|
|
97
97
|
|
|
98
98
|
const metrics = [
|
|
99
99
|
{ metric: "Open issues", value: String(openIssues), target: "0", status: openIssues === 0 ? "MET" : "NOT MET" },
|
|
100
100
|
{ metric: "Open PRs", value: String(openPrs), target: "0", status: openPrs === 0 ? "MET" : "NOT MET" },
|
|
101
101
|
{ metric: "Issues resolved (review or PR merge)", value: String(resolvedCount), target: `>= ${minResolved}`, status: resolvedCount >= minResolved ? "MET" : "NOT MET" },
|
|
102
|
-
{ metric: "Dedicated test files", value:
|
|
102
|
+
{ metric: "Dedicated test files", value: String(dedicatedTestCount), target: `>= ${minTests}`, status: dedicatedTestCount >= minTests ? "MET" : "NOT MET" },
|
|
103
103
|
{ metric: "Source TODO count", value: String(todoCount), target: `<= ${maxTodos}`, status: todoCount <= maxTodos ? "MET" : "NOT MET" },
|
|
104
104
|
{ metric: "Transformation budget used", value: `${cumulativeCost}/${budgetCap}`, target: budgetCap > 0 ? `< ${budgetCap}` : "unlimited", status: budgetCap > 0 && cumulativeCost >= budgetCap ? "EXHAUSTED" : "OK" },
|
|
105
105
|
{ metric: "Cumulative transforms", value: String(cumulativeCost), target: ">= 1", status: cumulativeCost >= 1 ? "MET" : "NOT MET" },
|
|
@@ -117,7 +117,7 @@ function buildMissionReadiness(metrics) {
|
|
|
117
117
|
const openIssues = parseInt(metrics.find((m) => m.metric === "Open issues")?.value || "0", 10);
|
|
118
118
|
const openPrs = parseInt(metrics.find((m) => m.metric === "Open PRs")?.value || "0", 10);
|
|
119
119
|
const resolved = parseInt(metrics.find((m) => m.metric === "Issues resolved (review or PR merge)")?.value || "0", 10);
|
|
120
|
-
const
|
|
120
|
+
const dedicatedTests = parseInt(metrics.find((m) => m.metric === "Dedicated test files")?.value || "0", 10);
|
|
121
121
|
const todoCount = parseInt(metrics.find((m) => m.metric === "Source TODO count")?.value || "0", 10);
|
|
122
122
|
const missionComplete = metrics.find((m) => m.metric === "Mission complete declared")?.value === "YES";
|
|
123
123
|
const missionFailed = metrics.find((m) => m.metric === "Mission failed declared")?.value === "YES";
|
|
@@ -136,7 +136,7 @@ function buildMissionReadiness(metrics) {
|
|
|
136
136
|
|
|
137
137
|
if (allMet) {
|
|
138
138
|
parts.push("Mission complete conditions ARE met.");
|
|
139
|
-
parts.push(`0 open issues, 0 open PRs, ${resolved} issue(s) resolved,
|
|
139
|
+
parts.push(`0 open issues, 0 open PRs, ${resolved} issue(s) resolved, ${dedicatedTests} dedicated test(s), TODOs: ${todoCount}.`);
|
|
140
140
|
} else {
|
|
141
141
|
parts.push("Mission complete conditions are NOT met.");
|
|
142
142
|
if (openIssues > 0) parts.push(`${openIssues} open issue(s) remain.`);
|
|
@@ -262,9 +262,9 @@ async function run() {
|
|
|
262
262
|
? readdirSync(libraryPath).filter((f) => f.endsWith(".md")).length
|
|
263
263
|
: 0;
|
|
264
264
|
|
|
265
|
-
// W3/W10:
|
|
266
|
-
let
|
|
267
|
-
if (
|
|
265
|
+
// W3/W10: Count dedicated test files (centrally, for all tasks)
|
|
266
|
+
let dedicatedTestCount = result.dedicatedTestCount ?? 0;
|
|
267
|
+
if (dedicatedTestCount === 0) {
|
|
268
268
|
try {
|
|
269
269
|
const { scanDirectory: scanDir } = await import("./copilot.js");
|
|
270
270
|
const testDirs = ["tests", "__tests__"];
|
|
@@ -275,17 +275,14 @@ async function run() {
|
|
|
275
275
|
if (/^(main|web|behaviour)\.test\.[jt]s$/.test(tf.name)) continue;
|
|
276
276
|
const content = readFileSync(tf.path, "utf8");
|
|
277
277
|
if (/from\s+['"].*src\/lib\//.test(content) || /require\s*\(\s*['"].*src\/lib\//.test(content)) {
|
|
278
|
-
|
|
279
|
-
break;
|
|
278
|
+
dedicatedTestCount++;
|
|
280
279
|
}
|
|
281
280
|
}
|
|
282
|
-
if (hasDedicatedTests) break;
|
|
283
281
|
}
|
|
284
282
|
}
|
|
285
283
|
} catch { /* ignore — scanDirectory not available in test environment */ }
|
|
286
284
|
}
|
|
287
|
-
|
|
288
|
-
result.hasDedicatedTests = hasDedicatedTests;
|
|
285
|
+
result.dedicatedTestCount = dedicatedTestCount;
|
|
289
286
|
|
|
290
287
|
// Count open automated issues (feature vs maintenance)
|
|
291
288
|
let featureIssueCount = 0;
|
|
@@ -40,7 +40,6 @@ function countTodos(dir) {
|
|
|
40
40
|
* Detect dedicated test files that import from src/lib/.
|
|
41
41
|
*/
|
|
42
42
|
function detectDedicatedTests() {
|
|
43
|
-
let hasDedicatedTests = false;
|
|
44
43
|
const dedicatedTestFiles = [];
|
|
45
44
|
const testDirs = ["tests", "__tests__"];
|
|
46
45
|
for (const dir of testDirs) {
|
|
@@ -51,14 +50,13 @@ function detectDedicatedTests() {
|
|
|
51
50
|
if (/^(main|web|behaviour)\.test\.[jt]s$/.test(tf.name)) continue;
|
|
52
51
|
const content = readFileSync(tf.path, "utf8");
|
|
53
52
|
if (/from\s+['"].*src\/lib\//.test(content) || /require\s*\(\s*['"].*src\/lib\//.test(content)) {
|
|
54
|
-
hasDedicatedTests = true;
|
|
55
53
|
dedicatedTestFiles.push(tf.name);
|
|
56
54
|
}
|
|
57
55
|
}
|
|
58
56
|
} catch { /* ignore */ }
|
|
59
57
|
}
|
|
60
58
|
}
|
|
61
|
-
return {
|
|
59
|
+
return { dedicatedTestCount: dedicatedTestFiles.length, dedicatedTestFiles };
|
|
62
60
|
}
|
|
63
61
|
|
|
64
62
|
/**
|
|
@@ -68,14 +66,14 @@ function detectDedicatedTests() {
|
|
|
68
66
|
function buildMetricAssessment(ctx, config) {
|
|
69
67
|
const thresholds = config.missionCompleteThresholds || {};
|
|
70
68
|
const minResolved = thresholds.minResolvedIssues ?? 3;
|
|
71
|
-
const
|
|
69
|
+
const minTests = thresholds.minDedicatedTests ?? 1;
|
|
72
70
|
const maxTodos = thresholds.maxSourceTodos ?? 0;
|
|
73
71
|
|
|
74
72
|
const metrics = [
|
|
75
73
|
{ metric: "Open issues", value: ctx.issuesSummary.length, target: 0, met: ctx.issuesSummary.length === 0 },
|
|
76
74
|
{ metric: "Open PRs", value: ctx.prsSummary.length, target: 0, met: ctx.prsSummary.length === 0 },
|
|
77
75
|
{ metric: "Issues resolved", value: ctx.resolvedCount, target: minResolved, met: ctx.resolvedCount >= minResolved },
|
|
78
|
-
{ metric: "Dedicated tests", value: ctx.
|
|
76
|
+
{ metric: "Dedicated tests", value: ctx.dedicatedTestCount, target: minTests, met: ctx.dedicatedTestCount >= minTests },
|
|
79
77
|
{ metric: "Source TODOs", value: ctx.sourceTodoCount, target: maxTodos, met: ctx.sourceTodoCount <= maxTodos },
|
|
80
78
|
{ metric: "Budget", value: ctx.cumulativeTransformationCost, target: ctx.transformationBudget || "unlimited", met: !(ctx.transformationBudget > 0 && ctx.cumulativeTransformationCost >= ctx.transformationBudget) },
|
|
81
79
|
];
|
|
@@ -86,7 +84,7 @@ function buildMetricAssessment(ctx, config) {
|
|
|
86
84
|
const table = [
|
|
87
85
|
"| Metric | Value | Target | Status |",
|
|
88
86
|
"|--------|-------|--------|--------|",
|
|
89
|
-
...metrics.map((m) => `| ${m.metric} | ${m.value} | ${typeof m.target === "number" ? (m.metric.includes("TODO") ? `<= ${m.target}` :
|
|
87
|
+
...metrics.map((m) => `| ${m.metric} | ${m.value} | ${typeof m.target === "number" ? (m.metric.includes("TODO") ? `<= ${m.target}` : `>= ${m.target}`) : m.target} | ${m.met ? "MET" : "NOT MET"} |`),
|
|
90
88
|
].join("\n");
|
|
91
89
|
|
|
92
90
|
let assessment;
|
|
@@ -134,8 +132,8 @@ function buildPrompt(ctx, agentInstructions, metricAssessment) {
|
|
|
134
132
|
]
|
|
135
133
|
: []),
|
|
136
134
|
`### Test Coverage`,
|
|
137
|
-
ctx.
|
|
138
|
-
? `Dedicated test files: ${ctx.dedicatedTestFiles.join(", ")}`
|
|
135
|
+
ctx.dedicatedTestCount > 0
|
|
136
|
+
? `Dedicated test files (${ctx.dedicatedTestCount}): ${ctx.dedicatedTestFiles.join(", ")}`
|
|
139
137
|
: "**No dedicated test files found.**",
|
|
140
138
|
"",
|
|
141
139
|
`### Source TODO Count: ${ctx.sourceTodoCount}`,
|
|
@@ -348,7 +346,7 @@ export async function direct(context) {
|
|
|
348
346
|
} catch { /* ignore */ }
|
|
349
347
|
|
|
350
348
|
// Dedicated tests
|
|
351
|
-
const {
|
|
349
|
+
const { dedicatedTestCount, dedicatedTestFiles } = detectDedicatedTests();
|
|
352
350
|
|
|
353
351
|
// TODO count
|
|
354
352
|
const sourcePath = config.paths.source?.path || "src/lib/";
|
|
@@ -365,7 +363,7 @@ export async function direct(context) {
|
|
|
365
363
|
resolvedCount,
|
|
366
364
|
prsSummary,
|
|
367
365
|
sourceExports,
|
|
368
|
-
|
|
366
|
+
dedicatedTestCount,
|
|
369
367
|
dedicatedTestFiles,
|
|
370
368
|
sourceTodoCount,
|
|
371
369
|
cumulativeTransformationCost,
|
|
@@ -424,7 +422,7 @@ export async function direct(context) {
|
|
|
424
422
|
narrative: `Director: ${reason}`,
|
|
425
423
|
metricAssessment: metricAssessment.assessment,
|
|
426
424
|
directorAnalysis: analysis,
|
|
427
|
-
|
|
425
|
+
dedicatedTestCount,
|
|
428
426
|
resolvedCount,
|
|
429
427
|
changes: outcome === "mission-complete"
|
|
430
428
|
? [{ action: "mission-complete", file: "MISSION_COMPLETE.md", sizeInfo: reason.substring(0, 100) }]
|
|
@@ -312,9 +312,9 @@ async function gatherContext(octokit, repo, config, t) {
|
|
|
312
312
|
}
|
|
313
313
|
} catch { /* ignore */ }
|
|
314
314
|
|
|
315
|
-
//
|
|
315
|
+
// Count dedicated test files (not just seed tests)
|
|
316
316
|
// A dedicated test imports from the source directory (src/lib/) rather than being a seed test
|
|
317
|
-
let
|
|
317
|
+
let dedicatedTestCount = 0;
|
|
318
318
|
let dedicatedTestFiles = [];
|
|
319
319
|
try {
|
|
320
320
|
const testDirs = ["tests", "__tests__"];
|
|
@@ -327,7 +327,7 @@ async function gatherContext(octokit, repo, config, t) {
|
|
|
327
327
|
const content = readFileSync(tf.path, "utf8");
|
|
328
328
|
// Check if it imports from src/lib/ (mission-specific code)
|
|
329
329
|
if (/from\s+['"].*src\/lib\//.test(content) || /require\s*\(\s*['"].*src\/lib\//.test(content)) {
|
|
330
|
-
|
|
330
|
+
dedicatedTestCount++;
|
|
331
331
|
dedicatedTestFiles.push(tf.name);
|
|
332
332
|
}
|
|
333
333
|
}
|
|
@@ -395,7 +395,7 @@ async function gatherContext(octokit, repo, config, t) {
|
|
|
395
395
|
cumulativeTransformationCost,
|
|
396
396
|
recentlyClosedSummary,
|
|
397
397
|
sourceExports,
|
|
398
|
-
|
|
398
|
+
dedicatedTestCount,
|
|
399
399
|
dedicatedTestFiles,
|
|
400
400
|
sourceTodoCount,
|
|
401
401
|
};
|
|
@@ -434,8 +434,8 @@ function buildPrompt(ctx, agentInstructions, config) {
|
|
|
434
434
|
]
|
|
435
435
|
: []),
|
|
436
436
|
`### Test Coverage`,
|
|
437
|
-
ctx.
|
|
438
|
-
? `Dedicated test files: ${ctx.dedicatedTestFiles.join(", ")}`
|
|
437
|
+
ctx.dedicatedTestCount > 0
|
|
438
|
+
? `Dedicated test files (${ctx.dedicatedTestCount}): ${ctx.dedicatedTestFiles.join(", ")}`
|
|
439
439
|
: "**No dedicated test files found.** Only seed tests (main.test.js, web.test.js) exist. Mission-complete requires dedicated tests that import from src/lib/.",
|
|
440
440
|
"",
|
|
441
441
|
`### Source TODO Count: ${ctx.sourceTodoCount}`,
|
|
@@ -447,7 +447,7 @@ function buildPrompt(ctx, agentInstructions, config) {
|
|
|
447
447
|
// W10: Build mission-complete metrics inline for the LLM
|
|
448
448
|
const thresholds = config?.missionCompleteThresholds || {};
|
|
449
449
|
const minResolved = thresholds.minResolvedIssues ?? 3;
|
|
450
|
-
const
|
|
450
|
+
const minTests = thresholds.minDedicatedTests ?? 1;
|
|
451
451
|
const maxTodos = thresholds.maxSourceTodos ?? 0;
|
|
452
452
|
const resolvedCount = ctx.recentlyClosedSummary.filter((s) => s.includes("RESOLVED")).length;
|
|
453
453
|
const rows = [
|
|
@@ -457,7 +457,7 @@ function buildPrompt(ctx, agentInstructions, config) {
|
|
|
457
457
|
`| Open issues | ${ctx.issuesSummary.length} | 0 | ${ctx.issuesSummary.length === 0 ? "MET" : "NOT MET"} |`,
|
|
458
458
|
`| Open PRs | ${ctx.prsSummary.length} | 0 | ${ctx.prsSummary.length === 0 ? "MET" : "NOT MET"} |`,
|
|
459
459
|
`| Issues resolved (RESOLVED) | ${resolvedCount} | >= ${minResolved} | ${resolvedCount >= minResolved ? "MET" : "NOT MET"} |`,
|
|
460
|
-
`| Dedicated test files | ${ctx.
|
|
460
|
+
`| Dedicated test files | ${ctx.dedicatedTestCount} | >= ${minTests} | ${ctx.dedicatedTestCount >= minTests ? "MET" : "NOT MET"} |`,
|
|
461
461
|
`| Source TODO count | ${ctx.sourceTodoCount} | <= ${maxTodos} | ${ctx.sourceTodoCount <= maxTodos ? "MET" : "NOT MET"} |`,
|
|
462
462
|
`| Budget used | ${ctx.cumulativeTransformationCost}/${ctx.transformationBudget} | < ${ctx.transformationBudget || "unlimited"} | ${ctx.transformationBudget > 0 && ctx.cumulativeTransformationCost >= ctx.transformationBudget ? "EXHAUSTED" : "OK"} |`,
|
|
463
463
|
"",
|
|
@@ -28,7 +28,7 @@ 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/screenshot files — these live on the
|
|
31
|
+
# Unstage log/screenshot files — these live on the agentic-lib-logs branch
|
|
32
32
|
git reset HEAD -- 'intentïon.md' 'intention.md' 'SCREENSHOT_INDEX.png' 2>/dev/null || true
|
|
33
33
|
if git diff --cached --quiet; then
|
|
34
34
|
echo "No changes to commit"
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# SPDX-License-Identifier: MIT
|
|
3
3
|
# Copyright (C) 2025-2026 Polycode Limited
|
|
4
|
-
# push-to-logs.sh — Push log/screenshot files to the
|
|
4
|
+
# push-to-logs.sh — Push log/screenshot files to the agentic-lib-logs orphan branch.
|
|
5
5
|
#
|
|
6
6
|
# Usage: bash .github/agentic-lib/scripts/push-to-logs.sh [file ...]
|
|
7
7
|
# e.g. bash .github/agentic-lib/scripts/push-to-logs.sh "intentïon.md" SCREENSHOT_INDEX.png
|
|
8
8
|
#
|
|
9
|
-
# Creates the
|
|
9
|
+
# Creates the agentic-lib-logs branch if it doesn't exist. Uses rebase/retry for
|
|
10
10
|
# concurrent pushes (same strategy as commit-if-changed).
|
|
11
11
|
|
|
12
12
|
set -euo pipefail
|
|
13
13
|
|
|
14
|
-
BRANCH="
|
|
14
|
+
BRANCH="agentic-lib-logs"
|
|
15
15
|
MAX_RETRIES=3
|
|
16
16
|
|
|
17
17
|
# Collect files that actually exist in the workspace
|
|
@@ -39,12 +39,12 @@ for f in "${FILES[@]}"; do
|
|
|
39
39
|
cp "$f" "${TMPDIR}/$(basename "$f")"
|
|
40
40
|
done
|
|
41
41
|
|
|
42
|
-
# Fetch the
|
|
42
|
+
# Fetch the agentic-lib-logs branch (may not exist yet)
|
|
43
43
|
REMOTE_EXISTS=""
|
|
44
44
|
git fetch origin "${BRANCH}" 2>/dev/null && REMOTE_EXISTS="true" || true
|
|
45
45
|
|
|
46
46
|
if [ "$REMOTE_EXISTS" = "true" ]; then
|
|
47
|
-
# Check out existing
|
|
47
|
+
# Check out existing agentic-lib-logs branch into a detached worktree-like state
|
|
48
48
|
git checkout "origin/${BRANCH}" -- . 2>/dev/null || true
|
|
49
49
|
git checkout -B "${BRANCH}" "origin/${BRANCH}"
|
|
50
50
|
else
|