@xn-intenton-z2a/agentic-lib 7.1.55 → 7.1.57

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/agentic-lib.toml CHANGED
@@ -7,7 +7,6 @@
7
7
 
8
8
  [schedule]
9
9
  supervisor = "daily" # off | weekly | daily | hourly | continuous
10
- model = "gpt-5-mini" # gpt-5-mini | claude-sonnet-4 | gpt-4.1
11
10
 
12
11
  [paths]
13
12
  mission = "test/MISSION.md" #@dist "MISSION.md"
@@ -35,5 +34,20 @@ attempts-per-issue = 2
35
34
  features-limit = 2
36
35
  library-limit = 32
37
36
 
37
+ [tuning]
38
+ # Profile sets defaults for all tuning knobs: min | recommended | max
39
+ # min = fast & cheap (CI testing), recommended = balanced, max = thorough
40
+ profile = "min" #@dist "recommended"
41
+ model = "gpt-5-mini" # gpt-5-mini | claude-sonnet-4 | gpt-4.1
42
+ # Override individual knobs below. Omit or comment out to use profile defaults.
43
+ # reasoning-effort = "low" # low | medium | high | xhigh
44
+ infinite-sessions = false # set to true for long sessions with compaction
45
+ # features-scan = 3 # feature files to include in prompts
46
+ # source-scan = 3 # source files to include
47
+ # source-content = 1000 # max chars per source file
48
+ # issues-scan = 5 # open issues to include
49
+ # document-summary = 500 # max chars for document summaries
50
+ # discussion-comments = 5 # discussion comments to include
51
+
38
52
  [bot]
39
53
  log-file = "test/intentïon.md" #@dist "intentïon.md"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xn-intenton-z2a/agentic-lib",
3
- "version": "7.1.55",
3
+ "version": "7.1.57",
4
4
  "description": "Agentic-lib Agentic Coding Systems SDK powering automated GitHub workflows.",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -60,6 +60,40 @@ const LIMIT_DEFAULTS = {
60
60
  library: 32,
61
61
  };
62
62
 
