@open330/oac 2026.221.1 → 2026.222.1

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.
@@ -8,7 +8,7 @@ import {
8
8
  estimateLocChanges,
9
9
  estimateTokens,
10
10
  resetCounters
11
- } from "../chunk-5GAUWC3L.js";
11
+ } from "../chunk-ALBVUNUY.js";
12
12
  export {
13
13
  ClaudeTokenCounter,
14
14
  CodexTokenCounter,
@@ -466,4 +466,4 @@ export {
466
466
  buildExecutionPlan,
467
467
  buildEpicExecutionPlan
468
468
  };
469
- //# sourceMappingURL=chunk-5GAUWC3L.js.map
469
+ //# sourceMappingURL=chunk-ALBVUNUY.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/budget/complexity.ts","../src/budget/estimator.ts","../src/budget/providers/claude-counter.ts","../src/budget/providers/codex-counter.ts","../src/budget/planner.ts"],"sourcesContent":["import type { Task, TaskComplexity, TaskSource } from \"./estimator.js\";\n\nconst SOURCE_LOC_BASELINE: Record<TaskSource, number> = {\n lint: 8,\n todo: 16,\n \"test-gap\": 48,\n \"dead-code\": 36,\n \"github-issue\": 88,\n custom: 40,\n};\n\nconst SOURCE_COMPLEXITY_SCORE: Record<TaskSource, number> = {\n lint: 0,\n todo: 0,\n \"test-gap\": 1,\n \"dead-code\": 1,\n \"github-issue\": 2,\n custom: 1,\n};\n\nconst ESTIMATED_LOC_KEYS = [\n \"estimatedLoc\",\n \"estimatedLOC\",\n \"estimatedLocChanges\",\n \"estimatedDiffSize\",\n \"loc\",\n \"locChanges\",\n \"linesChanged\",\n \"lineCount\",\n \"diffSize\",\n \"changeSize\",\n] as const;\n\nfunction parseNumericValue(value: unknown): number | undefined {\n if (typeof value === \"number\" && Number.isFinite(value) && value >= 0) {\n return value;\n }\n\n if (typeof value === \"string\") {\n const parsed = Number.parseFloat(value);\n if (Number.isFinite(parsed) && parsed >= 0) {\n return parsed;\n }\n }\n\n return undefined;\n}\n\nfunction readMetadataLocEstimate(metadata: Record<string, unknown>): number | undefined {\n for (const key of ESTIMATED_LOC_KEYS) {\n const directValue = parseNumericValue(metadata[key]);\n if (directValue !== undefined) {\n return directValue;\n }\n }\n\n const metrics = metadata.metrics;\n if (metrics && typeof metrics === \"object\" && !Array.isArray(metrics)) {\n const metricsRecord = metrics as Record<string, unknown>;\n for (const key of ESTIMATED_LOC_KEYS) {\n const metricValue = parseNumericValue(metricsRecord[key]);\n if (metricValue !== undefined) {\n return metricValue;\n }\n }\n }\n\n return undefined;\n}\n\nexport function estimateLocChanges(task: Task): number {\n const metadataEstimate = readMetadataLocEstimate(task.metadata);\n if (metadataEstimate !== undefined) {\n return Math.max(1, Math.round(metadataEstimate));\n }\n\n const sourceBaseline = SOURCE_LOC_BASELINE[task.source] ?? SOURCE_LOC_BASELINE.custom;\n const fileAdjustment = Math.max(task.targetFiles.length, 1) * 8;\n\n return Math.max(sourceBaseline, fileAdjustment);\n}\n\nexport function analyzeTaskComplexity(task: Task): TaskComplexity {\n const fileCount = task.targetFiles.length;\n const locChanges = estimateLocChanges(task);\n\n const fileScore = fileCount <= 1 ? 0 : fileCount <= 3 ? 1 : fileCount <= 6 ? 2 : 3;\n const locScore = locChanges <= 20 ? 0 : locChanges <= 80 ? 1 : locChanges <= 200 ? 2 : 3;\n const sourceScore = SOURCE_COMPLEXITY_SCORE[task.source] ?? SOURCE_COMPLEXITY_SCORE.custom;\n\n const totalScore = fileScore + locScore + sourceScore;\n\n if (totalScore <= 1) {\n return \"trivial\";\n }\n\n if (totalScore <= 3) {\n return \"simple\";\n }\n\n if (totalScore <= 6) {\n return \"moderate\";\n }\n\n return \"complex\";\n}\n","import { readFile } from \"node:fs/promises\";\nimport { isAbsolute, resolve } from \"node:path\";\n\nimport PQueue from \"p-queue\";\nimport type { Epic } from \"../core/types.js\";\nimport { analyzeTaskComplexity } from \"./complexity.js\";\nimport { ClaudeTokenCounter } from \"./providers/claude-counter.js\";\nimport { CodexTokenCounter } from \"./providers/codex-counter.js\";\n\nexport type AgentProviderId = \"claude-code\" | \"codex\" | \"opencode\" | string;\n\nexport type TaskSource = \"lint\" | \"todo\" | \"test-gap\" | \"dead-code\" | \"github-issue\" | \"custom\";\n\nexport type TaskComplexity = \"trivial\" | \"simple\" | \"moderate\" | \"complex\";\n\nexport type ExecutionMode = \"new-pr\" | \"update-pr\" | \"direct-commit\";\n\nexport interface Task {\n id: string;\n source: TaskSource;\n title: string;\n description: string;\n targetFiles: string[];\n priority: number;\n complexity: TaskComplexity;\n executionMode: ExecutionMode;\n linkedIssue?: {\n number: number;\n url: string;\n labels: string[];\n };\n metadata: Record<string, unknown>;\n discoveredAt: string;\n}\n\nexport interface TokenEstimate {\n taskId: string;\n providerId: AgentProviderId;\n contextTokens: number;\n promptTokens: number;\n expectedOutputTokens: number;\n totalEstimatedTokens: number;\n confidence: number;\n feasible: boolean;\n estimatedCostUsd?: number;\n}\n\nexport interface TokenCounter {\n countTokens(text: string): number;\n readonly invocationOverhead: number;\n readonly maxContextTokens: number;\n /** Free any cached resources (e.g. tiktoken encoders). Optional. */\n reset?(): void;\n}\n\ninterface TokenCountResult {\n tokens: number;\n usedFallback: boolean;\n}\n\ninterface ContextFileResult extends TokenCountResult {\n missing: boolean;\n}\n\nconst ESTIMATION_PADDING_MULTIPLIER = 1.2;\nconst FALLBACK_CONFIDENCE = 0.5;\n\nconst COMPLEXITY_MULTIPLIERS: Record<TaskComplexity, number> = {\n trivial: 0.5,\n simple: 1,\n moderate: 2,\n complex: 3.5,\n};\n\nconst COMPLEXITY_CONFIDENCE: Record<TaskComplexity, number> = {\n trivial: 0.9,\n simple: 0.75,\n moderate: 0.6,\n complex: 0.4,\n};\n\nconst COMPLEXITY_ORDER: Record<TaskComplexity, number> = {\n trivial: 0,\n simple: 1,\n moderate: 2,\n complex: 3,\n};\n\nconst claudeCounter = new ClaudeTokenCounter();\nconst codexCounter = new CodexTokenCounter();\n\n/**\n * Free cached tiktoken encoders held by the module-level counter singletons.\n * Useful for reclaiming memory in long-lived processes or between test runs.\n */\nexport function resetCounters(): void {\n claudeCounter.reset();\n codexCounter.reset();\n}\n\nfunction getTokenCounter(provider: AgentProviderId): TokenCounter {\n if (provider === \"claude-code\") {\n return claudeCounter;\n }\n\n return codexCounter;\n}\n\nfunction approximateTokenCount(text: string): number {\n if (text.length === 0) {\n return 0;\n }\n\n return Math.max(1, Math.ceil(text.length / 4));\n}\n\nfunction countTokensWithFallback(text: string, counter: TokenCounter): TokenCountResult {\n try {\n return {\n tokens: counter.countTokens(text),\n usedFallback: false,\n };\n } catch {\n return {\n tokens: approximateTokenCount(text),\n usedFallback: true,\n };\n }\n}\n\nfunction chooseConservativeComplexity(\n declaredComplexity: TaskComplexity,\n analyzedComplexity: TaskComplexity,\n): TaskComplexity {\n return COMPLEXITY_ORDER[declaredComplexity] >= COMPLEXITY_ORDER[analyzedComplexity]\n ? declaredComplexity\n : analyzedComplexity;\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n if (value < min) {\n return min;\n }\n\n if (value > max) {\n return max;\n }\n\n return value;\n}\n\nfunction resolveTargetFilePath(targetFile: string): string {\n return isAbsolute(targetFile) ? targetFile : resolve(process.cwd(), targetFile);\n}\n\nfunction safeStringify(value: unknown): string {\n try {\n const serialized = JSON.stringify(value);\n return serialized ?? \"null\";\n } catch {\n return \"[unserializable]\";\n }\n}\n\nasync function readContextFile(\n targetFile: string,\n counter: TokenCounter,\n): Promise<ContextFileResult> {\n const resolvedPath = resolveTargetFilePath(targetFile);\n\n try {\n const content = await readFile(resolvedPath, \"utf8\");\n const counted = countTokensWithFallback(content, counter);\n\n return {\n ...counted,\n missing: false,\n };\n } catch {\n return {\n tokens: 0,\n usedFallback: false,\n missing: true,\n };\n }\n}\n\nexport async function estimateTokens(\n task: Task,\n provider: AgentProviderId,\n): Promise<TokenEstimate> {\n const counter = getTokenCounter(provider);\n const uniqueTargetFiles = [...new Set(task.targetFiles)];\n\n const fileQueue = new PQueue({ concurrency: 50 });\n const fileResults = await Promise.all(\n uniqueTargetFiles.map(\n (targetFile) =>\n fileQueue.add(() => readContextFile(targetFile, counter)) as Promise<ContextFileResult>,\n ),\n );\n\n const repoStructureSeed = uniqueTargetFiles.join(\"\\n\");\n const repoStructureCount = countTokensWithFallback(repoStructureSeed, counter);\n\n const contextTokens =\n repoStructureCount.tokens + fileResults.reduce((sum, result) => sum + result.tokens, 0);\n\n const promptSeed = [\n `Task ID: ${task.id}`,\n `Title: ${task.title}`,\n `Source: ${task.source}`,\n `Priority: ${task.priority}`,\n `Description:\\n${task.description}`,\n `Target Files:\\n${uniqueTargetFiles.join(\"\\n\") || \"(none)\"}`,\n `Metadata: ${safeStringify(task.metadata)}`,\n ].join(\"\\n\\n\");\n\n const promptContentCount = countTokensWithFallback(promptSeed, counter);\n const promptTokens = counter.invocationOverhead + promptContentCount.tokens;\n\n const analyzedComplexity = analyzeTaskComplexity(task);\n const effectiveComplexity = chooseConservativeComplexity(task.complexity, analyzedComplexity);\n const expectedOutputTokens = Math.ceil(\n contextTokens * COMPLEXITY_MULTIPLIERS[effectiveComplexity],\n );\n\n const rawTotalTokens = contextTokens + promptTokens + expectedOutputTokens;\n const totalEstimatedTokens = Math.ceil(rawTotalTokens * ESTIMATION_PADDING_MULTIPLIER);\n\n const usedFallback =\n repoStructureCount.usedFallback ||\n promptContentCount.usedFallback ||\n fileResults.some((result) => result.usedFallback);\n\n const missingFileCount = fileResults.filter((result) => result.missing).length;\n\n let confidence = COMPLEXITY_CONFIDENCE[effectiveComplexity];\n if (usedFallback) {\n confidence = Math.min(confidence, FALLBACK_CONFIDENCE);\n }\n\n if (missingFileCount > 0) {\n confidence -= Math.min(0.25, missingFileCount * 0.05);\n }\n\n if (uniqueTargetFiles.length === 0) {\n confidence -= 0.1;\n }\n\n if (task.complexity !== analyzedComplexity) {\n confidence -= 0.05;\n }\n\n const feasible = totalEstimatedTokens <= counter.maxContextTokens;\n\n return {\n taskId: task.id,\n providerId: provider,\n contextTokens,\n promptTokens,\n expectedOutputTokens,\n totalEstimatedTokens,\n confidence: clamp(confidence, 0.1, 0.95),\n feasible,\n };\n}\n\n// ── Epic token estimation ────────────────────────────────────\n\nconst EPIC_CONTEXT_OVERHEAD = 1.2; // 20% overhead for shared module understanding\n\n/**\n * Estimate tokens for an entire epic by summing subtask estimates\n * plus a 20% context overhead for shared module understanding.\n */\nexport async function estimateEpicTokens(epic: Epic, provider: AgentProviderId): Promise<number> {\n if (epic.subtasks.length === 0) {\n return 0;\n }\n\n const epicQueue = new PQueue({ concurrency: 10 });\n const subtaskEstimates = await Promise.all(\n epic.subtasks.map(\n (task) => epicQueue.add(() => estimateTokens(task, provider)) as Promise<TokenEstimate>,\n ),\n );\n\n const subtaskTotal = subtaskEstimates.reduce(\n (sum, estimate) => sum + estimate.totalEstimatedTokens,\n 0,\n );\n\n return Math.ceil(subtaskTotal * EPIC_CONTEXT_OVERHEAD);\n}\n","import { type Tiktoken, get_encoding } from \"tiktoken\";\n\nconst CLAUDE_ENCODING = \"cl100k_base\";\nconst CLAUDE_INVOCATION_OVERHEAD = 1_500;\nconst CLAUDE_MAX_CONTEXT_TOKENS = 200_000;\n\nlet encoder: Tiktoken | undefined;\n\nfunction getEncoder(): Tiktoken {\n encoder ??= get_encoding(CLAUDE_ENCODING);\n return encoder;\n}\n\nexport class ClaudeTokenCounter {\n readonly invocationOverhead = CLAUDE_INVOCATION_OVERHEAD;\n readonly maxContextTokens = CLAUDE_MAX_CONTEXT_TOKENS;\n readonly encoding = CLAUDE_ENCODING;\n\n countTokens(text: string): number {\n return getEncoder().encode(text).length;\n }\n\n /** Free the cached tiktoken encoder so it can be re-created on next use. */\n reset(): void {\n if (encoder) {\n encoder.free();\n encoder = undefined;\n }\n }\n}\n","import { type Tiktoken, get_encoding } from \"tiktoken\";\n\nconst CODEX_INVOCATION_OVERHEAD = 1_000;\nconst CODEX_MAX_CONTEXT_TOKENS = 200_000;\nconst PRIMARY_ENCODING = \"o200k_base\";\nconst FALLBACK_ENCODING = \"cl100k_base\";\n\ntype SupportedCodexEncoding = typeof PRIMARY_ENCODING | typeof FALLBACK_ENCODING;\n\nlet encoder: Tiktoken | undefined;\nlet selectedEncoding: SupportedCodexEncoding | undefined;\n\nfunction getEncoder(): Tiktoken {\n if (encoder) {\n return encoder;\n }\n\n try {\n encoder = get_encoding(PRIMARY_ENCODING);\n selectedEncoding = PRIMARY_ENCODING;\n } catch {\n encoder = get_encoding(FALLBACK_ENCODING);\n selectedEncoding = FALLBACK_ENCODING;\n }\n\n return encoder;\n}\n\nexport class CodexTokenCounter {\n readonly invocationOverhead = CODEX_INVOCATION_OVERHEAD;\n readonly maxContextTokens = CODEX_MAX_CONTEXT_TOKENS;\n\n get encoding(): SupportedCodexEncoding {\n getEncoder();\n return selectedEncoding ?? FALLBACK_ENCODING;\n }\n\n countTokens(text: string): number {\n return getEncoder().encode(text).length;\n }\n\n /** Free the cached tiktoken encoder so it can be re-created on next use. */\n reset(): void {\n if (encoder) {\n encoder.free();\n encoder = undefined;\n }\n selectedEncoding = undefined;\n }\n}\n","import type { Epic } from \"../core/types.js\";\nimport type { AgentProviderId, Task, TokenEstimate } from \"./estimator.js\";\n\nconst DEFAULT_RESERVE_PERCENT = 0.1;\nconst MIN_CONFIDENCE_THRESHOLD = 0.5;\nconst TOO_COMPLEX_BUDGET_SHARE = 0.6;\n\ntype DeferredReason = \"budget_exceeded\" | \"low_confidence\" | \"too_complex\";\n\nexport interface ExecutionPlan {\n totalBudget: number;\n selectedTasks: Array<{\n task: Task;\n estimate: TokenEstimate;\n cumulativeBudgetUsed: number;\n }>;\n deferredTasks: Array<{\n task: Task;\n estimate: TokenEstimate;\n reason: DeferredReason;\n }>;\n reserveTokens: number;\n remainingTokens: number;\n}\n\ninterface CandidateTask {\n task: Task;\n estimate: TokenEstimate;\n}\n\nfunction normalizeBudget(budget: number): number {\n if (!Number.isFinite(budget) || budget <= 0) {\n return 0;\n }\n\n return Math.floor(budget);\n}\n\nfunction getFallbackEstimate(task: Task): TokenEstimate {\n return {\n taskId: task.id,\n providerId: \"unknown\" as AgentProviderId,\n contextTokens: 0,\n promptTokens: 0,\n expectedOutputTokens: 0,\n totalEstimatedTokens: Number.MAX_SAFE_INTEGER,\n confidence: 0,\n feasible: false,\n };\n}\n\nfunction classifyDeferredReason(\n task: Task,\n estimate: TokenEstimate,\n effectiveBudget: number,\n): DeferredReason | undefined {\n if (!estimate.feasible) {\n return \"budget_exceeded\";\n }\n\n if (estimate.confidence < MIN_CONFIDENCE_THRESHOLD) {\n return \"low_confidence\";\n }\n\n if (\n task.complexity === \"complex\" &&\n effectiveBudget > 0 &&\n estimate.totalEstimatedTokens > effectiveBudget * TOO_COMPLEX_BUDGET_SHARE\n ) {\n return \"too_complex\";\n }\n\n return undefined;\n}\n\nfunction scoreByPriorityPerToken(task: Task, estimate: TokenEstimate): number {\n if (estimate.totalEstimatedTokens <= 0) {\n return task.priority;\n }\n\n return task.priority / estimate.totalEstimatedTokens;\n}\n\nexport function buildExecutionPlan(\n tasks: Task[],\n estimates: Map<string, TokenEstimate>,\n budget: number,\n): ExecutionPlan {\n const totalBudget = normalizeBudget(budget);\n const reserveTokens = Math.floor(totalBudget * DEFAULT_RESERVE_PERCENT);\n const effectiveBudget = Math.max(0, totalBudget - reserveTokens);\n\n const deferredTasks: ExecutionPlan[\"deferredTasks\"] = [];\n const candidates: CandidateTask[] = [];\n\n for (const task of tasks) {\n const estimate = estimates.get(task.id) ?? getFallbackEstimate(task);\n const reason = classifyDeferredReason(task, estimate, effectiveBudget);\n\n if (reason) {\n deferredTasks.push({ task, estimate, reason });\n continue;\n }\n\n candidates.push({ task, estimate });\n }\n\n candidates.sort((left, right) => {\n const ratioDifference =\n scoreByPriorityPerToken(right.task, right.estimate) -\n scoreByPriorityPerToken(left.task, left.estimate);\n\n if (ratioDifference !== 0) {\n return ratioDifference;\n }\n\n const priorityDifference = right.task.priority - left.task.priority;\n if (priorityDifference !== 0) {\n return priorityDifference;\n }\n\n return left.estimate.totalEstimatedTokens - right.estimate.totalEstimatedTokens;\n });\n\n const selectedTasks: ExecutionPlan[\"selectedTasks\"] = [];\n let budgetUsed = 0;\n\n for (const candidate of candidates) {\n const nextBudgetUsed = budgetUsed + candidate.estimate.totalEstimatedTokens;\n\n if (nextBudgetUsed <= effectiveBudget) {\n budgetUsed = nextBudgetUsed;\n selectedTasks.push({\n task: candidate.task,\n estimate: candidate.estimate,\n cumulativeBudgetUsed: budgetUsed,\n });\n continue;\n }\n\n deferredTasks.push({\n task: candidate.task,\n estimate: candidate.estimate,\n reason: \"budget_exceeded\",\n });\n }\n\n return {\n totalBudget,\n selectedTasks,\n deferredTasks,\n reserveTokens,\n remainingTokens: Math.max(0, effectiveBudget - budgetUsed),\n };\n}\n\n// ── Epic execution plan ─────────────────────────────────────\n\nexport interface EpicExecutionPlan {\n totalBudget: number;\n selectedEpics: Array<{\n epic: Epic;\n estimatedTokens: number;\n cumulativeBudgetUsed: number;\n }>;\n deferredEpics: Array<{\n epic: Epic;\n estimatedTokens: number;\n reason: \"budget_exceeded\";\n }>;\n reserveTokens: number;\n remainingTokens: number;\n}\n\n/**\n * Build an execution plan for epics. Unlike task-level planning, epics are\n * sorted purely by priority (not priority/tokens ratio) since they are\n * already coherent units of work.\n */\nexport function buildEpicExecutionPlan(epics: Epic[], budget: number): EpicExecutionPlan {\n const totalBudget = normalizeBudget(budget);\n const reserveTokens = Math.floor(totalBudget * DEFAULT_RESERVE_PERCENT);\n const effectiveBudget = Math.max(0, totalBudget - reserveTokens);\n\n // Sort by priority descending (highest priority first)\n const sorted = [...epics].sort((a, b) => b.priority - a.priority);\n\n const selectedEpics: EpicExecutionPlan[\"selectedEpics\"] = [];\n const deferredEpics: EpicExecutionPlan[\"deferredEpics\"] = [];\n let budgetUsed = 0;\n\n for (const epic of sorted) {\n const tokens = epic.estimatedTokens;\n const nextBudgetUsed = budgetUsed + tokens;\n\n if (nextBudgetUsed <= effectiveBudget) {\n budgetUsed = nextBudgetUsed;\n selectedEpics.push({\n epic,\n estimatedTokens: tokens,\n cumulativeBudgetUsed: budgetUsed,\n });\n } else {\n deferredEpics.push({\n epic,\n estimatedTokens: tokens,\n reason: \"budget_exceeded\",\n });\n }\n }\n\n return {\n totalBudget,\n selectedEpics,\n deferredEpics,\n reserveTokens,\n remainingTokens: Math.max(0, effectiveBudget - budgetUsed),\n };\n}\n"],"mappings":"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","names":["get_encoding","encoder","getEncoder"]}
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  cloneRepo,
3
3
  resolveRepo
4
- } from "./chunk-OS3XDHOJ.js";
4
+ } from "./chunk-UCYK4Z6O.js";
5
5
  import {
6
6
  CompositeScanner,
7
7
  GitHubIssuesScanner,
@@ -20,19 +20,19 @@ import {
20
20
  persistContext,
21
21
  rankTasks,
22
22
  updateBacklog
23
- } from "./chunk-6JEFW6B7.js";
23
+ } from "./chunk-ZJBLRKCV.js";
24
24
  import {
25
25
  buildEpicExecutionPlan,
26
26
  buildExecutionPlan,
27
27
  estimateEpicTokens,
28
28
  estimateTokens
29
- } from "./chunk-5GAUWC3L.js";
29
+ } from "./chunk-ALBVUNUY.js";
30
30
  import {
31
31
  adapterRegistry,
32
32
  createSandbox,
33
33
  epicAsTask,
34
34
  executeTask
35
- } from "./chunk-EYUQMPVO.js";
35
+ } from "./chunk-JROCVTM7.js";
36
36
  import {
37
37
  UNLIMITED_BUDGET,
38
38
  createEventBus,
@@ -41,18 +41,18 @@ import {
41
41
  import {
42
42
  isRecord,
43
43
  truncate
44
- } from "./chunk-6A37SKAJ.js";
44
+ } from "./chunk-JDFAJP45.js";
45
45
  import {
46
46
  contributionLogSchema,
47
47
  writeContributionLog
48
48
  } from "./chunk-LQC5DLT7.js";
49
49
 
50
50
  // src/cli/cli.ts
51
- import { Command as Command13 } from "commander";
51
+ import { Command as Command12 } from "commander";
52
52
 
53
53
  // src/cli/commands/analyze.ts
54
54
  import Table from "cli-table3";
55
- import { Command as Command2 } from "commander";
55
+ import { Command } from "commander";
56
56
 
57
57
  // src/cli/github-auth.ts
58
58
  import { execFileSync, spawnSync } from "child_process";
@@ -100,7 +100,6 @@ function checkGitHubScopes(required = ["repo"]) {
100
100
 
101
101
  // src/cli/helpers.ts
102
102
  import chalk, { Chalk } from "chalk";
103
- import "commander";
104
103
  import ora from "ora";
105
104
  import PQueue from "p-queue";
106
105
 
@@ -269,10 +268,8 @@ async function estimateTaskMap(tasks, providerId, onProgress) {
269
268
 
270
269
  // src/cli/commands/analyze.ts
271
270
  function createAnalyzeCommand() {
272
- const command = new Command2("analyze");
273
- command.description(
274
- "Deep codebase analysis \u2014 build module graph and group findings into epics"
275
- ).option("--repo <owner/repo>", "Target repository (owner/repo or GitHub URL)").option("--force", "Force re-analysis even if context is fresh", false).option("--format <format>", "Output format: table|json", "table").action(async (options, cmd) => {
271
+ const command = new Command("analyze");
272
+ command.description("Deep codebase analysis \u2014 build module graph and group findings into epics").option("--repo <owner/repo>", "Target repository (owner/repo or GitHub URL)").option("--force", "Force re-analysis even if context is fresh", false).option("--format <format>", "Output format: table|json", "table").action(async (options, cmd) => {
276
273
  const globalOptions = getGlobalOptions(cmd);
277
274
  const ui = createUi(globalOptions);
278
275
  const outputJson = globalOptions.json || normalizeOutputFormat(options.format) === "json";
@@ -379,7 +376,7 @@ function buildScannerList(config, hasGitHubAuth) {
379
376
  }
380
377
 
381
378
  // src/cli/commands/completion.ts
382
- import { Command as Command3 } from "commander";
379
+ import { Command as Command2 } from "commander";
383
380
  var SUBCOMMANDS = [
384
381
  "init",
385
382
  "analyze",
@@ -392,7 +389,15 @@ var SUBCOMMANDS = [
392
389
  "status",
393
390
  "completion"
394
391
  ];
395
- var GLOBAL_OPTIONS = ["--config", "--verbose", "--quiet", "--json", "--no-color", "--help", "--version"];
392
+ var GLOBAL_OPTIONS = [
393
+ "--config",
394
+ "--verbose",
395
+ "--quiet",
396
+ "--json",
397
+ "--no-color",
398
+ "--help",
399
+ "--version"
400
+ ];
396
401
  var COMMAND_OPTIONS = {
397
402
  run: [
398
403
  "--repo",
@@ -477,17 +482,19 @@ function generateFish() {
477
482
  for (const [cmd, opts] of Object.entries(COMMAND_OPTIONS)) {
478
483
  for (const opt of opts) {
479
484
  const long = opt.replace(/^--/, "");
480
- lines.push(
481
- `complete -c oac -n '__fish_seen_subcommand_from ${cmd}' -l '${long}'`
482
- );
485
+ lines.push(`complete -c oac -n '__fish_seen_subcommand_from ${cmd}' -l '${long}'`);
483
486
  }
484
487
  }
485
488
  return lines.join("\n");
486
489
  }
487
490
  function createCompletionCommand() {
488
- const command = new Command3("completion");
491
+ const command = new Command2("completion");
489
492
  command.description("Generate shell completion scripts").argument("<shell>", "Shell type: bash, zsh, or fish").action((shell) => {
490
- const generators = { bash: generateBash, zsh: generateZsh, fish: generateFish };
493
+ const generators = {
494
+ bash: generateBash,
495
+ zsh: generateZsh,
496
+ fish: generateFish
497
+ };
491
498
  const gen = generators[shell];
492
499
  if (!gen) {
493
500
  throw new Error(`Unsupported shell "${shell}". Supported: bash, zsh, fish`);
@@ -506,10 +513,10 @@ Examples:
506
513
  }
507
514
 
508
515
  // src/cli/commands/doctor.ts
509
- import { Command as Command4 } from "commander";
516
+ import { Command as Command3 } from "commander";
510
517
  var MINIMUM_NODE_VERSION = "24.0.0";
511
518
  function createDoctorCommand() {
512
- const command = new Command4("doctor");
519
+ const command = new Command3("doctor");
513
520
  command.description("Check local environment readiness").action(async (_options, cmd) => {
514
521
  const globalOptions = getGlobalOptions(cmd);
515
522
  const ui = createUi(globalOptions);
@@ -749,9 +756,9 @@ async function runCommand(command, args) {
749
756
 
750
757
  // src/cli/commands/explain.ts
751
758
  import { resolve as resolve2 } from "path";
752
- import { Command as Command5 } from "commander";
759
+ import { Command as Command4 } from "commander";
753
760
  function createExplainCommand() {
754
- const command = new Command5("explain");
761
+ const command = new Command4("explain");
755
762
  command.description("Explain why a task or epic was selected and what the agent would do").argument("<id>", "Task or epic ID (from scan / analyze / run --dry-run output)").action(async (id, _options, cmd) => {
756
763
  const globalOptions = getGlobalOptions(cmd);
757
764
  const ui = createUi(globalOptions);
@@ -833,11 +840,13 @@ function createExplainCommand() {
833
840
  console.log(` ${finding.description}`);
834
841
  console.log("");
835
842
  console.log(ui.dim("What the agent would do:"));
836
- console.log(` 1. Check out a clean branch for this task`);
837
- console.log(` 2. Open ${finding.filePath}${finding.line ? ` at line ${finding.line}` : ""}`);
838
- console.log(` 3. Apply the fix described above`);
839
- console.log(` 4. Run tests and linters to verify`);
840
- console.log(` 5. Create a PR with the changes`);
843
+ console.log(" 1. Check out a clean branch for this task");
844
+ console.log(
845
+ ` 2. Open ${finding.filePath}${finding.line ? ` at line ${finding.line}` : ""}`
846
+ );
847
+ console.log(" 3. Apply the fix described above");
848
+ console.log(" 4. Run tests and linters to verify");
849
+ console.log(" 5. Create a PR with the changes");
841
850
  }
842
851
  });
843
852
  command.addHelpText(
@@ -878,7 +887,7 @@ import { constants as fsConstants2 } from "fs";
878
887
  import { access as access2, mkdir, readFile as readFile2, writeFile } from "fs/promises";
879
888
  import { resolve as resolve3 } from "path";
880
889
  import { checkbox, confirm, input } from "@inquirer/prompts";
881
- import { Command as Command6 } from "commander";
890
+ import { Command as Command5 } from "commander";
882
891
  var OAC_LOGO = [
883
892
  " ___ _ ___",
884
893
  " / _ \\ /_\\ / __|",
@@ -887,7 +896,7 @@ var OAC_LOGO = [
887
896
  ].join("\n");
888
897
  var OWNER_REPO_PATTERN = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+(?:\.git)?$/;
889
898
  function createInitCommand() {
890
- const command = new Command6("init");
899
+ const command = new Command5("init");
891
900
  command.description("Initialize OAC in the current directory").option("--minimal", "Generate a bare-bones config without the interactive wizard").option("--repo <owner/repo>", "Repository in owner/repo format (required with --minimal)").action(async (options, cmd) => {
892
901
  const globalOptions = getGlobalOptions(cmd);
893
902
  const ui = createUi(globalOptions);
@@ -1124,9 +1133,9 @@ async function ensureGitignoreEntry(dir, entry) {
1124
1133
  import { readFile as readFile3, readdir } from "fs/promises";
1125
1134
  import { resolve as resolve4 } from "path";
1126
1135
  import Table2 from "cli-table3";
1127
- import { Command as Command7 } from "commander";
1136
+ import { Command as Command6 } from "commander";
1128
1137
  function createLeaderboardCommand() {
1129
- const command = new Command7("leaderboard");
1138
+ const command = new Command6("leaderboard");
1130
1139
  command.description("Show contribution rankings").option("--limit <number>", "Max entries to show", parseInteger, 10).option("--sort <field>", "Sort by: runs, tasks, tokens, prs", "tasks").action(async (options, cmd) => {
1131
1140
  if (options.limit <= 0) {
1132
1141
  throw new Error("--limit must be a positive integer.");
@@ -1318,9 +1327,9 @@ function isFileNotFoundError(error) {
1318
1327
  import { readFile as readFile4, readdir as readdir2 } from "fs/promises";
1319
1328
  import { resolve as resolve5 } from "path";
1320
1329
  import Table3 from "cli-table3";
1321
- import { Command as Command8 } from "commander";
1330
+ import { Command as Command7 } from "commander";
1322
1331
  function createLogCommand() {
1323
- const command = new Command8("log");
1332
+ const command = new Command7("log");
1324
1333
  command.description("View contribution history").option("--limit <number>", "Max entries to show", parseInteger, 20).option("--repo <name>", "Filter by repo name").option("--source <type>", "Filter by task source").option("--since <date>", "Filter contributions after date (ISO string)").action(async (options, cmd) => {
1325
1334
  if (options.limit <= 0) {
1326
1335
  throw new Error("--limit must be a positive integer.");
@@ -1438,9 +1447,9 @@ function isFileNotFoundError2(error) {
1438
1447
 
1439
1448
  // src/cli/commands/plan.ts
1440
1449
  import Table4 from "cli-table3";
1441
- import { Command as Command9 } from "commander";
1450
+ import { Command as Command8 } from "commander";
1442
1451
  function createPlanCommand() {
1443
- const command = new Command9("plan");
1452
+ const command = new Command8("plan");
1444
1453
  command.description("Build an execution plan from discovered tasks").option("--repo <owner/repo>", "Target repository (owner/repo or GitHub URL)").option("--tokens <number>", "Token budget for planning", parseInteger).option("--provider <id>", "Agent provider id").action(async (options, cmd) => {
1445
1454
  const globalOptions = getGlobalOptions(cmd);
1446
1455
  const ui = createUi(globalOptions);
@@ -1465,6 +1474,7 @@ function createPlanCommand() {
1465
1474
  const scannedTasks = await scannerSelection.scanner.scan(resolvedRepo.localPath, {
1466
1475
  exclude: config?.discovery.exclude,
1467
1476
  maxTasks: config?.discovery.maxTasks,
1477
+ issueLabels: config?.discovery.issueLabels,
1468
1478
  repo: resolvedRepo
1469
1479
  });
1470
1480
  scanSpinner?.succeed(`Discovered ${scannedTasks.length} raw task(s)`);
@@ -1574,7 +1584,7 @@ function renderPlan(ui, data) {
1574
1584
  }
1575
1585
 
1576
1586
  // src/cli/commands/run/index.ts
1577
- import { Command as Command10 } from "commander";
1587
+ import { Command as Command9 } from "commander";
1578
1588
 
1579
1589
  // src/cli/commands/run/pipeline.ts
1580
1590
  import { randomUUID } from "crypto";
@@ -1771,6 +1781,7 @@ async function discoverTasks(ctx, options, config, ghToken, resolvedRepo) {
1771
1781
  const scannedTasks = await scannerSelection.scanner.scan(resolvedRepo.localPath, {
1772
1782
  exclude: config?.discovery.exclude,
1773
1783
  maxTasks: config?.discovery.maxTasks,
1784
+ issueLabels: config?.discovery.issueLabels,
1774
1785
  repo: resolvedRepo
1775
1786
  });
1776
1787
  scanSpinner?.succeed(`Discovered ${scannedTasks.length} raw task(s)`);
@@ -1852,7 +1863,9 @@ function renderDryRunDiff(ui, plan) {
1852
1863
  const sourceLabel = task.source.replace(/-/g, " ");
1853
1864
  const complexityColor = task.complexity === "trivial" || task.complexity === "simple" ? ui.green : task.complexity === "moderate" ? ui.yellow : ui.red;
1854
1865
  console.log(`${ui.green("+")} ${ui.bold(task.title)}`);
1855
- console.log(` ${ui.dim(`source: ${sourceLabel} complexity: `)}${complexityColor(task.complexity)}`);
1866
+ console.log(
1867
+ ` ${ui.dim(`source: ${sourceLabel} complexity: `)}${complexityColor(task.complexity)}`
1868
+ );
1856
1869
  if (task.targetFiles.length > 0) {
1857
1870
  for (const file of task.targetFiles.slice(0, 5)) {
1858
1871
  console.log(` ${ui.yellow("~")} ${file}`);
@@ -1997,7 +2010,7 @@ async function executeWithAgent(input2) {
1997
2010
  tokenBudget: input2.estimate.totalEstimatedTokens,
1998
2011
  timeoutMs: input2.timeoutSeconds * 1e3
1999
2012
  });
2000
- const commitResult = await commitSandboxChanges(sandbox.path, input2.task);
2013
+ const commitResult = await commitSandboxChanges(sandbox.path, input2.task, input2.baseBranch);
2001
2014
  const filesChanged = commitResult.filesChanged.length > 0 ? commitResult.filesChanged : result.filesChanged.length > 0 ? result.filesChanged : [];
2002
2015
  return {
2003
2016
  execution: {
@@ -2011,7 +2024,7 @@ async function executeWithAgent(input2) {
2011
2024
  sandbox: sandboxInfo
2012
2025
  };
2013
2026
  } catch (error) {
2014
- const commitResult = await commitSandboxChanges(sandbox.path, input2.task);
2027
+ const commitResult = await commitSandboxChanges(sandbox.path, input2.task, input2.baseBranch);
2015
2028
  if (commitResult.hasChanges) {
2016
2029
  return {
2017
2030
  execution: {
@@ -2038,25 +2051,26 @@ async function executeWithAgent(input2) {
2038
2051
  };
2039
2052
  }
2040
2053
  }
2041
- async function commitSandboxChanges(sandboxPath, task) {
2054
+ async function commitSandboxChanges(sandboxPath, task, baseBranch) {
2042
2055
  try {
2043
2056
  const statusResult = await execa2("git", ["status", "--porcelain"], { cwd: sandboxPath });
2044
- if (!statusResult.stdout.trim()) {
2045
- return { hasChanges: false, filesChanged: [] };
2057
+ if (statusResult.stdout.trim()) {
2058
+ await execa2("git", ["add", "-A"], { cwd: sandboxPath });
2059
+ await execa2(
2060
+ "git",
2061
+ ["commit", "-m", `[OAC] ${task.title}
2062
+
2063
+ Automated contribution by OAC.`],
2064
+ { cwd: sandboxPath }
2065
+ );
2046
2066
  }
2047
- await execa2("git", ["add", "-A"], { cwd: sandboxPath });
2048
- await execa2(
2067
+ const diffResult = await execa2(
2049
2068
  "git",
2050
- ["commit", "-m", `[OAC] ${task.title}
2051
-
2052
- Automated contribution by OAC using Codex CLI.`],
2069
+ ["diff", "--name-only", `origin/${baseBranch}`, "HEAD"],
2053
2070
  { cwd: sandboxPath }
2054
2071
  );
2055
- const diffResult = await execa2("git", ["diff", "--name-only", "HEAD~1", "HEAD"], {
2056
- cwd: sandboxPath
2057
- });
2058
2072
  const changedFiles = diffResult.stdout.trim().split("\n").filter(Boolean);
2059
- return { hasChanges: true, filesChanged: changedFiles };
2073
+ return { hasChanges: changedFiles.length > 0, filesChanged: changedFiles };
2060
2074
  } catch {
2061
2075
  return { hasChanges: false, filesChanged: [] };
2062
2076
  }
@@ -2396,10 +2410,7 @@ async function runEpicPipeline(ctx, params) {
2396
2410
  const { adapter } = await resolveAdapter(providerId);
2397
2411
  let epicCompletedCount = 0;
2398
2412
  const epicTotal = epicPlan.selectedEpics.length;
2399
- const executionSpinner = createSpinner(
2400
- ctx.suppressOutput,
2401
- `Executing ${epicTotal} epic(s)...`
2402
- );
2413
+ const executionSpinner = createSpinner(ctx.suppressOutput, `Executing ${epicTotal} epic(s)...`);
2403
2414
  const epicQueue = new PQueue3({ concurrency });
2404
2415
  const allTaskResults = await Promise.all(
2405
2416
  epicPlan.selectedEpics.map(
@@ -2565,7 +2576,6 @@ async function readMostRecentContributionLog(repoPath) {
2565
2576
  const parsed = contributionLogSchema.safeParse(JSON.parse(content));
2566
2577
  if (parsed.success) return parsed.data;
2567
2578
  } catch {
2568
- continue;
2569
2579
  }
2570
2580
  }
2571
2581
  return void 0;
@@ -2592,7 +2602,9 @@ async function runRetryPipeline(ctx, params) {
2592
2602
  if (!log) {
2593
2603
  retrySpinner?.fail("No contribution logs found in .oac/contributions/");
2594
2604
  if (!ctx.suppressOutput) {
2595
- console.log(ctx.ui.yellow("[oac] Run the pipeline at least once before using --retry-failed."));
2605
+ console.log(
2606
+ ctx.ui.yellow("[oac] Run the pipeline at least once before using --retry-failed.")
2607
+ );
2596
2608
  }
2597
2609
  return [];
2598
2610
  }
@@ -2818,10 +2830,8 @@ function parseTokens(value) {
2818
2830
  return parseInteger(value);
2819
2831
  }
2820
2832
  function createRunCommand() {
2821
- const command = new Command10("run");
2822
- command.alias("r").description(
2823
- "Run the full OAC pipeline \u2014 analyze, plan, and execute in one command"
2824
- ).option("--repo <owner/repo>", "Target repository (owner/repo or GitHub URL)").option("--tokens <value>", 'Token budget (number or "unlimited")', parseTokens).option("--provider <id>", "Agent provider id").option("--concurrency <number>", "Maximum parallel task executions", parseInteger).option("--dry-run", "Show plan without executing tasks", false).option("--mode <mode>", "Execution mode: new-pr|update-pr|direct-commit").option("--max-tasks <number>", "Maximum number of discovered tasks to consider", parseInteger).option("--timeout <seconds>", "Per-task timeout in seconds", parseInteger).option("--source <source>", "Filter tasks by source: lint, todo, github-issue, test-gap").option("--retry-failed", "Re-run only failed tasks from the most recent run", false).action(async (options, cmd) => {
2833
+ const command = new Command9("run");
2834
+ command.alias("r").description("Run the full OAC pipeline \u2014 analyze, plan, and execute in one command").option("--repo <owner/repo>", "Target repository (owner/repo or GitHub URL)").option("--tokens <value>", 'Token budget (number or "unlimited")', parseTokens).option("--provider <id>", "Agent provider id").option("--concurrency <number>", "Maximum parallel task executions", parseInteger).option("--dry-run", "Show plan without executing tasks", false).option("--mode <mode>", "Execution mode: new-pr|update-pr|direct-commit").option("--max-tasks <number>", "Maximum number of discovered tasks to consider", parseInteger).option("--timeout <seconds>", "Per-task timeout in seconds", parseInteger).option("--source <source>", "Filter tasks by source: lint, todo, github-issue, test-gap").option("--retry-failed", "Re-run only failed tasks from the most recent run", false).action(async (options, cmd) => {
2825
2835
  const globalOptions = getGlobalOptions(cmd);
2826
2836
  const ui = createUi(globalOptions);
2827
2837
  validateRunOptions(options);
@@ -2855,10 +2865,10 @@ Exit Codes:
2855
2865
 
2856
2866
  // src/cli/commands/scan.ts
2857
2867
  import Table7 from "cli-table3";
2858
- import { Command as Command11 } from "commander";
2868
+ import { Command as Command10 } from "commander";
2859
2869
  var SUPPORTED_SCANNERS = ["lint", "todo", "github-issues", "test-gap"];
2860
2870
  function createScanCommand() {
2861
- const command = new Command11("scan");
2871
+ const command = new Command10("scan");
2862
2872
  command.description("Quick task discovery \u2014 list individual issues ranked by priority").option("--repo <owner/repo>", "Target repository (owner/repo or GitHub URL)").option("--scanners <names>", "Comma-separated scanner filter (lint,todo)").option("--min-priority <number>", "Minimum priority threshold (0-100)", parseInteger, 20).option("--format <format>", "Output format: table|json", "table").action(async (options, cmd) => {
2863
2873
  const globalOptions = getGlobalOptions(cmd);
2864
2874
  const ui = createUi(globalOptions);
@@ -2891,6 +2901,7 @@ function createScanCommand() {
2891
2901
  const scannedTasks = await scannerSelection.scanner.scan(resolvedRepo.localPath, {
2892
2902
  exclude: config?.discovery.exclude,
2893
2903
  maxTasks: config?.discovery.maxTasks,
2904
+ issueLabels: config?.discovery.issueLabels,
2894
2905
  repo: resolvedRepo
2895
2906
  });
2896
2907
  scanSpinner?.succeed(`Scanned ${resolvedRepo.fullName}`);
@@ -3021,10 +3032,10 @@ function parseCsv(value) {
3021
3032
  // src/cli/commands/status.ts
3022
3033
  import { readFile as readFile6 } from "fs/promises";
3023
3034
  import { resolve as resolve7 } from "path";
3024
- import { Command as Command12 } from "commander";
3035
+ import { Command as Command11 } from "commander";
3025
3036
  var WATCH_INTERVAL_MS = 2e3;
3026
3037
  function createStatusCommand() {
3027
- const command = new Command12("status");
3038
+ const command = new Command11("status");
3028
3039
  command.description("Show current job status").option("--watch", "Poll every 2 seconds", false).action(async (options, cmd) => {
3029
3040
  const globalOptions = getGlobalOptions(cmd);
3030
3041
  const render = async () => {
@@ -3200,21 +3211,13 @@ function registerCommands(program) {
3200
3211
  program.addCommand(createExplainCommand());
3201
3212
  }
3202
3213
  async function createCliProgram() {
3203
- const version = true ? "2026.221.1" : "0.0.0";
3204
- const program = new Command13();
3214
+ const version = true ? "2026.222.1" : "0.0.0";
3215
+ const program = new Command12();
3205
3216
  program.name("oac").description("Open Agent Contribution CLI").version(version).option("--config <path>", "Config file path", "oac.config.ts").option("--verbose", "Enable verbose logging", false).option("--quiet", "Suppress non-error output", false).option("--json", "Output machine-readable JSON", false).option("--no-color", "Disable ANSI colors");
3206
3217
  registerCommands(program);
3207
3218
  program.addHelpText(
3208
3219
  "after",
3209
- `
3210
- Getting Started:
3211
- $ oac init Set up your project configuration
3212
- $ oac doctor Verify your environment is ready
3213
- $ oac analyze Analyze codebase for contribution opportunities
3214
- $ oac run Run the full contribution pipeline
3215
-
3216
- Documentation: https://github.com/Open330/open-agent-contribution
3217
- `
3220
+ "\nGetting Started:\n $ oac init Set up your project configuration\n $ oac doctor Verify your environment is ready\n $ oac analyze Analyze codebase for contribution opportunities\n $ oac run Run the full contribution pipeline\n\nDocumentation: https://github.com/Open330/open-agent-contribution\n"
3218
3221
  );
3219
3222
  return program;
3220
3223
  }
@@ -3230,4 +3233,4 @@ export {
3230
3233
  createCliProgram,
3231
3234
  runCli
3232
3235
  };
3233
- //# sourceMappingURL=chunk-E2C46KPJ.js.map
3236
+ //# sourceMappingURL=chunk-GPHH2IYN.js.map