@open330/oac 2026.221.2 → 2026.222.2

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.
Files changed (38) hide show
  1. package/README.md +170 -1
  2. package/dist/budget/index.js +1 -1
  3. package/dist/{chunk-EYUQMPVO.js → chunk-27FEE5KS.js} +86 -34
  4. package/dist/chunk-27FEE5KS.js.map +1 -0
  5. package/dist/{chunk-5GAUWC3L.js → chunk-ALBVUNUY.js} +1 -1
  6. package/dist/chunk-ALBVUNUY.js.map +1 -0
  7. package/dist/{chunk-VK33A5L4.js → chunk-ATVWSG75.js} +480 -232
  8. package/dist/chunk-ATVWSG75.js.map +1 -0
  9. package/dist/{chunk-7C7SC4TZ.js → chunk-I3TKNT4M.js} +9 -2
  10. package/dist/chunk-I3TKNT4M.js.map +1 -0
  11. package/dist/{chunk-6A37SKAJ.js → chunk-JDFAJP45.js} +1 -1
  12. package/dist/{chunk-6A37SKAJ.js.map → chunk-JDFAJP45.js.map} +1 -1
  13. package/dist/{chunk-OS3XDHOJ.js → chunk-UCYK4Z6O.js} +1 -1
  14. package/dist/chunk-UCYK4Z6O.js.map +1 -0
  15. package/dist/{chunk-OCCMKAJI.js → chunk-ZJBLRKCV.js} +3 -3
  16. package/dist/chunk-ZJBLRKCV.js.map +1 -0
  17. package/dist/cli/cli.js +7 -7
  18. package/dist/cli/index.js +7 -7
  19. package/dist/cli/index.js.map +1 -1
  20. package/dist/completion/index.d.ts +1 -1
  21. package/dist/completion/index.js +2 -2
  22. package/dist/completion/index.js.map +1 -1
  23. package/dist/{config-DequKoFA.d.ts → config-DnzZ7w92.d.ts} +60 -1
  24. package/dist/core/index.d.ts +1 -1
  25. package/dist/core/index.js +4 -2
  26. package/dist/dashboard/index.js +72 -23
  27. package/dist/dashboard/index.js.map +1 -1
  28. package/dist/discovery/index.d.ts +1 -1
  29. package/dist/discovery/index.js +2 -2
  30. package/dist/execution/index.js +3 -3
  31. package/dist/repo/index.js +1 -1
  32. package/package.json +13 -15
  33. package/dist/chunk-5GAUWC3L.js.map +0 -1
  34. package/dist/chunk-7C7SC4TZ.js.map +0 -1
  35. package/dist/chunk-EYUQMPVO.js.map +0 -1
  36. package/dist/chunk-OCCMKAJI.js.map +0 -1
  37. package/dist/chunk-OS3XDHOJ.js.map +0 -1
  38. package/dist/chunk-VK33A5L4.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/completion/github-pr.ts","../../src/completion/issue-linker.ts","../../src/completion/diff-validator.ts","../../src/completion/handler.ts"],"sourcesContent":["import type { Octokit } from \"@octokit/rest\";\nimport { type SimpleGit, simpleGit } from \"simple-git\";\nimport { type ResolvedRepo, completionError } from \"../core/index.js\";\n\nimport type { CreatedPR, PRCreationParams } from \"./types.js\";\n\ninterface PRDiffStats {\n filesChanged: number;\n linesAdded: number;\n linesRemoved: number;\n}\n\nexport async function createPR(params: PRCreationParams, octokit: Octokit): Promise<CreatedPR> {\n const { repo, task, result, branchName, baseBranch } = params;\n const pushedSha = await pushBranch(repo, branchName);\n const body = await buildPrBody(params);\n\n try {\n const created = await octokit.pulls.create({\n owner: repo.owner,\n repo: repo.name,\n title: `[OAC] ${task.title}`,\n body,\n head: branchName,\n base: baseBranch,\n draft: false,\n });\n\n await addLabels(octokit, repo, created.data.number, [\"oac-contribution\", task.source]);\n\n return {\n number: created.data.number,\n url: created.data.html_url,\n sha: created.data.head.sha || pushedSha,\n };\n } catch (error) {\n throw completionError(\n \"PR_CREATION_FAILED\",\n `Failed to create PR for \"${repo.fullName}\" on branch \"${branchName}\".`,\n {\n cause: error,\n context: {\n repo: repo.fullName,\n branchName,\n baseBranch,\n taskId: task.id,\n },\n },\n );\n }\n}\n\nexport async function pushBranch(repo: ResolvedRepo, branchName: string): Promise<string> {\n const git = simpleGit(resolveGitPath(repo));\n const headSha = (await git.revparse([\"HEAD\"])).trim();\n\n try {\n const remoteSha = await readRemoteBranchSha(git, branchName);\n if (remoteSha !== headSha) {\n await git.push(\"origin\", branchName);\n }\n } catch (error) {\n try {\n await git.raw([\"push\", \"--set-upstream\", \"origin\", branchName]);\n } catch (retryError) {\n throw completionError(\n \"PR_PUSH_REJECTED\",\n `Failed to push branch \"${branchName}\" for \"${repo.fullName}\".`,\n {\n cause: retryError,\n context: {\n repo: repo.fullName,\n branchName,\n headSha,\n initialError: error instanceof Error ? error.message : \"unknown push error\",\n },\n },\n );\n }\n }\n\n return headSha;\n}\n\nasync function buildPrBody(params: PRCreationParams): Promise<string> {\n const { repo, task, result, baseBranch, branchName } = params;\n const diffStats = await resolveDiffStats(repo, baseBranch, branchName);\n const linkedIssue = task.linkedIssue ? `\\nFixes #${task.linkedIssue.number}\\n` : \"\\n\";\n const agentLabel = resolveAgentLabel(task.metadata);\n const durationText = formatDurationSeconds(result.duration);\n const summaryText =\n task.description.trim().length > 0\n ? task.description.trim()\n : `Automated contribution for task \"${task.title}\".`;\n const filesChanged = result.filesChanged.length || diffStats.filesChanged;\n const filesPreview = renderFilesPreview(result.filesChanged);\n\n return [\n \"## Summary\",\n \"\",\n summaryText,\n \"\",\n \"## Changes\",\n \"\",\n filesPreview,\n \"\",\n `- **Files changed:** ${filesChanged}`,\n `- **Lines added:** ${diffStats.linesAdded}`,\n `- **Lines removed:** ${diffStats.linesRemoved}`,\n \"\",\n \"## Context\",\n \"\",\n `- **Task source:** ${task.source}`,\n `- **Agent:** ${agentLabel}`,\n `- **Tokens used:** ${result.totalTokensUsed}`,\n `- **Execution time:** ${durationText}`,\n linkedIssue.trimEnd(),\n \"\",\n \"---\",\n \"*This PR was automatically generated by OAC.*\",\n ].join(\"\\n\");\n}\n\nasync function resolveDiffStats(\n repo: ResolvedRepo,\n baseBranch: string,\n branchName: string,\n): Promise<PRDiffStats> {\n const git = simpleGit(resolveGitPath(repo));\n const ranges = [\n [`origin/${baseBranch}...${branchName}`],\n [`${baseBranch}...${branchName}`],\n [\"HEAD\"],\n [],\n ] as string[][];\n\n for (const range of ranges) {\n try {\n const summary = await git.diffSummary(range);\n return {\n filesChanged: summary.changed,\n linesAdded: summary.insertions,\n linesRemoved: summary.deletions,\n };\n } catch {} // best-effort: diff stats are optional\n }\n\n return {\n filesChanged: 0,\n linesAdded: 0,\n linesRemoved: 0,\n };\n}\n\nasync function addLabels(\n octokit: Octokit,\n repo: ResolvedRepo,\n prNumber: number,\n labels: string[],\n): Promise<void> {\n const uniqueLabels = [...new Set(labels.map((label) => label.trim()).filter(Boolean))];\n if (uniqueLabels.length === 0) {\n return;\n }\n\n try {\n await octokit.issues.addLabels({\n owner: repo.owner,\n repo: repo.name,\n issue_number: prNumber,\n labels: uniqueLabels,\n });\n } catch {\n // Labeling failure should not block PR creation.\n }\n}\n\nfunction resolveGitPath(repo: ResolvedRepo): string {\n return repo.worktreePath.trim().length > 0 ? repo.worktreePath : repo.localPath;\n}\n\nasync function readRemoteBranchSha(\n git: SimpleGit,\n branchName: string,\n): Promise<string | undefined> {\n const remoteHeads = await git.listRemote([\"--heads\", \"origin\", branchName]);\n const firstLine = remoteHeads\n .split(\"\\n\")\n .map((line) => line.trim())\n .find((line) => line.length > 0);\n\n if (!firstLine) {\n return undefined;\n }\n\n const [sha] = firstLine.split(/\\s+/);\n return sha;\n}\n\nfunction resolveAgentLabel(metadata: Record<string, unknown>): string {\n const fromAgent = readMetadataString(metadata, [\"agent\", \"agentName\", \"provider\"]);\n return fromAgent ?? \"unknown\";\n}\n\nfunction readMetadataString(metadata: Record<string, unknown>, keys: string[]): string | undefined {\n for (const key of keys) {\n const value = metadata[key];\n if (typeof value === \"string\" && value.trim().length > 0) {\n return value.trim();\n }\n }\n return undefined;\n}\n\nfunction renderFilesPreview(files: string[]): string {\n if (files.length === 0) {\n return \"- No file list was reported by the execution step.\";\n }\n\n const preview = files.slice(0, 15).map((path) => `- \\`${path}\\``);\n if (files.length > 15) {\n preview.push(`- ...and ${files.length - 15} more file(s)`);\n }\n\n return preview.join(\"\\n\");\n}\n\nfunction formatDurationSeconds(duration: number): string {\n if (!Number.isFinite(duration) || duration <= 0) {\n return \"0s\";\n }\n\n const seconds = duration > 1_000 ? duration / 1_000 : duration;\n if (seconds >= 100) {\n return `${Math.round(seconds)}s`;\n }\n\n return `${seconds.toFixed(1)}s`;\n}\n","import type { Octokit } from \"@octokit/rest\";\nimport { type ResolvedRepo, type Task, completionError } from \"../core/index.js\";\n\nimport type { CreatedPR } from \"./types.js\";\n\nexport async function linkIssueToePR(\n repo: ResolvedRepo,\n task: Task,\n pr: CreatedPR,\n octokit: Octokit,\n): Promise<void> {\n if (!task.linkedIssue) {\n return;\n }\n\n const issueNumber = task.linkedIssue.number;\n\n try {\n const issue = await octokit.issues.get({\n owner: repo.owner,\n repo: repo.name,\n issue_number: issueNumber,\n });\n\n if (issue.data.state === \"closed\") {\n return;\n }\n\n await octokit.issues.createComment({\n owner: repo.owner,\n repo: repo.name,\n issue_number: issueNumber,\n body: `OAC opened a PR for this issue: ${pr.url}`,\n });\n } catch (error) {\n if (isNonBlockingIssueError(error)) {\n return;\n }\n\n throw completionError(\n \"PR_CREATION_FAILED\",\n `Failed to link issue #${issueNumber} to PR #${pr.number}.`,\n {\n cause: error,\n context: {\n repo: repo.fullName,\n issueNumber,\n prNumber: pr.number,\n },\n },\n );\n }\n}\n\nexport const linkIssueToPR = linkIssueToePR;\n\nfunction isNonBlockingIssueError(error: unknown): boolean {\n if (!isStatusError(error)) {\n return false;\n }\n\n return error.status === 404 || error.status === 410 || error.status === 422;\n}\n\nfunction isStatusError(error: unknown): error is { status?: number } {\n return typeof error === \"object\" && error !== null && \"status\" in error;\n}\n","import { basename } from \"node:path\";\n\nimport { type SimpleGit, simpleGit } from \"simple-git\";\nimport type { OacConfig } from \"../core/index.js\";\nimport { truncate } from \"../core/utils.js\";\n\nconst DEFAULT_MAX_DIFF_LINES = 500;\nconst DEFAULT_FORBIDDEN_PATTERNS: RegExp[] = [\n /eval\\s*\\(/,\n /new\\s+Function\\s*\\(/,\n /child_process/,\n /\\bexecSync\\s*\\(/,\n /\\bspawnSync\\s*\\(/,\n];\nconst DEFAULT_PROTECTED_FILES = [\".env*\", \"*.pem\", \"*.key\"];\n\ninterface ResolvedValidationConfig {\n maxDiffLines: number;\n forbiddenPatterns: RegExp[];\n protectedFiles: string[];\n}\n\nexport interface DiffValidationConfig {\n maxDiffLines?: number;\n forbiddenPatterns?: RegExp[];\n protectedFiles?: string[];\n}\n\nexport interface ValidationResult {\n valid: boolean;\n warnings: string[];\n errors: string[];\n}\n\nexport async function validateDiff(\n repoPath: string,\n config?: DiffValidationConfig | OacConfig,\n): Promise<ValidationResult> {\n const git = simpleGit(repoPath);\n const settings = resolveValidationConfig(config);\n const warnings: string[] = [];\n const errors: string[] = [];\n\n const [diffSummary, changedFiles, patch] = await Promise.all([\n readDiffSummary(git),\n readChangedFiles(git),\n readPatch(git),\n ]);\n\n const totalLinesChanged = diffSummary.insertions + diffSummary.deletions;\n if (totalLinesChanged > settings.maxDiffLines) {\n errors.push(\n `Diff too large: ${totalLinesChanged} changed lines exceeds maxDiffLines=${settings.maxDiffLines}.`,\n );\n } else if (totalLinesChanged > Math.floor(settings.maxDiffLines * 0.8)) {\n warnings.push(\n `Diff is near the maximum size (${totalLinesChanged}/${settings.maxDiffLines} changed lines).`,\n );\n }\n\n if (totalLinesChanged === 0) {\n warnings.push(\"No changed lines detected in the current diff.\");\n }\n\n const protectedFileHits = changedFiles.filter((path) =>\n settings.protectedFiles.some((pattern) => matchesGlob(path, pattern)),\n );\n if (protectedFileHits.length > 0) {\n errors.push(`Protected files were modified: ${protectedFileHits.join(\", \")}.`);\n }\n\n const forbiddenHits = findForbiddenPatternHits(patch, settings.forbiddenPatterns);\n errors.push(...forbiddenHits);\n\n return {\n valid: errors.length === 0,\n warnings,\n errors,\n };\n}\n\nasync function readDiffSummary(git: SimpleGit) {\n try {\n return await git.diffSummary([\"HEAD\"]);\n } catch {\n return git.diffSummary();\n }\n}\n\nasync function readChangedFiles(git: SimpleGit): Promise<string[]> {\n const withHead = await tryGitDiff(git, [\"--name-only\", \"HEAD\"]);\n const output = withHead ?? (await git.diff([\"--name-only\"]));\n\n return output\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter((line) => line.length > 0);\n}\n\nasync function readPatch(git: SimpleGit): Promise<string> {\n const withHead = await tryGitDiff(git, [\"--no-color\", \"--unified=0\", \"HEAD\"]);\n if (withHead !== undefined) {\n return withHead;\n }\n return git.diff([\"--no-color\", \"--unified=0\"]);\n}\n\nasync function tryGitDiff(git: SimpleGit, args: string[]): Promise<string | undefined> {\n try {\n return await git.diff(args);\n } catch {\n return undefined;\n }\n}\n\nfunction resolveValidationConfig(\n config?: DiffValidationConfig | OacConfig,\n): ResolvedValidationConfig {\n const diffConfig = isOacConfig(config) ? undefined : config;\n const maxDiffLines = isOacConfig(config)\n ? config.execution.validation.maxDiffLines\n : diffConfig?.maxDiffLines;\n\n return {\n maxDiffLines:\n typeof maxDiffLines === \"number\" && maxDiffLines > 0\n ? Math.floor(maxDiffLines)\n : DEFAULT_MAX_DIFF_LINES,\n forbiddenPatterns:\n Array.isArray(diffConfig?.forbiddenPatterns) && diffConfig.forbiddenPatterns.length > 0\n ? diffConfig.forbiddenPatterns\n : DEFAULT_FORBIDDEN_PATTERNS,\n protectedFiles:\n Array.isArray(diffConfig?.protectedFiles) && diffConfig.protectedFiles.length > 0\n ? diffConfig.protectedFiles\n : DEFAULT_PROTECTED_FILES,\n };\n}\n\nfunction isOacConfig(value: DiffValidationConfig | OacConfig | undefined): value is OacConfig {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"execution\" in value &&\n typeof (value as { execution?: unknown }).execution === \"object\"\n );\n}\n\nfunction findForbiddenPatternHits(diffPatch: string, patterns: RegExp[]): string[] {\n const hits = new Set<string>();\n let currentFile = \"(unknown)\";\n\n for (const line of diffPatch.split(\"\\n\")) {\n if (line.startsWith(\"+++ b/\")) {\n currentFile = line.slice(\"+++ b/\".length).trim();\n continue;\n }\n\n if (!line.startsWith(\"+\") || line.startsWith(\"+++\")) {\n continue;\n }\n\n const addedLine = line.slice(1);\n for (const pattern of patterns) {\n if (patternMatches(pattern, addedLine)) {\n const preview = truncate(addedLine.trim(), 120);\n hits.add(`Forbidden pattern \"${pattern}\" found in ${currentFile}: \"${preview}\".`);\n }\n }\n }\n\n return [...hits];\n}\n\nfunction patternMatches(pattern: RegExp, input: string): boolean {\n const normalizedFlags = pattern.flags.replaceAll(\"g\", \"\");\n const matcher = new RegExp(pattern.source, normalizedFlags);\n return matcher.test(input);\n}\n\nfunction matchesGlob(path: string, pattern: string): boolean {\n const regex = globToRegex(pattern);\n const filename = basename(path);\n return regex.test(path) || regex.test(filename);\n}\n\nfunction globToRegex(glob: string): RegExp {\n const escaped = glob.replaceAll(/[-/\\\\^$+?.()|[\\]{}]/g, \"\\\\$&\").replaceAll(\"*\", \".*\");\n return new RegExp(`^${escaped}$`);\n}\n\n\n","import type { Octokit } from \"@octokit/rest\";\nimport {\n type OacConfig,\n OacError,\n type OacEventBus,\n type ResolvedRepo,\n type Task,\n completionError,\n executionError,\n} from \"../core/index.js\";\n\nimport {\n type DiffValidationConfig,\n type ValidationResult,\n validateDiff,\n} from \"./diff-validator.js\";\nimport { createPR, pushBranch } from \"./github-pr.js\";\nimport { linkIssueToePR } from \"./issue-linker.js\";\nimport type {\n CompletionResult,\n CreatedPR,\n ExternalTaskRef,\n PRCreationParams,\n ProjectManagementProvider,\n} from \"./types.js\";\n\nexport interface CompletionHandlerOptions {\n octokit: Octokit;\n eventBus: OacEventBus;\n providers?: ProjectManagementProvider[];\n diffValidationConfig?: DiffValidationConfig | OacConfig;\n}\n\nexport interface CompletionHandlerParams extends PRCreationParams {\n jobId: string;\n externalTaskRef?: ExternalTaskRef;\n diffValidationConfig?: DiffValidationConfig | OacConfig;\n}\n\nexport class CompletionHandler {\n private readonly octokit: Octokit;\n private readonly eventBus: OacEventBus;\n private readonly providers: ProjectManagementProvider[];\n private readonly diffValidationConfig?: DiffValidationConfig | OacConfig;\n\n public constructor(options: CompletionHandlerOptions) {\n this.octokit = options.octokit;\n this.eventBus = options.eventBus;\n this.providers = options.providers ?? [];\n this.diffValidationConfig = options.diffValidationConfig;\n }\n\n public async handle(params: CompletionHandlerParams): Promise<CompletionResult> {\n return this.complete(params);\n }\n\n public async complete(params: CompletionHandlerParams): Promise<CompletionResult> {\n const warnings: string[] = [];\n const externalTaskRef = this.resolveExternalTaskRef(params.task, params.externalTaskRef);\n\n try {\n this.emitProgress(params.jobId, params.result.totalTokensUsed, \"completion:validateDiff\");\n const validation = await validateDiff(\n resolveRepoPath(params.repo),\n params.diffValidationConfig ?? this.diffValidationConfig,\n );\n this.handleValidationResult(validation);\n warnings.push(...validation.warnings);\n\n this.emitProgress(params.jobId, params.result.totalTokensUsed, \"completion:duplicatePRGuard\");\n const duplicatePr = await this.findExistingOacPR(params.repo, params.task);\n if (duplicatePr) {\n const skipMsg = `Skipped: existing OAC PR #${duplicatePr} already targets issue #${params.task.linkedIssue?.number ?? \"unknown\"}.`;\n warnings.push(skipMsg);\n return {\n summary: skipMsg,\n filesChanged: params.result.filesChanged.length,\n tokensUsed: params.result.totalTokensUsed,\n };\n }\n\n warnings.push(...(await this.notifyStarted(externalTaskRef)));\n\n this.emitProgress(params.jobId, params.result.totalTokensUsed, \"completion:pushBranch\");\n await pushBranch(params.repo, params.branchName);\n\n this.emitProgress(params.jobId, params.result.totalTokensUsed, \"completion:createPR\");\n const pr = await createPR(params, this.octokit);\n this.eventBus.emit(\"pr:created\", { jobId: params.jobId, prUrl: pr.url });\n\n this.emitProgress(params.jobId, params.result.totalTokensUsed, \"completion:linkIssue\");\n const linkIssueWarning = await this.tryLinkIssue(params.repo, params.task, pr);\n if (linkIssueWarning) {\n warnings.push(linkIssueWarning);\n }\n\n this.emitProgress(params.jobId, params.result.totalTokensUsed, \"completion:notifyWebhooks\");\n warnings.push(...(await this.notifyPRCreated(externalTaskRef, pr)));\n\n const completionResult = buildCompletionResult(params, pr, warnings);\n warnings.push(...(await this.notifyCompleted(externalTaskRef, completionResult)));\n\n return completionResult;\n } catch (error) {\n const normalizedError = this.normalizePipelineError(error, params);\n this.eventBus.emit(\"execution:failed\", {\n jobId: params.jobId,\n error: normalizedError,\n });\n await this.notifyFailed(externalTaskRef, normalizedError.message);\n throw normalizedError;\n }\n }\n\n private emitProgress(jobId: string, tokensUsed: number, stage: string): void {\n this.eventBus.emit(\"execution:progress\", {\n jobId,\n tokensUsed,\n stage,\n });\n }\n\n private handleValidationResult(validation: ValidationResult): void {\n if (validation.valid) {\n return;\n }\n\n const hasForbiddenPattern = validation.errors.some((message) =>\n message.toLowerCase().includes(\"forbidden pattern\"),\n );\n const errorCode = hasForbiddenPattern\n ? \"VALIDATION_FORBIDDEN_PATTERN\"\n : \"VALIDATION_DIFF_TOO_LARGE\";\n\n throw executionError(errorCode, \"Diff validation failed.\", {\n context: {\n errors: validation.errors,\n warnings: validation.warnings,\n },\n });\n }\n\n private async tryLinkIssue(\n repo: ResolvedRepo,\n task: Task,\n pr: CreatedPR,\n ): Promise<string | undefined> {\n try {\n await linkIssueToePR(repo, task, pr, this.octokit);\n return undefined;\n } catch (error) {\n return `Issue linking warning: ${toErrorMessage(error)}`;\n }\n }\n\n private async notifyStarted(ref: ExternalTaskRef | undefined): Promise<string[]> {\n return this.notifyProviders(ref, \"notifyStarted\", (provider, taskRef) =>\n provider.notifyStarted(taskRef),\n );\n }\n\n private async notifyPRCreated(\n ref: ExternalTaskRef | undefined,\n pr: CreatedPR,\n ): Promise<string[]> {\n return this.notifyProviders(ref, \"notifyPRCreated\", (provider, taskRef) =>\n provider.notifyPRCreated(taskRef, pr.url),\n );\n }\n\n private async notifyCompleted(\n ref: ExternalTaskRef | undefined,\n result: CompletionResult,\n ): Promise<string[]> {\n return this.notifyProviders(ref, \"notifyCompleted\", (provider, taskRef) =>\n provider.notifyCompleted(taskRef, result),\n );\n }\n\n private async notifyFailed(ref: ExternalTaskRef | undefined, message: string): Promise<void> {\n await this.notifyProviders(ref, \"notifyFailed\", (provider, taskRef) =>\n provider.notifyFailed(taskRef, message),\n );\n }\n\n private async notifyProviders(\n ref: ExternalTaskRef | undefined,\n operationName: string,\n operation: (provider: ProjectManagementProvider, taskRef: ExternalTaskRef) => Promise<void>,\n ): Promise<string[]> {\n if (!ref) {\n return [];\n }\n\n const selectedProviders = this.providers.filter((provider) => provider.id === ref.provider);\n if (selectedProviders.length === 0) {\n return [];\n }\n\n const results = await Promise.allSettled(\n selectedProviders.map(async (provider) => {\n const isReachable = await provider.ping();\n if (!isReachable) {\n throw new Error(`Provider \"${provider.id}\" is unreachable.`);\n }\n await operation(provider, ref);\n }),\n );\n\n const warnings: string[] = [];\n for (let index = 0; index < results.length; index += 1) {\n const result = results[index];\n if (result.status === \"fulfilled\") {\n continue;\n }\n\n warnings.push(\n `${operationName} failed for provider \"${\n selectedProviders[index].id\n }\": ${toErrorMessage(result.reason)}`,\n );\n }\n\n return warnings;\n }\n\n /**\n * Pre-PR guard: checks for an existing open OAC pull request that already\n * targets the same issue. Returns the PR number if a duplicate exists.\n */\n private async findExistingOacPR(\n repo: ResolvedRepo,\n task: Task,\n ): Promise<number | undefined> {\n if (!task.linkedIssue) {\n return undefined;\n }\n\n const issueNumber = task.linkedIssue.number;\n\n try {\n const { data: pulls } = await this.octokit.pulls.list({\n owner: repo.owner,\n repo: repo.name,\n state: \"open\",\n per_page: 100,\n sort: \"updated\",\n direction: \"desc\",\n });\n\n const issueRefPattern = /(?:Fixes|Closes|Resolves)\\s+#(\\d+)/gi;\n for (const pr of pulls) {\n if (!pr.title.startsWith(\"[OAC]\")) continue;\n\n const body = pr.body ?? \"\";\n for (const match of body.matchAll(issueRefPattern)) {\n const num = Number.parseInt(match[1], 10);\n if (num === issueNumber) {\n return pr.number;\n }\n }\n }\n\n return undefined;\n } catch {\n // Guard failure should not block PR creation.\n return undefined;\n }\n }\n\n private resolveExternalTaskRef(\n task: Task,\n providedRef?: ExternalTaskRef,\n ): ExternalTaskRef | undefined {\n if (providedRef) {\n return providedRef;\n }\n\n if (task.linkedIssue) {\n return {\n provider: \"github\",\n externalId: `#${task.linkedIssue.number}`,\n url: task.linkedIssue.url,\n };\n }\n\n const metadata = task.metadata as Record<string, unknown>;\n const provider = readMetadataString(metadata, \"externalProvider\");\n const externalId = readMetadataString(metadata, \"externalId\");\n const url = readMetadataString(metadata, \"externalUrl\");\n\n if (!provider || !externalId) {\n return undefined;\n }\n\n return { provider, externalId, url };\n }\n\n private normalizePipelineError(error: unknown, params: CompletionHandlerParams): OacError {\n if (error instanceof OacError) {\n return error;\n }\n\n return completionError(\n \"PR_CREATION_FAILED\",\n `Completion pipeline failed for task \"${params.task.id}\" in \"${params.repo.fullName}\": ${toErrorMessage(\n error,\n )}`,\n {\n cause: error,\n context: {\n jobId: params.jobId,\n taskId: params.task.id,\n repo: params.repo.fullName,\n branchName: params.branchName,\n },\n },\n );\n }\n}\n\nfunction buildCompletionResult(\n params: CompletionHandlerParams,\n pr: CreatedPR,\n warnings: string[],\n): CompletionResult {\n const filesChanged = params.result.filesChanged.length;\n const warningSuffix = warnings.length > 0 ? ` Completed with ${warnings.length} warning(s).` : \"\";\n\n return {\n prUrl: pr.url,\n commitSha: pr.sha,\n summary: `Created PR #${pr.number} for \"${params.task.title}\".${warningSuffix}`,\n filesChanged,\n tokensUsed: params.result.totalTokensUsed,\n };\n}\n\nfunction resolveRepoPath(repo: ResolvedRepo): string {\n return repo.worktreePath.trim().length > 0 ? repo.worktreePath : repo.localPath;\n}\n\nfunction readMetadataString(metadata: Record<string, unknown>, key: string): string | undefined {\n const value = metadata[key];\n if (typeof value === \"string\" && value.trim().length > 0) {\n return value.trim();\n }\n return undefined;\n}\n\nfunction toErrorMessage(error: unknown): string {\n if (error instanceof Error && error.message.trim().length > 0) {\n return error.message.trim();\n }\n return \"Unknown error\";\n}\n"],"mappings":"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","names":["simpleGit","simpleGit","readMetadataString"]}
