phantom-pr 0.1.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 (159) hide show
  1. package/LICENSE.md +0 -0
  2. package/README.md +143 -0
  3. package/dist/adapters/git.d.ts +28 -0
  4. package/dist/adapters/git.js +112 -0
  5. package/dist/adapters/git.js.map +1 -0
  6. package/dist/adapters/github.d.ts +71 -0
  7. package/dist/adapters/github.js +194 -0
  8. package/dist/adapters/github.js.map +1 -0
  9. package/dist/cli.d.ts +47 -0
  10. package/dist/cli.js +201 -0
  11. package/dist/cli.js.map +1 -0
  12. package/dist/commands/context.d.ts +2 -0
  13. package/dist/commands/context.js +275 -0
  14. package/dist/commands/context.js.map +1 -0
  15. package/dist/commands/full.d.ts +13 -0
  16. package/dist/commands/full.js +590 -0
  17. package/dist/commands/full.js.map +1 -0
  18. package/dist/commands/gen_test.d.ts +2 -0
  19. package/dist/commands/gen_test.js +94 -0
  20. package/dist/commands/gen_test.js.map +1 -0
  21. package/dist/commands/index.d.ts +2 -0
  22. package/dist/commands/index.js +62 -0
  23. package/dist/commands/index.js.map +1 -0
  24. package/dist/commands/plan.d.ts +2 -0
  25. package/dist/commands/plan.js +107 -0
  26. package/dist/commands/plan.js.map +1 -0
  27. package/dist/commands/pr.d.ts +9 -0
  28. package/dist/commands/pr.js +400 -0
  29. package/dist/commands/pr.js.map +1 -0
  30. package/dist/commands/pr_list.d.ts +2 -0
  31. package/dist/commands/pr_list.js +158 -0
  32. package/dist/commands/pr_list.js.map +1 -0
  33. package/dist/commands/status.d.ts +6 -0
  34. package/dist/commands/status.js +132 -0
  35. package/dist/commands/status.js.map +1 -0
  36. package/dist/commands/test.d.ts +2 -0
  37. package/dist/commands/test.js +143 -0
  38. package/dist/commands/test.js.map +1 -0
  39. package/dist/commands/testability.d.ts +10 -0
  40. package/dist/commands/testability.js +406 -0
  41. package/dist/commands/testability.js.map +1 -0
  42. package/dist/commands/tests.d.ts +9 -0
  43. package/dist/commands/tests.js +801 -0
  44. package/dist/commands/tests.js.map +1 -0
  45. package/dist/core/code/exports.d.ts +5 -0
  46. package/dist/core/code/exports.js +68 -0
  47. package/dist/core/code/exports.js.map +1 -0
  48. package/dist/core/config/forkPolicy.d.ts +25 -0
  49. package/dist/core/config/forkPolicy.js +35 -0
  50. package/dist/core/config/forkPolicy.js.map +1 -0
  51. package/dist/core/config/load.d.ts +13 -0
  52. package/dist/core/config/load.js +35 -0
  53. package/dist/core/config/load.js.map +1 -0
  54. package/dist/core/config/types.d.ts +87 -0
  55. package/dist/core/config/types.js +2 -0
  56. package/dist/core/config/types.js.map +1 -0
  57. package/dist/core/config/validate.d.ts +4 -0
  58. package/dist/core/config/validate.js +246 -0
  59. package/dist/core/config/validate.js.map +1 -0
  60. package/dist/core/context/packer.d.ts +31 -0
  61. package/dist/core/context/packer.js +345 -0
  62. package/dist/core/context/packer.js.map +1 -0
  63. package/dist/core/context/types.d.ts +41 -0
  64. package/dist/core/context/types.js +2 -0
  65. package/dist/core/context/types.js.map +1 -0
  66. package/dist/core/converge/loop.d.ts +13 -0
  67. package/dist/core/converge/loop.js +35 -0
  68. package/dist/core/converge/loop.js.map +1 -0
  69. package/dist/core/converge/types.d.ts +15 -0
  70. package/dist/core/converge/types.js +2 -0
  71. package/dist/core/converge/types.js.map +1 -0
  72. package/dist/core/generator/llm/diffApply.d.ts +26 -0
  73. package/dist/core/generator/llm/diffApply.js +276 -0
  74. package/dist/core/generator/llm/diffApply.js.map +1 -0
  75. package/dist/core/generator/llm/qualityGate.d.ts +34 -0
  76. package/dist/core/generator/llm/qualityGate.js +324 -0
  77. package/dist/core/generator/llm/qualityGate.js.map +1 -0
  78. package/dist/core/generator/llmGenerator.d.ts +34 -0
  79. package/dist/core/generator/llmGenerator.js +245 -0
  80. package/dist/core/generator/llmGenerator.js.map +1 -0
  81. package/dist/core/generator/quality.d.ts +17 -0
  82. package/dist/core/generator/quality.js +31 -0
  83. package/dist/core/generator/quality.js.map +1 -0
  84. package/dist/core/generator/registry.d.ts +26 -0
  85. package/dist/core/generator/registry.js +29 -0
  86. package/dist/core/generator/registry.js.map +1 -0
  87. package/dist/core/generator/smokeGenerator.d.ts +11 -0
  88. package/dist/core/generator/smokeGenerator.js +27 -0
  89. package/dist/core/generator/smokeGenerator.js.map +1 -0
  90. package/dist/core/generator/types.d.ts +48 -0
  91. package/dist/core/generator/types.js +2 -0
  92. package/dist/core/generator/types.js.map +1 -0
  93. package/dist/core/index/indexer.d.ts +29 -0
  94. package/dist/core/index/indexer.js +167 -0
  95. package/dist/core/index/indexer.js.map +1 -0
  96. package/dist/core/jest/parser.d.ts +17 -0
  97. package/dist/core/jest/parser.js +90 -0
  98. package/dist/core/jest/parser.js.map +1 -0
  99. package/dist/core/llm/provider.d.ts +55 -0
  100. package/dist/core/llm/provider.js +105 -0
  101. package/dist/core/llm/provider.js.map +1 -0
  102. package/dist/core/logger.d.ts +19 -0
  103. package/dist/core/logger.js +44 -0
  104. package/dist/core/logger.js.map +1 -0
  105. package/dist/core/plan/planner.d.ts +16 -0
  106. package/dist/core/plan/planner.js +91 -0
  107. package/dist/core/plan/planner.js.map +1 -0
  108. package/dist/core/process/exec.d.ts +22 -0
  109. package/dist/core/process/exec.js +83 -0
  110. package/dist/core/process/exec.js.map +1 -0
  111. package/dist/core/redact.d.ts +6 -0
  112. package/dist/core/redact.js +49 -0
  113. package/dist/core/redact.js.map +1 -0
  114. package/dist/core/repo/boundary.d.ts +10 -0
  115. package/dist/core/repo/boundary.js +58 -0
  116. package/dist/core/repo/boundary.js.map +1 -0
  117. package/dist/core/stableJson.d.ts +1 -0
  118. package/dist/core/stableJson.js +32 -0
  119. package/dist/core/stableJson.js.map +1 -0
  120. package/dist/core/state/policy.d.ts +20 -0
  121. package/dist/core/state/policy.js +51 -0
  122. package/dist/core/state/policy.js.map +1 -0
  123. package/dist/core/state/state.d.ts +67 -0
  124. package/dist/core/state/state.js +142 -0
  125. package/dist/core/state/state.js.map +1 -0
  126. package/dist/core/state/storage.d.ts +9 -0
  127. package/dist/core/state/storage.js +25 -0
  128. package/dist/core/state/storage.js.map +1 -0
  129. package/dist/core/targets/resolve.d.ts +28 -0
  130. package/dist/core/targets/resolve.js +96 -0
  131. package/dist/core/targets/resolve.js.map +1 -0
  132. package/dist/core/testGenerator/conventions.d.ts +7 -0
  133. package/dist/core/testGenerator/conventions.js +29 -0
  134. package/dist/core/testGenerator/conventions.js.map +1 -0
  135. package/dist/core/testGenerator/generate.d.ts +35 -0
  136. package/dist/core/testGenerator/generate.js +127 -0
  137. package/dist/core/testGenerator/generate.js.map +1 -0
  138. package/dist/core/testRunner/hints.d.ts +12 -0
  139. package/dist/core/testRunner/hints.js +133 -0
  140. package/dist/core/testRunner/hints.js.map +1 -0
  141. package/dist/core/testRunner/infer.d.ts +24 -0
  142. package/dist/core/testRunner/infer.js +65 -0
  143. package/dist/core/testRunner/infer.js.map +1 -0
  144. package/dist/core/testRunner/resolve.d.ts +12 -0
  145. package/dist/core/testRunner/resolve.js +31 -0
  146. package/dist/core/testRunner/resolve.js.map +1 -0
  147. package/dist/core/testRunner/runner.d.ts +24 -0
  148. package/dist/core/testRunner/runner.js +145 -0
  149. package/dist/core/testRunner/runner.js.map +1 -0
  150. package/dist/core/testability/heuristics.d.ts +7 -0
  151. package/dist/core/testability/heuristics.js +35 -0
  152. package/dist/core/testability/heuristics.js.map +1 -0
  153. package/dist/core/tests/fixers.d.ts +14 -0
  154. package/dist/core/tests/fixers.js +59 -0
  155. package/dist/core/tests/fixers.js.map +1 -0
  156. package/dist/core/tests/types.d.ts +98 -0
  157. package/dist/core/tests/types.js +2 -0
  158. package/dist/core/tests/types.js.map +1 -0
  159. package/package.json +55 -0
