@xn-intenton-z2a/agentic-lib 7.1.51 → 7.1.53
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/bin/agentic-lib.js +20 -10
- package/package.json +1 -1
- package/src/actions/agentic-step/tasks/supervise.js +12 -13
- package/src/agents/agent-supervisor.md +11 -12
- package/src/seeds/{init.yml → agentic-lib-init.yml} +73 -36
- package/src/seeds/{test.yml → agentic-lib-test.yml} +6 -7
- package/src/seeds/zero-package.json +1 -1
- package/src/workflows/{agent-discussions-bot.yml → agentic-lib-bot.yml} +8 -6
- package/src/workflows/{agent-supervisor-schedule.yml → agentic-lib-schedule.yml} +14 -36
- package/src/workflows/agentic-lib-workflow.yml +708 -0
- package/src/workflows/agent-flow-fix-code.yml +0 -123
- package/src/workflows/agent-flow-maintain.yml +0 -115
- package/src/workflows/agent-flow-review.yml +0 -108
- package/src/workflows/agent-flow-transform.yml +0 -201
- package/src/workflows/agent-supervisor.yml +0 -266
- package/src/workflows/ci-automerge.yml +0 -457
package/bin/agentic-lib.js
CHANGED
|
@@ -664,15 +664,23 @@ function initWorkflows() {
|
|
|
664
664
|
initCopyFile(resolve(workflowsDir, f), resolve(target, ".github/workflows", f), `workflows/${f}`);
|
|
665
665
|
}
|
|
666
666
|
}
|
|
667
|
-
const seedTest = resolve(srcDir, "seeds/test.yml");
|
|
667
|
+
const seedTest = resolve(srcDir, "seeds/agentic-lib-test.yml");
|
|
668
668
|
if (existsSync(seedTest)) {
|
|
669
|
-
templateWorkflows.add("test.yml");
|
|
670
|
-
initCopyFile(
|
|
669
|
+
templateWorkflows.add("agentic-lib-test.yml");
|
|
670
|
+
initCopyFile(
|
|
671
|
+
seedTest,
|
|
672
|
+
resolve(target, ".github/workflows/agentic-lib-test.yml"),
|
|
673
|
+
"workflows/agentic-lib-test.yml (from seeds)",
|
|
674
|
+
);
|
|
671
675
|
}
|
|
672
|
-
const seedInit = resolve(srcDir, "seeds/init.yml");
|
|
676
|
+
const seedInit = resolve(srcDir, "seeds/agentic-lib-init.yml");
|
|
673
677
|
if (existsSync(seedInit)) {
|
|
674
|
-
templateWorkflows.add("init.yml");
|
|
675
|
-
initCopyFile(
|
|
678
|
+
templateWorkflows.add("agentic-lib-init.yml");
|
|
679
|
+
initCopyFile(
|
|
680
|
+
seedInit,
|
|
681
|
+
resolve(target, ".github/workflows/agentic-lib-init.yml"),
|
|
682
|
+
"workflows/agentic-lib-init.yml (from seeds)",
|
|
683
|
+
);
|
|
676
684
|
}
|
|
677
685
|
removeStaleWorkflows(templateWorkflows);
|
|
678
686
|
}
|
|
@@ -911,10 +919,12 @@ function initPurgeGitHub() {
|
|
|
911
919
|
|
|
912
920
|
// Close all open issues
|
|
913
921
|
try {
|
|
914
|
-
const issuesJson = execSync(
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
922
|
+
const issuesJson = execSync(`gh issue list --repo ${repoSlug} --state open --json number,title --limit 100`, {
|
|
923
|
+
cwd: target,
|
|
924
|
+
encoding: "utf8",
|
|
925
|
+
timeout: 30000,
|
|
926
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
927
|
+
});
|
|
918
928
|
const issues = JSON.parse(issuesJson || "[]");
|
|
919
929
|
if (issues.length === 0) {
|
|
920
930
|
console.log(" No open issues to close");
|
package/package.json
CHANGED
|
@@ -130,12 +130,11 @@ function buildPrompt(ctx, agentInstructions) {
|
|
|
130
130
|
"Pick one or more actions. Output them in the format below.",
|
|
131
131
|
"",
|
|
132
132
|
"### Workflow Dispatches",
|
|
133
|
-
"- `dispatch:
|
|
134
|
-
"- `dispatch:
|
|
135
|
-
"- `dispatch:
|
|
136
|
-
"- `dispatch:
|
|
137
|
-
"- `dispatch:
|
|
138
|
-
"- `dispatch:ci-automerge` — Merge open PRs with the automerge label if checks pass",
|
|
133
|
+
"- `dispatch:agentic-lib-workflow | mode: dev-only | issue-number: <N>` — Pick up issue #N, generate code, open PR. Always specify the issue-number of the oldest ready issue.",
|
|
134
|
+
"- `dispatch:agentic-lib-workflow | mode: maintain-only` — Refresh feature definitions and library docs",
|
|
135
|
+
"- `dispatch:agentic-lib-workflow | mode: review-only` — Close resolved issues, enhance issue criteria",
|
|
136
|
+
"- `dispatch:agentic-lib-workflow | mode: pr-cleanup-only` — Merge open PRs with the automerge label if checks pass",
|
|
137
|
+
"- `dispatch:agentic-lib-bot` — Proactively post in discussions",
|
|
139
138
|
"",
|
|
140
139
|
"### GitHub API Actions",
|
|
141
140
|
"- `github:create-issue | title: <text> | labels: <comma-separated>` — Create a new issue",
|
|
@@ -197,20 +196,20 @@ async function executeDispatch(octokit, repo, actionName, params) {
|
|
|
197
196
|
if (params["issue-number"]) inputs["issue-number"] = params["issue-number"];
|
|
198
197
|
|
|
199
198
|
// Guard: skip transform dispatch if one is already running
|
|
200
|
-
if (workflowFile === "
|
|
199
|
+
if (workflowFile === "agentic-lib-workflow.yml") {
|
|
201
200
|
try {
|
|
202
201
|
const { data: runs } = await octokit.rest.actions.listWorkflowRuns({
|
|
203
202
|
...repo,
|
|
204
|
-
workflow_id: "
|
|
203
|
+
workflow_id: "agentic-lib-workflow.yml",
|
|
205
204
|
status: "in_progress",
|
|
206
205
|
per_page: 1,
|
|
207
206
|
});
|
|
208
207
|
if (runs.total_count > 0) {
|
|
209
|
-
core.info("
|
|
210
|
-
return "skipped:
|
|
208
|
+
core.info("Workflow already running — skipping dispatch");
|
|
209
|
+
return "skipped:workflow-already-running";
|
|
211
210
|
}
|
|
212
211
|
} catch (err) {
|
|
213
|
-
core.warning(`Could not check
|
|
212
|
+
core.warning(`Could not check workflow status: ${err.message}`);
|
|
214
213
|
}
|
|
215
214
|
}
|
|
216
215
|
|
|
@@ -257,7 +256,7 @@ async function executeRespondDiscussions(octokit, repo, params) {
|
|
|
257
256
|
if (url) inputs["discussion-url"] = url;
|
|
258
257
|
await octokit.rest.actions.createWorkflowDispatch({
|
|
259
258
|
...repo,
|
|
260
|
-
workflow_id: "
|
|
259
|
+
workflow_id: "agentic-lib-bot.yml",
|
|
261
260
|
ref: "main",
|
|
262
261
|
inputs,
|
|
263
262
|
});
|
|
@@ -281,7 +280,7 @@ async function executeSetSchedule(octokit, repo, frequency) {
|
|
|
281
280
|
core.info(`Setting supervisor schedule to: ${frequency}`);
|
|
282
281
|
await octokit.rest.actions.createWorkflowDispatch({
|
|
283
282
|
...repo,
|
|
284
|
-
workflow_id: "
|
|
283
|
+
workflow_id: "agentic-lib-schedule.yml",
|
|
285
284
|
ref: "main",
|
|
286
285
|
inputs: { frequency },
|
|
287
286
|
});
|
|
@@ -10,24 +10,23 @@ You are the supervisor of an autonomous coding repository. Your job is to advanc
|
|
|
10
10
|
|
|
11
11
|
## Decision Framework
|
|
12
12
|
|
|
13
|
-
1. **Check what's already in progress** — don't duplicate work. If
|
|
14
|
-
2. **Prioritise code generation** — the goal is working code. Prefer actions that produce code (
|
|
13
|
+
1. **Check what's already in progress** — don't duplicate work. If the workflow is already running, don't dispatch another.
|
|
14
|
+
2. **Prioritise code generation** — the goal is working code. Prefer actions that produce code (dev-only, fix) over metadata (maintain, label).
|
|
15
15
|
3. **Keep the issue pipeline full** — the biggest bottleneck is running out of open issues. Proactively create issues when capacity allows.
|
|
16
16
|
4. **Respect limits** — don't create issues beyond the WIP limit shown in the context. Don't dispatch workflows that will fail due to missing prerequisites.
|
|
17
17
|
|
|
18
18
|
## When to use each action
|
|
19
19
|
|
|
20
20
|
- **github:create-issue** — When open issues < WIP limit. Derive the issue title from unimplemented features or mission goals. Always include relevant labels (`automated`, `enhancement`).
|
|
21
|
-
- **dispatch:
|
|
22
|
-
- **dispatch:
|
|
23
|
-
- **dispatch:
|
|
24
|
-
- **dispatch:
|
|
25
|
-
- **dispatch:
|
|
26
|
-
- **dispatch:ci-automerge** — When open PRs with the `automerge` label appear ready to merge but no merge activity shows in recent runs. Recovery action — ci-automerge normally fires on event triggers.
|
|
21
|
+
- **dispatch:agentic-lib-workflow | mode: dev-only | issue-number: \<N\>** — When there are open issues with the `ready` label and no workflow is currently running.
|
|
22
|
+
- **dispatch:agentic-lib-workflow | mode: review-only** — After observing a recent transform completion, or when there are unenhanced issues needing the `ready` label.
|
|
23
|
+
- **dispatch:agentic-lib-workflow | mode: maintain-only** — When features are below their limit AND no maintain appears in the last 3 workflow runs.
|
|
24
|
+
- **dispatch:agentic-lib-workflow | mode: pr-cleanup-only** — When open PRs with the `automerge` label appear ready to merge but no merge activity shows in recent runs.
|
|
25
|
+
- **dispatch:agentic-lib-bot** — When you want to proactively engage in discussions or respond to a user request.
|
|
27
26
|
- **github:label-issue** — When an issue needs better categorisation for prioritisation.
|
|
28
27
|
- **github:close-issue** — When an issue is clearly resolved or no longer relevant.
|
|
29
28
|
- **respond:discussions** — When replying to a user request that came through the discussions bot. Include the discussion URL and a clear message.
|
|
30
|
-
- **set-schedule:\<frequency\>** — Change the
|
|
29
|
+
- **set-schedule:\<frequency\>** — Change the workflow schedule. Use `weekly` when mission is substantially achieved, `continuous` to ramp up for active development.
|
|
31
30
|
- **nop** — When everything is running optimally: transform is active, issues are flowing, no failures.
|
|
32
31
|
|
|
33
32
|
## Stale Issue Detection
|
|
@@ -48,8 +47,8 @@ When ALL of the following conditions are met, the mission is accomplished:
|
|
|
48
47
|
4. Evidence artifacts exist under `docs/` (example outputs, test results, or walkthroughs)
|
|
49
48
|
|
|
50
49
|
When all conditions are met:
|
|
51
|
-
1. `dispatch:
|
|
52
|
-
2. `set-schedule:off` — stop the
|
|
50
|
+
1. `dispatch:agentic-lib-bot` — announce mission accomplished in the discussions thread
|
|
51
|
+
2. `set-schedule:off` — stop the workflow. The mission is done.
|
|
53
52
|
3. Log `mission-accomplished` in the activity log.
|
|
54
53
|
|
|
55
54
|
### Ongoing Missions
|
|
@@ -60,7 +59,7 @@ Never use `set-schedule:off` for ongoing missions.
|
|
|
60
59
|
### Mission Substantially Complete (bounded, but minor gaps)
|
|
61
60
|
When the transform agent has implemented all major features but minor polish remains
|
|
62
61
|
(e.g. missing README examples, incomplete edge case coverage):
|
|
63
|
-
1. `dispatch:
|
|
62
|
+
1. `dispatch:agentic-lib-bot` — announce near-completion in the discussions thread
|
|
64
63
|
2. `set-schedule:weekly` — reduce to weekly maintenance check-ins
|
|
65
64
|
3. Check that `docs/` contains evidence of the library working before declaring done
|
|
66
65
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
|
2
2
|
# Copyright (C) 2025-2026 Polycode Limited
|
|
3
|
-
# .github/workflows/init.yml
|
|
3
|
+
# .github/workflows/agentic-lib-init.yml
|
|
4
4
|
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
5
|
+
# Self-contained init: update agentic-lib, purge, push to main [skip ci].
|
|
6
|
+
# Does NOT create a PR. Does NOT trigger any other workflow.
|
|
7
|
+
# Closes hanging init PRs before running.
|
|
8
8
|
|
|
9
|
-
name: init
|
|
10
|
-
run-name: "init [${{ github.ref_name }}]"
|
|
9
|
+
name: agentic-lib-init
|
|
10
|
+
run-name: "agentic-lib-init [${{ github.ref_name }}]"
|
|
11
11
|
|
|
12
12
|
on:
|
|
13
13
|
schedule:
|
|
@@ -114,17 +114,25 @@ jobs:
|
|
|
114
114
|
steps:
|
|
115
115
|
- uses: actions/checkout@v4
|
|
116
116
|
with:
|
|
117
|
+
ref: main
|
|
117
118
|
token: ${{ secrets.WORKFLOW_TOKEN }}
|
|
118
119
|
|
|
119
120
|
- uses: actions/setup-node@v4
|
|
120
121
|
with:
|
|
121
122
|
node-version: "24"
|
|
122
123
|
|
|
123
|
-
- name:
|
|
124
|
+
- name: Close hanging init PRs
|
|
125
|
+
if: env.INIT_MODE == 'purge'
|
|
126
|
+
env:
|
|
127
|
+
GH_TOKEN: ${{ secrets.WORKFLOW_TOKEN }}
|
|
124
128
|
run: |
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
129
|
+
# Close any open PRs from previous init runs
|
|
130
|
+
gh pr list --state open --json number,headRefName \
|
|
131
|
+
--jq '.[] | select(.headRefName | startswith("agentic-lib-init-")) | .number' \
|
|
132
|
+
| while read -r pr_num; do
|
|
133
|
+
echo "Closing hanging init PR #${pr_num}"
|
|
134
|
+
gh pr close "$pr_num" --delete-branch || true
|
|
135
|
+
done
|
|
128
136
|
|
|
129
137
|
- name: Update agentic-lib to latest
|
|
130
138
|
run: npm update @xn-intenton-z2a/agentic-lib
|
|
@@ -152,11 +160,62 @@ jobs:
|
|
|
152
160
|
|
|
153
161
|
- run: npm test
|
|
154
162
|
|
|
155
|
-
- name:
|
|
163
|
+
- name: Update schedule (if requested)
|
|
164
|
+
if: needs.params.outputs.schedule != ''
|
|
165
|
+
uses: actions/github-script@v7
|
|
166
|
+
with:
|
|
167
|
+
script: |
|
|
168
|
+
const fs = require('fs');
|
|
169
|
+
const frequency = '${{ needs.params.outputs.schedule }}';
|
|
170
|
+
const model = '${{ needs.params.outputs.model || 'gpt-5-mini' }}';
|
|
171
|
+
const workflowPath = '.github/workflows/agentic-lib-workflow.yml';
|
|
172
|
+
const tomlPath = 'agentic-lib.toml';
|
|
173
|
+
|
|
174
|
+
const SCHEDULE_MAP = {
|
|
175
|
+
off: null,
|
|
176
|
+
weekly: '0 6 * * 1',
|
|
177
|
+
daily: '0 6 * * *',
|
|
178
|
+
hourly: '0 * * * *',
|
|
179
|
+
continuous: '*/15 * * * *',
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
if (fs.existsSync(workflowPath)) {
|
|
183
|
+
let content = fs.readFileSync(workflowPath, 'utf8');
|
|
184
|
+
const cron = SCHEDULE_MAP[frequency];
|
|
185
|
+
content = content.replace(/\n schedule:\n - cron: "[^"]*"\n/g, '\n');
|
|
186
|
+
if (cron) {
|
|
187
|
+
const scheduleBlock = `\n schedule:\n - cron: "${cron}"\n`;
|
|
188
|
+
content = content.replace(/\non:\n/, `\non:${scheduleBlock}`);
|
|
189
|
+
}
|
|
190
|
+
const dateStamp = `# Schedule updated: ${new Date().toISOString()}`;
|
|
191
|
+
const stampRegex = /^# Schedule updated: .*/m;
|
|
192
|
+
if (stampRegex.test(content)) {
|
|
193
|
+
content = content.replace(stampRegex, dateStamp);
|
|
194
|
+
} else {
|
|
195
|
+
content = content.replace(/^(# .*\n)+/m, (match) => match + dateStamp + '\n');
|
|
196
|
+
}
|
|
197
|
+
fs.writeFileSync(workflowPath, content);
|
|
198
|
+
core.info(`Updated schedule to: ${frequency}`);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (fs.existsSync(tomlPath)) {
|
|
202
|
+
let toml = fs.readFileSync(tomlPath, 'utf8');
|
|
203
|
+
const scheduleModelRegex = /(\[schedule\][^\[]*?)(^\s*model\s*=\s*"[^"]*")/m;
|
|
204
|
+
if (scheduleModelRegex.test(toml)) {
|
|
205
|
+
toml = toml.replace(scheduleModelRegex, `$1model = "${model}"`);
|
|
206
|
+
}
|
|
207
|
+
const scheduleSupervisorRegex = /(\[schedule\][^\[]*?)(^\s*supervisor\s*=\s*"[^"]*")/m;
|
|
208
|
+
if (scheduleSupervisorRegex.test(toml)) {
|
|
209
|
+
toml = toml.replace(scheduleSupervisorRegex, `$1supervisor = "${frequency}"`);
|
|
210
|
+
}
|
|
211
|
+
fs.writeFileSync(tomlPath, toml);
|
|
212
|
+
core.info(`Updated agentic-lib.toml: model=${model}, supervisor=${frequency}`);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
- name: Commit and push to main [skip ci]
|
|
156
216
|
env:
|
|
157
217
|
GH_TOKEN: ${{ secrets.WORKFLOW_TOKEN }}
|
|
158
218
|
run: |
|
|
159
|
-
# Use the WORKFLOW_TOKEN owner's identity so GitHub re-registers cron schedules
|
|
160
219
|
TOKEN_USER=$(gh api /user --jq '.login')
|
|
161
220
|
TOKEN_ID=$(gh api /user --jq '.id')
|
|
162
221
|
git config user.name "${TOKEN_USER}"
|
|
@@ -164,27 +223,5 @@ jobs:
|
|
|
164
223
|
git add -A
|
|
165
224
|
git diff --cached --quiet && echo "No changes" && exit 0
|
|
166
225
|
VERSION=$(npx @xn-intenton-z2a/agentic-lib version 2>/dev/null || echo "latest")
|
|
167
|
-
git commit -m "init ${INIT_MODE} (agentic-lib@${VERSION})"
|
|
168
|
-
git push origin
|
|
169
|
-
|
|
170
|
-
- name: Create PR
|
|
171
|
-
if: success()
|
|
172
|
-
env:
|
|
173
|
-
GITHUB_TOKEN: ${{ secrets.WORKFLOW_TOKEN }}
|
|
174
|
-
run: |
|
|
175
|
-
gh pr create \
|
|
176
|
-
--title "init ${INIT_MODE} ($(date -u +%Y-%m-%d))" \
|
|
177
|
-
--body "Nightly init ${INIT_MODE}. Auto-labelled for automerge." \
|
|
178
|
-
--label automerge \
|
|
179
|
-
--base main \
|
|
180
|
-
--head "$BRANCH"
|
|
181
|
-
|
|
182
|
-
# Configure schedule after init completes (if schedule parameter provided)
|
|
183
|
-
configure-schedule:
|
|
184
|
-
needs: [params, init]
|
|
185
|
-
if: needs.params.outputs.schedule != ''
|
|
186
|
-
uses: ./.github/workflows/agent-supervisor-schedule.yml
|
|
187
|
-
with:
|
|
188
|
-
frequency: ${{ needs.params.outputs.schedule }}
|
|
189
|
-
model: ${{ needs.params.outputs.model }}
|
|
190
|
-
secrets: inherit
|
|
226
|
+
git commit -m "init ${INIT_MODE} (agentic-lib@${VERSION}) [skip ci]"
|
|
227
|
+
git push origin main
|
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
|
2
2
|
# Copyright (C) 2025-2026 Polycode Limited
|
|
3
|
-
# .github/workflows/test.yml
|
|
3
|
+
# .github/workflows/agentic-lib-test.yml
|
|
4
4
|
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
# This file is part of the example suite for `agentic-lib` see: https://github.com/xn-intenton-z2a/agentic-lib
|
|
8
|
-
# This file is licensed under the MIT License. For details, see LICENSE-MIT
|
|
5
|
+
# Test workflow seeded by agentic-lib init.
|
|
6
|
+
# Also callable via workflow_call from the main pipeline.
|
|
9
7
|
|
|
10
|
-
name: test
|
|
11
|
-
run-name: "test [${{ github.ref_name }}]"
|
|
8
|
+
name: agentic-lib-test
|
|
9
|
+
run-name: "agentic-lib-test [${{ github.ref_name }}]"
|
|
12
10
|
|
|
13
11
|
on:
|
|
14
12
|
push:
|
|
15
13
|
branches: [main]
|
|
16
14
|
pull_request:
|
|
17
15
|
branches: [main]
|
|
16
|
+
workflow_call:
|
|
18
17
|
workflow_dispatch:
|
|
19
18
|
|
|
20
19
|
jobs:
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
|
2
2
|
# Copyright (C) 2025-2026 Polycode Limited
|
|
3
|
-
# .github/workflows/
|
|
3
|
+
# .github/workflows/agentic-lib-bot.yml
|
|
4
4
|
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
5
|
+
# Discussions bot: responds to GitHub Discussions using the Copilot SDK.
|
|
6
|
+
# Checks thread + repo context, responds, and can escalate to the main
|
|
7
|
+
# workflow by dispatching agentic-lib-workflow.yml with a message parameter.
|
|
7
8
|
|
|
8
|
-
name:
|
|
9
|
-
run-name: "
|
|
9
|
+
name: agentic-lib-bot
|
|
10
|
+
run-name: "agentic-lib-bot [${{ github.ref_name }}]"
|
|
10
11
|
concurrency:
|
|
11
12
|
group: agentic-lib-bot-${{ github.event.discussion.node_id || github.run_id }}
|
|
12
13
|
cancel-in-progress: false
|
|
@@ -25,7 +26,7 @@ on:
|
|
|
25
26
|
workflow_dispatch:
|
|
26
27
|
inputs:
|
|
27
28
|
discussion-url:
|
|
28
|
-
description: "Discussion URL to respond to
|
|
29
|
+
description: "Discussion URL to respond to"
|
|
29
30
|
type: string
|
|
30
31
|
required: false
|
|
31
32
|
default: ""
|
|
@@ -43,6 +44,7 @@ permissions:
|
|
|
43
44
|
contents: read
|
|
44
45
|
issues: write
|
|
45
46
|
discussions: write
|
|
47
|
+
actions: write
|
|
46
48
|
|
|
47
49
|
env:
|
|
48
50
|
configPath: ".github/agentic-lib/agents/agentic-lib.yml"
|
|
@@ -1,20 +1,18 @@
|
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
|
2
2
|
# Copyright (C) 2025-2026 Polycode Limited
|
|
3
|
-
# .github/workflows/
|
|
3
|
+
# .github/workflows/agentic-lib-schedule.yml
|
|
4
4
|
#
|
|
5
|
-
# Changes the
|
|
5
|
+
# Changes the agentic-lib-workflow's cron schedule by editing the workflow file
|
|
6
6
|
# directly and pushing to main. Also updates the model setting in agentic-lib.toml.
|
|
7
|
-
# This is the control plane for how often the supervisor runs proactively
|
|
8
|
-
# and which LLM model is used.
|
|
9
7
|
|
|
10
|
-
name:
|
|
11
|
-
run-name: "
|
|
8
|
+
name: agentic-lib-schedule
|
|
9
|
+
run-name: "agentic-lib-schedule -> ${{ inputs.frequency }} (${{ inputs.model }})"
|
|
12
10
|
|
|
13
11
|
on:
|
|
14
12
|
workflow_call:
|
|
15
13
|
inputs:
|
|
16
14
|
frequency:
|
|
17
|
-
description: "How often the
|
|
15
|
+
description: "How often the workflow should run"
|
|
18
16
|
required: true
|
|
19
17
|
type: string
|
|
20
18
|
model:
|
|
@@ -25,7 +23,7 @@ on:
|
|
|
25
23
|
workflow_dispatch:
|
|
26
24
|
inputs:
|
|
27
25
|
frequency:
|
|
28
|
-
description: "How often the
|
|
26
|
+
description: "How often the workflow should run"
|
|
29
27
|
required: true
|
|
30
28
|
type: choice
|
|
31
29
|
options:
|
|
@@ -56,14 +54,14 @@ jobs:
|
|
|
56
54
|
ref: main
|
|
57
55
|
token: ${{ secrets.WORKFLOW_TOKEN }}
|
|
58
56
|
|
|
59
|
-
- name: Update
|
|
57
|
+
- name: Update workflow schedule and model
|
|
60
58
|
uses: actions/github-script@v7
|
|
61
59
|
with:
|
|
62
60
|
script: |
|
|
63
61
|
const fs = require('fs');
|
|
64
62
|
const frequency = '${{ inputs.frequency }}';
|
|
65
63
|
const model = '${{ inputs.model || 'gpt-5-mini' }}';
|
|
66
|
-
const workflowPath = '.github/workflows/
|
|
64
|
+
const workflowPath = '.github/workflows/agentic-lib-workflow.yml';
|
|
67
65
|
const tomlPath = 'agentic-lib.toml';
|
|
68
66
|
|
|
69
67
|
const SCHEDULE_MAP = {
|
|
@@ -74,34 +72,28 @@ jobs:
|
|
|
74
72
|
continuous: '*/15 * * * *',
|
|
75
73
|
};
|
|
76
74
|
|
|
77
|
-
// Update
|
|
75
|
+
// Update agentic-lib-workflow.yml schedule
|
|
78
76
|
let content = fs.readFileSync(workflowPath, 'utf8');
|
|
79
77
|
const cron = SCHEDULE_MAP[frequency];
|
|
80
78
|
|
|
81
|
-
// Remove any existing schedule block
|
|
82
|
-
// The schedule block looks like:
|
|
83
|
-
// schedule:
|
|
84
|
-
// - cron: "..."
|
|
79
|
+
// Remove any existing schedule block
|
|
85
80
|
content = content.replace(/\n schedule:\n - cron: "[^"]*"\n/g, '\n');
|
|
86
81
|
|
|
87
82
|
if (cron) {
|
|
88
83
|
// Insert schedule block after the 'on:' line
|
|
89
84
|
const scheduleBlock = `\n schedule:\n - cron: "${cron}"\n`;
|
|
90
|
-
// Insert before workflow_run or workflow_dispatch (whichever comes first after 'on:')
|
|
91
85
|
content = content.replace(
|
|
92
86
|
/\non:\n/,
|
|
93
87
|
`\non:${scheduleBlock}`
|
|
94
88
|
);
|
|
95
89
|
}
|
|
96
90
|
|
|
97
|
-
//
|
|
98
|
-
// (GitHub re-registers cron schedules on push)
|
|
91
|
+
// Stamp the file with current date so the commit is never empty
|
|
99
92
|
const dateStamp = `# Schedule updated: ${new Date().toISOString()}`;
|
|
100
93
|
const stampRegex = /^# Schedule updated: .*/m;
|
|
101
94
|
if (stampRegex.test(content)) {
|
|
102
95
|
content = content.replace(stampRegex, dateStamp);
|
|
103
96
|
} else {
|
|
104
|
-
// Insert after the header comment block
|
|
105
97
|
content = content.replace(
|
|
106
98
|
/^(# .*\n)+/m,
|
|
107
99
|
(match) => match + dateStamp + '\n'
|
|
@@ -109,31 +101,24 @@ jobs:
|
|
|
109
101
|
}
|
|
110
102
|
|
|
111
103
|
fs.writeFileSync(workflowPath, content);
|
|
112
|
-
core.info(`Updated
|
|
104
|
+
core.info(`Updated workflow schedule to: ${frequency} (cron: ${cron || 'none'})`);
|
|
113
105
|
|
|
114
106
|
// Update agentic-lib.toml with model and supervisor settings
|
|
115
107
|
if (fs.existsSync(tomlPath)) {
|
|
116
108
|
let toml = fs.readFileSync(tomlPath, 'utf8');
|
|
117
109
|
|
|
118
|
-
// Update model setting within [schedule] section
|
|
119
|
-
// Match model line that appears after [schedule] but before any other section
|
|
120
|
-
// Allow optional leading whitespace for robustness
|
|
121
110
|
const scheduleModelRegex = /(\[schedule\][^\[]*?)(^\s*model\s*=\s*"[^"]*")/m;
|
|
122
111
|
if (scheduleModelRegex.test(toml)) {
|
|
123
|
-
// Model exists in schedule section - update it
|
|
124
112
|
toml = toml.replace(scheduleModelRegex, `$1model = "${model}"`);
|
|
125
113
|
} else if (toml.match(/^\[schedule\]/m)) {
|
|
126
|
-
// No model in schedule section - add it after supervisor line (or after section header)
|
|
127
114
|
const supervisorLineRegex = /^(\s*supervisor\s*=\s*"[^"]*")(\s*#.*)?$/m;
|
|
128
115
|
if (supervisorLineRegex.test(toml)) {
|
|
129
116
|
toml = toml.replace(supervisorLineRegex, `$1$2\nmodel = "${model}"`);
|
|
130
117
|
} else {
|
|
131
|
-
// Add after [schedule] header (handle optional trailing content)
|
|
132
118
|
toml = toml.replace(/^(\[schedule\].*)$/m, `$1\nmodel = "${model}"`);
|
|
133
119
|
}
|
|
134
120
|
}
|
|
135
121
|
|
|
136
|
-
// Update supervisor setting within [schedule] section
|
|
137
122
|
const scheduleSupervisorRegex = /(\[schedule\][^\[]*?)(^\s*supervisor\s*=\s*"[^"]*")/m;
|
|
138
123
|
if (scheduleSupervisorRegex.test(toml)) {
|
|
139
124
|
toml = toml.replace(scheduleSupervisorRegex, `$1supervisor = "${frequency}"`);
|
|
@@ -149,20 +134,13 @@ jobs:
|
|
|
149
134
|
env:
|
|
150
135
|
GH_TOKEN: ${{ secrets.WORKFLOW_TOKEN }}
|
|
151
136
|
run: |
|
|
152
|
-
# Use the WORKFLOW_TOKEN owner's identity so GitHub re-registers cron schedules
|
|
153
137
|
TOKEN_USER=$(gh api /user --jq '.login')
|
|
154
138
|
TOKEN_ID=$(gh api /user --jq '.id')
|
|
155
139
|
git config user.name "${TOKEN_USER}"
|
|
156
140
|
git config user.email "${TOKEN_ID}+${TOKEN_USER}@users.noreply.github.com"
|
|
157
141
|
FREQUENCY="${{ inputs.frequency }}"
|
|
158
142
|
MODEL="${{ inputs.model }}"
|
|
159
|
-
git add .github/workflows/
|
|
143
|
+
git add .github/workflows/agentic-lib-workflow.yml agentic-lib.toml
|
|
160
144
|
git diff --cached --quiet && echo "No changes to commit" && exit 0
|
|
161
|
-
git commit -m "
|
|
145
|
+
git commit -m "schedule: set to ${FREQUENCY}, model ${MODEL:-gpt-5-mini}"
|
|
162
146
|
git push origin main
|
|
163
|
-
|
|
164
|
-
- name: Dispatch supervisor
|
|
165
|
-
if: inputs.frequency != 'off'
|
|
166
|
-
env:
|
|
167
|
-
GH_TOKEN: ${{ secrets.WORKFLOW_TOKEN }}
|
|
168
|
-
run: gh workflow run agent-supervisor.yml --repo $GITHUB_REPOSITORY
|