1
+ {"version":3,"sources":["../../src/completion/github-pr.ts","../../src/completion/issue-linker.ts","../../src/completion/diff-validator.ts","../../src/completion/handler.ts"],"sourcesContent":["import type { Octokit } from \"@octokit/rest\";\nimport { type SimpleGit, simpleGit } from \"simple-git\";\nimport { type ResolvedRepo, completionError } from \"../core/index.js\";\n\nimport type { CreatedPR, PRCreationParams } from \"./types.js\";\n\ninterface PRDiffStats {\n filesChanged: number;\n linesAdded: number;\n linesRemoved: number;\n}\n\nexport async function createPR(params: PRCreationParams, octokit: Octokit): Promise<CreatedPR> {\n const { repo, task, result, branchName, baseBranch } = params;\n const pushedSha = await pushBranch(repo, branchName);\n const body = await buildPrBody(params);\n\n try {\n const created = await octokit.pulls.create({\n owner: repo.owner,\n repo: repo.name,\n title: `[OAC] ${task.title}`,\n body,\n head: branchName,\n base: baseBranch,\n draft: false,\n });\n\n await addLabels(octokit, repo, created.data.number, [\"oac-contribution\", task.source]);\n\n return {\n number: created.data.number,\n url: created.data.html_url,\n sha: created.data.head.sha || pushedSha,\n };\n } catch (error) {\n throw completionError(\n \"PR_CREATION_FAILED\",\n `Failed to create PR for \"${repo.fullName}\" on branch \"${branchName}\".`,\n {\n cause: error,\n context: {\n repo: repo.fullName,\n branchName,\n baseBranch,\n taskId: task.id,\n },\n },\n );\n }\n}\n\nexport async function pushBranch(repo: ResolvedRepo, branchName: string): Promise<string> {\n const git = simpleGit(resolveGitPath(repo));\n const headSha = (await git.revparse([\"HEAD\"])).trim();\n\n try {\n const remoteSha = await readRemoteBranchSha(git, branchName);\n if (remoteSha !== headSha) {\n await git.push(\"origin\", branchName);\n }\n } catch (error) {\n try {\n await git.raw([\"push\", \"--set-upstream\", \"origin\", branchName]);\n } catch (retryError) {\n throw completionError(\n \"PR_PUSH_REJECTED\",\n `Failed to push branch \"${branchName}\" for \"${repo.fullName}\".`,\n {\n cause: retryError,\n context: {\n repo: repo.fullName,\n branchName,\n headSha,\n initialError: error instanceof Error ? error.message : \"unknown push error\",\n },\n },\n );\n }\n }\n\n return headSha;\n}\n\nasync function buildPrBody(params: PRCreationParams): Promise<string> {\n const { repo, task, result, baseBranch, branchName } = params;\n const diffStats = await resolveDiffStats(repo, baseBranch, branchName);\n const linkedIssue = task.linkedIssue ? `\\nFixes #${task.linkedIssue.number}\\n` : \"\\n\";\n const agentLabel = resolveAgentLabel(task.metadata);\n const durationText = formatDurationSeconds(result.duration);\n const summaryText =\n task.description.trim().length > 0\n ? task.description.trim()\n : `Automated contribution for task \"${task.title}\".`;\n const filesChanged = result.filesChanged.length || diffStats.filesChanged;\n const filesPreview = renderFilesPreview(result.filesChanged);\n\n return [\n \"## Summary\",\n \"\",\n summaryText,\n \"\",\n \"## Changes\",\n \"\",\n filesPreview,\n \"\",\n `- **Files changed:** ${filesChanged}`,\n `- **Lines added:** ${diffStats.linesAdded}`,\n `- **Lines removed:** ${diffStats.linesRemoved}`,\n \"\",\n \"## Context\",\n \"\",\n `- **Task source:** ${task.source}`,\n `- **Agent:** ${agentLabel}`,\n `- **Tokens used:** ${result.totalTokensUsed}`,\n `- **Execution time:** ${durationText}`,\n linkedIssue.trimEnd(),\n \"\",\n \"---\",\n \"*This PR was automatically generated by OAC.*\",\n ].join(\"\\n\");\n}\n\nasync function resolveDiffStats(\n repo: ResolvedRepo,\n baseBranch: string,\n branchName: string,\n): Promise<PRDiffStats> {\n const git = simpleGit(resolveGitPath(repo));\n const ranges = [\n [`origin/${baseBranch}...${branchName}`],\n [`${baseBranch}...${branchName}`],\n [\"HEAD\"],\n [],\n ] as string[][];\n\n for (const range of ranges) {\n try {\n const summary = await git.diffSummary(range);\n return {\n filesChanged: summary.changed,\n linesAdded: summary.insertions,\n linesRemoved: summary.deletions,\n };\n } catch {} // best-effort: diff stats are optional\n }\n\n return {\n filesChanged: 0,\n linesAdded: 0,\n linesRemoved: 0,\n };\n}\n\nasync function addLabels(\n octokit: Octokit,\n repo: ResolvedRepo,\n prNumber: number,\n labels: string[],\n): Promise<void> {\n const uniqueLabels = [...new Set(labels.map((label) => label.trim()).filter(Boolean))];\n if (uniqueLabels.length === 0) {\n return;\n }\n\n try {\n await octokit.issues.addLabels({\n owner: repo.owner,\n repo: repo.name,\n issue_number: prNumber,\n labels: uniqueLabels,\n });\n } catch {\n // Labeling failure should not block PR creation.\n }\n}\n\nfunction resolveGitPath(repo: ResolvedRepo): string {\n return repo.worktreePath.trim().length > 0 ? repo.worktreePath : repo.localPath;\n}\n\nasync function readRemoteBranchSha(\n git: SimpleGit,\n branchName: string,\n): Promise<string | undefined> {\n const remoteHeads = await git.listRemote([\"--heads\", \"origin\", branchName]);\n const firstLine = remoteHeads\n .split(\"\\n\")\n .map((line) => line.trim())\n .find((line) => line.length > 0);\n\n if (!firstLine) {\n return undefined;\n }\n\n const [sha] = firstLine.split(/\\s+/);\n return sha;\n}\n\nfunction resolveAgentLabel(metadata: Record<string, unknown>): string {\n const fromAgent = readMetadataString(metadata, [\"agent\", \"agentName\", \"provider\"]);\n return fromAgent ?? \"unknown\";\n}\n\nfunction readMetadataString(metadata: Record<string, unknown>, keys: string[]): string | undefined {\n for (const key of keys) {\n const value = metadata[key];\n if (typeof value === \"string\" && value.trim().length > 0) {\n return value.trim();\n }\n }\n return undefined;\n}\n\nfunction renderFilesPreview(files: string[]): string {\n if (files.length === 0) {\n return \"- No file list was reported by the execution step.\";\n }\n\n const preview = files.slice(0, 15).map((path) => `- \\`${path}\\``);\n if (files.length > 15) {\n preview.push(`- ...and ${files.length - 15} more file(s)`);\n }\n\n return preview.join(\"\\n\");\n}\n\nfunction formatDurationSeconds(duration: number): string {\n if (!Number.isFinite(duration) || duration <= 0) {\n return \"0s\";\n }\n\n const seconds = duration > 1_000 ? duration / 1_000 : duration;\n if (seconds >= 100) {\n return `${Math.round(seconds)}s`;\n }\n\n return `${seconds.toFixed(1)}s`;\n}\n","import type { Octokit } from \"@octokit/rest\";\nimport { type ResolvedRepo, type Task, completionError } from \"../core/index.js\";\n\nimport type { CreatedPR } from \"./types.js\";\n\nexport async function linkIssueToePR(\n repo: ResolvedRepo,\n task: Task,\n pr: CreatedPR,\n octokit: Octokit,\n): Promise<void> {\n if (!task.linkedIssue) {\n return;\n }\n\n const issueNumber = task.linkedIssue.number;\n\n try {\n const issue = await octokit.issues.get({\n owner: repo.owner,\n repo: repo.name,\n issue_number: issueNumber,\n });\n\n if (issue.data.state === \"closed\") {\n return;\n }\n\n await octokit.issues.createComment({\n owner: repo.owner,\n repo: repo.name,\n issue_number: issueNumber,\n body: `OAC opened a PR for this issue: ${pr.url}`,\n });\n } catch (error) {\n if (isNonBlockingIssueError(error)) {\n return;\n }\n\n throw completionError(\n \"PR_CREATION_FAILED\",\n `Failed to link issue #${issueNumber} to PR #${pr.number}.`,\n {\n cause: error,\n context: {\n repo: repo.fullName,\n issueNumber,\n prNumber: pr.number,\n },\n },\n );\n }\n}\n\nexport const linkIssueToPR = linkIssueToePR;\n\nfunction isNonBlockingIssueError(error: unknown): boolean {\n if (!isStatusError(error)) {\n return false;\n }\n\n return error.status === 404 || error.status === 410 || error.status === 422;\n}\n\nfunction isStatusError(error: unknown): error is { status?: number } {\n return typeof error === \"object\" && error !== null && \"status\" in error;\n}\n","import { basename } from \"node:path\";\n\nimport { type SimpleGit, simpleGit } from \"simple-git\";\nimport type { OacConfig } from \"../core/index.js\";\nimport { truncate } from \"../core/utils.js\";\n\nconst DEFAULT_MAX_DIFF_LINES = 500;\nconst DEFAULT_FORBIDDEN_PATTERNS: RegExp[] = [\n /eval\\s*\\(/,\n /new\\s+Function\\s*\\(/,\n /child_process/,\n /\\bexecSync\\s*\\(/,\n /\\bspawnSync\\s*\\(/,\n];\nconst DEFAULT_PROTECTED_FILES = [\".env*\", \"*.pem\", \"*.key\"];\n\ninterface ResolvedValidationConfig {\n maxDiffLines: number;\n forbiddenPatterns: RegExp[];\n protectedFiles: string[];\n}\n\nexport interface DiffValidationConfig {\n maxDiffLines?: number;\n forbiddenPatterns?: RegExp[];\n protectedFiles?: string[];\n}\n\nexport interface ValidationResult {\n valid: boolean;\n warnings: string[];\n errors: string[];\n}\n\nexport async function validateDiff(\n repoPath: string,\n config?: DiffValidationConfig | OacConfig,\n): Promise<ValidationResult> {\n const git = simpleGit(repoPath);\n const settings = resolveValidationConfig(config);\n const warnings: string[] = [];\n const errors: string[] = [];\n\n const [diffSummary, changedFiles, patch] = await Promise.all([\n readDiffSummary(git),\n readChangedFiles(git),\n readPatch(git),\n ]);\n\n const totalLinesChanged = diffSummary.insertions + diffSummary.deletions;\n if (totalLinesChanged > settings.maxDiffLines) {\n errors.push(\n `Diff too large: ${totalLinesChanged} changed lines exceeds maxDiffLines=${settings.maxDiffLines}.`,\n );\n } else if (totalLinesChanged > Math.floor(settings.maxDiffLines * 0.8)) {\n warnings.push(\n `Diff is near the maximum size (${totalLinesChanged}/${settings.maxDiffLines} changed lines).`,\n );\n }\n\n if (totalLinesChanged === 0) {\n warnings.push(\"No changed lines detected in the current diff.\");\n }\n\n const protectedFileHits = changedFiles.filter((path) =>\n settings.protectedFiles.some((pattern) => matchesGlob(path, pattern)),\n );\n if (protectedFileHits.length > 0) {\n errors.push(`Protected files were modified: ${protectedFileHits.join(\", \")}.`);\n }\n\n const forbiddenHits = findForbiddenPatternHits(patch, settings.forbiddenPatterns);\n errors.push(...forbiddenHits);\n\n return {\n valid: errors.length === 0,\n warnings,\n errors,\n };\n}\n\nasync function readDiffSummary(git: SimpleGit) {\n try {\n return await git.diffSummary([\"HEAD\"]);\n } catch {\n return git.diffSummary();\n }\n}\n\nasync function readChangedFiles(git: SimpleGit): Promise<string[]> {\n const withHead = await tryGitDiff(git, [\"--name-only\", \"HEAD\"]);\n const output = withHead ?? (await git.diff([\"--name-only\"]));\n\n return output\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter((line) => line.length > 0);\n}\n\nasync function readPatch(git: SimpleGit): Promise<string> {\n const withHead = await tryGitDiff(git, [\"--no-color\", \"--unified=0\", \"HEAD\"]);\n if (withHead !== undefined) {\n return withHead;\n }\n return git.diff([\"--no-color\", \"--unified=0\"]);\n}\n\nasync function tryGitDiff(git: SimpleGit, args: string[]): Promise<string | undefined> {\n try {\n return await git.diff(args);\n } catch {\n return undefined;\n }\n}\n\nfunction resolveValidationConfig(\n config?: DiffValidationConfig | OacConfig,\n): ResolvedValidationConfig {\n const diffConfig = isOacConfig(config) ? undefined : config;\n const maxDiffLines = isOacConfig(config)\n ? config.execution.validation.maxDiffLines\n : diffConfig?.maxDiffLines;\n\n return {\n maxDiffLines:\n typeof maxDiffLines === \"number\" && maxDiffLines > 0\n ? Math.floor(maxDiffLines)\n : DEFAULT_MAX_DIFF_LINES,\n forbiddenPatterns:\n Array.isArray(diffConfig?.forbiddenPatterns) && diffConfig.forbiddenPatterns.length > 0\n ? diffConfig.forbiddenPatterns\n : DEFAULT_FORBIDDEN_PATTERNS,\n protectedFiles:\n Array.isArray(diffConfig?.protectedFiles) && diffConfig.protectedFiles.length > 0\n ? diffConfig.protectedFiles\n : DEFAULT_PROTECTED_FILES,\n };\n}\n\nfunction isOacConfig(value: DiffValidationConfig | OacConfig | undefined): value is OacConfig {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"execution\" in value &&\n typeof (value as { execution?: unknown }).execution === \"object\"\n );\n}\n\nfunction findForbiddenPatternHits(diffPatch: string, patterns: RegExp[]): string[] {\n const hits = new Set<string>();\n let currentFile = \"(unknown)\";\n\n for (const line of diffPatch.split(\"\\n\")) {\n if (line.startsWith(\"+++ b/\")) {\n currentFile = line.slice(\"+++ b/\".length).trim();\n continue;\n }\n\n if (!line.startsWith(\"+\") || line.startsWith(\"+++\")) {\n continue;\n }\n\n const addedLine = line.slice(1);\n for (const pattern of patterns) {\n if (patternMatches(pattern, addedLine)) {\n const preview = truncate(addedLine.trim(), 120);\n hits.add(`Forbidden pattern \"${pattern}\" found in ${currentFile}: \"${preview}\".`);\n }\n }\n }\n\n return [...hits];\n}\n\nfunction patternMatches(pattern: RegExp, input: string): boolean {\n const normalizedFlags = pattern.flags.replaceAll(\"g\", \"\");\n const matcher = new RegExp(pattern.source, normalizedFlags);\n return matcher.test(input);\n}\n\nfunction matchesGlob(path: string, pattern: string): boolean {\n const regex = globToRegex(pattern);\n const filename = basename(path);\n return regex.test(path) || regex.test(filename);\n}\n\nfunction globToRegex(glob: string): RegExp {\n const escaped = glob.replaceAll(/[-/\\\\^$+?.()|[\\]{}]/g, \"\\\\$&\").replaceAll(\"*\", \".*\");\n return new RegExp(`^${escaped}$`);\n}\n","import type { Octokit } from \"@octokit/rest\";\nimport {\n type OacConfig,\n OacError,\n type OacEventBus,\n type ResolvedRepo,\n type Task,\n completionError,\n executionError,\n} from \"../core/index.js\";\n\nimport {\n type DiffValidationConfig,\n type ValidationResult,\n validateDiff,\n} from \"./diff-validator.js\";\nimport { createPR, pushBranch } from \"./github-pr.js\";\nimport { linkIssueToePR } from \"./issue-linker.js\";\nimport type {\n CompletionResult,\n CreatedPR,\n ExternalTaskRef,\n PRCreationParams,\n ProjectManagementProvider,\n} from \"./types.js\";\n\nexport interface CompletionHandlerOptions {\n octokit: Octokit;\n eventBus: OacEventBus;\n providers?: ProjectManagementProvider[];\n diffValidationConfig?: DiffValidationConfig | OacConfig;\n}\n\nexport interface CompletionHandlerParams extends PRCreationParams {\n jobId: string;\n externalTaskRef?: ExternalTaskRef;\n diffValidationConfig?: DiffValidationConfig | OacConfig;\n}\n\nexport class CompletionHandler {\n private readonly octokit: Octokit;\n private readonly eventBus: OacEventBus;\n private readonly providers: ProjectManagementProvider[];\n private readonly diffValidationConfig?: DiffValidationConfig | OacConfig;\n\n public constructor(options: CompletionHandlerOptions) {\n this.octokit = options.octokit;\n this.eventBus = options.eventBus;\n this.providers = options.providers ?? [];\n this.diffValidationConfig = options.diffValidationConfig;\n }\n\n public async handle(params: CompletionHandlerParams): Promise<CompletionResult> {\n return this.complete(params);\n }\n\n public async complete(params: CompletionHandlerParams): Promise<CompletionResult> {\n const warnings: string[] = [];\n const externalTaskRef = this.resolveExternalTaskRef(params.task, params.externalTaskRef);\n\n try {\n this.emitProgress(params.jobId, params.result.totalTokensUsed, \"completion:validateDiff\");\n const validation = await validateDiff(\n resolveRepoPath(params.repo),\n params.diffValidationConfig ?? this.diffValidationConfig,\n );\n this.handleValidationResult(validation);\n warnings.push(...validation.warnings);\n\n this.emitProgress(params.jobId, params.result.totalTokensUsed, \"completion:duplicatePRGuard\");\n const duplicatePr = await this.findExistingOacPR(params.repo, params.task);\n if (duplicatePr) {\n const skipMsg = `Skipped: existing OAC PR #${duplicatePr} already targets issue #${params.task.linkedIssue?.number ?? \"unknown\"}.`;\n warnings.push(skipMsg);\n return {\n summary: skipMsg,\n filesChanged: params.result.filesChanged.length,\n tokensUsed: params.result.totalTokensUsed,\n };\n }\n\n warnings.push(...(await this.notifyStarted(externalTaskRef)));\n\n this.emitProgress(params.jobId, params.result.totalTokensUsed, \"completion:pushBranch\");\n await pushBranch(params.repo, params.branchName);\n\n this.emitProgress(params.jobId, params.result.totalTokensUsed, \"completion:createPR\");\n const pr = await createPR(params, this.octokit);\n this.eventBus.emit(\"pr:created\", { jobId: params.jobId, prUrl: pr.url });\n\n this.emitProgress(params.jobId, params.result.totalTokensUsed, \"completion:linkIssue\");\n const linkIssueWarning = await this.tryLinkIssue(params.repo, params.task, pr);\n if (linkIssueWarning) {\n warnings.push(linkIssueWarning);\n }\n\n this.emitProgress(params.jobId, params.result.totalTokensUsed, \"completion:notifyWebhooks\");\n warnings.push(...(await this.notifyPRCreated(externalTaskRef, pr)));\n\n const completionResult = buildCompletionResult(params, pr, warnings);\n warnings.push(...(await this.notifyCompleted(externalTaskRef, completionResult)));\n\n return completionResult;\n } catch (error) {\n const normalizedError = this.normalizePipelineError(error, params);\n this.eventBus.emit(\"execution:failed\", {\n jobId: params.jobId,\n error: normalizedError,\n });\n await this.notifyFailed(externalTaskRef, normalizedError.message);\n throw normalizedError;\n }\n }\n\n private emitProgress(jobId: string, tokensUsed: number, stage: string): void {\n this.eventBus.emit(\"execution:progress\", {\n jobId,\n tokensUsed,\n stage,\n });\n }\n\n private handleValidationResult(validation: ValidationResult): void {\n if (validation.valid) {\n return;\n }\n\n const hasForbiddenPattern = validation.errors.some((message) =>\n message.toLowerCase().includes(\"forbidden pattern\"),\n );\n const errorCode = hasForbiddenPattern\n ? \"VALIDATION_FORBIDDEN_PATTERN\"\n : \"VALIDATION_DIFF_TOO_LARGE\";\n\n throw executionError(errorCode, \"Diff validation failed.\", {\n context: {\n errors: validation.errors,\n warnings: validation.warnings,\n },\n });\n }\n\n private async tryLinkIssue(\n repo: ResolvedRepo,\n task: Task,\n pr: CreatedPR,\n ): Promise<string | undefined> {\n try {\n await linkIssueToePR(repo, task, pr, this.octokit);\n return undefined;\n } catch (error) {\n return `Issue linking warning: ${toErrorMessage(error)}`;\n }\n }\n\n private async notifyStarted(ref: ExternalTaskRef | undefined): Promise<string[]> {\n return this.notifyProviders(ref, \"notifyStarted\", (provider, taskRef) =>\n provider.notifyStarted(taskRef),\n );\n }\n\n private async notifyPRCreated(\n ref: ExternalTaskRef | undefined,\n pr: CreatedPR,\n ): Promise<string[]> {\n return this.notifyProviders(ref, \"notifyPRCreated\", (provider, taskRef) =>\n provider.notifyPRCreated(taskRef, pr.url),\n );\n }\n\n private async notifyCompleted(\n ref: ExternalTaskRef | undefined,\n result: CompletionResult,\n ): Promise<string[]> {\n return this.notifyProviders(ref, \"notifyCompleted\", (provider, taskRef) =>\n provider.notifyCompleted(taskRef, result),\n );\n }\n\n private async notifyFailed(ref: ExternalTaskRef | undefined, message: string): Promise<void> {\n await this.notifyProviders(ref, \"notifyFailed\", (provider, taskRef) =>\n provider.notifyFailed(taskRef, message),\n );\n }\n\n private async notifyProviders(\n ref: ExternalTaskRef | undefined,\n operationName: string,\n operation: (provider: ProjectManagementProvider, taskRef: ExternalTaskRef) => Promise<void>,\n ): Promise<string[]> {\n if (!ref) {\n return [];\n }\n\n const selectedProviders = this.providers.filter((provider) => provider.id === ref.provider);\n if (selectedProviders.length === 0) {\n return [];\n }\n\n const results = await Promise.allSettled(\n selectedProviders.map(async (provider) => {\n const isReachable = await provider.ping();\n if (!isReachable) {\n throw new Error(`Provider \"${provider.id}\" is unreachable.`);\n }\n await operation(provider, ref);\n }),\n );\n\n const warnings: string[] = [];\n for (let index = 0; index < results.length; index += 1) {\n const result = results[index];\n if (result.status === \"fulfilled\") {\n continue;\n }\n\n warnings.push(\n `${operationName} failed for provider \"${\n selectedProviders[index].id\n }\": ${toErrorMessage(result.reason)}`,\n );\n }\n\n return warnings;\n }\n\n /**\n * Pre-PR guard: checks for an existing open OAC pull request that already\n * targets the same issue. Returns the PR number if a duplicate exists.\n */\n private async findExistingOacPR(repo: ResolvedRepo, task: Task): Promise<number | undefined> {\n if (!task.linkedIssue) {\n return undefined;\n }\n\n const issueNumber = task.linkedIssue.number;\n\n try {\n const { data: pulls } = await this.octokit.pulls.list({\n owner: repo.owner,\n repo: repo.name,\n state: \"open\",\n per_page: 100,\n sort: \"updated\",\n direction: \"desc\",\n });\n\n const issueRefPattern = /(?:Fixes|Closes|Resolves)\\s+#(\\d+)/gi;\n for (const pr of pulls) {\n if (!pr.title.startsWith(\"[OAC]\")) continue;\n\n const body = pr.body ?? \"\";\n for (const match of body.matchAll(issueRefPattern)) {\n const num = Number.parseInt(match[1], 10);\n if (num === issueNumber) {\n return pr.number;\n }\n }\n }\n\n return undefined;\n } catch {\n // Guard failure should not block PR creation.\n return undefined;\n }\n }\n\n private resolveExternalTaskRef(\n task: Task,\n providedRef?: ExternalTaskRef,\n ): ExternalTaskRef | undefined {\n if (providedRef) {\n return providedRef;\n }\n\n if (task.linkedIssue) {\n return {\n provider: \"github\",\n externalId: `#${task.linkedIssue.number}`,\n url: task.linkedIssue.url,\n };\n }\n\n const metadata = task.metadata as Record<string, unknown>;\n const provider = readMetadataString(metadata, \"externalProvider\");\n const externalId = readMetadataString(metadata, \"externalId\");\n const url = readMetadataString(metadata, \"externalUrl\");\n\n if (!provider || !externalId) {\n return undefined;\n }\n\n return { provider, externalId, url };\n }\n\n private normalizePipelineError(error: unknown, params: CompletionHandlerParams): OacError {\n if (error instanceof OacError) {\n return error;\n }\n\n return completionError(\n \"PR_CREATION_FAILED\",\n `Completion pipeline failed for task \"${params.task.id}\" in \"${params.repo.fullName}\": ${toErrorMessage(\n error,\n )}`,\n {\n cause: error,\n context: {\n jobId: params.jobId,\n taskId: params.task.id,\n repo: params.repo.fullName,\n branchName: params.branchName,\n },\n },\n );\n }\n}\n\nfunction buildCompletionResult(\n params: CompletionHandlerParams,\n pr: CreatedPR,\n warnings: string[],\n): CompletionResult {\n const filesChanged = params.result.filesChanged.length;\n const warningSuffix = warnings.length > 0 ? ` Completed with ${warnings.length} warning(s).` : \"\";\n\n return {\n prUrl: pr.url,\n commitSha: pr.sha,\n summary: `Created PR #${pr.number} for \"${params.task.title}\".${warningSuffix}`,\n filesChanged,\n tokensUsed: params.result.totalTokensUsed,\n };\n}\n\nfunction resolveRepoPath(repo: ResolvedRepo): string {\n return repo.worktreePath.trim().length > 0 ? repo.worktreePath : repo.localPath;\n}\n\nfunction readMetadataString(metadata: Record<string, unknown>, key: string): string | undefined {\n const value = metadata[key];\n if (typeof value === \"string\" && value.trim().length > 0) {\n return value.trim();\n }\n return undefined;\n}\n\nfunction toErrorMessage(error: unknown): string {\n if (error instanceof Error && error.message.trim().length > 0) {\n return error.message.trim();\n }\n return \"Unknown error\";\n}\n"],"mappings":"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","names":["simpleGit","simpleGit","readMetadataString"]}
@@ -442,6 +442,19 @@ declare const AnalyzeSchema: z.ZodDefault<z.ZodObject<{
442
442
  staleAfterMs?: number | undefined;
443
443
  contextDir?: string | undefined;
444
444
  }>>;
