@xn-intenton-z2a/agentic-lib 7.1.40 → 7.1.42

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/README.md CHANGED
@@ -157,7 +157,6 @@ Configuration lives in `agentic-lib.toml` at your project root:
157
157
 
158
158
  ```toml
159
159
  [schedule]
160
- tier = "schedule-1" # schedule-1 through schedule-4
161
160
  supervisor = "daily" # off | weekly | daily | hourly | continuous
162
161
 
163
162
  [paths]
@@ -134,7 +134,7 @@ async function runTask(taskName) {
134
134
  const writablePaths = getWritablePathsFromConfig(config);
135
135
  const readOnlyPaths = getReadOnlyPathsFromConfig(config);
136
136
 
137
- console.log(`[config] schedule=${config.schedule}`);
137
+ console.log(`[config] supervisor=${config.supervisor || "daily"}`);
138
138
  console.log(`[config] writable=${writablePaths.join(", ")}`);
139
139
  console.log(`[config] test=${config.testScript}`);
140
140
  console.log("");
@@ -241,7 +241,6 @@ async function loadTaskConfig() {
241
241
  const { parse } = await import("smol-toml");
242
242
  const toml = parse(readFileSync(tomlPath, "utf8"));
243
243
  return {
244
- schedule: toml.schedule?.tier || "schedule-1",
245
244
  missionPath: toml.paths?.mission || "MISSION.md",
246
245
  sourcePath: toml.paths?.source || "src/lib/",
247
246
  testsPath: toml.paths?.tests || "tests/unit/",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xn-intenton-z2a/agentic-lib",
3
- "version": "7.1.40",
3
+ "version": "7.1.42",
4
4
  "description": "Agentic-lib Agentic Coding Systems SDK powering automated GitHub workflows.",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -60,6 +60,22 @@ const LIMIT_DEFAULTS = {
60
60
  library: 32,
61
61
  };
62
62
 
63
+ /**
64
+ * Read package.json from the project root, returning empty string if not found.
65
+ * @param {string} tomlPath - Path to the TOML config (used to derive project root)
66
+ * @param {string} depsRelPath - Relative path to package.json (from config)
67
+ * @returns {string} Raw package.json content or empty string
68
+ */
69
+ function readPackageJson(tomlPath, depsRelPath) {
70
+ try {
71
+ const projectRoot = dirname(tomlPath);
72
+ const pkgPath = join(projectRoot, depsRelPath);
73
+ return existsSync(pkgPath) ? readFileSync(pkgPath, "utf8") : "";
74
+ } catch {
75
+ return "";
76
+ }
77
+ }
78
+
63
79
  /**
64
80
  * Load configuration from agentic-lib.toml.
65
81
  *
@@ -85,7 +101,8 @@ export function loadConfig(configPath) {
85
101
  throw new Error(`Config file not found: ${tomlPath}. Create agentic-lib.toml in the project root.`);
86
102
  }
87
103
 
88
- const toml = parseToml(readFileSync(tomlPath, "utf8"));
104
+ const rawToml = readFileSync(tomlPath, "utf8");
105
+ const toml = parseToml(rawToml);
89
106
 
90
107
  // Merge TOML paths with defaults, normalising library-sources → librarySources
91
108
  const rawPaths = { ...toml.paths };
@@ -119,7 +136,6 @@ export function loadConfig(configPath) {
119
136
  const bot = toml.bot || {};
120
137
 
121
138
  return {
122
- schedule: toml.schedule?.tier || "schedule-1",
123
139
  supervisor: toml.schedule?.supervisor || "daily",
124
140
  model: toml.schedule?.model || "gpt-5-mini",
125
141
  paths,
@@ -137,6 +153,8 @@ export function loadConfig(configPath) {
137
153
  tdd: toml.tdd === true,
138
154
  writablePaths,
139
155
  readOnlyPaths,
156
+ configToml: rawToml,
157
+ packageJson: readPackageJson(tomlPath, mergedPaths.dependencies),
140
158
  };
141
159
  }
142
160
 
@@ -171,15 +171,25 @@ export function scanDirectory(dirPath, extensions, options = {}) {
171
171
  *
172
172
  * @param {string[]} writablePaths
173
173
  * @param {string[]} [readOnlyPaths=[]]
174
+ * @param {Object} [contextFiles] - Optional raw file contents to include
175
+ * @param {string} [contextFiles.configToml] - Raw agentic-lib.toml text
176
+ * @param {string} [contextFiles.packageJson] - Raw package.json text
174
177
  * @returns {string}
175
178
  */
176
- export function formatPathsSection(writablePaths, readOnlyPaths = []) {
177
- return [
179
+ export function formatPathsSection(writablePaths, readOnlyPaths = [], contextFiles) {
180
+ const lines = [
178
181
  "## File Paths",
179
182
  "### Writable (you may modify these)",
180
183
  writablePaths.length > 0 ? writablePaths.map((p) => `- ${p}`).join("\n") : "- (none)",
181
184
  "",
182
185
  "### Read-Only (for context only, do NOT modify)",
183
186
  readOnlyPaths.length > 0 ? readOnlyPaths.map((p) => `- ${p}`).join("\n") : "- (none)",
184
- ].join("\n");
187
+ ];
188
+ if (contextFiles?.configToml) {
189
+ lines.push("", "### Configuration (agentic-lib.toml)", "```toml", contextFiles.configToml, "```");
190
+ }
191
+ if (contextFiles?.packageJson) {
192
+ lines.push("", "### Dependencies (package.json)", "```json", contextFiles.packageJson, "```");
193
+ }
194
+ return lines.join("\n");
185
195
  }
@@ -5,7 +5,7 @@
5
5
  // Appends structured entries to the intentïon.md activity log,
6
6
  // including commit URLs and safety-check outcomes.
7
7
 
8
- import { writeFileSync, appendFileSync, existsSync, mkdirSync } from "fs";
8
+ import { writeFileSync, readFileSync, appendFileSync, existsSync, mkdirSync } from "fs";
9
9
  import { dirname } from "path";
10
10
  import * as core from "@actions/core";
11
11
 
@@ -73,8 +73,20 @@ export function logActivity({
73
73
 
74
74
  const entry = parts.join("\n");
75
75
 
76
+ const MAX_ENTRIES = 30;
77
+
76
78
  if (existsSync(filepath)) {
77
- appendFileSync(filepath, entry);
79
+ // Rotate: keep only the header + last MAX_ENTRIES entries
80
+ const existing = readFileSync(filepath, "utf8");
81
+ const sections = existing.split("\n## ");
82
+ if (sections.length > MAX_ENTRIES + 1) {
83
+ // sections[0] is the header, sections[1..] are entries (prefixed with "## " after split)
84
+ const header = sections[0];
85
+ const kept = sections.slice(-(MAX_ENTRIES));
86
+ writeFileSync(filepath, header + "\n## " + kept.join("\n## ") + entry);
87
+ } else {
88
+ appendFileSync(filepath, entry);
89
+ }
78
90
  } else {
79
91
  writeFileSync(filepath, `# intentïon Activity Log\n${entry}`);
