@xn-intenton-z2a/agentic-lib 7.1.13 → 7.1.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.
package/package.json
CHANGED
|
@@ -32,8 +32,7 @@ env:
|
|
|
32
32
|
configPath: ".github/agentic-lib/agents/agentic-lib.yml"
|
|
33
33
|
|
|
34
34
|
jobs:
|
|
35
|
-
maintain
|
|
36
|
-
if: inputs.step == 'all' || inputs.step == 'features' || github.event_name == 'schedule'
|
|
35
|
+
maintain:
|
|
37
36
|
runs-on: ubuntu-latest
|
|
38
37
|
steps:
|
|
39
38
|
- uses: actions/checkout@v4
|
|
@@ -48,14 +47,18 @@ jobs:
|
|
|
48
47
|
working-directory: .github/agentic-lib/actions/agentic-step
|
|
49
48
|
run: npm ci
|
|
50
49
|
|
|
51
|
-
- name: Load config
|
|
52
|
-
id:
|
|
50
|
+
- name: Load config
|
|
51
|
+
id: config
|
|
53
52
|
run: |
|
|
54
53
|
CONFIG="${{ env.configPath }}"
|
|
55
54
|
FEATURES=$(yq -r '.paths.featuresPath.path // ".github/agentic-lib/features/"' "$CONFIG")
|
|
56
|
-
|
|
55
|
+
LIBRARY=$(yq -r '.paths.libraryDocumentsPath.path // "library/"' "$CONFIG")
|
|
56
|
+
SOURCES=$(yq -r '.paths.librarySourcesFilepath.path // "SOURCES.md"' "$CONFIG")
|
|
57
|
+
echo "featuresWritablePaths=${FEATURES}" >> $GITHUB_OUTPUT
|
|
58
|
+
echo "libraryWritablePaths=${LIBRARY};${SOURCES}" >> $GITHUB_OUTPUT
|
|
57
59
|
|
|
58
60
|
- name: Maintain features
|
|
61
|
+
if: inputs.step == 'all' || inputs.step == 'features' || github.event_name == 'schedule'
|
|
59
62
|
uses: ./.github/agentic-lib/actions/agentic-step
|
|
60
63
|
env:
|
|
61
64
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -64,40 +67,10 @@ jobs:
|
|
|
64
67
|
task: "maintain-features"
|
|
65
68
|
config: ${{ env.configPath }}
|
|
66
69
|
instructions: ".github/agentic-lib/agents/agent-maintain-features.md"
|
|
67
|
-
writable-paths: ${{ steps.
|
|
68
|
-
|
|
69
|
-
- name: Commit and push changes
|
|
70
|
-
uses: ./.github/agentic-lib/actions/commit-if-changed
|
|
71
|
-
with:
|
|
72
|
-
commit-message: "agentic-step: maintain-features"
|
|
73
|
-
push-ref: ${{ github.ref_name }}
|
|
74
|
-
|
|
75
|
-
maintain-library:
|
|
76
|
-
needs: maintain-features
|
|
77
|
-
if: always() && (inputs.step == 'all' || inputs.step == 'library' || github.event_name == 'schedule')
|
|
78
|
-
runs-on: ubuntu-latest
|
|
79
|
-
steps:
|
|
80
|
-
- uses: actions/checkout@v4
|
|
81
|
-
with:
|
|
82
|
-
fetch-depth: 0
|
|
83
|
-
|
|
84
|
-
- uses: actions/setup-node@v4
|
|
85
|
-
with:
|
|
86
|
-
node-version: "24"
|
|
87
|
-
|
|
88
|
-
- name: Install agentic-step dependencies
|
|
89
|
-
working-directory: .github/agentic-lib/actions/agentic-step
|
|
90
|
-
run: npm ci
|
|
91
|
-
|
|
92
|
-
- name: Load config for library
|
|
93
|
-
id: library-config
|
|
94
|
-
run: |
|
|
95
|
-
CONFIG="${{ env.configPath }}"
|
|
96
|
-
LIBRARY=$(yq -r '.paths.libraryDocumentsPath.path // "library/"' "$CONFIG")
|
|
97
|
-
SOURCES=$(yq -r '.paths.librarySourcesFilepath.path // "SOURCES.md"' "$CONFIG")
|
|
98
|
-
echo "writablePaths=${LIBRARY};${SOURCES}" >> $GITHUB_OUTPUT
|
|
70
|
+
writable-paths: ${{ steps.config.outputs.featuresWritablePaths }}
|
|
99
71
|
|
|
100
72
|
- name: Maintain library
|
|
73
|
+
if: inputs.step == 'all' || inputs.step == 'library' || github.event_name == 'schedule'
|
|
101
74
|
uses: ./.github/agentic-lib/actions/agentic-step
|
|
102
75
|
env:
|
|
103
76
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -106,10 +79,10 @@ jobs:
|
|
|
106
79
|
task: "maintain-library"
|
|
107
80
|
config: ${{ env.configPath }}
|
|
108
81
|
instructions: ".github/agentic-lib/agents/agent-maintain-library.md"
|
|
109
|
-
writable-paths: ${{ steps.
|
|
82
|
+
writable-paths: ${{ steps.config.outputs.libraryWritablePaths }}
|
|
110
83
|
|
|
111
84
|
- name: Commit and push changes
|
|
112
85
|
uses: ./.github/agentic-lib/actions/commit-if-changed
|
|
113
86
|
with:
|
|
114
|
-
commit-message: "agentic-step: maintain
|
|
87
|
+
commit-message: "agentic-step: maintain features and library"
|
|
115
88
|
push-ref: ${{ github.ref_name }}
|
|
@@ -3,7 +3,12 @@
|
|
|
3
3
|
# .github/workflows/agent-supervisor.yml
|
|
4
4
|
#
|
|
5
5
|
# Reactive orchestration — triggers workflows based on telemetry.
|
|
6
|
-
#
|
|
6
|
+
# Watches all agentic workflows and takes corrective or follow-up actions:
|
|
7
|
+
# - Failed builds on PR branches → dispatch fix-code (with loop protection)
|
|
8
|
+
# - Successful merges → dispatch transform to pick up next issue
|
|
9
|
+
# - Discussion bot actions → dispatch maintain or transform as follow-up
|
|
10
|
+
# - Stale issues → dispatch review
|
|
11
|
+
# - Stale conflicting PRs → remove automerge label
|
|
7
12
|
|
|
8
13
|
name: agent-supervisor
|
|
9
14
|
run-name: "agent-supervisor [${{ github.ref_name }}]"
|
|
@@ -14,6 +19,10 @@ on:
|
|
|
14
19
|
- test
|
|
15
20
|
- agent-flow-transform
|
|
16
21
|
- agent-flow-maintain
|
|
22
|
+
- agent-flow-fix-code
|
|
23
|
+
- agent-flow-review
|
|
24
|
+
- agent-discussions-bot
|
|
25
|
+
- ci-automerge
|
|
17
26
|
types:
|
|
18
27
|
- completed
|
|
19
28
|
workflow_dispatch:
|
|
@@ -22,8 +31,14 @@ permissions:
|
|
|
22
31
|
actions: write
|
|
23
32
|
contents: read
|
|
24
33
|
issues: read
|
|
34
|
+
pull-requests: write
|
|
25
35
|
checks: read
|
|
26
36
|
|
|
37
|
+
env:
|
|
38
|
+
maxFixAttempts: "3"
|
|
39
|
+
staleDays: "14"
|
|
40
|
+
stalePrDays: "3"
|
|
41
|
+
|
|
27
42
|
jobs:
|
|
28
43
|
evaluate:
|
|
29
44
|
runs-on: ubuntu-latest
|
|
@@ -32,54 +47,173 @@ jobs:
|
|
|
32
47
|
uses: actions/github-script@v7
|
|
33
48
|
with:
|
|
34
49
|
script: |
|
|
50
|
+
const owner = context.repo.owner;
|
|
51
|
+
const repo = context.repo.repo;
|
|
35
52
|
const workflowRun = context.payload.workflow_run;
|
|
53
|
+
const workflowName = workflowRun?.name || '';
|
|
54
|
+
const conclusion = workflowRun?.conclusion || '';
|
|
55
|
+
const branch = workflowRun?.head_branch || '';
|
|
56
|
+
const isAgenticBranch = branch && !['main', 'master'].includes(branch);
|
|
57
|
+
const maxFixAttempts = parseInt(process.env.maxFixAttempts) || 3;
|
|
58
|
+
const staleDays = parseInt(process.env.staleDays) || 14;
|
|
59
|
+
const stalePrDays = parseInt(process.env.stalePrDays) || 3;
|
|
36
60
|
|
|
37
|
-
|
|
38
|
-
if (workflowRun && workflowRun.conclusion === 'failure') {
|
|
39
|
-
const branch = workflowRun.head_branch;
|
|
40
|
-
const isAgenticBranch = !['main', 'master'].includes(branch);
|
|
61
|
+
core.info(`Supervisor: workflow="${workflowName}" conclusion="${conclusion}" branch="${branch}"`);
|
|
41
62
|
|
|
42
|
-
|
|
43
|
-
core.info(`Workflow "${workflowRun.name}" failed on branch ${branch}. Dispatching fix-code.`);
|
|
63
|
+
// ─── 1. Failure on PR branch → dispatch fix-code (with loop protection) ───
|
|
44
64
|
|
|
45
|
-
|
|
65
|
+
try {
|
|
66
|
+
if (workflowRun && conclusion === 'failure' && isAgenticBranch) {
|
|
46
67
|
const { data: prs } = await github.rest.pulls.list({
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
head: `${context.repo.owner}:${branch}`,
|
|
68
|
+
owner, repo, state: 'open',
|
|
69
|
+
head: `${owner}:${branch}`,
|
|
50
70
|
per_page: 1,
|
|
51
71
|
});
|
|
52
72
|
|
|
53
73
|
if (prs.length > 0) {
|
|
54
|
-
|
|
55
|
-
|
|
74
|
+
const pr = prs[0];
|
|
75
|
+
const prNumber = pr.number;
|
|
76
|
+
|
|
77
|
+
// Count prior fix-code runs for this branch to prevent infinite loops
|
|
78
|
+
const { data: fixRuns } = await github.rest.actions.listWorkflowRuns({
|
|
79
|
+
owner, repo,
|
|
56
80
|
workflow_id: 'agent-flow-fix-code.yml',
|
|
57
|
-
|
|
58
|
-
|
|
81
|
+
branch,
|
|
82
|
+
per_page: maxFixAttempts + 1,
|
|
59
83
|
});
|
|
60
|
-
|
|
84
|
+
const fixCount = fixRuns.total_count;
|
|
85
|
+
|
|
86
|
+
if (fixCount >= maxFixAttempts) {
|
|
87
|
+
core.info(`PR #${prNumber} has had ${fixCount} fix attempts (limit: ${maxFixAttempts}). Removing automerge label.`);
|
|
88
|
+
try {
|
|
89
|
+
await github.rest.issues.removeLabel({
|
|
90
|
+
owner, repo, issue_number: prNumber, name: 'automerge',
|
|
91
|
+
});
|
|
92
|
+
} catch (e) { /* label may not exist */ }
|
|
93
|
+
await github.rest.issues.createComment({
|
|
94
|
+
owner, repo, issue_number: prNumber,
|
|
95
|
+
body: `Supervisor: ${fixCount} fix-code attempts have failed. Removing automerge label — manual intervention needed.`,
|
|
96
|
+
});
|
|
97
|
+
} else {
|
|
98
|
+
core.info(`Dispatching fix-code for PR #${prNumber} (attempt ${fixCount + 1}/${maxFixAttempts}).`);
|
|
99
|
+
await github.rest.actions.createWorkflowDispatch({
|
|
100
|
+
owner, repo,
|
|
101
|
+
workflow_id: 'agent-flow-fix-code.yml',
|
|
102
|
+
ref: 'main',
|
|
103
|
+
inputs: { 'pr-number': String(prNumber) },
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
} catch (err) {
|
|
109
|
+
core.warning(`Fix-code dispatch failed: ${err.message}`);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// ─── 2. Successful merge → dispatch transform for next issue ──────────
|
|
113
|
+
|
|
114
|
+
try {
|
|
115
|
+
if (workflowName === 'ci-automerge' && conclusion === 'success') {
|
|
116
|
+
core.info('Automerge succeeded. Dispatching transform to pick up next issue.');
|
|
117
|
+
await github.rest.actions.createWorkflowDispatch({
|
|
118
|
+
owner, repo,
|
|
119
|
+
workflow_id: 'agent-flow-transform.yml',
|
|
120
|
+
ref: 'main',
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
} catch (err) {
|
|
124
|
+
core.warning(`Post-merge transform dispatch failed: ${err.message}`);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// ─── 3. Discussion bot follow-through ─────────────────────────────────
|
|
128
|
+
|
|
129
|
+
try {
|
|
130
|
+
if (workflowName === 'agent-discussions-bot' && conclusion === 'success') {
|
|
131
|
+
// Check the most recent run's jobs for the outcome
|
|
132
|
+
const runId = workflowRun.id;
|
|
133
|
+
const { data: jobs } = await github.rest.actions.listJobsForWorkflowRun({
|
|
134
|
+
owner, repo, run_id: runId,
|
|
135
|
+
});
|
|
136
|
+
const respondJob = jobs.jobs.find(j => j.name === 'respond');
|
|
137
|
+
if (respondJob) {
|
|
138
|
+
// Look through step names/outputs for action indicators
|
|
139
|
+
const steps = respondJob.steps || [];
|
|
140
|
+
const agenticStep = steps.find(s => s.name === 'Respond to discussion');
|
|
141
|
+
if (agenticStep && agenticStep.conclusion === 'success') {
|
|
142
|
+
core.info('Discussion bot completed. Dispatching maintain to pick up any new features.');
|
|
143
|
+
await github.rest.actions.createWorkflowDispatch({
|
|
144
|
+
owner, repo,
|
|
145
|
+
workflow_id: 'agent-flow-maintain.yml',
|
|
146
|
+
ref: 'main',
|
|
147
|
+
});
|
|
148
|
+
}
|
|
61
149
|
}
|
|
62
150
|
}
|
|
151
|
+
} catch (err) {
|
|
152
|
+
core.warning(`Discussion bot follow-through failed: ${err.message}`);
|
|
63
153
|
}
|
|
64
154
|
|
|
65
|
-
//
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
const fourteenDaysAgo = new Date(Date.now() - 14 * 24 * 60 * 60 * 1000);
|
|
76
|
-
const staleIssues = issues.filter(i => new Date(i.updated_at) < fourteenDaysAgo);
|
|
77
|
-
|
|
78
|
-
if (staleIssues.length > 0) {
|
|
79
|
-
core.info(`Found ${staleIssues.length} stale issue(s). Dispatching review.`);
|
|
80
|
-
await github.rest.actions.createWorkflowDispatch({
|
|
81
|
-
...context.repo,
|
|
82
|
-
workflow_id: 'agent-flow-review.yml',
|
|
83
|
-
ref: context.ref,
|
|
155
|
+
// ─── 4. Stale issues → dispatch review ────────────────────────────────
|
|
156
|
+
|
|
157
|
+
try {
|
|
158
|
+
const { data: issues } = await github.rest.issues.listForRepo({
|
|
159
|
+
owner, repo, state: 'open',
|
|
160
|
+
labels: 'automated',
|
|
161
|
+
sort: 'updated',
|
|
162
|
+
direction: 'asc',
|
|
163
|
+
per_page: 5,
|
|
84
164
|
});
|
|
165
|
+
|
|
166
|
+
const cutoff = new Date(Date.now() - staleDays * 24 * 60 * 60 * 1000);
|
|
167
|
+
const staleIssues = issues.filter(i => new Date(i.updated_at) < cutoff);
|
|
168
|
+
|
|
169
|
+
if (staleIssues.length > 0) {
|
|
170
|
+
core.info(`Found ${staleIssues.length} stale issue(s). Dispatching review.`);
|
|
171
|
+
await github.rest.actions.createWorkflowDispatch({
|
|
172
|
+
owner, repo,
|
|
173
|
+
workflow_id: 'agent-flow-review.yml',
|
|
174
|
+
ref: 'main',
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
} catch (err) {
|
|
178
|
+
core.warning(`Stale issue check failed: ${err.message}`);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// ─── 5. Stale conflicting PRs → remove automerge label ────────────────
|
|
182
|
+
|
|
183
|
+
try {
|
|
184
|
+
const { data: openPRs } = await github.rest.pulls.list({
|
|
185
|
+
owner, repo, state: 'open',
|
|
186
|
+
sort: 'updated',
|
|
187
|
+
direction: 'asc',
|
|
188
|
+
per_page: 10,
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
const prCutoff = new Date(Date.now() - stalePrDays * 24 * 60 * 60 * 1000);
|
|
192
|
+
for (const pr of openPRs) {
|
|
193
|
+
const hasAutomerge = pr.labels.some(l => l.name === 'automerge');
|
|
194
|
+
if (!hasAutomerge) continue;
|
|
195
|
+
|
|
196
|
+
const isStale = new Date(pr.updated_at) < prCutoff;
|
|
197
|
+
if (!isStale) continue;
|
|
198
|
+
|
|
199
|
+
// Fetch full PR to get mergeable_state
|
|
200
|
+
const { data: fullPr } = await github.rest.pulls.get({
|
|
201
|
+
owner, repo, pull_number: pr.number,
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
if (fullPr.mergeable_state === 'dirty' || fullPr.mergeable === false) {
|
|
205
|
+
core.info(`PR #${pr.number} has conflicts and is stale (${stalePrDays}+ days). Removing automerge label.`);
|
|
206
|
+
try {
|
|
207
|
+
await github.rest.issues.removeLabel({
|
|
208
|
+
owner, repo, issue_number: pr.number, name: 'automerge',
|
|
209
|
+
});
|
|
210
|
+
} catch (e) { /* label may not exist */ }
|
|
211
|
+
await github.rest.issues.createComment({
|
|
212
|
+
owner, repo, issue_number: pr.number,
|
|
213
|
+
body: `Supervisor: this PR has had conflicts for ${stalePrDays}+ days. Removing automerge label — resolve conflicts and re-add to retry.`,
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
} catch (err) {
|
|
218
|
+
core.warning(`Stale PR check failed: ${err.message}`);
|
|
85
219
|
}
|
|
@@ -12,6 +12,11 @@ run-name: "ci-automerge [${{ github.ref_name }}]"
|
|
|
12
12
|
on:
|
|
13
13
|
pull_request:
|
|
14
14
|
check_suite:
|
|
15
|
+
workflow_run:
|
|
16
|
+
workflows:
|
|
17
|
+
- test
|
|
18
|
+
types:
|
|
19
|
+
- completed
|
|
15
20
|
workflow_dispatch:
|
|
16
21
|
workflow_call:
|
|
17
22
|
inputs:
|
|
@@ -148,7 +153,12 @@ jobs:
|
|
|
148
153
|
|
|
149
154
|
ls:
|
|
150
155
|
needs: label
|
|
151
|
-
if:
|
|
156
|
+
if: >-
|
|
157
|
+
github.event_name == 'schedule' ||
|
|
158
|
+
github.event_name == 'workflow_dispatch' ||
|
|
159
|
+
github.event_name == 'workflow_run' ||
|
|
160
|
+
inputs.workflow == 'true' ||
|
|
161
|
+
github.event_name == 'workflow_call'
|
|
152
162
|
runs-on: ubuntu-latest
|
|
153
163
|
steps:
|
|
154
164
|
- name: Determine pull request number
|
|
@@ -346,18 +356,21 @@ jobs:
|
|
|
346
356
|
message = `Branch '${pullRequest.head.ref}' deleted.`;
|
|
347
357
|
prMerged = 'true';
|
|
348
358
|
} else if (pullRequest.mergeable_state === 'dirty' || pullRequest.mergeable === false) {
|
|
349
|
-
message = `PR #${pullNumber} has conflicts.
|
|
359
|
+
message = `PR #${pullNumber} has conflicts. Removing automerge label.`;
|
|
360
|
+
try {
|
|
361
|
+
await github.rest.issues.removeLabel({
|
|
362
|
+
owner, repo, issue_number: pullNumber, name: 'automerge',
|
|
363
|
+
});
|
|
364
|
+
} catch (e) {
|
|
365
|
+
core.info(`Could not remove automerge label: ${e.message}`);
|
|
366
|
+
}
|
|
350
367
|
await github.rest.issues.createComment({
|
|
351
368
|
owner, repo, issue_number: pullNumber,
|
|
352
|
-
body: `
|
|
369
|
+
body: `Automerge label removed — this PR has conflicts (mergeable_state: ${pullRequest.mergeable_state}). Resolve conflicts and re-add the label to retry.`,
|
|
353
370
|
});
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
message += ` Branch '${pullRequest.head.ref}' deleted.`;
|
|
358
|
-
} catch (error) {
|
|
359
|
-
message += ` Failed to delete branch: ${error.message}`;
|
|
360
|
-
}
|
|
371
|
+
prMerged = 'false';
|
|
372
|
+
} else if (pullRequest.mergeable_state === 'unstable') {
|
|
373
|
+
message = `PR #${pullNumber} checks still running (mergeable_state: unstable). Will retry when test workflow completes.`;
|
|
361
374
|
prMerged = 'false';
|
|
362
375
|
} else if (pullRequest.mergeable === null) {
|
|
363
376
|
message = `PR #${pullNumber} does not yet have a value for mergeability.`;
|