@xn-intenton-z2a/agentic-lib 7.1.74 → 7.1.76
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-init.yml +4 -4
- package/.github/workflows/agentic-lib-workflow.yml +38 -37
- package/package.json +1 -1
- package/src/actions/agentic-step/copilot.js +10 -2
- package/src/actions/agentic-step/tasks/discussions.js +11 -1
- package/src/actions/agentic-step/tasks/maintain-features.js +9 -2
- package/src/actions/agentic-step/tasks/supervise.js +9 -5
- package/src/seeds/zero-package.json +1 -1
|
@@ -213,10 +213,10 @@ jobs:
|
|
|
213
213
|
|
|
214
214
|
const SCHEDULE_MAP = {
|
|
215
215
|
off: null,
|
|
216
|
-
weekly: '
|
|
217
|
-
daily: '
|
|
218
|
-
hourly: '
|
|
219
|
-
continuous: '
|
|
216
|
+
weekly: '15 6 * * 1',
|
|
217
|
+
daily: '15 6 * * *',
|
|
218
|
+
hourly: '15 * * * *',
|
|
219
|
+
continuous: '5,15,25,35,45,55 * * * *',
|
|
220
220
|
};
|
|
221
221
|
|
|
222
222
|
if (fs.existsSync(workflowPath)) {
|
|
@@ -293,44 +293,10 @@ jobs:
|
|
|
293
293
|
outputs:
|
|
294
294
|
telemetry: ${{ steps.gather.outputs.telemetry }}
|
|
295
295
|
|
|
296
|
-
# ─── Supervisor: LLM decides what to do ─────────────────────────────
|
|
297
|
-
supervisor:
|
|
298
|
-
needs: [params, pr-cleanup, telemetry]
|
|
299
|
-
if: |
|
|
300
|
-
always() &&
|
|
301
|
-
(needs.params.outputs.mode == 'full' || needs.params.outputs.mode == 'dev-only') &&
|
|
302
|
-
needs.params.result == 'success'
|
|
303
|
-
runs-on: ubuntu-latest
|
|
304
|
-
steps:
|
|
305
|
-
- uses: actions/checkout@v6
|
|
306
|
-
|
|
307
|
-
- uses: actions/setup-node@v6
|
|
308
|
-
with:
|
|
309
|
-
node-version: "24"
|
|
310
|
-
|
|
311
|
-
- name: Self-init (agentic-lib dev only)
|
|
312
|
-
if: hashFiles('scripts/self-init.sh') != '' && hashFiles('.github/agentic-lib/actions/agentic-step/package.json') == ''
|
|
313
|
-
run: bash scripts/self-init.sh
|
|
314
|
-
|
|
315
|
-
- name: Install agentic-step dependencies
|
|
316
|
-
working-directory: .github/agentic-lib/actions/agentic-step
|
|
317
|
-
run: npm ci
|
|
318
|
-
|
|
319
|
-
- name: Run supervisor
|
|
320
|
-
if: github.repository != 'xn-intenton-z2a/agentic-lib'
|
|
321
|
-
uses: ./.github/agentic-lib/actions/agentic-step
|
|
322
|
-
env:
|
|
323
|
-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
324
|
-
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
|
|
325
|
-
with:
|
|
326
|
-
task: "supervise"
|
|
327
|
-
config: ${{ needs.params.outputs.config-path }}
|
|
328
|
-
instructions: ".github/agentic-lib/agents/agent-supervisor.md"
|
|
329
|
-
model: ${{ needs.params.outputs.model }}
|
|
330
|
-
|
|
331
296
|
# ─── Maintain: features + library (push to main) ───────────────────
|
|
297
|
+
# Runs early (parallel with pr-cleanup/telemetry) so supervisor sees features.
|
|
332
298
|
maintain:
|
|
333
|
-
needs: [params
|
|
299
|
+
needs: [params]
|
|
334
300
|
if: |
|
|
335
301
|
always() &&
|
|
336
302
|
(needs.params.outputs.mode == 'full' || needs.params.outputs.mode == 'maintain-only') &&
|
|
@@ -416,6 +382,41 @@ jobs:
|
|
|
416
382
|
commit-message: "agentic-step: maintain features and library"
|
|
417
383
|
push-ref: ${{ github.ref_name }}
|
|
418
384
|
|
|
385
|
+
# ─── Supervisor: LLM decides what to do (after maintain has features) ──
|
|
386
|
+
supervisor:
|
|
387
|
+
needs: [params, pr-cleanup, telemetry, maintain]
|
|
388
|
+
if: |
|
|
389
|
+
always() &&
|
|
390
|
+
(needs.params.outputs.mode == 'full' || needs.params.outputs.mode == 'dev-only') &&
|
|
391
|
+
needs.params.result == 'success'
|
|
392
|
+
runs-on: ubuntu-latest
|
|
393
|
+
steps:
|
|
394
|
+
- uses: actions/checkout@v6
|
|
395
|
+
|
|
396
|
+
- uses: actions/setup-node@v6
|
|
397
|
+
with:
|
|
398
|
+
node-version: "24"
|
|
399
|
+
|
|
400
|
+
- name: Self-init (agentic-lib dev only)
|
|
401
|
+
if: hashFiles('scripts/self-init.sh') != '' && hashFiles('.github/agentic-lib/actions/agentic-step/package.json') == ''
|
|
402
|
+
run: bash scripts/self-init.sh
|
|
403
|
+
|
|
404
|
+
- name: Install agentic-step dependencies
|
|
405
|
+
working-directory: .github/agentic-lib/actions/agentic-step
|
|
406
|
+
run: npm ci
|
|
407
|
+
|
|
408
|
+
- name: Run supervisor
|
|
409
|
+
if: github.repository != 'xn-intenton-z2a/agentic-lib'
|
|
410
|
+
uses: ./.github/agentic-lib/actions/agentic-step
|
|
411
|
+
env:
|
|
412
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
413
|
+
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
|
|
414
|
+
with:
|
|
415
|
+
task: "supervise"
|
|
416
|
+
config: ${{ needs.params.outputs.config-path }}
|
|
417
|
+
instructions: ".github/agentic-lib/agents/agent-supervisor.md"
|
|
418
|
+
model: ${{ needs.params.outputs.model }}
|
|
419
|
+
|
|
419
420
|
# ─── Fix stuck PRs with failing checks ─────────────────────────────
|
|
420
421
|
fix-stuck:
|
|
421
422
|
needs: [params, supervisor]
|
|
@@ -579,7 +580,7 @@ jobs:
|
|
|
579
580
|
|
|
580
581
|
# ─── Review: close resolved issues, enhance with criteria ──────────
|
|
581
582
|
review-features:
|
|
582
|
-
needs: [params,
|
|
583
|
+
needs: [params, supervisor]
|
|
583
584
|
if: |
|
|
584
585
|
always() &&
|
|
585
586
|
(needs.params.outputs.mode == 'full' || needs.params.outputs.mode == 'review-only') &&
|
package/package.json
CHANGED
|
@@ -83,19 +83,27 @@ export function generateOutline(raw, filePath) {
|
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
/**
|
|
86
|
-
* Filter issues by recency and label quality.
|
|
86
|
+
* Filter issues by recency, init epoch, and label quality.
|
|
87
87
|
*
|
|
88
88
|
* @param {Array} issues - GitHub issue objects
|
|
89
89
|
* @param {Object} [options]
|
|
90
90
|
* @param {number} [options.staleDays=30] - Issues older than this with no activity are excluded
|
|
91
91
|
* @param {boolean} [options.excludeBotOnly=true] - Exclude issues with only bot labels
|
|
92
|
+
* @param {string} [options.initTimestamp] - ISO timestamp; exclude issues created before this epoch
|
|
92
93
|
* @returns {Array} Filtered issues
|
|
93
94
|
*/
|
|
94
95
|
export function filterIssues(issues, options = {}) {
|
|
95
|
-
const { staleDays = 30, excludeBotOnly = true } = options;
|
|
96
|
+
const { staleDays = 30, excludeBotOnly = true, initTimestamp } = options;
|
|
96
97
|
const cutoff = Date.now() - staleDays * 86400000;
|
|
98
|
+
const initEpoch = initTimestamp ? new Date(initTimestamp).getTime() : 0;
|
|
97
99
|
|
|
98
100
|
return issues.filter((issue) => {
|
|
101
|
+
// Exclude issues created before the most recent init
|
|
102
|
+
if (initEpoch > 0) {
|
|
103
|
+
const created = new Date(issue.created_at).getTime();
|
|
104
|
+
if (created < initEpoch) return false;
|
|
105
|
+
}
|
|
106
|
+
|
|
99
107
|
const lastActivity = new Date(issue.updated_at || issue.created_at).getTime();
|
|
100
108
|
if (lastActivity < cutoff) return false;
|
|
101
109
|
|
|
@@ -187,8 +187,10 @@ export async function discussions(context) {
|
|
|
187
187
|
const { data: openIssues } = await octokit.rest.issues.listForRepo({
|
|
188
188
|
...repo, state: "open", per_page: 10, sort: "created", direction: "asc",
|
|
189
189
|
});
|
|
190
|
+
const initTimestampForIssues = config?.init?.timestamp || null;
|
|
191
|
+
const initEpochForIssues = initTimestampForIssues ? new Date(initTimestampForIssues).getTime() : 0;
|
|
190
192
|
repoContext.issuesSummary = openIssues
|
|
191
|
-
.filter((i) => !i.pull_request)
|
|
193
|
+
.filter((i) => !i.pull_request && (initEpochForIssues <= 0 || new Date(i.created_at).getTime() >= initEpochForIssues))
|
|
192
194
|
.map((i) => {
|
|
193
195
|
const labels = i.labels.map((l) => l.name).join(", ");
|
|
194
196
|
return `#${i.number}: ${i.title} [${labels || "no labels"}]`;
|
|
@@ -238,6 +240,14 @@ export async function discussions(context) {
|
|
|
238
240
|
}
|
|
239
241
|
|
|
240
242
|
const discussion = await fetchDiscussion(octokit, discussionUrl, t.discussionComments || 10);
|
|
243
|
+
|
|
244
|
+
// Filter discussion comments to only those after the most recent init
|
|
245
|
+
const initTs = config?.init?.timestamp || null;
|
|
246
|
+
if (initTs && discussion.comments.length > 0) {
|
|
247
|
+
const initDate = new Date(initTs);
|
|
248
|
+
discussion.comments = discussion.comments.filter((c) => new Date(c.createdAt) >= initDate);
|
|
249
|
+
}
|
|
250
|
+
|
|
241
251
|
const prompt = buildPrompt(discussionUrl, discussion, context, t, repoContext);
|
|
242
252
|
const { content, tokensUsed, inputTokens, outputTokens, cost } = await runCopilotTask({
|
|
243
253
|
model,
|
|
@@ -45,13 +45,20 @@ export async function maintainFeatures(context) {
|
|
|
45
45
|
contentLimit: t.documentSummary || 1000,
|
|
46
46
|
});
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
// Filter closed issues to only those created after the most recent init
|
|
49
|
+
const initTimestamp = config.init?.timestamp || null;
|
|
50
|
+
const initEpoch = initTimestamp ? new Date(initTimestamp).getTime() : 0;
|
|
51
|
+
|
|
52
|
+
const { data: closedIssuesRaw } = await octokit.rest.issues.listForRepo({
|
|
49
53
|
...repo,
|
|
50
54
|
state: "closed",
|
|
51
55
|
per_page: t.issuesScan || 20,
|
|
52
56
|
sort: "updated",
|
|
53
57
|
direction: "desc",
|
|
54
58
|
});
|
|
59
|
+
const closedIssues = initEpoch > 0
|
|
60
|
+
? closedIssuesRaw.filter((i) => new Date(i.created_at).getTime() >= initEpoch)
|
|
61
|
+
: closedIssuesRaw;
|
|
55
62
|
|
|
56
63
|
const agentInstructions = instructions || "Maintain the feature set by creating, updating, or pruning features.";
|
|
57
64
|
|
|
@@ -68,7 +75,7 @@ export async function maintainFeatures(context) {
|
|
|
68
75
|
libraryDocs.length > 0 ? `## Library Documents (${libraryDocs.length})` : "",
|
|
69
76
|
...libraryDocs.map((d) => `### ${d.name}\n${d.content}`),
|
|
70
77
|
"",
|
|
71
|
-
`## Recently Closed Issues (${closedIssues.length})`,
|
|
78
|
+
`## Recently Closed Issues (${closedIssues.length}${initTimestamp ? `, since init ${initTimestamp}` : ""})`,
|
|
72
79
|
...closedIssues.slice(0, Math.floor((t.issuesScan || 20) / 2)).map((i) => `- #${i.number}: ${i.title}`),
|
|
73
80
|
"",
|
|
74
81
|
"## Your Task",
|
|
@@ -51,6 +51,9 @@ async function gatherContext(octokit, repo, config, t) {
|
|
|
51
51
|
: [];
|
|
52
52
|
const libraryLimit = config.paths.library?.limit || 32;
|
|
53
53
|
|
|
54
|
+
// Read init timestamp for epoch boundary (used by issue filtering below)
|
|
55
|
+
const initTimestamp = config.init?.timestamp || null;
|
|
56
|
+
|
|
54
57
|
const { data: openIssues } = await octokit.rest.issues.listForRepo({
|
|
55
58
|
...repo,
|
|
56
59
|
state: "open",
|
|
@@ -59,7 +62,7 @@ async function gatherContext(octokit, repo, config, t) {
|
|
|
59
62
|
direction: "asc",
|
|
60
63
|
});
|
|
61
64
|
const issuesOnly = openIssues.filter((i) => !i.pull_request);
|
|
62
|
-
const filteredIssues = filterIssues(issuesOnly, { staleDays: t.staleDays || 30 });
|
|
65
|
+
const filteredIssues = filterIssues(issuesOnly, { staleDays: t.staleDays || 30, initTimestamp });
|
|
63
66
|
const oldestReadyIssue = filteredIssues.find((i) => i.labels.some((l) => l.name === "ready"));
|
|
64
67
|
const issuesSummary = filteredIssues.map((i) => {
|
|
65
68
|
const age = Math.floor((Date.now() - new Date(i.created_at).getTime()) / 86400000);
|
|
@@ -77,7 +80,11 @@ async function gatherContext(octokit, repo, config, t) {
|
|
|
77
80
|
sort: "updated",
|
|
78
81
|
direction: "desc",
|
|
79
82
|
});
|
|
80
|
-
|
|
83
|
+
const initEpoch = initTimestamp ? new Date(initTimestamp).getTime() : 0;
|
|
84
|
+
const closedIssuesFiltered = closedIssuesRaw.filter((i) =>
|
|
85
|
+
!i.pull_request && (initEpoch <= 0 || new Date(i.created_at).getTime() >= initEpoch)
|
|
86
|
+
);
|
|
87
|
+
for (const ci of closedIssuesFiltered) {
|
|
81
88
|
let closeReason = "closed";
|
|
82
89
|
try {
|
|
83
90
|
const { data: comments } = await octokit.rest.issues.listComments({
|
|
@@ -110,9 +117,6 @@ async function gatherContext(octokit, repo, config, t) {
|
|
|
110
117
|
return `#${pr.number}: ${pr.title} (${pr.head.ref}) [${labels || "no labels"}] (${age}d old)`;
|
|
111
118
|
});
|
|
112
119
|
|
|
113
|
-
// Read init timestamp for epoch boundary
|
|
114
|
-
const initTimestamp = config.init?.timestamp || null;
|
|
115
|
-
|
|
116
120
|
let workflowsSummary = [];
|
|
117
121
|
let actionsSinceInit = [];
|
|
118
122
|
try {
|