80
92
  }
@@ -100,6 +100,8 @@ function buildPrompt(discussionUrl, discussion, context) {
100
100
  contributing ? `### Contributing\n${contributing}` : "",
101
101
  `### Current Features\n${featureNames.join(", ") || "none"}`,
102
102
  recentActivity ? `### Recent Activity\n${recentActivity}` : "",
103
+ config.configToml ? `### Configuration (agentic-lib.toml)\n\`\`\`toml\n${config.configToml}\n\`\`\`` : "",
104
+ config.packageJson ? `### Dependencies (package.json)\n\`\`\`json\n${config.packageJson}\n\`\`\`` : "",
103
105
  "",
104
106
  "## Actions",
105
107
  "Include exactly one action tag in your response. Only mention actions to the user when relevant.",
@@ -49,6 +49,8 @@ export async function enhanceIssue(context) {
49
49
  "",
50
50
  contributing ? `## Contributing Guidelines\n${contributing.substring(0, 1000)}` : "",
51
51
  features.length > 0 ? `## Related Features\n${features.map((f) => f.content).join("\n---\n")}` : "",
52
+ config.configToml ? `## Configuration (agentic-lib.toml)\n\`\`\`toml\n${config.configToml}\n\`\`\`` : "",
53
+ config.packageJson ? `## Dependencies (package.json)\n\`\`\`json\n${config.packageJson}\n\`\`\`` : "",
52
54
  "",
53
55
  "## Your Task",
54
56
  "Write an enhanced version of this issue body that includes:",
@@ -46,7 +46,7 @@ export async function fixCode(context) {
46
46
  "## Failing Checks",
47
47
  failureDetails,
48
48
  "",
49
- formatPathsSection(writablePaths, readOnlyPaths),
49
+ formatPathsSection(writablePaths, readOnlyPaths, config),
50
50
  "",
51
51
  "## Constraints",
52
52
  `- Run \`${testCommand}\` to validate your fixes`,
@@ -55,7 +55,7 @@ export async function maintainFeatures(context) {
55
55
  `2. If there are fewer than ${featureLimit} features, create new features aligned with the mission.`,
56
56
  "3. Ensure each feature has clear, testable acceptance criteria.",
57
57
  "",
58
- formatPathsSection(writablePaths, config.readOnlyPaths),
58
+ formatPathsSection(writablePaths, config.readOnlyPaths, config),
59
59
  "",
60
60
  "## Constraints",
61
61
  `- Maximum ${featureLimit} feature files`,
@@ -44,7 +44,7 @@ export async function maintainLibrary(context) {
44
44
  "2. Create or update library documents based on the source content.",
45
45
  "3. Remove library documents that no longer have corresponding sources.",
46
46
  "",
47
- formatPathsSection(writablePaths, config.readOnlyPaths),
47
+ formatPathsSection(writablePaths, config.readOnlyPaths, config),
48
48
  "",
49
49
  "## Constraints",
50
50
  `- Maximum ${libraryLimit} library documents`,
@@ -71,7 +71,7 @@ export async function resolveIssue(context) {
71
71
  comments.length > 0 ? "## Issue Comments" : "",
72
72
  ...comments.map((c) => `**${c.user.login}:** ${c.body}`),
73
73
  "",
74
- formatPathsSection(writablePaths, readOnlyPaths),
74
+ formatPathsSection(writablePaths, readOnlyPaths, config),
75
75
  "",
76
76
  "## Constraints",
77
77
  `- Run \`${testCommand}\` to validate your changes`,
@@ -17,21 +17,41 @@ import { runCopilotTask, scanDirectory } from "../copilot.js";
17
17
  export async function reviewIssue(context) {
18
18
  const { octokit, repo, config, issueNumber, instructions, model } = context;
19
19
 
20
- // If no specific issue, review the oldest open automated issue
20
+ // If no specific issue, review the oldest open automated issue that hasn't been recently reviewed
21
21
  let targetIssueNumber = issueNumber;
22
22
  if (!targetIssueNumber) {
23
23
  const { data: openIssues } = await octokit.rest.issues.listForRepo({
24
24
  ...repo,
25
25
  state: "open",
26
26
  labels: "automated",
27
- per_page: 1,
27
+ per_page: 5,
28
28
  sort: "created",
29
29
  direction: "asc",
30
30
  });
31
31
  if (openIssues.length === 0) {
32
32
  return { outcome: "nop", details: "No open automated issues to review" };
33
33
  }
34
- targetIssueNumber = openIssues[0].number;
34
+ // Try each issue, skipping ones that already have a recent automated review comment
35
+ for (const candidate of openIssues) {
36
+ const { data: comments } = await octokit.rest.issues.listComments({
37
+ ...repo,
38
+ issue_number: candidate.number,
39
+ per_page: 5,
40
+ sort: "created",
41
+ direction: "desc",
42
+ });
43
+ const hasRecentReview = comments.some(
44
+ (c) => c.body?.includes("**Automated Review Result:**") && Date.now() - new Date(c.created_at).getTime() < 86400000,
45
+ );
46
+ if (!hasRecentReview) {
47
+ targetIssueNumber = candidate.number;
48
+ break;
49
+ }
50
+ }
51
+ // Fall back to the oldest if all have been recently reviewed
52
+ if (!targetIssueNumber) {
53
+ targetIssueNumber = openIssues[0].number;
54
+ }
35
55
  }
36
56
 
37
57
  const { data: issue } = await octokit.rest.issues.get({
@@ -67,6 +87,9 @@ export async function reviewIssue(context) {
67
87
  `## Current Tests (${testFiles.length} files)`,
68
88
  ...testFiles.map((f) => `### ${f.name}\n\`\`\`\n${f.content}\n\`\`\``),
69
89
  "",
90
+ config.configToml ? `## Configuration (agentic-lib.toml)\n\`\`\`toml\n${config.configToml}\n\`\`\`` : "",
91
+ config.packageJson ? `## Dependencies (package.json)\n\`\`\`json\n${config.packageJson}\n\`\`\`` : "",
92
+ "",
70
93
  "## Your Task",
71
94
  "Determine if this issue has been resolved by the current code.",
72
95
  "Respond with exactly one of:",
@@ -74,8 +74,9 @@ async function gatherContext(octokit, repo, config) {
74
74
  issuesSummary,
75
75
  prsSummary,
76
76
  workflowsSummary,
77
- schedule: config.schedule,
78
77
  supervisor: config.supervisor,
78
+ configToml: config.configToml,
79
+ packageJson: config.packageJson,
79
80
  featureIssuesWipLimit: config.featureDevelopmentIssuesWipLimit,
80
81
  maintenanceIssuesWipLimit: config.maintenanceIssuesWipLimit,
81
82
  };
@@ -108,8 +109,14 @@ function buildPrompt(ctx, agentInstructions) {
108
109
  `### Recent Activity`,
109
110
  ctx.recentActivity || "none",
110
111
  "",
111
- `### Schedule: ${ctx.schedule}, Supervisor: ${ctx.supervisor}`,
112
+ `### Supervisor: ${ctx.supervisor}`,
112
113
  "",
114
+ "### Configuration (agentic-lib.toml)",
115
+ "```toml",
116
+ ctx.configToml || "",
117
+ "```",
118
+ "",
119
+ ...(ctx.packageJson ? ["### Dependencies (package.json)", "```json", ctx.packageJson, "```", ""] : []),
113
120
  `### Issue Limits`,
114
121
  `Feature development WIP limit: ${ctx.featureIssuesWipLimit}`,
115
122
  `Maintenance WIP limit: ${ctx.maintenanceIssuesWipLimit}`,
@@ -124,6 +131,7 @@ function buildPrompt(ctx, agentInstructions) {
124
131
  "- `dispatch:agent-flow-review` — Close resolved issues, enhance issue criteria",
125
132
  "- `dispatch:agent-flow-fix-code | pr-number: <N>` — Fix a failing PR",
126
133
  "- `dispatch:agent-discussions-bot` — Proactively post in discussions",
134
+ "- `dispatch:ci-automerge` — Merge open PRs with the automerge label if checks pass",
127
135
  "",
128
136
  "### GitHub API Actions",
129
137
  "- `github:create-issue | title: <text> | labels: <comma-separated>` — Create a new issue",
@@ -82,7 +82,7 @@ export async function transform(context) {
82
82
  "Determine the single most impactful next step to transform this repository.",
83
83
  "Then implement that step.",
84
84
  "",
85
- formatPathsSection(writablePaths, readOnlyPaths),
85
+ formatPathsSection(writablePaths, readOnlyPaths, config),
86
86
  "",
87
87
  "## Constraints",
88
88
  `- Run \`${testCommand}\` to validate your changes`,
@@ -153,7 +153,7 @@ async function transformTdd({
153
153
  `## Open Issues (${openIssues.length})`,
154
154
  ...openIssues.slice(0, 10).map((i) => `- #${i.number}: ${i.title}`),
155
155
  "",
156
- formatPathsSection(writablePaths, readOnlyPaths),
156
+ formatPathsSection(writablePaths, readOnlyPaths, _config),
157
157
  "",
158
158
  "## Constraints",
159
159
  "- Write ONLY test code in this phase",
@@ -193,7 +193,7 @@ async function transformTdd({
193
193
  `## Current Source Files (${sourceFiles.length})`,
194
194
  ...sourceFiles.map((f) => `### ${f.name}\n\`\`\`\n${f.content}\n\`\`\``),
195
195
  "",
196
- formatPathsSection(writablePaths, readOnlyPaths),
196
+ formatPathsSection(writablePaths, readOnlyPaths, _config),
197
197
  "",
198
198
  "## Output Artifacts",
199
199
  "If your changes produce output artifacts (plots, visualizations, data files, usage examples),",
@@ -28,7 +28,15 @@ runs:
28
28
  git add -A
29
29
  if git diff --cached --quiet; then
30
30
  echo "No changes to commit"
31
+ elif git diff --cached --name-only | grep -qvE '(intentïon\.md|intention\.md)$'; then
32
+ # At least one non-log file changed — proceed with commit
33
+ true
31
34
  else
35
+ echo "Only log files changed — skipping commit"
36
+ git reset HEAD -- . > /dev/null 2>&1
37
+ exit 0
38
+ fi
39
+ if ! git diff --cached --quiet; then
32
40
  git commit -m "${{ inputs.commit-message }}"
33
41
  REF="${{ inputs.push-ref }}"
34
42
  MAX_RETRIES=3
@@ -23,13 +23,16 @@ You are the supervisor of an autonomous coding repository. Your job is to advanc
23
23
  - **dispatch:agent-flow-fix-code** — When a specific PR has failing checks. Always include the pr-number.
24
24
  - **dispatch:agent-flow-maintain** — When features are below their limit AND no maintain appears in the last 3 workflow runs.
25
25
  - **dispatch:agent-discussions-bot** — When you want to proactively engage in discussions or respond to a user request.
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.
26
27
  - **github:label-issue** — When an issue needs better categorisation for prioritisation.
27
28
  - **github:close-issue** — When an issue is clearly resolved or no longer relevant.
28
29
  - **respond:discussions** — When replying to a user request that came through the discussions bot. Include the discussion URL and a clear message.
29
30
  - **set-schedule:\<frequency\>** — Change the supervisor schedule. Use `weekly` when mission is substantially achieved, `continuous` to ramp up for active development.
30
31
  - **nop** — When everything is running optimally: transform is active, issues are flowing, no failures.
31
32
 
32
- ## Guidelines
33
+ ## Stale Issue Detection
34
+
35
+ When open issues with the `automated` label lack the `ready` label and are more than 1 day old, and review has run without adding labels, use `github:label-issue` to add the `ready` label directly. Don't wait for review to fix itself — if issues are stuck without `ready` for more than a cycle, label them so transform can pick them up.
33
36
 
34
37
  ## Mission Lifecycle
35
38
 
@@ -1,6 +1,3 @@
1
- # Which agentic-lib workflow schedule should be used?
2
- schedule: schedule-1
3
-
4
1
  # Mapping for from symbolic keys to filepaths for access by agentic-lib workflows with limits and access permissions
5
2
  paths:
6
3
  # Filepaths for elaborator workflows
@@ -6,7 +6,6 @@
6
6
  # Place it at the root of your project.
7
7
 
8
8
  [schedule]
9
- tier = "schedule-1" # schedule-1 through schedule-4
10
9
  supervisor = "daily" # off | weekly | daily | hourly | continuous
11
10
  model = "gpt-5-mini" # gpt-5-mini | claude-sonnet-4 | gpt-4.1
12
11
 
@@ -14,7 +14,7 @@
14
14
  "author": "",
15
15
  "license": "MIT",
16
16
  "dependencies": {
17
- "@xn-intenton-z2a/agentic-lib": "^7.1.40"
17
+ "@xn-intenton-z2a/agentic-lib": "^7.1.42"
18
18
  },
19
19
  "devDependencies": {
20
20
  "@vitest/coverage-v8": "^4.0.0",
@@ -22,8 +22,6 @@ on:
22
22
  types:
23
23
  - created
24
24
  - edited
25
- schedule:
26
- - cron: "7 12 */28 * *"
27
25
  workflow_dispatch:
28
26
  inputs:
29
27
  discussion-url:
@@ -12,8 +12,6 @@ concurrency:
12
12
  cancel-in-progress: true
13
13
 
14
14
  on:
15
- schedule:
16
- - cron: "33 7 * * 1"
17
15
  workflow_dispatch:
18
16
  inputs:
19
17
  step:
@@ -11,8 +11,6 @@ concurrency:
11
11
  cancel-in-progress: true
12
12
 
13
13
  on:
14
- schedule:
15
- - cron: "47 8 */3 * *"
16
14
  workflow_dispatch:
17
15
  inputs:
18
16
  step:
@@ -103,7 +101,7 @@ jobs:
103
101
  ...context.repo,
104
102
  state: 'open',
105
103
  labels: 'automated',
106
- per_page: 1,
104
+ per_page: 20,
107
105
  sort: 'created',
108
106
  direction: 'asc',
109
107
  });
@@ -12,8 +12,6 @@ concurrency:
12
12
  cancel-in-progress: true
13
13
 
14
14
  on:
15
- schedule:
16
- - cron: "33 8 * * 1"
17
15
  workflow_dispatch:
18
16
  inputs:
19
17
  model:
@@ -25,8 +25,6 @@ on:
25
25
  type: string
26
26
  required: false
27
27
  default: "true"
28
- schedule:
29
- - cron: "03 8,9 * * 1"
30
28
 
31
29
  env:
32
30
  pullRequestLabel: "automerge"
@@ -154,7 +152,6 @@ jobs:
154
152
  ls:
155
153
  needs: label
156
154
  if: >-
157
- github.event_name == 'schedule' ||
158
155
  github.event_name == 'workflow_dispatch' ||
159
156
  github.event_name == 'workflow_run' ||
160
157
  inputs.workflow == 'true' ||