@@ -0,0 +1,22 @@
1
+ export type ExecResult = {
2
+ cmd: string;
3
+ args: string[];
4
+ cwd: string;
5
+ exitCode: number | null;
6
+ stdout: string;
7
+ stderr: string;
8
+ };
9
+ export declare class ExecError extends Error {
10
+ readonly result: ExecResult;
11
+ constructor(message: string, result: ExecResult);
12
+ }
13
+ export declare function exec(cmd: string, args: string[], opts?: {
14
+ cwd: string;
15
+ env?: NodeJS.ProcessEnv;
16
+ timeoutMs?: number;
17
+ }): Promise<ExecResult>;
18
+ export declare function execOrThrow(cmd: string, args: string[], opts?: {
19
+ cwd: string;
20
+ env?: NodeJS.ProcessEnv;
21
+ timeoutMs?: number;
22
+ }): Promise<ExecResult>;
@@ -0,0 +1,83 @@
1
+ import { spawn } from 'node:child_process';
2
+ export class ExecError extends Error {
3
+ result;
4
+ constructor(message, result) {
5
+ super(message);
6
+ this.name = 'ExecError';
7
+ this.result = result;
8
+ }
9
+ }
10
+ export async function exec(cmd, args, opts = { cwd: process.cwd() }) {
11
+ const cwd = opts.cwd;
12
+ const child = spawn(cmd, args, {
13
+ cwd,
14
+ env: opts.env ?? process.env,
15
+ shell: false,
16
+ stdio: ['ignore', 'pipe', 'pipe'],
17
+ windowsHide: true,
18
+ });
19
+ // NOTE: Do not `unref()` this child process. If we unref the only active handles,
20
+ // Node's test runner can treat the event loop as idle and cancel pending tests.
21
+ // Do NOT unref stdout/stderr: keep the event loop alive until we settle and clean up.
22
+ let stdout = '';
23
+ let stderr = '';
24
+ child.stdout?.setEncoding('utf8');
25
+ child.stderr?.setEncoding('utf8');
26
+ const onStdout = (c) => (stdout += c);
27
+ const onStderr = (c) => (stderr += c);
28
+ child.stdout?.on('data', onStdout);
29
+ child.stderr?.on('data', onStderr);
30
+ return await new Promise((resolve) => {
31
+ let settled = false;
32
+ let timeoutTimer = null;
33
+ const cleanup = (onExit, onClose, onError) => {
34
+ if (timeoutTimer)
35
+ clearTimeout(timeoutTimer);
36
+ child.off('exit', onExit);
37
+ child.off('close', onClose);
38
+ child.off('error', onError);
39
+ child.stdout?.off?.('data', onStdout);
40
+ child.stderr?.off?.('data', onStderr);
41
+ try {
42
+ child.stdout?.destroy?.();
43
+ }
44
+ catch { }
45
+ try {
46
+ child.stderr?.destroy?.();
47
+ }
48
+ catch { }
49
+ };
50
+ const settleOnce = (exitCode, onExit, onClose, onError) => {
51
+ if (settled)
52
+ return;
53
+ settled = true;
54
+ cleanup(onExit, onClose, onError);
55
+ resolve({ cmd, args, cwd, exitCode, stdout, stderr });
56
+ };
57
+ const onExit = (code) => settleOnce(code, onExit, onClose, onError);
58
+ const onClose = (code) => settleOnce(code, onExit, onClose, onError);
59
+ const onError = () => settleOnce(null, onExit, onClose, onError);
60
+ child.once('exit', onExit);
61
+ child.once('close', onClose);
62
+ child.once('error', onError);
63
+ if (opts.timeoutMs != null) {
64
+ timeoutTimer = setTimeout(() => {
65
+ try {
66
+ child.kill();
67
+ }
68
+ catch { }
69
+ // Settle immediately for determinism.
70
+ settleOnce(null, onExit, onClose, onError);
71
+ }, Math.max(1, opts.timeoutMs));
72
+ timeoutTimer.unref();
73
+ }
74
+ });
75
+ }
76
+ export async function execOrThrow(cmd, args, opts = { cwd: process.cwd() }) {
77
+ const r = await exec(cmd, args, opts);
78
+ if (r.exitCode !== 0) {
79
+ throw new ExecError(`Command failed: ${cmd} ${args.join(' ')}`, r);
80
+ }
81
+ return r;
82
+ }
83
+ //# sourceMappingURL=exec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exec.js","sourceRoot":"","sources":["../../../src/core/process/exec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAW3C,MAAM,OAAO,SAAU,SAAQ,KAAK;IAClB,MAAM,CAAa;IACnC,YAAY,OAAe,EAAE,MAAkB;QAC7C,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;QACxB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF;AAED,MAAM,CAAC,KAAK,UAAU,IAAI,CACxB,GAAW,EACX,IAAc,EACd,OAAqE,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE;IAE3F,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;IACrB,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE;QAC7B,GAAG;QACH,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG;QAC5B,KAAK,EAAE,KAAK;QACZ,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;QACjC,WAAW,EAAE,IAAI;KAClB,CAAC,CAAC;IACH,kFAAkF;IAClF,gFAAgF;IAChF,sFAAsF;IAEtF,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAClC,KAAK,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAClC,MAAM,QAAQ,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC;IAC9C,MAAM,QAAQ,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC;IAC9C,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACnC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAEnC,OAAO,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QACnC,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,IAAI,YAAY,GAA0B,IAAI,CAAC;QAE/C,MAAM,OAAO,GAAG,CAAC,MAAW,EAAE,OAAY,EAAE,OAAY,EAAE,EAAE;YAC1D,IAAI,YAAY;gBAAE,YAAY,CAAC,YAAY,CAAC,CAAC;YAC7C,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YAC1B,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC5B,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC5B,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;YACtC,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;YACtC,IAAI,CAAC;gBACH,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,CAAC;YAC5B,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;YACV,IAAI,CAAC;gBACH,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,CAAC;YAC5B,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;QACZ,CAAC,CAAC;QAEF,MAAM,UAAU,GAAG,CAAC,QAAuB,EAAE,MAAW,EAAE,OAAY,EAAE,OAAY,EAAE,EAAE;YACtF,IAAI,OAAO;gBAAE,OAAO;YACpB,OAAO,GAAG,IAAI,CAAC;YACf,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;YAClC,OAAO,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,CAAC,CAAC;QAEF,MAAM,MAAM,GAAG,CAAC,IAAmB,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACnF,MAAM,OAAO,GAAG,CAAC,IAAmB,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACpF,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QAEjE,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC3B,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC7B,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAE7B,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,EAAE,CAAC;YAC3B,YAAY,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC7B,IAAI,CAAC;oBACH,KAAK,CAAC,IAAI,EAAE,CAAC;gBACf,CAAC;gBAAC,MAAM,CAAC,CAAA,CAAC;gBACV,sCAAsC;gBACtC,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;YAC7C,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;YAChC,YAAY,CAAC,KAAK,EAAE,CAAC;QACvB,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,GAAW,EACX,IAAc,EACd,OAAqE,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE;IAE3F,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IACtC,IAAI,CAAC,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,SAAS,CAAC,mBAAmB,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IACrE,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC"}
@@ -0,0 +1,6 @@
1
+ export declare function redactText(input: string): string;
2
+ export declare function truncateLine(line: string, maxLen: number): string;
3
+ export declare function truncateText(input: string, opts: {
4
+ maxLineLen: number;
5
+ maxLines: number;
6
+ }): string;
@@ -0,0 +1,49 @@
1
+ const RULES = [
2
+ // Generic key/value secrets (common in logs): token=..., password: ..., apiKey "...", etc.
3
+ {
4
+ name: 'kv-secrets',
5
+ pattern: /\b(token|access[_-]?token|refresh[_-]?token|password|passphrase|secret|api[_-]?key|private[_-]?key)\b\s*[:=]\s*([^\s'"]+|"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')/gi,
6
+ replacement: '$1=<redacted>',
7
+ },
8
+ // GitHub tokens
9
+ { name: 'ghp', pattern: /\bghp_[A-Za-z0-9]{20,}\b/g, replacement: 'ghp_<redacted>' },
10
+ {
11
+ name: 'github-pat',
12
+ pattern: /\bgithub_pat_[A-Za-z0-9_]{20,}\b/g,
13
+ replacement: 'github_pat_<redacted>',
14
+ },
15
+ // Slack tokens
16
+ { name: 'slack', pattern: /\bxox[baprs]-[A-Za-z0-9-]{10,}\b/g, replacement: 'xox<redacted>' },
17
+ // AWS access key id (best-effort; does not catch secret access key)
18
+ { name: 'aws-akid', pattern: /\bAKIA[0-9A-Z]{16}\b/g, replacement: 'AKIA<redacted>' },
19
+ // Private key blocks
20
+ {
21
+ name: 'pem',
22
+ pattern: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/g,
23
+ replacement: '-----BEGIN PRIVATE KEY-----<redacted>-----END PRIVATE KEY-----',
24
+ },
25
+ ];
26
+ export function redactText(input) {
27
+ let out = input;
28
+ for (const rule of RULES) {
29
+ out = out.replace(rule.pattern, rule.replacement);
30
+ }
31
+ return out;
32
+ }
33
+ export function truncateLine(line, maxLen) {
34
+ if (maxLen <= 0)
35
+ return '';
36
+ if (line.length <= maxLen)
37
+ return line;
38
+ return `${line.slice(0, Math.max(0, maxLen - 14))}…[truncated]`;
39
+ }
40
+ export function truncateText(input, opts) {
41
+ const maxLines = Math.max(1, opts.maxLines);
42
+ const maxLineLen = Math.max(1, opts.maxLineLen);
43
+ const lines = input.split('\n');
44
+ const sliced = lines.slice(0, maxLines).map((l) => truncateLine(l, maxLineLen));
45
+ if (lines.length > maxLines)
46
+ sliced.push('…[truncated lines]');
47
+ return sliced.join('\n');
48
+ }
49
+ //# sourceMappingURL=redact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redact.js","sourceRoot":"","sources":["../../src/core/redact.ts"],"names":[],"mappings":"AAEA,MAAM,KAAK,GAAiB;IAC1B,2FAA2F;IAC3F;QACE,IAAI,EAAE,YAAY;QAClB,OAAO,EACL,iKAAiK;QACnK,WAAW,EAAE,eAAe;KAC7B;IACD,gBAAgB;IAChB,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,2BAA2B,EAAE,WAAW,EAAE,gBAAgB,EAAE;IACpF;QACE,IAAI,EAAE,YAAY;QAClB,OAAO,EAAE,mCAAmC;QAC5C,WAAW,EAAE,uBAAuB;KACrC;IACD,eAAe;IACf,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,mCAAmC,EAAE,WAAW,EAAE,eAAe,EAAE;IAC7F,oEAAoE;IACpE,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,uBAAuB,EAAE,WAAW,EAAE,gBAAgB,EAAE;IACrF,qBAAqB;IACrB;QACE,IAAI,EAAE,KAAK;QACX,OAAO,EAAE,6EAA6E;QACtF,WAAW,EAAE,gEAAgE;KAC9E;CACF,CAAC;AAEF,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,IAAI,GAAG,GAAG,KAAK,CAAC;IAChB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IACpD,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,MAAc;IACvD,IAAI,MAAM,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IAC3B,IAAI,IAAI,CAAC,MAAM,IAAI,MAAM;QAAE,OAAO,IAAI,CAAC;IACvC,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,EAAE,CAAC,CAAC,cAAc,CAAC;AAClE,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,KAAa,EAAE,IAA8C;IACxF,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC5C,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;IAEhD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAChC,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC;IAChF,IAAI,KAAK,CAAC,MAAM,GAAG,QAAQ;QAAE,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IAC/D,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,10 @@
1
+ export type BoundaryKind = 'js' | 'py' | 'unknown';
2
+ export type RepoBoundary = {
3
+ packageRootAbs: string;
4
+ kind: BoundaryKind;
5
+ boundaryFileRel: string | null;
6
+ };
7
+ export declare function findNearestRepoBoundary(opts: {
8
+ rootAbs: string;
9
+ targetPathOrDirAbs: string;
10
+ }): RepoBoundary;
@@ -0,0 +1,58 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ function toPosix(p) {
4
+ return p.replace(/\\/g, '/');
5
+ }
6
+ function existsFile(dirAbs, name) {
7
+ const p = path.join(dirAbs, name);
8
+ try {
9
+ return fs.existsSync(p) && fs.statSync(p).isFile();
10
+ }
11
+ catch {
12
+ return false;
13
+ }
14
+ }
15
+ const MARKERS = [
16
+ { name: 'package.json', kind: 'js' },
17
+ { name: 'pyproject.toml', kind: 'py' },
18
+ { name: 'pytest.ini', kind: 'py' },
19
+ { name: 'setup.cfg', kind: 'py' },
20
+ ];
21
+ export function findNearestRepoBoundary(opts) {
22
+ const rootAbs = path.resolve(opts.rootAbs);
23
+ const startAbs = path.resolve(opts.targetPathOrDirAbs);
24
+ const startDirAbs = (() => {
25
+ try {
26
+ return fs.statSync(startAbs).isDirectory() ? startAbs : path.dirname(startAbs);
27
+ }
28
+ catch {
29
+ // If the path doesn't exist, assume it's a file path when it has an extension, otherwise a directory path.
30
+ return path.extname(startAbs) ? path.dirname(startAbs) : startAbs;
31
+ }
32
+ })();
33
+ let current = startDirAbs;
34
+ while (true) {
35
+ for (const m of MARKERS) {
36
+ if (!existsFile(current, m.name))
37
+ continue;
38
+ const boundaryFileAbs = path.join(current, m.name);
39
+ return {
40
+ packageRootAbs: current,
41
+ kind: m.kind,
42
+ boundaryFileRel: toPosix(path.relative(rootAbs, boundaryFileAbs)),
43
+ };
44
+ }
45
+ const parent = path.dirname(current);
46
+ if (current === rootAbs)
47
+ break;
48
+ if (parent === current)
49
+ break;
50
+ // Stop walking once we leave the repo root.
51
+ const rel = path.relative(rootAbs, parent);
52
+ if (rel.startsWith('..') || path.isAbsolute(rel))
53
+ break;
54
+ current = parent;
55
+ }
56
+ return { packageRootAbs: rootAbs, kind: 'unknown', boundaryFileRel: null };
57
+ }
58
+ //# sourceMappingURL=boundary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boundary.js","sourceRoot":"","sources":["../../../src/core/repo/boundary.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAU7B,SAAS,OAAO,CAAC,CAAS;IACxB,OAAO,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AAC/B,CAAC;AAED,SAAS,UAAU,CAAC,MAAc,EAAE,IAAY;IAC9C,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAClC,IAAI,CAAC;QACH,OAAO,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IACrD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,OAAO,GAAgD;IAC3D,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,IAAI,EAAE;IACpC,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,IAAI,EAAE;IACtC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,IAAI,EAAE;IAClC,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE;CAClC,CAAC;AAEF,MAAM,UAAU,uBAAuB,CAAC,IAAqD;IAC3F,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IAEvD,MAAM,WAAW,GAAG,CAAC,GAAG,EAAE;QACxB,IAAI,CAAC;YACH,OAAO,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACjF,CAAC;QAAC,MAAM,CAAC;YACP,2GAA2G;YAC3G,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;QACpE,CAAC;IACH,CAAC,CAAC,EAAE,CAAC;IAEL,IAAI,OAAO,GAAG,WAAW,CAAC;IAC1B,OAAO,IAAI,EAAE,CAAC;QACZ,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACxB,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC;gBAAE,SAAS;YAC3C,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;YACnD,OAAO;gBACL,cAAc,EAAE,OAAO;gBACvB,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,eAAe,EAAE,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;aAClE,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACrC,IAAI,OAAO,KAAK,OAAO;YAAE,MAAM;QAC/B,IAAI,MAAM,KAAK,OAAO;YAAE,MAAM;QAC9B,4CAA4C;QAC5C,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC3C,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,MAAM;QACxD,OAAO,GAAG,MAAM,CAAC;IACnB,CAAC;IAED,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC;AAC7E,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function stableStringify(value: unknown): string;
@@ -0,0 +1,32 @@
1
+ function isPlainObject(value) {
2
+ if (value == null || typeof value !== 'object')
3
+ return false;
4
+ const proto = Object.getPrototypeOf(value);
5
+ return proto === Object.prototype || proto === null;
6
+ }
7
+ function toStableJson(value) {
8
+ if (value == null)
9
+ return null;
10
+ if (typeof value === 'string' || typeof value === 'boolean')
11
+ return value;
12
+ if (typeof value === 'number')
13
+ return Number.isFinite(value) ? value : null;
14
+ if (Array.isArray(value))
15
+ return value.map((v) => toStableJson(v));
16
+ if (isPlainObject(value)) {
17
+ const out = {};
18
+ const keys = Object.keys(value).sort((a, b) => a.localeCompare(b));
19
+ for (const key of keys) {
20
+ const v = value[key];
21
+ // Preserve explicit nulls; convert undefined to null for stable reporting.
22
+ out[key] = v === undefined ? null : toStableJson(v);
23
+ }
24
+ return out;
25
+ }
26
+ // Non-JSON values are not expected in config; stringify as a safe fallback.
27
+ return String(value);
28
+ }
29
+ export function stableStringify(value) {
30
+ return JSON.stringify(toStableJson(value), null, 2);
31
+ }
32
+ //# sourceMappingURL=stableJson.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stableJson.js","sourceRoot":"","sources":["../../src/core/stableJson.ts"],"names":[],"mappings":"AAQA,SAAS,aAAa,CAAC,KAAc;IACnC,IAAI,KAAK,IAAI,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC7D,MAAM,KAAK,GAAG,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IAC3C,OAAO,KAAK,KAAK,MAAM,CAAC,SAAS,IAAI,KAAK,KAAK,IAAI,CAAC;AACtD,CAAC;AAED,SAAS,YAAY,CAAC,KAAc;IAClC,IAAI,KAAK,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC;IAC/B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IAC1E,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;IAE5E,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;IAEnE,IAAI,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,GAAG,GAAyB,EAAE,CAAC;QACrC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;QACnE,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,MAAM,CAAC,GAAI,KAAiC,CAAC,GAAG,CAAC,CAAC;YAClD,2EAA2E;YAC3E,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACtD,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED,4EAA4E;IAC5E,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,OAAO,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACtD,CAAC"}
@@ -0,0 +1,20 @@
1
+ export type PolicyFile = {
2
+ schemaVersion: 1;
3
+ workingTestCommand: string | null;
4
+ allowTestabilityEdits: boolean;
5
+ denyTestabilityPaths: string[];
6
+ notes: string[];
7
+ };
8
+ export declare function initPolicy(): PolicyFile;
9
+ export declare function loadOrInitPolicy(opts?: {
10
+ root?: string;
11
+ }): {
12
+ path: string;
13
+ policy: PolicyFile;
14
+ };
15
+ export declare function savePolicy(opts: {
16
+ root?: string;
17
+ policy: PolicyFile;
18
+ }): {
19
+ path: string;
20
+ };
@@ -0,0 +1,51 @@
1
+ import path from 'node:path';
2
+ import { getAgentPaths, readJsonIfExists, writeStableJson } from './storage.js';
3
+ function isPlainObject(value) {
4
+ if (value == null || typeof value !== 'object')
5
+ return false;
6
+ const proto = Object.getPrototypeOf(value);
7
+ return proto === Object.prototype || proto === null;
8
+ }
9
+ export function initPolicy() {
10
+ return {
11
+ schemaVersion: 1,
12
+ workingTestCommand: null,
13
+ // Default allow; policy can deny specific path prefixes after observing PR outcomes.
14
+ allowTestabilityEdits: true,
15
+ denyTestabilityPaths: [],
16
+ notes: [],
17
+ };
18
+ }
19
+ function coercePolicyFile(value) {
20
+ if (!isPlainObject(value))
21
+ return initPolicy();
22
+ if (value.schemaVersion !== 1)
23
+ return initPolicy();
24
+ const workingTestCommand = typeof value.workingTestCommand === 'string' ? value.workingTestCommand : null;
25
+ const allowTestabilityEdits = typeof value.allowTestabilityEdits === 'boolean' ? value.allowTestabilityEdits : true;
26
+ const denyTestabilityPaths = Array.isArray(value.denyTestabilityPaths)
27
+ ? value.denyTestabilityPaths.filter((p) => typeof p === 'string' && p.trim() !== '')
28
+ : [];
29
+ const notes = Array.isArray(value.notes) ? value.notes.filter((n) => typeof n === 'string') : [];
30
+ return { schemaVersion: 1, workingTestCommand, allowTestabilityEdits, denyTestabilityPaths, notes };
31
+ }
32
+ export function loadOrInitPolicy(opts) {
33
+ const root = path.resolve(process.cwd(), opts?.root ?? '.');
34
+ const { policyPath } = getAgentPaths(root);
35
+ const existing = readJsonIfExists(policyPath);
36
+ if (existing == null) {
37
+ const policy = initPolicy();
38
+ writeStableJson(policyPath, policy);
39
+ return { path: policyPath, policy };
40
+ }
41
+ const policy = coercePolicyFile(existing);
42
+ return { path: policyPath, policy };
43
+ }
44
+ export function savePolicy(opts) {
45
+ const root = path.resolve(process.cwd(), opts.root ?? '.');
46
+ const { policyPath } = getAgentPaths(root);
47
+ const policy = { ...opts.policy, schemaVersion: 1 };
48
+ writeStableJson(policyPath, policy);
49
+ return { path: policyPath };
50
+ }
51
+ //# sourceMappingURL=policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy.js","sourceRoot":"","sources":["../../../src/core/state/policy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ export type TargetStatus = 'none' | 'open' | 'merged' | 'closed';
2
+ export type TargetRun = {
3
+ atMs: number;
4
+ outcome: 'pass' | 'fail' | 'skipped';
5
+ notes?: string;
6
+ };
7
+ export type TargetState = {
8
+ id: string;
9
+ status: TargetStatus;
10
+ lastPr?: {
11
+ url: string;
12
+ id?: string;
13
+ };
14
+ prOpenedAtMs?: number;
15
+ stale?: boolean;
16
+ closedReason?: 'staleHours' | string;
17
+ runs: TargetRun[];
18
+ createdAtMs: number;
19
+ updatedAtMs: number;
20
+ };
21
+ export type CompanionStatus = 'none' | 'open' | 'merged' | 'closed';
22
+ export type CompanionRun = {
23
+ atMs: number;
24
+ outcome: 'pass' | 'fail' | 'skipped';
25
+ notes?: string;
26
+ };
27
+ export type CompanionTargetState = {
28
+ key: string;
29
+ parentPrNumber: number;
30
+ parentHeadSha: string;
31
+ targetId: string;
32
+ status: CompanionStatus;
33
+ lastPr?: {
34
+ url: string;
35
+ id?: string;
36
+ };
37
+ runs: CompanionRun[];
38
+ createdAtMs: number;
39
+ updatedAtMs: number;
40
+ };
41
+ export type StateFile = {
42
+ schemaVersion: 2;
43
+ updatedAtMs: number;
44
+ scheduledTargets: Record<string, TargetState>;
45
+ companionTargets: Record<string, CompanionTargetState>;
46
+ };
47
+ export declare function makeCompanionKey(opts: {
48
+ parentPrNumber: number;
49
+ parentHeadSha: string;
50
+ targetId: string;
51
+ }): string;
52
+ export declare function hasCompanionWork(state: StateFile, key: string): boolean;
53
+ export declare function initState(nowMs: number): StateFile;
54
+ export declare function loadOrInitState(opts?: {
55
+ root?: string;
56
+ nowMs?: number;
57
+ }): {
58
+ path: string;
59
+ state: StateFile;
60
+ };
61
+ export declare function saveState(opts: {
62
+ root?: string;
63
+ nowMs?: number;
64
+ state: StateFile;
65
+ }): {
66
+ path: string;
67
+ };
@@ -0,0 +1,142 @@
1
+ import path from 'node:path';
2
+ import { getAgentPaths, readJsonIfExists, writeStableJson } from './storage.js';
3
+ function isPlainObject(value) {
4
+ if (value == null || typeof value !== 'object')
5
+ return false;
6
+ const proto = Object.getPrototypeOf(value);
7
+ return proto === Object.prototype || proto === null;
8
+ }
9
+ function coerceScheduledTargets(value, nowMs) {
10
+ const targets = {};
11
+ if (!isPlainObject(value))
12
+ return targets;
13
+ for (const [k, v] of Object.entries(value)) {
14
+ if (!isPlainObject(v))
15
+ continue;
16
+ const id = typeof v.id === 'string' ? v.id : k;
17
+ const status = v.status === 'none' || v.status === 'open' || v.status === 'merged' || v.status === 'closed'
18
+ ? v.status
19
+ : 'none';
20
+ const createdAtMs = typeof v.createdAtMs === 'number' ? Math.trunc(v.createdAtMs) : nowMs;
21
+ const updatedAtMs = typeof v.updatedAtMs === 'number' ? Math.trunc(v.updatedAtMs) : createdAtMs;
22
+ const prOpenedAtMs = typeof v.prOpenedAtMs === 'number' ? Math.trunc(v.prOpenedAtMs) : undefined;
23
+ const lastPrRaw = v.lastPr;
24
+ const lastPr = isPlainObject(lastPrRaw) && typeof lastPrRaw.url === 'string'
25
+ ? (() => {
26
+ const url = String(lastPrRaw.url);
27
+ if (lastPrRaw.id === undefined)
28
+ return { url };
29
+ return { url, id: String(lastPrRaw.id) };
30
+ })()
31
+ : undefined;
32
+ const stale = typeof v.stale === 'boolean' ? v.stale : undefined;
33
+ const closedReason = typeof v.closedReason === 'string' ? v.closedReason : undefined;
34
+ const runs = Array.isArray(v.runs)
35
+ ? v.runs
36
+ .filter((r) => isPlainObject(r))
37
+ .map((r) => {
38
+ const base = {
39
+ atMs: typeof r.atMs === 'number' ? Math.trunc(r.atMs) : createdAtMs,
40
+ outcome: r.outcome === 'pass' || r.outcome === 'fail' || r.outcome === 'skipped' ? r.outcome : 'fail',
41
+ };
42
+ const notes = typeof r.notes === 'string' ? r.notes : undefined;
43
+ return notes === undefined ? base : { ...base, notes };
44
+ })
45
+ : [];
46
+ const base = { id, status, runs, createdAtMs, updatedAtMs };
47
+ const withPr = lastPr ? { ...base, lastPr } : base;
48
+ const withPrTime = prOpenedAtMs !== undefined ? { ...withPr, prOpenedAtMs } : withPr;
49
+ const withStale = stale !== undefined ? { ...withPrTime, stale } : withPrTime;
50
+ targets[k] = closedReason !== undefined ? { ...withStale, closedReason } : withStale;
51
+ }
52
+ return targets;
53
+ }
54
+ function coerceCompanionTargets(value, nowMs) {
55
+ const out = {};
56
+ if (!isPlainObject(value))
57
+ return out;
58
+ for (const [k, v] of Object.entries(value)) {
59
+ if (!isPlainObject(v))
60
+ continue;
61
+ const key = typeof v.key === 'string' ? String(v.key) : k;
62
+ const parentPrNumber = typeof v.parentPrNumber === 'number' ? Math.trunc(v.parentPrNumber) : 0;
63
+ const parentHeadSha = typeof v.parentHeadSha === 'string' ? String(v.parentHeadSha) : '';
64
+ const targetId = typeof v.targetId === 'string' ? String(v.targetId) : '';
65
+ const statusRaw = v.status;
66
+ const status = statusRaw === 'none' || statusRaw === 'open' || statusRaw === 'merged' || statusRaw === 'closed' ? statusRaw : 'none';
67
+ const createdAtMs = typeof v.createdAtMs === 'number' ? Math.trunc(v.createdAtMs) : nowMs;
68
+ const updatedAtMs = typeof v.updatedAtMs === 'number' ? Math.trunc(v.updatedAtMs) : createdAtMs;
69
+ const lastPrRaw = v.lastPr;
70
+ const lastPr = isPlainObject(lastPrRaw) && typeof lastPrRaw.url === 'string'
71
+ ? (() => {
72
+ const url = String(lastPrRaw.url);
73
+ if (lastPrRaw.id === undefined)
74
+ return { url };
75
+ return { url, id: String(lastPrRaw.id) };
76
+ })()
77
+ : undefined;
78
+ const runs = Array.isArray(v.runs)
79
+ ? v.runs
80
+ .filter((r) => isPlainObject(r))
81
+ .map((r) => {
82
+ const base = {
83
+ atMs: typeof r.atMs === 'number' ? Math.trunc(r.atMs) : createdAtMs,
84
+ outcome: r.outcome === 'pass' || r.outcome === 'fail' || r.outcome === 'skipped' ? r.outcome : 'fail',
85
+ };
86
+ const notes = typeof r.notes === 'string' ? r.notes : undefined;
87
+ return notes === undefined ? base : { ...base, notes };
88
+ })
89
+ : [];
90
+ out[k] = { key, parentPrNumber, parentHeadSha, targetId, status, runs, createdAtMs, updatedAtMs, ...(lastPr ? { lastPr } : {}) };
91
+ }
92
+ return out;
93
+ }
94
+ export function makeCompanionKey(opts) {
95
+ const pr = Math.max(0, Math.trunc(opts.parentPrNumber));
96
+ const sha = String(opts.parentHeadSha ?? '').trim().toLowerCase();
97
+ const tid = String(opts.targetId ?? '').trim();
98
+ return `cp_${pr}_${sha}_${tid}`;
99
+ }
100
+ export function hasCompanionWork(state, key) {
101
+ return !!state.companionTargets[key];
102
+ }
103
+ function coerceStateFile(value, nowMs) {
104
+ if (!isPlainObject(value))
105
+ return initState(nowMs);
106
+ const schemaVersion = value.schemaVersion;
107
+ const updatedAt = typeof value.updatedAtMs === 'number' ? Math.trunc(value.updatedAtMs) : nowMs;
108
+ if (schemaVersion === 1) {
109
+ const scheduledTargets = coerceScheduledTargets(value.targets, nowMs);
110
+ return { schemaVersion: 2, updatedAtMs: updatedAt, scheduledTargets, companionTargets: {} };
111
+ }
112
+ if (schemaVersion !== 2)
113
+ return initState(nowMs);
114
+ const scheduledTargets = coerceScheduledTargets(value.scheduledTargets, nowMs);
115
+ const companionTargets = coerceCompanionTargets(value.companionTargets, nowMs);
116
+ return { schemaVersion: 2, updatedAtMs: updatedAt, scheduledTargets, companionTargets };
117
+ }
118
+ export function initState(nowMs) {
119
+ return { schemaVersion: 2, updatedAtMs: nowMs, scheduledTargets: {}, companionTargets: {} };
120
+ }
121
+ export function loadOrInitState(opts) {
122
+ const root = path.resolve(process.cwd(), opts?.root ?? '.');
123
+ const nowMs = opts?.nowMs ?? Date.now();
124
+ const { statePath } = getAgentPaths(root);
125
+ const existing = readJsonIfExists(statePath);
126
+ if (existing == null) {
127
+ const state = initState(nowMs);
128
+ writeStableJson(statePath, state);
129
+ return { path: statePath, state };
130
+ }
131
+ const state = coerceStateFile(existing, nowMs);
132
+ return { path: statePath, state };
133
+ }
134
+ export function saveState(opts) {
135
+ const root = path.resolve(process.cwd(), opts.root ?? '.');
136
+ const nowMs = opts.nowMs ?? Date.now();
137
+ const { statePath } = getAgentPaths(root);
138
+ const state = { ...opts.state, schemaVersion: 2, updatedAtMs: nowMs };
139
+ writeStableJson(statePath, state);
140
+ return { path: statePath };
141
+ }
142
+ //# sourceMappingURL=state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../../../src/core/state/state.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export type AgentFilePaths = {
2
+ dir: string;
3
+ statePath: string;
4
+ policyPath: string;
5
+ };
6
+ export declare function getAgentPaths(root: string): AgentFilePaths;
7
+ export declare function ensureDir(dir: string): void;
8
+ export declare function readJsonIfExists(filePath: string): unknown | null;
9
+ export declare function writeStableJson(filePath: string, value: unknown): void;
@@ -0,0 +1,25 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { stableStringify } from '../stableJson.js';
4
+ export function getAgentPaths(root) {
5
+ const dir = path.join(root, '.test-agent');
6
+ return {
7
+ dir,
8
+ statePath: path.join(dir, 'state.json'),
9
+ policyPath: path.join(dir, 'policy.json'),
10
+ };
11
+ }
12
+ export function ensureDir(dir) {
13
+ fs.mkdirSync(dir, { recursive: true });
14
+ }
15
+ export function readJsonIfExists(filePath) {
16
+ if (!fs.existsSync(filePath))
17
+ return null;
18
+ const raw = fs.readFileSync(filePath, 'utf8');
19
+ return JSON.parse(raw);
20
+ }
21
+ export function writeStableJson(filePath, value) {
22
+ ensureDir(path.dirname(filePath));
23
+ fs.writeFileSync(filePath, stableStringify(value) + '\n', 'utf8');
24
+ }
25
+ //# sourceMappingURL=storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.js","sourceRoot":"","sources":["../../../src/core/state/storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAQnD,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;IAC3C,OAAO;QACL,GAAG;QACH,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC;QACvC,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,aAAa,CAAC;KAC1C,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,GAAW;IACnC,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,QAAgB;IAC/C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAC;IAC1C,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC9C,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,QAAgB,EAAE,KAAc;IAC9D,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;IAClC,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,eAAe,CAAC,KAAK,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC;AACpE,CAAC"}