@tokenfactory/acc-runner 0.25.0 → 0.27.0

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 (162) hide show
  1. package/README.md +77 -4
  2. package/package.json +1 -1
  3. package/dist/anthropic-auth.d.ts +0 -53
  4. package/dist/anthropic-auth.d.ts.map +0 -1
  5. package/dist/anthropic-auth.js +0 -89
  6. package/dist/anthropic-auth.js.map +0 -1
  7. package/dist/bin-resolve.d.ts +0 -16
  8. package/dist/bin-resolve.d.ts.map +0 -1
  9. package/dist/bin-resolve.js +0 -35
  10. package/dist/bin-resolve.js.map +0 -1
  11. package/dist/cli.d.ts +0 -3
  12. package/dist/cli.d.ts.map +0 -1
  13. package/dist/cli.js +0 -128
  14. package/dist/cli.js.map +0 -1
  15. package/dist/config.d.ts +0 -121
  16. package/dist/config.d.ts.map +0 -1
  17. package/dist/config.js +0 -396
  18. package/dist/config.js.map +0 -1
  19. package/dist/cost-pricing.d.ts +0 -130
  20. package/dist/cost-pricing.d.ts.map +0 -1
  21. package/dist/cost-pricing.js +0 -191
  22. package/dist/cost-pricing.js.map +0 -1
  23. package/dist/doctor.d.ts +0 -37
  24. package/dist/doctor.d.ts.map +0 -1
  25. package/dist/doctor.js +0 -658
  26. package/dist/doctor.js.map +0 -1
  27. package/dist/failure-classifier.d.ts +0 -112
  28. package/dist/failure-classifier.d.ts.map +0 -1
  29. package/dist/failure-classifier.js +0 -353
  30. package/dist/failure-classifier.js.map +0 -1
  31. package/dist/gh.d.ts +0 -22
  32. package/dist/gh.d.ts.map +0 -1
  33. package/dist/gh.js +0 -48
  34. package/dist/gh.js.map +0 -1
  35. package/dist/git.d.ts +0 -50
  36. package/dist/git.d.ts.map +0 -1
  37. package/dist/git.js +0 -127
  38. package/dist/git.js.map +0 -1
  39. package/dist/github-client.d.ts +0 -133
  40. package/dist/github-client.d.ts.map +0 -1
  41. package/dist/github-client.js +0 -234
  42. package/dist/github-client.js.map +0 -1
  43. package/dist/keychain.d.ts +0 -21
  44. package/dist/keychain.d.ts.map +0 -1
  45. package/dist/keychain.js +0 -45
  46. package/dist/keychain.js.map +0 -1
  47. package/dist/login.d.ts +0 -12
  48. package/dist/login.d.ts.map +0 -1
  49. package/dist/login.js +0 -133
  50. package/dist/login.js.map +0 -1
  51. package/dist/logout.d.ts +0 -2
  52. package/dist/logout.d.ts.map +0 -1
  53. package/dist/logout.js +0 -31
  54. package/dist/logout.js.map +0 -1
  55. package/dist/mcp-spawn.d.ts +0 -30
  56. package/dist/mcp-spawn.d.ts.map +0 -1
  57. package/dist/mcp-spawn.js +0 -145
  58. package/dist/mcp-spawn.js.map +0 -1
  59. package/dist/messaging.d.ts +0 -49
  60. package/dist/messaging.d.ts.map +0 -1
  61. package/dist/messaging.js +0 -36
  62. package/dist/messaging.js.map +0 -1
  63. package/dist/pkg-version.d.ts +0 -3
  64. package/dist/pkg-version.d.ts.map +0 -1
  65. package/dist/pkg-version.js +0 -20
  66. package/dist/pkg-version.js.map +0 -1
  67. package/dist/profiles/designer-prompt.d.ts +0 -18
  68. package/dist/profiles/designer-prompt.d.ts.map +0 -1
  69. package/dist/profiles/designer-prompt.js +0 -172
  70. package/dist/profiles/designer-prompt.js.map +0 -1
  71. package/dist/profiles/developer-prompt.d.ts +0 -24
  72. package/dist/profiles/developer-prompt.d.ts.map +0 -1
  73. package/dist/profiles/developer-prompt.js +0 -24
  74. package/dist/profiles/developer-prompt.js.map +0 -1
  75. package/dist/profiles/manager-prompt.d.ts +0 -34
  76. package/dist/profiles/manager-prompt.d.ts.map +0 -1
  77. package/dist/profiles/manager-prompt.js +0 -93
  78. package/dist/profiles/manager-prompt.js.map +0 -1
  79. package/dist/profiles/tester-prompt.d.ts +0 -28
  80. package/dist/profiles/tester-prompt.d.ts.map +0 -1
  81. package/dist/profiles/tester-prompt.js +0 -165
  82. package/dist/profiles/tester-prompt.js.map +0 -1
  83. package/dist/prompt.d.ts +0 -38
  84. package/dist/prompt.d.ts.map +0 -1
  85. package/dist/prompt.js +0 -78
  86. package/dist/prompt.js.map +0 -1
  87. package/dist/runtime/cache-dir.d.ts +0 -2
  88. package/dist/runtime/cache-dir.d.ts.map +0 -1
  89. package/dist/runtime/cache-dir.js +0 -15
  90. package/dist/runtime/cache-dir.js.map +0 -1
  91. package/dist/runtime/conflict-resolver.d.ts +0 -65
  92. package/dist/runtime/conflict-resolver.d.ts.map +0 -1
  93. package/dist/runtime/conflict-resolver.js +0 -477
  94. package/dist/runtime/conflict-resolver.js.map +0 -1
  95. package/dist/runtime/expand-args.d.ts +0 -28
  96. package/dist/runtime/expand-args.d.ts.map +0 -1
  97. package/dist/runtime/expand-args.js +0 -50
  98. package/dist/runtime/expand-args.js.map +0 -1
  99. package/dist/runtime/locks.d.ts +0 -21
  100. package/dist/runtime/locks.d.ts.map +0 -1
  101. package/dist/runtime/locks.js +0 -97
  102. package/dist/runtime/locks.js.map +0 -1
  103. package/dist/runtime/provision-mutex.d.ts +0 -37
  104. package/dist/runtime/provision-mutex.d.ts.map +0 -1
  105. package/dist/runtime/provision-mutex.js +0 -67
  106. package/dist/runtime/provision-mutex.js.map +0 -1
  107. package/dist/runtime/quarantine.d.ts +0 -26
  108. package/dist/runtime/quarantine.d.ts.map +0 -1
  109. package/dist/runtime/quarantine.js +0 -50
  110. package/dist/runtime/quarantine.js.map +0 -1
  111. package/dist/runtime/resolution-integrity.d.ts +0 -86
  112. package/dist/runtime/resolution-integrity.d.ts.map +0 -1
  113. package/dist/runtime/resolution-integrity.js +0 -248
  114. package/dist/runtime/resolution-integrity.js.map +0 -1
  115. package/dist/runtime/reviewer.d.ts +0 -81
  116. package/dist/runtime/reviewer.d.ts.map +0 -1
  117. package/dist/runtime/reviewer.js +0 -374
  118. package/dist/runtime/reviewer.js.map +0 -1
  119. package/dist/runtime/rework.d.ts +0 -48
  120. package/dist/runtime/rework.d.ts.map +0 -1
  121. package/dist/runtime/rework.js +0 -136
  122. package/dist/runtime/rework.js.map +0 -1
  123. package/dist/runtime/singleton.d.ts +0 -47
  124. package/dist/runtime/singleton.d.ts.map +0 -1
  125. package/dist/runtime/singleton.js +0 -200
  126. package/dist/runtime/singleton.js.map +0 -1
  127. package/dist/runtime/version-drift.d.ts +0 -31
  128. package/dist/runtime/version-drift.d.ts.map +0 -1
  129. package/dist/runtime/version-drift.js +0 -114
  130. package/dist/runtime/version-drift.js.map +0 -1
  131. package/dist/runtime/worktree.d.ts +0 -74
  132. package/dist/runtime/worktree.d.ts.map +0 -1
  133. package/dist/runtime/worktree.js +0 -206
  134. package/dist/runtime/worktree.js.map +0 -1
  135. package/dist/secrets/inject.d.ts +0 -70
  136. package/dist/secrets/inject.d.ts.map +0 -1
  137. package/dist/secrets/inject.js +0 -102
  138. package/dist/secrets/inject.js.map +0 -1
  139. package/dist/supabase.d.ts +0 -4
  140. package/dist/supabase.d.ts.map +0 -1
  141. package/dist/supabase.js +0 -36
  142. package/dist/supabase.js.map +0 -1
  143. package/dist/task-runner.d.ts +0 -313
  144. package/dist/task-runner.d.ts.map +0 -1
  145. package/dist/task-runner.js +0 -1766
  146. package/dist/task-runner.js.map +0 -1
  147. package/dist/token-provider.d.ts +0 -50
  148. package/dist/token-provider.d.ts.map +0 -1
  149. package/dist/token-provider.js +0 -177
  150. package/dist/token-provider.js.map +0 -1
  151. package/dist/types.d.ts +0 -120
  152. package/dist/types.d.ts.map +0 -1
  153. package/dist/types.js +0 -16
  154. package/dist/types.js.map +0 -1
  155. package/dist/version-check.d.ts +0 -17
  156. package/dist/version-check.d.ts.map +0 -1
  157. package/dist/version-check.js +0 -56
  158. package/dist/version-check.js.map +0 -1
  159. package/dist/watch.d.ts +0 -295
  160. package/dist/watch.d.ts.map +0 -1
  161. package/dist/watch.js +0 -1532
  162. package/dist/watch.js.map +0 -1