63
+ // Tuning profiles: min (fast/cheap), recommended (balanced), max (thorough)
64
+ const TUNING_PROFILES = {
65
+ min: {
66
+ reasoningEffort: "low",
67
+ infiniteSessions: false,
68
+ featuresScan: 3,
69
+ sourceScan: 3,
70
+ sourceContent: 1000,
71
+ issuesScan: 5,
72
+ documentSummary: 500,
73
+ discussionComments: 5,
74
+ },
75
+ recommended: {
76
+ reasoningEffort: "medium",
77
+ infiniteSessions: true,
78
+ featuresScan: 10,
79
+ sourceScan: 10,
80
+ sourceContent: 5000,
81
+ issuesScan: 20,
82
+ documentSummary: 2000,
83
+ discussionComments: 10,
84
+ },
85
+ max: {
86
+ reasoningEffort: "high",
87
+ infiniteSessions: true,
88
+ featuresScan: 50,
89
+ sourceScan: 50,
90
+ sourceContent: 20000,
91
+ issuesScan: 100,
92
+ documentSummary: 10000,
93
+ discussionComments: 25,
94
+ },
95
+ };
96
+
63
97
  /**
64
98
  * Read package.json from the project root, returning empty string if not found.
65
99
  * @param {string} tomlPath - Path to the TOML config (used to derive project root)
@@ -76,6 +110,33 @@ function readPackageJson(tomlPath, depsRelPath) {
76
110
  }
77
111
  }
78
112
 
113
+ /**
114
+ * Resolve tuning configuration: start from profile defaults, apply explicit overrides.
115
+ */
116
+ function resolveTuning(tuningSection) {
117
+ const profileName = tuningSection.profile || "recommended";
118
+ const profile = TUNING_PROFILES[profileName] || TUNING_PROFILES.recommended;
119
+ const tuning = { ...profile };
120
+
121
+ if (tuningSection["reasoning-effort"]) tuning.reasoningEffort = tuningSection["reasoning-effort"];
122
+ if (tuningSection["infinite-sessions"] === true || tuningSection["infinite-sessions"] === false) {
123
+ tuning.infiniteSessions = tuningSection["infinite-sessions"];
124
+ }
125
+ const numericOverrides = {
126
+ "features-scan": "featuresScan",
127
+ "source-scan": "sourceScan",
128
+ "source-content": "sourceContent",
129
+ "issues-scan": "issuesScan",
130
+ "document-summary": "documentSummary",
131
+ "discussion-comments": "discussionComments",
132
+ };
133
+ for (const [tomlKey, jsKey] of Object.entries(numericOverrides)) {
134
+ if (tuningSection[tomlKey] > 0) tuning[jsKey] = tuningSection[tomlKey];
135
+ }
136
+
137
+ return tuning;
138
+ }
139
+
79
140
  /**
80
141
  * Load configuration from agentic-lib.toml.
81
142
  *
@@ -132,12 +193,15 @@ export function loadConfig(configPath) {
132
193
  paths.features.limit = limits["features-limit"] || LIMIT_DEFAULTS.features;
133
194
  paths.library.limit = limits["library-limit"] || LIMIT_DEFAULTS.library;
134
195
 
196
+ const tuning = resolveTuning(toml.tuning || {});
197
+
135
198
  const execution = toml.execution || {};
136
199
  const bot = toml.bot || {};
137
200
 
138
201
  return {
139
202
  supervisor: toml.schedule?.supervisor || "daily",
140
- model: toml.schedule?.model || "gpt-5-mini",
203
+ model: toml.tuning?.model || toml.schedule?.model || "gpt-5-mini",
204
+ tuning,
141
205
  paths,
142
206
  buildScript: execution.build || "npm run build",
143
207
  testScript: execution.test || "npm test",
@@ -48,11 +48,12 @@ export function buildClientOptions(githubToken) {
48
48
  * @param {string} options.prompt - The prompt to send
49
49
  * @param {string[]} options.writablePaths - Paths the agent may modify
50
50
  * @param {string} [options.githubToken] - Optional token; falls back to COPILOT_GITHUB_TOKEN env var.
51
+ * @param {Object} [options.tuning] - Tuning config (reasoningEffort, infiniteSessions)
51
52
  * @returns {Promise<{content: string, tokensUsed: number}>}
52
53
  */