445
+ declare const ContextPolicySchema: z.ZodDefault<z.ZodObject<{
446
+ mode: z.ZodDefault<z.ZodEnum<["off", "warn", "enforce"]>>;
447
+ requiredGlobs: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
448
+ maxAckItems: z.ZodDefault<z.ZodNumber>;
449
+ }, "strict", z.ZodTypeAny, {
450
+ mode: "off" | "warn" | "enforce";
451
+ requiredGlobs: string[];
452
+ maxAckItems: number;
453
+ }, {
454
+ mode?: "off" | "warn" | "enforce" | undefined;
455
+ requiredGlobs?: string[] | undefined;
456
+ maxAckItems?: number | undefined;
457
+ }>>;
445
458
  declare const OacConfigSchema: z.ZodObject<{
446
459
  repos: z.ZodDefault<z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodObject<{
447
460
  name: z.ZodString;
@@ -782,6 +795,19 @@ declare const OacConfigSchema: z.ZodObject<{
782
795
  staleAfterMs?: number | undefined;
783
796
  contextDir?: string | undefined;
784
797
  }>>;
798
+ context: z.ZodDefault<z.ZodObject<{
799
+ mode: z.ZodDefault<z.ZodEnum<["off", "warn", "enforce"]>>;
800
+ requiredGlobs: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
801
+ maxAckItems: z.ZodDefault<z.ZodNumber>;
802
+ }, "strict", z.ZodTypeAny, {
803
+ mode: "off" | "warn" | "enforce";
804
+ requiredGlobs: string[];
805
+ maxAckItems: number;
806
+ }, {
807
+ mode?: "off" | "warn" | "enforce" | undefined;
808
+ requiredGlobs?: string[] | undefined;
809
+ maxAckItems?: number | undefined;
810
+ }>>;
785
811
  }, "strict", z.ZodTypeAny, {
786
812
  repos: (string | {
787
813
  name: string;
@@ -865,6 +891,11 @@ declare const OacConfigSchema: z.ZodObject<{
865
891
  staleAfterMs: number;
866
892
  contextDir: string;
867
893
  };
894
+ context: {
895
+ mode: "off" | "warn" | "enforce";
896
+ requiredGlobs: string[];
897
+ maxAckItems: number;
898
+ };
868
899
  }, {
869
900
  repos?: (string | {
870
901
  name: string;
@@ -948,6 +979,11 @@ declare const OacConfigSchema: z.ZodObject<{
948
979
  staleAfterMs?: number | undefined;
949
980
  contextDir?: string | undefined;
950
981
  } | undefined;
982
+ context?: {
983
+ mode?: "off" | "warn" | "enforce" | undefined;
984
+ requiredGlobs?: string[] | undefined;
985
+ maxAckItems?: number | undefined;
986
+ } | undefined;
951
987
  }>;
952
988
  declare const OacConfig: z.ZodObject<{
953
989
  repos: z.ZodDefault<z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodObject<{
@@ -1289,6 +1325,19 @@ declare const OacConfig: z.ZodObject<{
1289
1325
  staleAfterMs?: number | undefined;
1290
1326
  contextDir?: string | undefined;
1291
1327
  }>>;
1328
+ context: z.ZodDefault<z.ZodObject<{
1329
+ mode: z.ZodDefault<z.ZodEnum<["off", "warn", "enforce"]>>;
1330
+ requiredGlobs: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
1331
+ maxAckItems: z.ZodDefault<z.ZodNumber>;
1332
+ }, "strict", z.ZodTypeAny, {
1333
+ mode: "off" | "warn" | "enforce";
1334
+ requiredGlobs: string[];
1335
+ maxAckItems: number;
1336
+ }, {
1337
+ mode?: "off" | "warn" | "enforce" | undefined;
1338
+ requiredGlobs?: string[] | undefined;
1339
+ maxAckItems?: number | undefined;
1340
+ }>>;
1292
1341
  }, "strict", z.ZodTypeAny, {
1293
1342
  repos: (string | {
1294
1343
  name: string;
@@ -1372,6 +1421,11 @@ declare const OacConfig: z.ZodObject<{
1372
1421
  staleAfterMs: number;
1373
1422
  contextDir: string;
1374
1423
  };
1424
+ context: {
1425
+ mode: "off" | "warn" | "enforce";
1426
+ requiredGlobs: string[];
1427
+ maxAckItems: number;
1428
+ };
1375
1429
  }, {
1376
1430
  repos?: (string | {
1377
1431
  name: string;
@@ -1455,6 +1509,11 @@ declare const OacConfig: z.ZodObject<{
1455
1509
  staleAfterMs?: number | undefined;
1456
1510
  contextDir?: string | undefined;
1457
1511
  } | undefined;
1512
+ context?: {
1513
+ mode?: "off" | "warn" | "enforce" | undefined;
1514
+ requiredGlobs?: string[] | undefined;
1515
+ maxAckItems?: number | undefined;
1516
+ } | undefined;
1458
1517
  }>;
1459
1518
  type OacConfig = z.output<typeof OacConfigSchema>;
1460
1519
  type OacConfigInput = z.input<typeof OacConfigSchema>;
@@ -1465,4 +1524,4 @@ declare function defineConfig(config: OacConfigInput): OacConfigInput;
1465
1524
  declare function interpolateEnvVars(value: string, env?: Record<string, string | undefined>, path?: string[]): string;
1466
1525
  declare function loadConfig(config?: unknown, options?: LoadConfigOptions): OacConfig;
1467
1526
 
1468
- export { AnalyzeSchema as A, BudgetSchema as B, CompletionSchema as C, DashboardSchema as D, ExecutionSchema as E, JiraIntegrationSchema as J, LinearIntegrationSchema as L, OacConfig as O, PrSchema as P, RepoTargetSchema as R, TrackingSchema as T, ValidationSchema as V, DiscoveryScannersSchema as a, DiscoverySchema as b, type LoadConfigOptions as c, type OacConfigInput as d, OacConfigSchema as e, ProviderSchema as f, defineConfig as g, interpolateEnvVars as i, loadConfig as l };
1527
+ export { AnalyzeSchema as A, BudgetSchema as B, CompletionSchema as C, DashboardSchema as D, ExecutionSchema as E, JiraIntegrationSchema as J, LinearIntegrationSchema as L, OacConfig as O, PrSchema as P, RepoTargetSchema as R, TrackingSchema as T, ValidationSchema as V, ContextPolicySchema as a, DiscoveryScannersSchema as b, DiscoverySchema as c, type LoadConfigOptions as d, type OacConfigInput as e, OacConfigSchema as f, ProviderSchema as g, defineConfig as h, interpolateEnvVars as i, loadConfig as l };
@@ -1,4 +1,4 @@
1
- export { A as AnalyzeSchema, B as BudgetSchema, C as CompletionSchema, D as DashboardSchema, a as DiscoveryScannersSchema, b as DiscoverySchema, E as ExecutionSchema, J as JiraIntegrationSchema, L as LinearIntegrationSchema, c as LoadConfigOptions, O as OacConfig, d as OacConfigInput, e as OacConfigSchema, P as PrSchema, f as ProviderSchema, R as RepoTargetSchema, T as TrackingSchema, V as ValidationSchema, g as defineConfig, i as interpolateEnvVars, l as loadConfig } from '../config-DequKoFA.js';
1
+ export { A as AnalyzeSchema, B as BudgetSchema, C as CompletionSchema, a as ContextPolicySchema, D as DashboardSchema, b as DiscoveryScannersSchema, c as DiscoverySchema, E as ExecutionSchema, J as JiraIntegrationSchema, L as LinearIntegrationSchema, d as LoadConfigOptions, O as OacConfig, e as OacConfigInput, f as OacConfigSchema, P as PrSchema, g as ProviderSchema, R as RepoTargetSchema, T as TrackingSchema, V as ValidationSchema, h as defineConfig, i as interpolateEnvVars, l as loadConfig } from '../config-DnzZ7w92.js';
2
2
  export { B as BUDGET_ERROR_CODES, a as BudgetErrorCode, C as COMPLETION_ERROR_CODES, b as CONFIG_ERROR_CODES, c as CompletionErrorCode, d as ConfigErrorCode, D as DISCOVERY_ERROR_CODES, e as DiscoveryErrorCode, E as EXECUTION_ERROR_CODES, f as ExecutionErrorCode, O as OAC_ERROR_CODES, g as OacError, h as OacErrorCode, i as OacErrorOptions, j as OacErrorSeverity, k as OacEventBus, l as OacEvents, R as REPO_ERROR_CODES, m as RepoErrorCode, S as SYSTEM_ERROR_CODES, n as SystemErrorCode, o as budgetError, p as completionError, q as configError, r as createEventBus, s as discoveryError, t as executionError, u as repoError } from '../event-bus-KiuR6e3P.js';
3
3
  export { A as AgentProviderId, C as ContributionLog, a as ContributionTask, E as Epic, b as EpicStatus, c as ExecutionMode, d as ExecutionPlan, e as ExecutionResult, R as ResolvedRepo, f as RunSummary, T as Task, g as TaskComplexity, h as TaskSource, i as TokenEstimate, U as UNLIMITED_BUDGET } from '../types-Ck7IucqK.js';
4
4
  import 'zod';
@@ -5,6 +5,7 @@ import {
5
5
  COMPLETION_ERROR_CODES,
6
6
  CONFIG_ERROR_CODES,
7
7
  CompletionSchema,
8
+ ContextPolicySchema,
8
9
  DISCOVERY_ERROR_CODES,
9
10
  DashboardSchema,
10
11
  DiscoveryScannersSchema,
@@ -35,13 +36,13 @@ import {
35
36
  interpolateEnvVars,
36
37
  loadConfig,
37
38
  repoError
38
- } from "../chunk-7C7SC4TZ.js";
39
+ } from "../chunk-I3TKNT4M.js";
39
40
  import {
40
41
  createMemoryMonitor,
41
42
  getMemorySnapshot,
42
43
  isRecord,
43
44
  truncate
44
- } from "../chunk-6A37SKAJ.js";
45
+ } from "../chunk-JDFAJP45.js";
45
46
  export {
46
47
  AnalyzeSchema,
47
48
  BUDGET_ERROR_CODES,
@@ -49,6 +50,7 @@ export {
49
50
  COMPLETION_ERROR_CODES,
50
51
  CONFIG_ERROR_CODES,
51
52
  CompletionSchema,
53
+ ContextPolicySchema,
52
54
  DISCOVERY_ERROR_CODES,
53
55
  DashboardSchema,
54
56
  DiscoveryScannersSchema,
@@ -1,27 +1,27 @@
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,
8
8
  LintScanner,
9
9
  TodoScanner,
10
10
  rankTasks
11
- } from "../chunk-OCCMKAJI.js";
11
+ } from "../chunk-ZJBLRKCV.js";
12
12
  import {
13
13
  buildExecutionPlan,
14
14
  estimateTokens
15
- } from "../chunk-5GAUWC3L.js";
15
+ } from "../chunk-ALBVUNUY.js";
16
16
  import {
17
17
  CodexAdapter,
18
18
  createSandbox,
19
19
  executeTask
20
- } from "../chunk-EYUQMPVO.js";
20
+ } from "../chunk-27FEE5KS.js";
21
21
  import {
22
22
  createEventBus
23
- } from "../chunk-7C7SC4TZ.js";
24
- import "../chunk-6A37SKAJ.js";
23
+ } from "../chunk-I3TKNT4M.js";
24
+ import "../chunk-JDFAJP45.js";
25
25
  import {
26
26
  buildLeaderboard,
27
27
  contributionLogSchema,
@@ -31,12 +31,14 @@ import {
31
31
  // src/dashboard/server.ts
32
32
  import { randomUUID as randomUUID2 } from "crypto";
33
33
  import { readFile, readdir } from "fs/promises";
34
- import { resolve } from "path";
34
+ import { resolve as resolve2 } from "path";
35
35
  import cors from "@fastify/cors";
36
36
  import Fastify from "fastify";
37
37
 
38
38
  // src/dashboard/pipeline.ts
39
39
  import { randomUUID } from "crypto";
40
+ import { mkdir, writeFile } from "fs/promises";
41
+ import { join, resolve } from "path";
40
42
  import { execa } from "execa";
41
43
  import PQueue from "p-queue";
42
44
  function buildScanners() {
@@ -64,7 +66,7 @@ async function executeWithCodex(input) {
64
66
  tokenBudget: input.estimate.totalEstimatedTokens,
65
67
  timeoutMs: input.timeoutSeconds * 1e3
66
68
  });
67
- const commitResult = await commitSandboxChanges(sandbox.path, input.task);
69
+ const commitResult = await commitSandboxChanges(sandbox.path, input.task, input.baseBranch);
68
70
  const filesChanged = commitResult.filesChanged.length > 0 ? commitResult.filesChanged : result.filesChanged.length > 0 ? result.filesChanged : [];
69
71
  return {
70
72
  execution: {
@@ -78,7 +80,7 @@ async function executeWithCodex(input) {
78
80
  sandbox: sandboxInfo
79
81
  };
80
82
  } catch (error) {
81
- const commitResult = await commitSandboxChanges(sandbox.path, input.task);
83
+ const commitResult = await commitSandboxChanges(sandbox.path, input.task, input.baseBranch);
82
84
  if (commitResult.hasChanges) {
83
85
  return {
84
86
  execution: {
@@ -105,23 +107,24 @@ async function executeWithCodex(input) {
105
107
  };
106
108
  }
107
109
  }
108
- async function commitSandboxChanges(sandboxPath, task) {
110
+ async function commitSandboxChanges(sandboxPath, task, baseBranch) {
109
111
  try {
110
112
  const statusResult = await execa("git", ["status", "--porcelain"], { cwd: sandboxPath });
111
- if (!statusResult.stdout.trim()) {
112
- return { hasChanges: false, filesChanged: [] };
113
+ if (statusResult.stdout.trim()) {
114
+ await execa("git", ["add", "-A"], { cwd: sandboxPath });
115
+ await execa(
116
+ "git",
117
+ ["commit", "-m", `[OAC] ${task.title}
118
+
119
+ Automated contribution by OAC.`],
120
+ { cwd: sandboxPath }
121
+ );
113
122
  }
114
- await execa("git", ["add", "-A"], { cwd: sandboxPath });
115
- await execa("git", ["commit", "-m", `[OAC] ${task.title}
116
-
117
- Automated contribution by OAC.`], {
118
- cwd: sandboxPath
119
- });
120
- const diffResult = await execa("git", ["diff", "--name-only", "HEAD~1", "HEAD"], {
123
+ const diffResult = await execa("git", ["diff", "--name-only", `origin/${baseBranch}`, "HEAD"], {
121
124
  cwd: sandboxPath
122
125
  });
123
126
  const changedFiles = diffResult.stdout.trim().split("\n").filter(Boolean);
124
- return { hasChanges: true, filesChanged: changedFiles };
127
+ return { hasChanges: changedFiles.length > 0, filesChanged: changedFiles };
125
128
  } catch {
126
129
  return { hasChanges: false, filesChanged: [] };
127
130
  }
@@ -206,6 +209,45 @@ function resolveGithubUsername() {
206
209
  }
207
210
  return "oac-user";
208
211
  }
212
+ async function writeContributionToSandbox(input) {
213
+ const { sandboxPath, task, execution, runId, repoOwner } = input;
214
+ const contributionsDir = resolve(sandboxPath, ".oac", "contributions");
215
+ await mkdir(contributionsDir, { recursive: true });
216
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
217
+ const contributor = resolveGithubUsername();
218
+ const datePrefix = timestamp.replace(/[:.]/g, "").replace("T", "-").slice(0, 15);
219
+ const safeTaskId = task.id.replace(/[^A-Za-z0-9-]/g, "-").replace(/-+/g, "-").slice(0, 40);
220
+ const filename = `${datePrefix}-${safeTaskId}.json`;
221
+ const metadata = {
222
+ version: "1.0",
223
+ runId,
224
+ timestamp,
225
+ contributor,
226
+ task: {
227
+ id: task.id,
228
+ title: task.title,
229
+ source: task.source,
230
+ complexity: task.complexity,
231
+ linkedIssue: task.linkedIssue ? { number: task.linkedIssue.number, url: task.linkedIssue.url } : void 0
232
+ },
233
+ execution: {
234
+ success: execution.success,
235
+ tokensUsed: execution.totalTokensUsed,
236
+ duration: execution.duration,
237
+ filesChanged: execution.filesChanged
238
+ }
239
+ };
240
+ const filePath = join(contributionsDir, filename);
241
+ await writeFile(filePath, `${JSON.stringify(metadata, null, 2)}
242
+ `, "utf8");
243
+ try {
244
+ await execa("git", ["add", filePath], { cwd: sandboxPath });
245
+ await execa("git", ["commit", "-m", "[OAC] Add contribution metadata"], {
246
+ cwd: sandboxPath
247
+ });
248
+ } catch {
249
+ }
250
+ }
209
251
  async function executePipeline(config, onEvent) {
210
252
  const runId = randomUUID();
211
253
  const startedAt = (/* @__PURE__ */ new Date()).toISOString();
@@ -327,6 +369,13 @@ async function executePipeline(config, onEvent) {
327
369
  }
328
370
  let pr;
329
371
  if (execution.success && sandbox && execution.filesChanged.length > 0) {
372
+ await writeContributionToSandbox({
373
+ sandboxPath: sandbox.sandboxPath,
374
+ task: entry.task,
375
+ execution,
376
+ runId,
377
+ repoOwner: resolvedRepo.owner
378
+ });
330
379
  emit({
331
380
  type: "run:stage",
332
381
  stage: "creating-pr",
@@ -1067,7 +1116,7 @@ function broadcastEvent(event) {
1067
1116
  }
1068
1117
  }
1069
1118
  async function readContributionLogs(oacDir) {
1070
- const contributionsPath = resolve(oacDir, ".oac", "contributions");
1119
+ const contributionsPath = resolve2(oacDir, ".oac", "contributions");
1071
1120
  let entries;
1072
1121
  try {
1073
1122
  entries = await readdir(contributionsPath, { withFileTypes: true, encoding: "utf8" });
@@ -1078,7 +1127,7 @@ async function readContributionLogs(oacDir) {
1078
1127
  const results = await Promise.all(
1079
1128
  files.map(async (fileName) => {
1080
1129
  try {
1081
- const content = await readFile(resolve(contributionsPath, fileName), "utf8");
1130
+ const content = await readFile(resolve2(contributionsPath, fileName), "utf8");
1082
1131
  const parsed = contributionLogSchema.safeParse(JSON.parse(content));
1083
1132
  return parsed.success ? parsed.data : null;
1084
1133
  } catch {
@@ -1093,7 +1142,7 @@ async function readRunStatus(oacDir) {
1093
1142
  return currentRun;
1094
1143
  }
1095
1144
  try {
1096
- const content = await readFile(resolve(oacDir, ".oac", "status.json"), "utf8");
1145
+ const content = await readFile(resolve2(oacDir, ".oac", "status.json"), "utf8");
1097
1146
  return JSON.parse(content);
1098
1147
  } catch {
1099
1148
  return { status: "idle", message: "No active runs" };