package/dist/prompt.js DELETED
@@ -1,78 +0,0 @@
1
- /**
2
- * renderTaskPrompt — duplicated slim copy of src/lib/promptTemplate.ts.
3
- *
4
- * Adds the two RUNNER_PROTOCOL §3.2 mandatory header lines (Branch + PR
5
- * title + base branch) so the agent emits a PR ACC can match by webhook.
6
- *
7
- * v0.3 dedupes via a shared workspace package; for now we keep the small
8
- * function here so the CLI stays a single-package install.
9
- */
10
- function slug(title) {
11
- return title
12
- .toLowerCase()
13
- .replace(/[^a-z0-9]+/g, "-")
14
- .replace(/^-+|-+$/g, "")
15
- .slice(0, 40) || "task";
16
- }
17
- export function branchForTask(taskId, title, branch) {
18
- if (branch && branch.trim())
19
- return branch.trim();
20
- return `acc/${taskId}-${slug(title)}`;
21
- }
22
- export function prTitleForTask(taskId, title) {
23
- return `[${taskId}] ${title}`;
24
- }
25
- export function renderTaskPrompt(input) {
26
- const { task, agent, model } = input;
27
- const integrationBranch = input.integrationBranch ?? "acc/integration";
28
- const targetRepo = input.targetRepo ?? "tokenfactory-pvt-ltd/TechArch";
29
- const branch = branchForTask(task.id, task.title, task.branch);
30
- const prTitle = prTitleForTask(task.id, task.title);
31
- const lines = [];
32
- // Mandatory protocol header — RUNNER_PROTOCOL §3.2.
33
- lines.push(`**Branch:** ${branch}`);
34
- lines.push(`**PR title:** ${prTitle}`);
35
- lines.push(`**Open the PR against:** ${integrationBranch} on ${targetRepo}.`);
36
- lines.push("");
37
- lines.push(`# Task ${task.id}: ${task.title}`);
38
- lines.push("");
39
- if (agent?.name || model?.name) {
40
- lines.push(`You are ${agent?.name ?? "an AI agent"}. You will be running this task on ${model?.name ?? "a model"}.`);
41
- lines.push("");
42
- }
43
- if (task.description) {
44
- lines.push("## Description");
45
- lines.push(task.description);
46
- lines.push("");
47
- }
48
- lines.push("## Allowed file scope");
49
- lines.push(...(task.allowed.length ? task.allowed.map((f) => `- ${f}`) : ["- (no scope restrictions)"]));
50
- lines.push("");
51
- lines.push("## Forbidden files (DO NOT TOUCH)");
52
- lines.push(...(task.forbidden.length ? task.forbidden.map((f) => `- ${f}`) : ["- (none)"]));
53
- lines.push("");
54
- if (input.contracts?.length) {
55
- lines.push("## Contracts in force");
56
- lines.push(...input.contracts.map((c) => `- ${c.name}${c.version ? ` ${c.version}` : ""}${c.status ? ` (${c.status})` : ""}`));
57
- lines.push("");
58
- }
59
- lines.push("## Acceptance criteria");
60
- lines.push(...(task.acceptance.length ? task.acceptance.map((a) => `- ${a}`) : ["- (none)"]));
61
- lines.push("");
62
- lines.push("## Required report format (PR body)");
63
- lines.push("- Summary (3 sentences)");
64
- lines.push("- Files changed (path, +added/-removed)");
65
- lines.push("- Implemented");
66
- lines.push("- Not implemented");
67
- lines.push("- Risks");
68
- lines.push("- Follow-ups");
69
- lines.push("- Verification (typecheck/lint/build/test/manual)");
70
- lines.push("");
71
- if (task.typecheck_cmd) {
72
- lines.push("## Typecheck");
73
- lines.push(`Run \`${task.typecheck_cmd}\` after edits and include the result in the report.`);
74
- lines.push("");
75
- }
76
- return lines.join("\n");
77
- }
78
- //# sourceMappingURL=prompt.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export declare function cacheDir(): string;
2
- //# sourceMappingURL=cache-dir.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cache-dir.d.ts","sourceRoot":"","sources":["../../src/runtime/cache-dir.ts"],"names":[],"mappings":"AAWA,wBAAgB,QAAQ,IAAI,MAAM,CAKjC"}
@@ -1,15 +0,0 @@
1
- /**
2
- * v0.14.0 (T-54-2): single source of truth for the runner cache root.
3
- *
4
- * `quarantine.ts` already honoured ACC_RUNNER_CACHE_DIR inline; the
5
- * singleton-lock and last-task-env modules added in this release reuse the
6
- * same resolution so tests can point all cache state at a tmpdir with one
7
- * env var. Defaults to ~/.cache/acc-runner (unchanged from prior releases).
8
- */
9
- import os from "node:os";
10
- import path from "node:path";
11
- export function cacheDir() {
12
- return (process.env.ACC_RUNNER_CACHE_DIR?.trim() ||
13
- path.join(os.homedir(), ".cache", "acc-runner"));
14
- }
15
- //# sourceMappingURL=cache-dir.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cache-dir.js","sourceRoot":"","sources":["../../src/runtime/cache-dir.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,UAAU,QAAQ;IACtB,OAAO,CACL,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,IAAI,EAAE;QACxC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,YAAY,CAAC,CAChD,CAAC;AACJ,CAAC"}
@@ -1,65 +0,0 @@
1
- import type { RunnerSupabaseClient } from "../supabase.js";
2
- export interface ConflictMeta {
3
- pr_number: number;
4
- repo: string;
5
- head_ref: string;
6
- base_ref: string;
7
- }
8
- export interface ConflictResolutionOutcome {
9
- action: "resolved" | "unresolvable" | "policy_disabled" | "escalated";
10
- reason?: string;
11
- files_resolved?: string[];
12
- files_skipped?: string[];
13
- }
14
- export interface ConflictResolutionDeps {
15
- supabase: RunnerSupabaseClient;
16
- /** Override for tests — defaults to using gh CLI. */
17
- ghApi?: <T>(endpoint: string, opts?: GhApiOptions) => Promise<T>;
18
- /** Override for tests — defaults to querying acc.tasks directly. */
19
- countPriorAttempts?: (prNumber: number) => Promise<number>;
20
- /** Override for tests — defaults to org_settings query. */
21
- loadConflictPolicy?: () => Promise<{
22
- enabled: boolean;
23
- }>;
24
- }
25
- export interface GhApiOptions {
26
- method?: "GET" | "PUT" | "POST";
27
- fields?: Record<string, string>;
28
- jq?: string;
29
- }
30
- export declare const MAX_CONFLICT_ATTEMPTS = 3;
31
- export type FileClass = "vercel.json" | "planning" | "current-cycle" | "min-version" | "package-version";
32
- /**
33
- * Extract conflict metadata from the task description.
34
- * Sweep C embeds: <!-- acc-conflict: {"pr_number":N,"repo":"owner/repo","head_ref":"...","base_ref":"..."} -->
35
- *
36
- * Fallback: accept a plain JSON description (used in tests and by early
37
- * versions of Sweep C that didn't wrap in an HTML comment).
38
- */
39
- export declare function parseConflictMeta(description: string | null | undefined, fallback?: {
40
- pr_number?: number | null;
41
- repo?: string | null;
42
- integration_branch?: string | null;
43
- }): ConflictMeta | null;
44
- export declare function classifyFile(filename: string): FileClass | null;
45
- export declare function hasConflictMarkers(...sides: string[]): boolean;
46
- export declare function mergeVercelCrons(baseStr: string, headStr: string): string | null;
47
- export declare function resolvePlanning(base: string | null, head: string | null): {
48
- write: boolean;
49
- content: string;
50
- } | null;
51
- export declare function mergeCurrentCycle(baseStr: string, headStr: string): string | null;
52
- export declare function mergeMinVersion(baseStr: string, headStr: string): string | null;
53
- export declare function mergePackageVersion(baseStr: string, headStr: string): string | null;
54
- declare function defaultGhApi<T>(endpoint: string, opts?: GhApiOptions): Promise<T>;
55
- /** Two-call base∩head intersection: files changed on BOTH sides since the merge base. */
56
- export declare function computeConflictSet(repo: string, baseRef: string, headRef: string, ghApi: typeof defaultGhApi): Promise<string[]>;
57
- /**
58
- * Attempt to resolve conflicts for the PR referenced in `meta`.
59
- *
60
- * Returns a structured outcome that task-runner.ts uses to decide the
61
- * final task transition (done / failed / escalated).
62
- */
63
- export declare function resolveConflict(meta: ConflictMeta, deps: ConflictResolutionDeps): Promise<ConflictResolutionOutcome>;
64
- export {};
65
- //# sourceMappingURL=conflict-resolver.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"conflict-resolver.d.ts","sourceRoot":"","sources":["../../src/runtime/conflict-resolver.ts"],"names":[],"mappings":"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"}
@@ -1,477 +0,0 @@
1
- /**
2
- * v0.48 T-48-5: Autonomous conflict-resolution runner path.
3
- *
4
- * Called from task-runner.ts when it detects task.type === 'conflict_resolution'.
5
- * Resolves conflicts on the real base∩head file set (two compare calls so only
6
- * files changed on BOTH sides are treated as conflicted — the #412 class fix),
7
- * pushes the resolution to the PR head branch via `gh api`, and escalates to
8
- * conflict_unresolvable after ≤3 attempts.
9
- *
10
- * Policy gate: org_settings.conflict_policy.enabled === false → skip (detect-and-skip mode).
11
- * Retry bound: after 3 failed conflict_resolution tasks for the same PR, the runner
12
- * escalates by setting block_reason='conflict_unresolvable' and transitioning to 'done'.
13
- */
14
- import { execa } from "execa";
15
- // ─────────────────────────────────────────────────────────────────────────────
16
- // Constants
17
- // ─────────────────────────────────────────────────────────────────────────────
18
- export const MAX_CONFLICT_ATTEMPTS = 3;
19
- // Sentinel that Sweep C embeds in task descriptions so the runner knows
20
- // which PR to target and which branches to compare.
21
- const META_RE = /<!--\s*acc-conflict:\s*(\{[^}]*\})\s*-->/;
22
- const PLANNING_RE = /^planning\/V0_\d+(_[A-Z_]+)?\.md$/;
23
- // ─────────────────────────────────────────────────────────────────────────────
24
- // Metadata parsing
25
- // ─────────────────────────────────────────────────────────────────────────────
26
- /**
27
- * Extract conflict metadata from the task description.
28
- * Sweep C embeds: <!-- acc-conflict: {"pr_number":N,"repo":"owner/repo","head_ref":"...","base_ref":"..."} -->
29
- *
30
- * Fallback: accept a plain JSON description (used in tests and by early
31
- * versions of Sweep C that didn't wrap in an HTML comment).
32
- */
33
- export function parseConflictMeta(description, fallback) {
34
- if (description) {
35
- const match = META_RE.exec(description);
36
- if (match) {
37
- try {
38
- const parsed = JSON.parse(match[1]);
39
- if (typeof parsed.pr_number === "number" &&
40
- typeof parsed.repo === "string" &&
41
- typeof parsed.head_ref === "string" &&
42
- typeof parsed.base_ref === "string") {
43
- return parsed;
44
- }
45
- }
46
- catch {
47
- // fall through to plain-JSON attempt
48
- }
49
- }
50
- // Plain JSON fallback (test convenience + early Sweep C format).
51
- try {
52
- const parsed = JSON.parse(description);
53
- if (typeof parsed.pr_number === "number" &&
54
- typeof parsed.repo === "string" &&
55
- typeof parsed.head_ref === "string" &&
56
- typeof parsed.base_ref === "string") {
57
- return parsed;
58
- }
59
- }
60
- catch {
61
- // fall through
62
- }
63
- }
64
- // Last resort: reconstruct from task fields when description has no JSON.
65
- const prNumber = fallback?.pr_number;
66
- const repo = fallback?.repo;
67
- if (typeof prNumber === "number" && typeof repo === "string" && repo.includes("/")) {
68
- return {
69
- pr_number: prNumber,
70
- repo,
71
- // head_ref is not available from the task row alone; caller must provide or
72
- // we derive it from the PR via the GitHub API at resolution time.
73
- head_ref: "",
74
- base_ref: fallback?.integration_branch ?? "acc/integration",
75
- };
76
- }
77
- return null;
78
- }
79
- // ─────────────────────────────────────────────────────────────────────────────
80
- // File-class resolution (mirrors api/scheduled/conflict-resolver.ts)
81
- // ─────────────────────────────────────────────────────────────────────────────
82
- export function classifyFile(filename) {
83
- if (filename === "vercel.json")
84
- return "vercel.json";
85
- if (filename === "api/runner/min-version.ts")
86
- return "min-version";
87
- if (filename === "packages/acc-runner/package.json")
88
- return "package-version";
89
- if (filename.endsWith("CURRENT_CYCLE.md"))
90
- return "current-cycle";
91
- return PLANNING_RE.test(filename) ? "planning" : null;
92
- }
93
- function cmpSemver(a, b) {
94
- const parts = (s) => s.split(/[.+-]/).map((x) => Number(x) || 0);
95
- const [pa, pb] = [parts(a), parts(b)];
96
- const len = Math.max(pa.length, pb.length);
97
- for (let i = 0; i < len; i++) {
98
- if ((pa[i] ?? 0) !== (pb[i] ?? 0))
99
- return (pa[i] ?? 0) - (pb[i] ?? 0);
100
- }
101
- return 0;
102
- }
103
- const CONFLICT_MARKER_RE = /^(<{7}|={7}|>{7})/m;
104
- export function hasConflictMarkers(...sides) {
105
- return sides.some((s) => CONFLICT_MARKER_RE.test(s));
106
- }
107
- export function mergeVercelCrons(baseStr, headStr) {
108
- let base, head;
109
- try {
110
- base = JSON.parse(baseStr);
111
- head = JSON.parse(headStr);
112
- }
113
- catch {
114
- return null;
115
- }
116
- for (const k of new Set([...Object.keys(base), ...Object.keys(head)])) {
117
- if (k !== "crons" && JSON.stringify(base[k]) !== JSON.stringify(head[k]))
118
- return null;
119
- }
120
- const arr = (v) => (Array.isArray(v) ? v : []);
121
- const seen = new Set();
122
- const crons = [...arr(base.crons), ...arr(head.crons)]
123
- .filter((c) => {
124
- const p = c?.path;
125
- return typeof p === "string" && !seen.has(p) && (seen.add(p), true);
126
- })
127
- .sort((a, b) => String(a.path ?? "").localeCompare(String(b.path ?? "")));
128
- return JSON.stringify({ ...head, crons }, null, 2) + "\n";
129
- }
130
- export function resolvePlanning(base, head) {
131
- if (base !== null && head === null)
132
- return { write: true, content: base };
133
- if (head !== null && (base === null || base === head))
134
- return { write: false, content: head };
135
- if (base !== null && head !== null)
136
- return { write: true, content: base };
137
- return null;
138
- }
139
- export function mergeCurrentCycle(baseStr, headStr) {
140
- if (hasConflictMarkers(baseStr, headStr))
141
- return null;
142
- const headLines = headStr.split("\n");
143
- const seen = new Set(headLines);
144
- const additions = baseStr.split("\n").filter((l) => !seen.has(l) && (seen.add(l), true));
145
- if (additions.length === 0)
146
- return null;
147
- return [...headLines, ...additions].join("\n");
148
- }
149
- const MIN_VERSION_RE = /(export const MIN_VERSION\s*=\s*")([^"]+)(")/;
150
- const CURRENT_VERSION_RE = /(export const CURRENT_VERSION\s*=\s*")([^"]+)(")/;
151
- export function mergeMinVersion(baseStr, headStr) {
152
- const bMin = MIN_VERSION_RE.exec(baseStr), hMin = MIN_VERSION_RE.exec(headStr);
153
- const bCur = CURRENT_VERSION_RE.exec(baseStr), hCur = CURRENT_VERSION_RE.exec(headStr);
154
- if (!bMin || !hMin || !bCur || !hCur)
155
- return null;
156
- const setVer = (re, value) => (s) => s.replace(re, (_m, pre, _v, post) => `${pre}${value}${post}`);
157
- const neutralise = (s) => setVer(CURRENT_VERSION_RE, "@")(setVer(MIN_VERSION_RE, "@")(s));
158
- if (neutralise(baseStr) !== neutralise(headStr))
159
- return null;
160
- const min = cmpSemver(bMin[2], hMin[2]) >= 0 ? bMin[2] : hMin[2];
161
- const cur = cmpSemver(bCur[2], hCur[2]) >= 0 ? bCur[2] : hCur[2];
162
- return setVer(CURRENT_VERSION_RE, cur)(setVer(MIN_VERSION_RE, min)(headStr));
163
- }
164
- export function mergePackageVersion(baseStr, headStr) {
165
- let base, head;
166
- try {
167
- base = JSON.parse(baseStr);
168
- head = JSON.parse(headStr);
169
- }
170
- catch {
171
- return null;
172
- }
173
- const bv = base.version, hv = head.version;
174
- if (typeof bv !== "string" || typeof hv !== "string")
175
- return null;
176
- if (JSON.stringify({ ...base, version: 0 }) !==
177
- JSON.stringify({ ...head, version: 0 }))
178
- return null;
179
- const version = cmpSemver(bv, hv) >= 0 ? bv : hv;
180
- return JSON.stringify({ ...base, version }, null, 2) + "\n";
181
- }
182
- // ─────────────────────────────────────────────────────────────────────────────
183
- // GitHub API helpers (gh CLI)
184
- // ─────────────────────────────────────────────────────────────────────────────
185
- async function defaultGhApi(endpoint, opts = {}) {
186
- const args = ["api", endpoint];
187
- if (opts.method && opts.method !== "GET") {
188
- args.push("-X", opts.method);
189
- }
190
- if (opts.fields) {
191
- for (const [k, v] of Object.entries(opts.fields)) {
192
- args.push("-f", `${k}=${v}`);
193
- }
194
- }
195
- if (opts.jq) {
196
- args.push("--jq", opts.jq);
197
- }
198
- const { stdout } = await execa("gh", args, {
199
- env: process.env,
200
- reject: false,
201
- // gh api exits non-zero on 4xx/5xx; capture stdout to parse the error.
202
- });
203
- const text = stdout.trim();
204
- if (!text)
205
- return null;
206
- // When --jq returns a simple string, it may not be valid JSON.
207
- if (opts.jq) {
208
- try {
209
- return JSON.parse(text);
210
- }
211
- catch {
212
- return text;
213
- }
214
- }
215
- return JSON.parse(text);
216
- }
217
- /** Two-call base∩head intersection: files changed on BOTH sides since the merge base. */
218
- export async function computeConflictSet(repo, baseRef, headRef, ghApi) {
219
- const [owner, repoName] = repo.split("/");
220
- const base = `repos/${owner}/${repoName}`;
221
- // Files changed on head branch since fork (three-dot = relative to merge base)
222
- const headCompare = await ghApi(`${base}/compare/${encodeURIComponent(baseRef)}...${encodeURIComponent(headRef)}`);
223
- const headFiles = new Set((headCompare?.files ?? []).map((f) => f.filename));
224
- // Files changed on base branch since fork
225
- const baseCompare = await ghApi(`${base}/compare/${encodeURIComponent(headRef)}...${encodeURIComponent(baseRef)}`);
226
- const baseFiles = (baseCompare?.files ?? []).map((f) => f.filename);
227
- // Intersection = files both sides changed = truly conflicted
228
- return baseFiles.filter((f) => headFiles.has(f));
229
- }
230
- async function fetchPRDetail(repo, prNumber, ghApi) {
231
- const [owner, repoName] = repo.split("/");
232
- const pr = await ghApi(`repos/${owner}/${repoName}/pulls/${prNumber}`);
233
- return pr;
234
- }
235
- async function fetchFileContent(repo, path, ref, ghApi) {
236
- const [owner, repoName] = repo.split("/");
237
- try {
238
- const r = await ghApi(`repos/${owner}/${repoName}/contents/${path}?ref=${encodeURIComponent(ref)}`);
239
- if (!r || !r.content)
240
- return null;
241
- const raw = r.encoding === "base64" || !r.encoding
242
- ? Buffer.from(r.content.replace(/\n/g, ""), "base64").toString("utf8")
243
- : r.content;
244
- return { content: raw, sha: r.sha };
245
- }
246
- catch {
247
- return null;
248
- }
249
- }
250
- async function putFileContent(repo, path, content, branch, sha, ghApi) {
251
- const [owner, repoName] = repo.split("/");
252
- const fields = {
253
- message: `chore(acc): auto-resolve conflict in ${path} (T-48-5)`,
254
- content: Buffer.from(content, "utf8").toString("base64"),
255
- branch,
256
- };
257
- if (sha)
258
- fields.sha = sha;
259
- await ghApi(`repos/${owner}/${repoName}/contents/${path}`, {
260
- method: "PUT",
261
- fields,
262
- });
263
- }
264
- // ─────────────────────────────────────────────────────────────────────────────
265
- // Policy + retry count helpers
266
- // ─────────────────────────────────────────────────────────────────────────────
267
- async function defaultLoadConflictPolicy(supabase) {
268
- try {
269
- // any-allowed: org_settings shape isn't typed in the runner
270
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
271
- const { data } = await supabase.from("org_settings")
272
- .select("conflict_policy")
273
- .limit(1)
274
- .maybeSingle();
275
- const row = data;
276
- // Missing key or null → default to enabled=true (opt-out model).
277
- if (row?.conflict_policy?.enabled === false)
278
- return { enabled: false };
279
- }
280
- catch {
281
- // Network error → assume enabled so the runner still attempts resolution.
282
- }
283
- return { enabled: true };
284
- }
285
- async function defaultCountPriorAttempts(supabase, prNumber) {
286
- try {
287
- // any-allowed: tasks shape isn't fully typed in the runner
288
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
289
- const { data, error } = await supabase.from("tasks")
290
- .select("id")
291
- .eq("type", "conflict_resolution")
292
- .eq("pr_number", prNumber)
293
- .eq("status", "failed");
294
- if (error)
295
- return 0;
296
- return (data ?? []).length;
297
- }
298
- catch {
299
- return 0;
300
- }
301
- }
302
- // ─────────────────────────────────────────────────────────────────────────────
303
- // Main resolution entry point
304
- // ─────────────────────────────────────────────────────────────────────────────
305
- /**
306
- * Attempt to resolve conflicts for the PR referenced in `meta`.
307
- *
308
- * Returns a structured outcome that task-runner.ts uses to decide the
309
- * final task transition (done / failed / escalated).
310
- */
311
- export async function resolveConflict(meta, deps) {
312
- const ghApi = deps.ghApi ?? defaultGhApi;
313
- // ── 1. Policy gate ──────────────────────────────────────────────────────────
314
- const policy = deps.loadConflictPolicy
315
- ? await deps.loadConflictPolicy()
316
- : await defaultLoadConflictPolicy(deps.supabase);
317
- if (!policy.enabled) {
318
- return { action: "policy_disabled", reason: "conflict_policy.enabled=false" };
319
- }
320
- // ── 2. Retry bound ──────────────────────────────────────────────────────────
321
- const priorAttempts = deps.countPriorAttempts
322
- ? await deps.countPriorAttempts(meta.pr_number)
323
- : await defaultCountPriorAttempts(deps.supabase, meta.pr_number);
324
- if (priorAttempts >= MAX_CONFLICT_ATTEMPTS) {
325
- return {
326
- action: "escalated",
327
- reason: `max attempts (${MAX_CONFLICT_ATTEMPTS}) reached for PR #${meta.pr_number}`,
328
- };
329
- }
330
- // ── 3. Resolve head_ref from GitHub if not present in meta ──────────────────
331
- let { head_ref, base_ref } = meta;
332
- if (!head_ref) {
333
- try {
334
- const pr = await fetchPRDetail(meta.repo, meta.pr_number, ghApi);
335
- head_ref = pr.head.ref;
336
- base_ref = pr.base.ref;
337
- }
338
- catch (err) {
339
- return {
340
- action: "unresolvable",
341
- reason: `failed to fetch PR detail: ${err.message?.slice(0, 200)}`,
342
- };
343
- }
344
- }
345
- // ── 4. Compute real conflict set (base∩head) ────────────────────────────────
346
- let conflictFiles;
347
- try {
348
- conflictFiles = await computeConflictSet(meta.repo, base_ref, head_ref, ghApi);
349
- }
350
- catch (err) {
351
- return {
352
- action: "unresolvable",
353
- reason: `compare API failed: ${err.message?.slice(0, 200)}`,
354
- };
355
- }
356
- if (conflictFiles.length === 0) {
357
- // PR was already resolved or had no real file overlap — mark as resolved.
358
- return { action: "resolved", reason: "no conflicted files in base∩head", files_resolved: [] };
359
- }
360
- // ── 5. Check every conflicted file is resolvable ────────────────────────────
361
- const unresolvable = conflictFiles.filter((f) => classifyFile(f) === null);
362
- if (unresolvable.length > 0) {
363
- return {
364
- action: "unresolvable",
365
- reason: `non-resolvable files in conflict set: ${unresolvable.join(", ")}`,
366
- files_skipped: unresolvable,
367
- };
368
- }
369
- // ── 6. Fetch content + compute writes ──────────────────────────────────────
370
- const writes = [];
371
- const filesResolved = [];
372
- const filesSkipped = [];
373
- for (const filePath of conflictFiles) {
374
- const cls = classifyFile(filePath);
375
- const baseContent = await fetchFileContent(meta.repo, filePath, base_ref, ghApi);
376
- const headContent = await fetchFileContent(meta.repo, filePath, head_ref, ghApi);
377
- let merged = null;
378
- let shouldWrite = true;
379
- if (cls === "vercel.json") {
380
- if (!baseContent || !headContent) {
381
- filesSkipped.push(filePath);
382
- continue;
383
- }
384
- merged = mergeVercelCrons(baseContent.content, headContent.content);
385
- if (merged === null) {
386
- filesSkipped.push(filePath);
387
- continue;
388
- }
389
- if (merged === headContent.content)
390
- shouldWrite = false;
391
- }
392
- else if (cls === "current-cycle") {
393
- if (!baseContent || !headContent) {
394
- filesSkipped.push(filePath);
395
- continue;
396
- }
397
- if (hasConflictMarkers(baseContent.content, headContent.content)) {
398
- filesSkipped.push(filePath);
399
- continue;
400
- }
401
- merged = mergeCurrentCycle(baseContent.content, headContent.content);
402
- if (merged === null) {
403
- shouldWrite = false;
404
- merged = headContent.content;
405
- }
406
- }
407
- else if (cls === "min-version") {
408
- if (!baseContent || !headContent) {
409
- filesSkipped.push(filePath);
410
- continue;
411
- }
412
- merged = mergeMinVersion(baseContent.content, headContent.content);
413
- if (merged === null) {
414
- filesSkipped.push(filePath);
415
- continue;
416
- }
417
- if (merged === headContent.content)
418
- shouldWrite = false;
419
- }
420
- else if (cls === "package-version") {
421
- if (!baseContent || !headContent) {
422
- filesSkipped.push(filePath);
423
- continue;
424
- }
425
- merged = mergePackageVersion(baseContent.content, headContent.content);
426
- if (merged === null) {
427
- filesSkipped.push(filePath);
428
- continue;
429
- }
430
- if (merged === headContent.content)
431
- shouldWrite = false;
432
- }
433
- else {
434
- // planning
435
- const r = resolvePlanning(baseContent?.content ?? null, headContent?.content ?? null);
436
- if (r === null) {
437
- filesSkipped.push(filePath);
438
- continue;
439
- }
440
- merged = r.content;
441
- shouldWrite = r.write;
442
- }
443
- if (shouldWrite && merged !== null) {
444
- writes.push({ path: filePath, content: merged, sha: headContent?.sha });
445
- }
446
- filesResolved.push(filePath);
447
- }
448
- if (filesSkipped.length > 0) {
449
- return {
450
- action: "unresolvable",
451
- reason: `could not merge: ${filesSkipped.join(", ")}`,
452
- files_skipped: filesSkipped,
453
- files_resolved: filesResolved,
454
- };
455
- }
456
- // ── 7. Push merged content ─────────────────────────────────────────────────
457
- for (const w of writes) {
458
- try {
459
- await putFileContent(meta.repo, w.path, w.content, head_ref, w.sha, ghApi);
460
- }
461
- catch (err) {
462
- return {
463
- action: "unresolvable",
464
- reason: `put content ${w.path} failed: ${err.message?.slice(0, 200)}`,
465
- files_resolved: filesResolved,
466
- };
467
- }
468
- }
469
- return {
470
- action: "resolved",
471
- files_resolved: filesResolved,
472
- reason: writes.length > 0
473
- ? `pushed ${writes.length} file(s): ${writes.map((w) => w.path).join(", ")}`
474
- : "conflict already resolved (no writes needed)",
475
- };
476
- }
477
- //# sourceMappingURL=conflict-resolver.js.map