53
- export async function runCopilotTask({ model, systemMessage, prompt, writablePaths, githubToken }) {
54
+ export async function runCopilotTask({ model, systemMessage, prompt, writablePaths, githubToken, tuning }) {
54
55
  core.info(
55
- `[copilot] Creating client (model=${model}, promptLen=${prompt.length}, writablePaths=${writablePaths.length})`,
56
+ `[copilot] Creating client (model=${model}, promptLen=${prompt.length}, writablePaths=${writablePaths.length}, tuning=${tuning?.reasoningEffort || "default"})`,
56
57
  );
57
58
 
58
59
  const clientOptions = buildClientOptions(githubToken);
@@ -60,13 +61,20 @@ export async function runCopilotTask({ model, systemMessage, prompt, writablePat
60
61
 
61
62
  try {
62
63
  core.info("[copilot] Creating session...");
63
- const session = await client.createSession({
64
+ const sessionConfig = {
64
65
  model,
65
66
  systemMessage: { content: systemMessage },
66
67
  tools: createAgentTools(writablePaths),
67
68
  onPermissionRequest: approveAll,
68
69
  workingDirectory: process.cwd(),
69
- });
70
+ };
71
+ if (tuning?.reasoningEffort) {
72
+ sessionConfig.reasoningEffort = tuning.reasoningEffort;
73
+ }
74
+ if (tuning?.infiniteSessions === true) {
75
+ sessionConfig.infiniteSessions = {};
76
+ }
77
+ const session = await client.createSession(sessionConfig);
70
78
  core.info(`[copilot] Session created: ${session.sessionId}`);
71
79
 
72
80
  // Check auth status now that client is connected
@@ -96,7 +96,7 @@ async function run() {
96
96
  if (result.tokensUsed) core.setOutput("tokens-used", String(result.tokensUsed));
97
97
  if (result.model) core.setOutput("model", result.model);
98
98
 
99
- // Log to intentïon.md
99
+ // Log to intentïon.md (commit-if-changed excludes this on non-default branches)
100
100
  const intentionFilepath = config.intentionBot?.intentionFilepath;
101
101
  if (intentionFilepath) {
102
102
  logActivity({
@@ -11,7 +11,7 @@ import { runCopilotTask, readOptionalFile, scanDirectory } from "../copilot.js";
11
11
 
12
12
  const BOT_LOGINS = ["github-actions[bot]", "github-actions"];
13
13
 
14
- async function fetchDiscussion(octokit, discussionUrl) {
14
+ async function fetchDiscussion(octokit, discussionUrl, commentsLimit = 10) {
15
15
  const urlMatch = discussionUrl.match(/github\.com\/([^/]+)\/([^/]+)\/discussions\/(\d+)/);
16
16
  if (!urlMatch) {
17
17
  core.warning(`Could not parse discussion URL: ${discussionUrl}`);
@@ -26,7 +26,7 @@ async function fetchDiscussion(octokit, discussionUrl) {
26
26
  id
27
27
  title
28
28
  body
29
- comments(last: 10) {
29
+ comments(last: ${commentsLimit}) {
30
30
  nodes {
31
31
  body
32
32
  author { login }
@@ -53,7 +53,7 @@ async function fetchDiscussion(octokit, discussionUrl) {
53
53
  }
54
54
  }
55
55
 
56
- function buildPrompt(discussionUrl, discussion, context) {
56
+ function buildPrompt(discussionUrl, discussion, context, t) {
57
57
  const { config, instructions } = context;
58
58
  const { title, body, comments } = discussion;
59
59
 
@@ -63,7 +63,7 @@ function buildPrompt(discussionUrl, discussion, context) {
63
63
  const lastBotReply = botReplies.length > 0 ? botReplies[botReplies.length - 1] : null;
64
64
 
65
65
  const mission = readOptionalFile(config.paths.mission.path);
66
- const contributing = readOptionalFile(config.paths.contributing.path, 1000);
66
+ const contributing = readOptionalFile(config.paths.contributing.path, t.documentSummary || 1000);
67
67
  const featuresPath = config.paths.features.path;
68
68
  const featureNames = existsSync(featuresPath)
69
69
  ? scanDirectory(featuresPath, ".md").map((f) => f.name.replace(".md", ""))
@@ -152,20 +152,21 @@ async function postReply(octokit, nodeId, replyBody) {
152
152
  */
153
153
  export async function discussions(context) {
154
154
  const { octokit, model, discussionUrl } = context;
155
+ const t = context.config?.tuning || {};
155
156
 
156
157
  if (!discussionUrl) {
157
158
  throw new Error("discussions task requires discussion-url input");
158
159
  }
159
160
 
160
- const discussion = await fetchDiscussion(octokit, discussionUrl);
161
- const prompt = buildPrompt(discussionUrl, discussion, context);
162
-
161
+ const discussion = await fetchDiscussion(octokit, discussionUrl, t.discussionComments || 10);
162
+ const prompt = buildPrompt(discussionUrl, discussion, context, t);
163
163
  const { content, tokensUsed, inputTokens, outputTokens, cost } = await runCopilotTask({
164
164
  model,
165
165
  systemMessage:
166
166
  "You are this repository. Respond in first person. Be concise and engaging — never repeat what you said in your last reply. Adapt to the user's language level. Encourage experimentation and suggest interesting projects. When a user requests an action, pass it to the supervisor via [ACTION:request-supervisor]. Protect the mission: push back on requests that contradict it.",
167
167
  prompt,
168
168
  writablePaths: [],
169
+ tuning: t,
169
170
  });
170
171
 
171
172
  const actionMatch = content.match(/\[ACTION:(\S+?)\](.+)?/);
@@ -13,7 +13,7 @@ import { runCopilotTask, readOptionalFile, scanDirectory } from "../copilot.js";
13
13
  /**
14
14
  * Enhance a single GitHub issue with testable acceptance criteria.
15
15
  */
16
- async function enhanceSingleIssue({ octokit, repo, config, issueNumber, instructions, model }) {
16
+ async function enhanceSingleIssue({ octokit, repo, config, issueNumber, instructions, model, tuning: t }) {
17
17
  if (await isIssueResolved(octokit, repo, issueNumber)) {
18
18
  return { outcome: "nop", details: `Issue #${issueNumber} already resolved` };
19
19
  }
@@ -28,7 +28,7 @@ async function enhanceSingleIssue({ octokit, repo, config, issueNumber, instruct
28
28
  }
29
29
 
30
30
  const contributing = readOptionalFile(config.paths.contributing.path);
31
- const features = scanDirectory(config.paths.features.path, ".md", { contentLimit: 2000 });
31
+ const features = scanDirectory(config.paths.features.path, ".md", { contentLimit: t.documentSummary || 2000 });
32
32
 
33
33
  const agentInstructions = instructions || "Enhance this issue with clear, testable acceptance criteria.";
34
34
 
@@ -39,7 +39,7 @@ async function enhanceSingleIssue({ octokit, repo, config, issueNumber, instruct
39
39
  `## Issue #${issueNumber}: ${issue.title}`,
40
40
  issue.body || "(no description)",
41
41
  "",
42
- contributing ? `## Contributing Guidelines\n${contributing.substring(0, 1000)}` : "",
42
+ contributing ? `## Contributing Guidelines\n${contributing.substring(0, t.documentSummary || 2000)}` : "",
43
43
  features.length > 0 ? `## Related Features\n${features.map((f) => f.content).join("\n---\n")}` : "",
44
44
  config.configToml ? `## Configuration (agentic-lib.toml)\n\`\`\`toml\n${config.configToml}\n\`\`\`` : "",
45
45
  config.packageJson ? `## Dependencies (package.json)\n\`\`\`json\n${config.packageJson}\n\`\`\`` : "",
@@ -64,6 +64,7 @@ async function enhanceSingleIssue({ octokit, repo, config, issueNumber, instruct
64
64
  systemMessage: "You are a requirements analyst. Enhance GitHub issues with clear, testable acceptance criteria.",
65
65
  prompt,
66
66
  writablePaths: [],
67
+ tuning: t,
67
68
  });
68
69
 
69
70
  if (enhancedBody.trim()) {
@@ -113,10 +114,11 @@ async function enhanceSingleIssue({ octokit, repo, config, issueNumber, instruct
113
114
  */
114
115
  export async function enhanceIssue(context) {
115
116
  const { octokit, repo, config, issueNumber, instructions, model } = context;
117
+ const t = config.tuning || {};
116
118
 
117
119
  // Single issue mode
118
120
  if (issueNumber) {
119
- return enhanceSingleIssue({ octokit, repo, config, issueNumber, instructions, model });
121
+ return enhanceSingleIssue({ octokit, repo, config, issueNumber, instructions, model, tuning: t });
120
122
  }
121
123
 
122
124
  // Batch mode: find up to 3 unready automated issues
@@ -149,6 +151,7 @@ export async function enhanceIssue(context) {
149
151
  issueNumber: issue.number,
150
152
  instructions,
151
153
  model,
154
+ tuning: t,
152
155
  });
153
156
  results.push(result);
154
157
  totalTokens += result.tokensUsed || 0;
@@ -93,11 +93,13 @@ export async function fixCode(context) {
93
93
  "- Make minimal changes to fix the failing tests",
94
94
  ].join("\n");
95
95
 
96
+ const t = config.tuning || {};
96
97
  const { tokensUsed, inputTokens, outputTokens, cost } = await runCopilotTask({
97
98
  model,
98
99
  systemMessage: `You are an autonomous coding agent fixing failing tests on PR #${prNumber}. Make minimal, targeted changes to fix the test failures.`,
99
100
  prompt,
100
101
  writablePaths,
102
+ tuning: t,
101
103
  });
102
104
 
103
105
  core.info(`Copilot SDK fix response received (${tokensUsed} tokens)`);
@@ -15,19 +15,20 @@ import { runCopilotTask, readOptionalFile, scanDirectory, formatPathsSection } f
15
15
  */
16
16
  export async function maintainFeatures(context) {
17
17
  const { config, instructions, writablePaths, model, octokit, repo } = context;
18
+ const t = config.tuning || {};
18
19
 
19
20
  const mission = readOptionalFile(config.paths.mission.path);
20
21
  const featuresPath = config.paths.features.path;
21
22
  const featureLimit = config.paths.features.limit;
22
- const features = scanDirectory(featuresPath, ".md");
23
+ const features = scanDirectory(featuresPath, ".md", { fileLimit: t.featuresScan || 10 });
23
24
  const libraryDocs = scanDirectory(config.paths.library.path, ".md", {
24
- contentLimit: 1000,
25
+ contentLimit: t.documentSummary || 1000,
25
26
  });
26
27
 
27
28
  const { data: closedIssues } = await octokit.rest.issues.listForRepo({
28
29
  ...repo,
29
30
  state: "closed",
30
- per_page: 20,
31
+ per_page: t.issuesScan || 20,
31
32
  sort: "updated",
32
33
  direction: "desc",
33
34
  });
@@ -48,7 +49,7 @@ export async function maintainFeatures(context) {
48
49
  ...libraryDocs.map((d) => `### ${d.name}\n${d.content}`),
49
50
  "",
50
51
  `## Recently Closed Issues (${closedIssues.length})`,
51
- ...closedIssues.slice(0, 10).map((i) => `- #${i.number}: ${i.title}`),
52
+ ...closedIssues.slice(0, Math.floor((t.issuesScan || 20) / 2)).map((i) => `- #${i.number}: ${i.title}`),
52
53
  "",
53
54
  "## Your Task",
54
55
  `1. Review each existing feature — if it is already implemented or irrelevant, delete it.`,
@@ -68,6 +69,7 @@ export async function maintainFeatures(context) {
68
69
  "You are a feature lifecycle manager. Create, update, and prune feature specification files to keep the project focused on its mission.",
69
70
  prompt,
70
71
  writablePaths,
72
+ tuning: t,
71
73
  });
72
74
 
73
75
  return {
@@ -16,6 +16,7 @@ import { runCopilotTask, readOptionalFile, scanDirectory, formatPathsSection } f
16
16
  */
17
17
  export async function maintainLibrary(context) {
18
18
  const { config, instructions, writablePaths, model } = context;
19
+ const t = config.tuning || {};
19
20
 
20
21
  const sources = readOptionalFile(config.paths.librarySources.path);
21
22
  if (!sources.trim()) {
@@ -25,7 +26,7 @@ export async function maintainLibrary(context) {
25
26
 
26
27
  const libraryPath = config.paths.library.path;
27
28
  const libraryLimit = config.paths.library.limit;
28
- const libraryDocs = scanDirectory(libraryPath, ".md", { contentLimit: 500 });
29
+ const libraryDocs = scanDirectory(libraryPath, ".md", { contentLimit: t.documentSummary || 500 });
29
30
 
30
31
  const agentInstructions = instructions || "Maintain the library by updating documents from sources.";
31
32
 
@@ -56,6 +57,7 @@ export async function maintainLibrary(context) {
56
57
  "You are a knowledge librarian. Maintain a library of technical documents extracted from web sources.",
57
58
  prompt,
58
59
  writablePaths,
60
+ tuning: t,
59
61
  });
60
62
 
61
63
  return {
@@ -78,11 +78,13 @@ export async function resolveIssue(context) {
78
78
  contributing ? `\n## Contributing Guidelines\n${contributing}` : "",
79
79
  ].join("\n");
80
80
 
81
+ const t = config.tuning || {};
81
82
  const { content: resultContent, tokensUsed, inputTokens, outputTokens, cost } = await runCopilotTask({
82
83
  model,
83
84
  systemMessage: `You are an autonomous coding agent resolving GitHub issue #${issueNumber}. Write clean, tested code. Only modify files listed under "Writable" paths. Read-only paths are for context only.`,
84
85
  prompt,
85
86
  writablePaths,
87
+ tuning: t,
86
88
  });
87
89
 
88
90
  core.info(`Copilot SDK response received (${tokensUsed} tokens)`);
@@ -21,7 +21,7 @@ import { runCopilotTask, scanDirectory } from "../copilot.js";
21
21
  * @param {string} params.model - Model name
22
22
  * @returns {Promise<Object>} Result with outcome, tokensUsed, model
23
23
  */
24
- async function reviewSingleIssue({ octokit, repo, config, targetIssueNumber, instructions, model }) {
24
+ async function reviewSingleIssue({ octokit, repo, config, targetIssueNumber, instructions, model, tuning: t }) {
25
25
  const { data: issue } = await octokit.rest.issues.get({
26
26
  ...repo,
27
27
  issue_number: Number(targetIssueNumber),
@@ -32,18 +32,18 @@ async function reviewSingleIssue({ octokit, repo, config, targetIssueNumber, ins
32
32
  }
33
33
 
34
34
  const sourceFiles = scanDirectory(config.paths.source.path, [".js", ".ts"], {
35
- contentLimit: 5000,
36
- fileLimit: 20,
35
+ contentLimit: t.sourceContent || 5000,
36
+ fileLimit: t.sourceScan || 20,
37
37
  recursive: true,
38
38
  });
39
39
  const testFiles = scanDirectory(config.paths.tests.path, [".test.js", ".test.ts"], {
40
- contentLimit: 5000,
41
- fileLimit: 20,
40
+ contentLimit: t.sourceContent || 5000,
41
+ fileLimit: t.sourceScan || 20,
42
42
  recursive: true,
43
43
  });
44
44
  const docsFiles = scanDirectory(config.paths.documentation?.path || "docs/", [".md"], {
45
- fileLimit: 10,
46
- contentLimit: 2000,
45
+ fileLimit: t.featuresScan || 10,
46
+ contentLimit: t.documentSummary || 2000,
47
47
  });
48
48
 
49
49
  const agentInstructions = instructions || "Review whether this issue has been resolved by the current codebase.";
@@ -85,6 +85,7 @@ async function reviewSingleIssue({ octokit, repo, config, targetIssueNumber, ins
85
85
  systemMessage: "You are a code reviewer determining if GitHub issues have been resolved.",
86
86
  prompt,
87
87
  writablePaths: [],
88
+ tuning: t,
88
89
  });
89
90
 
90
91
  // Strip leading markdown formatting (e.g., **RESOLVED** or *RESOLVED*)
@@ -184,10 +185,11 @@ async function findUnreviewedIssues(octokit, repo, limit) {
184
185
  */
185
186
  export async function reviewIssue(context) {
186
187
  const { octokit, repo, config, issueNumber, instructions, model } = context;
188
+ const t = config.tuning || {};
187
189
 
188
190
  // Single issue mode
189
191
  if (issueNumber) {
190
- return reviewSingleIssue({ octokit, repo, config, targetIssueNumber: issueNumber, instructions, model });
192
+ return reviewSingleIssue({ octokit, repo, config, targetIssueNumber: issueNumber, instructions, model, tuning: t });
191
193
  }
192
194
 
193
195
  // Batch mode: find up to 3 unreviewed issues
@@ -204,7 +206,9 @@ export async function reviewIssue(context) {
204
206
 
205
207
  for (const num of issueNumbers) {
206
208
  core.info(`Batch reviewing issue #${num} (${results.length + 1}/${issueNumbers.length})`);
207
- const result = await reviewSingleIssue({ octokit, repo, config, targetIssueNumber: num, instructions, model });
209
+ const result = await reviewSingleIssue({
210
+ octokit, repo, config, targetIssueNumber: num, instructions, model, tuning: t,
211
+ });
208
212
  results.push(result);
209
213
  totalTokens += result.tokensUsed || 0;
210
214
  totalInputTokens += result.inputTokens || 0;
@@ -9,7 +9,7 @@ import * as core from "@actions/core";
9
9
  import { existsSync } from "fs";
10
10
  import { runCopilotTask, readOptionalFile, scanDirectory } from "../copilot.js";
11
11
 
12
- async function gatherContext(octokit, repo, config) {
12
+ async function gatherContext(octokit, repo, config, t) {
13
13
  const mission = readOptionalFile(config.paths.mission.path);
14
14
  const recentActivity = readOptionalFile(config.intentionBot.intentionFilepath).split("\n").slice(-20).join("\n");
15
15
 
@@ -28,7 +28,7 @@ async function gatherContext(octokit, repo, config) {
28
28
  const { data: openIssues } = await octokit.rest.issues.listForRepo({
29
29
  ...repo,
30
30
  state: "open",
31
- per_page: 20,
31
+ per_page: t.issuesScan || 20,
32
32
  sort: "created",
33
33
  direction: "asc",
34
34
  });
@@ -305,8 +305,9 @@ async function executeAction(octokit, repo, action, params) {
305
305
  */
306
306
  export async function supervise(context) {
307
307
  const { octokit, repo, config, instructions, model } = context;
308
+ const t = config.tuning || {};
308
309
 
309
- const ctx = await gatherContext(octokit, repo, config);
310
+ const ctx = await gatherContext(octokit, repo, config, t);
310
311
  const agentInstructions = instructions || "You are the supervisor. Decide what actions to take.";
311
312
  const prompt = buildPrompt(ctx, agentInstructions);
312
313
 
@@ -316,6 +317,7 @@ export async function supervise(context) {
316
317
  "You are the supervisor of an autonomous coding repository. Your job is to advance the mission by choosing which workflows to dispatch and which GitHub actions to take. Pick multiple actions when appropriate. Be strategic — consider what's already in progress, what's blocked, and what will make the most impact.",
317
318
  prompt,
318
319
  writablePaths: [],
320
+ tuning: t,
319
321
  });
320
322
 
321
323
  const actions = parseActions(content);
@@ -16,6 +16,7 @@ import { runCopilotTask, readOptionalFile, scanDirectory, formatPathsSection } f
16
16
  */
17
17
  export async function transform(context) {
18
18
  const { config, instructions, writablePaths, testCommand, model, octokit, repo, issueNumber } = context;
19
+ const t = config.tuning || {};
19
20
 
20
21
  // Read mission (required)
21
22
  const mission = readOptionalFile(config.paths.mission.path);
@@ -24,16 +25,17 @@ export async function transform(context) {
24
25
  return { outcome: "nop", details: "No mission file found" };
25
26
  }
26
27
 
27
- const features = scanDirectory(config.paths.features.path, ".md");
28
+ const features = scanDirectory(config.paths.features.path, ".md", { fileLimit: t.featuresScan || 10 });
28
29
  const sourceFiles = scanDirectory(config.paths.source.path, [".js", ".ts"], {
29
- contentLimit: 5000,
30
+ fileLimit: t.sourceScan || 10,
31
+ contentLimit: t.sourceContent || 5000,
30
32
  recursive: true,
31
33
  });
32
34
 
33
35
  const { data: openIssues } = await octokit.rest.issues.listForRepo({
34
36
  ...repo,
35
37
  state: "open",
36
- per_page: 20,
38
+ per_page: t.issuesScan || 20,
37
39
  });
38
40
 
39
41
  // Fetch target issue if specified
@@ -67,6 +69,7 @@ export async function transform(context) {
67
69
  features,
68
70
  sourceFiles,
69
71
  openIssues,
72
+ tuning: t,
70
73
  });
71
74
  }
72
75
 
@@ -88,13 +91,13 @@ export async function transform(context) {
88
91
  mission,
89
92
  "",
90
93
  `## Current Features (${features.length})`,
91
- ...features.map((f) => `### ${f.name}\n${f.content.substring(0, 2000)}`),
94
+ ...features.map((f) => `### ${f.name}\n${f.content.substring(0, t.documentSummary || 2000)}`),
92
95
  "",
93
96
  `## Current Source Files (${sourceFiles.length})`,
94
97
  ...sourceFiles.map((f) => `### ${f.name}\n\`\`\`\n${f.content}\n\`\`\``),
95
98
  "",
96
99
  `## Open Issues (${openIssues.length})`,
97
- ...openIssues.slice(0, 20).map((i) => `- #${i.number}: ${i.title}`),
100
+ ...openIssues.slice(0, t.issuesScan || 20).map((i) => `- #${i.number}: ${i.title}`),
98
101
  "",
99
102
  "## Output Artifacts",
100
103
  "If your changes produce output artifacts (plots, visualizations, data files, usage examples),",
@@ -126,6 +129,7 @@ export async function transform(context) {
126
129
  "You are an autonomous code transformation agent. Your goal is to advance the repository toward its mission by making the most impactful change possible in a single step.",
127
130
  prompt,
128
131
  writablePaths,
132
+ tuning: t,
129
133
  });
130
134
 
131
135
  core.info(`Transformation step completed (${tokensUsed} tokens)`);
@@ -155,6 +159,7 @@ async function transformTdd({
155
159
  features,
156
160
  sourceFiles,
157
161
  openIssues,
162
+ tuning: t,
158
163
  }) {
159
164
  let totalTokens = 0;
160
165
 
@@ -175,13 +180,13 @@ async function transformTdd({
175
180
  mission,
176
181
  "",
177
182
  `## Current Features (${features.length})`,
178
- ...features.map((f) => `### ${f.name}\n${f.content.substring(0, 2000)}`),
183
+ ...features.map((f) => `### ${f.name}\n${f.content.substring(0, t.documentSummary || 2000)}`),
179
184
  "",
180
185
  `## Current Source Files (${sourceFiles.length})`,
181
186
  ...sourceFiles.map((f) => `### ${f.name}\n\`\`\`\n${f.content}\n\`\`\``),
182
187
  "",
183
188
  `## Open Issues (${openIssues.length})`,
184
- ...openIssues.slice(0, 20).map((i) => `- #${i.number}: ${i.title}`),
189
+ ...openIssues.slice(0, t.issuesScan || 20).map((i) => `- #${i.number}: ${i.title}`),
185
190
  "",
186
191
  formatPathsSection(writablePaths, readOnlyPaths, _config),
187
192
  "",
@@ -197,6 +202,7 @@ async function transformTdd({
197
202
  "You are a TDD agent. In this phase, write ONLY a failing test that captures the next feature requirement. Do not write implementation code.",
198
203
  prompt: testPrompt,
199
204
  writablePaths,
205
+ tuning: t,
200
206
  });
201
207
  totalTokens += phase1.tokensUsed;
202
208
  const testResult = phase1.content;
@@ -242,6 +248,7 @@ async function transformTdd({
242
248
  "You are a TDD agent. A failing test was written in Phase 1. Write the minimum implementation to make it pass. Do not modify the test.",
243
249
  prompt: implPrompt,
244
250
  writablePaths,
251
+ tuning: t,
245
252
  });
246
253
  totalTokens += phase2.tokensUsed;
247
254
 
@@ -26,6 +26,11 @@ runs:
26
26
  git config --local user.email 'action@github.com'
27
27
  git config --local user.name 'GitHub Actions[bot]'
28
28
  git add -A
29
+ # Unstage log files on non-default branches to avoid merge conflicts
30
+ REF="${{ inputs.push-ref }}"
31
+ if [ -n "$REF" ] && [ "$REF" != "main" ] && [ "$REF" != "master" ]; then
32
+ git reset HEAD -- 'intentïon.md' 'intention.md' 2>/dev/null || true
33
+ fi
29
34
  if git diff --cached --quiet; then
30
35
  echo "No changes to commit"
31
36
  elif git diff --cached --name-only | grep -qvE '(intentïon\.md|intention\.md)$'; then
@@ -14,7 +14,7 @@
14
14
  "author": "",
15
15
  "license": "MIT",
16
16
  "dependencies": {
17
- "@xn-intenton-z2a/agentic-lib": "^7.1.55"
17
+ "@xn-intenton-z2a/agentic-lib": "^7.1.57"
18
18
  },
19
19
  "devDependencies": {
20
20
  "@vitest/coverage-v8": "^4.0.18",