@loopover/miner 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 (218) hide show
  1. package/DEPLOYMENT.md +156 -0
  2. package/Dockerfile +38 -0
  3. package/README.md +269 -0
  4. package/bin/gittensory-miner-mcp.d.ts +64 -0
  5. package/bin/gittensory-miner-mcp.js +279 -0
  6. package/bin/gittensory-miner.js +196 -0
  7. package/docs/coding-agent-driver.md +140 -0
  8. package/docs/config-precedence.md +96 -0
  9. package/docs/cross-repo-discovery-phase1.md +55 -0
  10. package/docs/discovery-index-contract.md +60 -0
  11. package/docs/discovery-plane-operator-guide.md +101 -0
  12. package/docs/env-reference.md +30 -0
  13. package/docs/fleet-run-manifest.md +50 -0
  14. package/docs/miner-goal-spec.md +76 -0
  15. package/docs/miner-selfimprove-calibration.md +105 -0
  16. package/docs/observability.md +60 -0
  17. package/docs/operations-runbook.md +209 -0
  18. package/docs/repo-agnostic-capability-audit.md +129 -0
  19. package/docs/unattended-scheduling.md +107 -0
  20. package/expected-engine.version +1 -0
  21. package/lib/ams-policy.d.ts +20 -0
  22. package/lib/ams-policy.js +68 -0
  23. package/lib/attempt-cli.d.ts +99 -0
  24. package/lib/attempt-cli.js +523 -0
  25. package/lib/attempt-input-builder.d.ts +24 -0
  26. package/lib/attempt-input-builder.js +91 -0
  27. package/lib/attempt-log.d.ts +37 -0
  28. package/lib/attempt-log.js +177 -0
  29. package/lib/attempt-runner.d.ts +59 -0
  30. package/lib/attempt-runner.js +164 -0
  31. package/lib/attempt-worktree.d.ts +31 -0
  32. package/lib/attempt-worktree.js +94 -0
  33. package/lib/calibration-cli.d.ts +1 -0
  34. package/lib/calibration-cli.js +92 -0
  35. package/lib/calibration-run.d.ts +161 -0
  36. package/lib/calibration-run.js +232 -0
  37. package/lib/calibration-types.d.ts +46 -0
  38. package/lib/calibration-types.js +74 -0
  39. package/lib/calibration.d.ts +24 -0
  40. package/lib/calibration.js +99 -0
  41. package/lib/ci-poller.d.ts +33 -0
  42. package/lib/ci-poller.js +234 -0
  43. package/lib/claim-adjudication.d.ts +21 -0
  44. package/lib/claim-adjudication.js +36 -0
  45. package/lib/claim-conflict-resolver.d.ts +29 -0
  46. package/lib/claim-conflict-resolver.js +101 -0
  47. package/lib/claim-ledger-cli.d.ts +59 -0
  48. package/lib/claim-ledger-cli.js +320 -0
  49. package/lib/claim-ledger-expiry.d.ts +20 -0
  50. package/lib/claim-ledger-expiry.js +41 -0
  51. package/lib/claim-ledger.d.ts +63 -0
  52. package/lib/claim-ledger.js +303 -0
  53. package/lib/cli-error.d.ts +3 -0
  54. package/lib/cli-error.js +27 -0
  55. package/lib/cli.d.ts +3 -0
  56. package/lib/cli.js +72 -0
  57. package/lib/coding-agent-construction.d.ts +17 -0
  58. package/lib/coding-agent-construction.js +103 -0
  59. package/lib/coding-agent-house-rules.d.ts +24 -0
  60. package/lib/coding-agent-house-rules.js +64 -0
  61. package/lib/coding-task-spec.d.ts +44 -0
  62. package/lib/coding-task-spec.js +183 -0
  63. package/lib/config-precedence.d.ts +25 -0
  64. package/lib/config-precedence.js +38 -0
  65. package/lib/deny-check.d.ts +11 -0
  66. package/lib/deny-check.js +76 -0
  67. package/lib/deny-hook-synthesis.d.ts +93 -0
  68. package/lib/deny-hook-synthesis.js +399 -0
  69. package/lib/deny-hooks.d.ts +28 -0
  70. package/lib/deny-hooks.js +155 -0
  71. package/lib/deployment-docs-audit.d.ts +41 -0
  72. package/lib/deployment-docs-audit.js +115 -0
  73. package/lib/discover-cli.d.ts +94 -0
  74. package/lib/discover-cli.js +284 -0
  75. package/lib/discovery-throttle.d.ts +8 -0
  76. package/lib/discovery-throttle.js +33 -0
  77. package/lib/env-file-indirection.d.ts +4 -0
  78. package/lib/env-file-indirection.js +45 -0
  79. package/lib/event-ledger-cli.d.ts +82 -0
  80. package/lib/event-ledger-cli.js +266 -0
  81. package/lib/event-ledger.d.ts +37 -0
  82. package/lib/event-ledger.js +210 -0
  83. package/lib/execute-local-write.d.ts +14 -0
  84. package/lib/execute-local-write.js +50 -0
  85. package/lib/feasibility-cli.d.ts +25 -0
  86. package/lib/feasibility-cli.js +80 -0
  87. package/lib/forge-config.d.ts +17 -0
  88. package/lib/forge-config.js +37 -0
  89. package/lib/governor-action-mode.d.ts +26 -0
  90. package/lib/governor-action-mode.js +47 -0
  91. package/lib/governor-chokepoint-persisted.d.ts +18 -0
  92. package/lib/governor-chokepoint-persisted.js +46 -0
  93. package/lib/governor-chokepoint.d.ts +14 -0
  94. package/lib/governor-chokepoint.js +52 -0
  95. package/lib/governor-kill-switch.d.ts +26 -0
  96. package/lib/governor-kill-switch.js +47 -0
  97. package/lib/governor-ledger-cli.d.ts +32 -0
  98. package/lib/governor-ledger-cli.js +155 -0
  99. package/lib/governor-ledger.d.ts +46 -0
  100. package/lib/governor-ledger.js +203 -0
  101. package/lib/governor-open-pr.d.ts +21 -0
  102. package/lib/governor-open-pr.js +27 -0
  103. package/lib/governor-pause-cli.d.ts +23 -0
  104. package/lib/governor-pause-cli.js +171 -0
  105. package/lib/governor-run-halt.d.ts +37 -0
  106. package/lib/governor-run-halt.js +58 -0
  107. package/lib/governor-state.d.ts +63 -0
  108. package/lib/governor-state.js +363 -0
  109. package/lib/governor-write-rate-limit.d.ts +30 -0
  110. package/lib/governor-write-rate-limit.js +64 -0
  111. package/lib/harness-submission-trigger.d.ts +69 -0
  112. package/lib/harness-submission-trigger.js +138 -0
  113. package/lib/http-retry.d.ts +12 -0
  114. package/lib/http-retry.js +52 -0
  115. package/lib/laptop-init.d.ts +53 -0
  116. package/lib/laptop-init.js +332 -0
  117. package/lib/live-issue-snapshot.d.ts +16 -0
  118. package/lib/live-issue-snapshot.js +117 -0
  119. package/lib/local-store.d.ts +18 -0
  120. package/lib/local-store.js +62 -0
  121. package/lib/logger.d.ts +58 -0
  122. package/lib/logger.js +167 -0
  123. package/lib/loop-cli.d.ts +66 -0
  124. package/lib/loop-cli.js +540 -0
  125. package/lib/loop-closure.d.ts +35 -0
  126. package/lib/loop-closure.js +66 -0
  127. package/lib/loop-reentry.d.ts +51 -0
  128. package/lib/loop-reentry.js +124 -0
  129. package/lib/manage-poll.d.ts +79 -0
  130. package/lib/manage-poll.js +254 -0
  131. package/lib/manage-status.d.ts +70 -0
  132. package/lib/manage-status.js +241 -0
  133. package/lib/metrics-cli.d.ts +9 -0
  134. package/lib/metrics-cli.js +50 -0
  135. package/lib/migrate-cli.d.ts +24 -0
  136. package/lib/migrate-cli.js +111 -0
  137. package/lib/miner-goal-spec.d.ts +12 -0
  138. package/lib/miner-goal-spec.js +67 -0
  139. package/lib/opportunity-fanout.d.ts +86 -0
  140. package/lib/opportunity-fanout.js +597 -0
  141. package/lib/opportunity-ranker.d.ts +36 -0
  142. package/lib/opportunity-ranker.js +118 -0
  143. package/lib/orb-export.d.ts +54 -0
  144. package/lib/orb-export.js +206 -0
  145. package/lib/plan-store-cli.d.ts +37 -0
  146. package/lib/plan-store-cli.js +151 -0
  147. package/lib/plan-store.d.ts +51 -0
  148. package/lib/plan-store.js +231 -0
  149. package/lib/policy-doc-cache.d.ts +25 -0
  150. package/lib/policy-doc-cache.js +79 -0
  151. package/lib/policy-verdict-cache.d.ts +35 -0
  152. package/lib/policy-verdict-cache.js +106 -0
  153. package/lib/portfolio-dashboard.d.ts +30 -0
  154. package/lib/portfolio-dashboard.js +105 -0
  155. package/lib/portfolio-discovery.d.ts +29 -0
  156. package/lib/portfolio-discovery.js +100 -0
  157. package/lib/portfolio-queue-cli.d.ts +87 -0
  158. package/lib/portfolio-queue-cli.js +509 -0
  159. package/lib/portfolio-queue-expiry.d.ts +20 -0
  160. package/lib/portfolio-queue-expiry.js +51 -0
  161. package/lib/portfolio-queue-manager.d.ts +50 -0
  162. package/lib/portfolio-queue-manager.js +134 -0
  163. package/lib/portfolio-queue.d.ts +62 -0
  164. package/lib/portfolio-queue.js +351 -0
  165. package/lib/pr-disposition-poller.d.ts +26 -0
  166. package/lib/pr-disposition-poller.js +163 -0
  167. package/lib/pr-number-parse.d.ts +4 -0
  168. package/lib/pr-number-parse.js +23 -0
  169. package/lib/pr-outcome.d.ts +41 -0
  170. package/lib/pr-outcome.js +90 -0
  171. package/lib/prediction-ledger.d.ts +47 -0
  172. package/lib/prediction-ledger.js +222 -0
  173. package/lib/pretooluse-hook.d.ts +31 -0
  174. package/lib/pretooluse-hook.js +93 -0
  175. package/lib/process-lifecycle.d.ts +31 -0
  176. package/lib/process-lifecycle.js +106 -0
  177. package/lib/purge-cli.d.ts +44 -0
  178. package/lib/purge-cli.js +198 -0
  179. package/lib/rejection-signal.d.ts +6 -0
  180. package/lib/rejection-signal.js +101 -0
  181. package/lib/rejection-state-machine.d.ts +37 -0
  182. package/lib/rejection-state-machine.js +81 -0
  183. package/lib/rejection-templates.d.ts +12 -0
  184. package/lib/rejection-templates.js +71 -0
  185. package/lib/replay-objective-anchor.d.ts +79 -0
  186. package/lib/replay-objective-anchor.js +179 -0
  187. package/lib/replay-snapshot.d.ts +41 -0
  188. package/lib/replay-snapshot.js +288 -0
  189. package/lib/replay-task-generation.d.ts +126 -0
  190. package/lib/replay-task-generation.js +223 -0
  191. package/lib/repo-clone.d.ts +19 -0
  192. package/lib/repo-clone.js +102 -0
  193. package/lib/run-state-cli.d.ts +27 -0
  194. package/lib/run-state-cli.js +154 -0
  195. package/lib/run-state.d.ts +37 -0
  196. package/lib/run-state.js +150 -0
  197. package/lib/schema-version.d.ts +17 -0
  198. package/lib/schema-version.js +71 -0
  199. package/lib/self-review-context.d.ts +28 -0
  200. package/lib/self-review-context.js +339 -0
  201. package/lib/slop-assessment.d.ts +3 -0
  202. package/lib/slop-assessment.js +20 -0
  203. package/lib/stack-detection.d.ts +41 -0
  204. package/lib/stack-detection.js +248 -0
  205. package/lib/status.d.ts +64 -0
  206. package/lib/status.js +441 -0
  207. package/lib/store-maintenance.d.ts +31 -0
  208. package/lib/store-maintenance.js +183 -0
  209. package/lib/submission-freshness-check.d.ts +32 -0
  210. package/lib/submission-freshness-check.js +93 -0
  211. package/lib/update-check.d.ts +36 -0
  212. package/lib/update-check.js +161 -0
  213. package/lib/version.d.ts +3 -0
  214. package/lib/version.js +10 -0
  215. package/lib/worktree-allocator.d.ts +39 -0
  216. package/lib/worktree-allocator.js +262 -0
  217. package/package.json +50 -0
  218. package/schema/miner-goal-spec.schema.json +111 -0
@@ -0,0 +1,58 @@
1
+ export type LogLevel = "silent" | "error" | "warn" | "info" | "debug";
2
+
3
+ export const LOG_LEVELS: readonly LogLevel[];
4
+ export const DEFAULT_LOG_LEVEL: LogLevel;
5
+
6
+ export function isLogLevel(value: unknown): value is LogLevel;
7
+
8
+ export function resolveLogLevel(signals?: {
9
+ level?: string | undefined;
10
+ quiet?: boolean | undefined;
11
+ verbose?: boolean | undefined;
12
+ envLevel?: string | undefined;
13
+ }): LogLevel;
14
+
15
+ export function extractLogOptions(argv: string[]): {
16
+ options: { quiet: boolean; verbose: boolean; level: string | undefined };
17
+ rest: string[];
18
+ };
19
+
20
+ export function formatFields(fields?: Record<string, unknown> | null | undefined): string;
21
+
22
+ export function formatLine(line: {
23
+ level: string;
24
+ message: string;
25
+ fields?: Record<string, unknown> | null | undefined;
26
+ pretty?: boolean | undefined;
27
+ timestamp?: string | undefined;
28
+ }): string;
29
+
30
+ export interface LoggerStreams {
31
+ stdout?: { write(chunk: string): unknown } | undefined;
32
+ stderr?: { write(chunk: string): unknown } | undefined;
33
+ }
34
+
35
+ export interface LoggerOptions {
36
+ level?: string | undefined;
37
+ quiet?: boolean | undefined;
38
+ verbose?: boolean | undefined;
39
+ pretty?: boolean | undefined;
40
+ fields?: Record<string, unknown> | undefined;
41
+ env?: Record<string, string | undefined> | undefined;
42
+ streams?: LoggerStreams | undefined;
43
+ now?: (() => string) | undefined;
44
+ }
45
+
46
+ export interface Logger {
47
+ level: LogLevel;
48
+ isLevelEnabled(level: string): boolean;
49
+ error(message: string, fields?: Record<string, unknown>): void;
50
+ warn(message: string, fields?: Record<string, unknown>): void;
51
+ info(message: string, fields?: Record<string, unknown>): void;
52
+ debug(message: string, fields?: Record<string, unknown>): void;
53
+ child(fields: Record<string, unknown>): Logger;
54
+ }
55
+
56
+ export function createLogger(options?: LoggerOptions): Logger;
57
+ export function configureLogger(options?: LoggerOptions): Logger;
58
+ export function getLogger(): Logger;
package/lib/logger.js ADDED
@@ -0,0 +1,167 @@
1
+ // Level-aware logging abstraction for the miner CLI (#4835): every CLI file previously reached for ad hoc
2
+ // `console.log`/`console.error` with no shared level control, so an operator could neither quiet routine
3
+ // chatter nor turn on verbose diagnostics. This module is the one dependency-light logger the CLI configures
4
+ // once at startup and every command shares. It is deliberately pure/injectable — `streams`, `now`, and `env`
5
+ // are all overridable — so the branchy level/format logic is unit-testable without touching real stdio.
6
+ //
7
+ // Levels are ordered by severity; a logger at level L emits a method only when the method's severity rank is at
8
+ // or below L's rank (so `error` always survives except at `silent`, and `debug` only shows at the most verbose
9
+ // setting). `error`/`warn` go to stderr, `info`/`debug` to stdout, matching the existing convention where the
10
+ // update-check nudge writes to stderr and normal command output writes to stdout.
11
+
12
+ /** Supported log levels, least to most verbose. `silent` suppresses everything. */
13
+ export const LOG_LEVELS = ["silent", "error", "warn", "info", "debug"];
14
+
15
+ /** The level used when nothing (flag, env var, or explicit option) selects one. */
16
+ export const DEFAULT_LOG_LEVEL = "info";
17
+
18
+ // Numeric severity rank per level (higher = more verbose). A method emits when its rank <= the active rank.
19
+ const LEVEL_RANK = { silent: 0, error: 1, warn: 2, info: 3, debug: 4 };
20
+
21
+ const defaultClock = () => new Date().toISOString();
22
+
23
+ /** True when `value` names a supported log level. Non-string input is never a level (so an absent option or a
24
+ * typo'd env var falls through to the next signal instead of throwing). */
25
+ export function isLogLevel(value) {
26
+ return typeof value === "string" && Object.prototype.hasOwnProperty.call(LEVEL_RANK, value);
27
+ }
28
+
29
+ /**
30
+ * Resolve the active level from the available signals, most explicit first: an explicit `level` wins, then
31
+ * `--quiet` (→ `error`), then `--verbose` (→ `debug`), then the env-provided level, else the default. `quiet`
32
+ * beats `verbose` when both are set, so the safer/quieter choice wins a contradictory invocation. An
33
+ * unrecognized `level`/`envLevel` is ignored rather than throwing — a typo logs at the default, never crashes.
34
+ * @param {{ level?: string, quiet?: boolean, verbose?: boolean, envLevel?: string }} [signals]
35
+ * @returns {string}
36
+ */
37
+ export function resolveLogLevel({ level, quiet = false, verbose = false, envLevel } = {}) {
38
+ if (isLogLevel(level)) return level;
39
+ if (quiet) return "error";
40
+ if (verbose) return "debug";
41
+ if (isLogLevel(envLevel)) return envLevel;
42
+ return DEFAULT_LOG_LEVEL;
43
+ }
44
+
45
+ /**
46
+ * Split the global logging flags out of a CLI argv slice, returning the parsed options plus `rest` — the argv
47
+ * with those flags (and any `--log-level` value) removed so downstream command parsing never sees them.
48
+ * Recognizes `--quiet`, `--verbose`, `--log-level <level>`, and `--log-level=<level>`. No short aliases: `-v`
49
+ * is already `--version` and `-h` is `--help` in the CLI entrypoint.
50
+ * @param {string[]} argv
51
+ * @returns {{ options: { quiet: boolean, verbose: boolean, level: string | undefined }, rest: string[] }}
52
+ */
53
+ export function extractLogOptions(argv) {
54
+ let quiet = false;
55
+ let verbose = false;
56
+ let level;
57
+ const rest = [];
58
+ for (let index = 0; index < argv.length; index += 1) {
59
+ const arg = argv[index];
60
+ if (arg === "--quiet") {
61
+ quiet = true;
62
+ continue;
63
+ }
64
+ if (arg === "--verbose") {
65
+ verbose = true;
66
+ continue;
67
+ }
68
+ if (arg === "--log-level") {
69
+ level = argv[index + 1];
70
+ index += 1;
71
+ continue;
72
+ }
73
+ if (arg.startsWith("--log-level=")) {
74
+ level = arg.slice("--log-level=".length);
75
+ continue;
76
+ }
77
+ rest.push(arg);
78
+ }
79
+ return { options: { quiet, verbose, level }, rest };
80
+ }
81
+
82
+ function formatFieldValue(value) {
83
+ // Quote a string only when it contains whitespace (so it stays one token); serialize everything else as JSON.
84
+ if (typeof value === "string") return /\s/.test(value) ? JSON.stringify(value) : value;
85
+ return JSON.stringify(value);
86
+ }
87
+
88
+ /**
89
+ * Render structured fields as a stable, sorted ` key=value` suffix (sorted so output is deterministic across
90
+ * runs). `undefined` values are dropped; an empty/absent field set yields an empty string.
91
+ * @param {Record<string, unknown> | null | undefined} fields
92
+ * @returns {string}
93
+ */
94
+ export function formatFields(fields) {
95
+ if (!fields) return "";
96
+ const parts = [];
97
+ for (const key of Object.keys(fields).sort()) {
98
+ const value = fields[key];
99
+ if (value === undefined) continue;
100
+ parts.push(`${key}=${formatFieldValue(value)}`);
101
+ }
102
+ return parts.length > 0 ? ` ${parts.join(" ")}` : "";
103
+ }
104
+
105
+ /**
106
+ * Format one log line. Plain mode (the default) is just `message` + any field suffix, keeping human CLI output
107
+ * identical to a bare `console.log`. Pretty mode prefixes an optional timestamp and the uppercased level tag,
108
+ * for operators who want machine-scannable diagnostics.
109
+ * @param {{ level: string, message: string, fields?: Record<string, unknown> | null, pretty?: boolean, timestamp?: string }} line
110
+ * @returns {string}
111
+ */
112
+ export function formatLine({ level, message, fields, pretty, timestamp }) {
113
+ const suffix = formatFields(fields);
114
+ if (!pretty) return `${message}${suffix}`;
115
+ const stamp = timestamp ? `[${timestamp}] ` : "";
116
+ return `${stamp}${level.toUpperCase()} ${message}${suffix}`;
117
+ }
118
+
119
+ /**
120
+ * Build a level-aware logger. All I/O is injectable for tests: `streams` (defaults to process stdout/stderr),
121
+ * `now` (defaults to an ISO-8601 clock, only consulted in `pretty` mode), and `env` (defaults to process.env,
122
+ * read for `GITTENSORY_MINER_LOG_LEVEL`). `fields` seeds every line with contextual fields; `child(extra)`
123
+ * returns a logger that merges additional fields onto this one.
124
+ * @param {import("./logger.js").LoggerOptions} [options]
125
+ * @returns {import("./logger.js").Logger}
126
+ */
127
+ export function createLogger(options = {}) {
128
+ const { level, quiet, verbose, pretty = false, fields: baseFields, env = process.env, streams, now } = options;
129
+ const stdout = streams?.stdout ?? process.stdout;
130
+ const stderr = streams?.stderr ?? process.stderr;
131
+ const clock = now ?? defaultClock;
132
+ const envLevel = env.GITTENSORY_MINER_LOG_LEVEL ?? "";
133
+ const activeLevel = resolveLogLevel({ level, quiet, verbose, envLevel });
134
+ const threshold = LEVEL_RANK[activeLevel];
135
+
136
+ function emit(methodLevel, stream, message, fields) {
137
+ if (LEVEL_RANK[methodLevel] > threshold) return;
138
+ const merged = baseFields || fields ? { ...baseFields, ...fields } : undefined;
139
+ const timestamp = pretty ? clock() : undefined;
140
+ stream.write(`${formatLine({ level: methodLevel, message, fields: merged, pretty, timestamp })}\n`);
141
+ }
142
+
143
+ return {
144
+ level: activeLevel,
145
+ isLevelEnabled: (methodLevel) => LEVEL_RANK[methodLevel] <= threshold,
146
+ error: (message, fields) => emit("error", stderr, message, fields),
147
+ warn: (message, fields) => emit("warn", stderr, message, fields),
148
+ info: (message, fields) => emit("info", stdout, message, fields),
149
+ debug: (message, fields) => emit("debug", stdout, message, fields),
150
+ child: (childFields) => createLogger({ ...options, fields: { ...baseFields, ...childFields } }),
151
+ };
152
+ }
153
+
154
+ // Process-wide logger. The CLI entrypoint calls `configureLogger` once from the parsed global flags/env so every
155
+ // command shares one configured instance via `getLogger`; until then this default-level instance is used.
156
+ let processLogger = createLogger();
157
+
158
+ /** Reconfigure the process-wide logger from resolved startup options and return it. */
159
+ export function configureLogger(options) {
160
+ processLogger = createLogger(options);
161
+ return processLogger;
162
+ }
163
+
164
+ /** The process-wide logger configured by `configureLogger` (a default-level logger before then). */
165
+ export function getLogger() {
166
+ return processLogger;
167
+ }
@@ -0,0 +1,66 @@
1
+ import type { AttemptCliResult } from "./attempt-cli.js";
2
+ import type { PortfolioQueueStore } from "./portfolio-queue.js";
3
+ import type { GovernorState } from "./governor-state.js";
4
+ import type { EventLedger } from "./event-ledger.js";
5
+ import type { GovernorLedger } from "./governor-ledger.js";
6
+ import type { RunStateStore } from "./run-state.js";
7
+ import type { PollPrDispositionOptions } from "./pr-disposition-poller.js";
8
+ import type { CheckRunConclusion, PollCheckRunsOptions } from "./ci-poller.js";
9
+
10
+ export type ParsedLoopArgs =
11
+ | { error: string }
12
+ | {
13
+ targets: string[];
14
+ search: string | null;
15
+ minerLogin: string;
16
+ base: string;
17
+ live: boolean;
18
+ dryRun: boolean;
19
+ maxCycles: number | undefined;
20
+ cycleDelayMs: number;
21
+ json: boolean;
22
+ };
23
+
24
+ export function parseLoopArgs(args: string[]): ParsedLoopArgs;
25
+
26
+ export type LoopCycleSummary = {
27
+ cycle: number;
28
+ outcome: "idle_queue_empty" | "halted" | "attempted" | "skipped_malformed_identifier";
29
+ reason?: string;
30
+ repoFullName?: string;
31
+ identifier?: string;
32
+ attemptOutcome?: AttemptCliResult["outcome"] | "attempt_error";
33
+ reentryOutcome?: "merged" | "disengaged" | "other";
34
+ prNumber?: number | null;
35
+ ciConclusion?: CheckRunConclusion | null;
36
+ reentered?: boolean;
37
+ reasons?: string[];
38
+ };
39
+
40
+ export type RunLoopOptions = {
41
+ env?: Record<string, string | undefined>;
42
+ nowMs?: number;
43
+ githubToken?: string;
44
+ apiBaseUrl?: string;
45
+ sleepFn?: (delayMs: number) => Promise<void>;
46
+ openGovernorState?: () => GovernorState;
47
+ initEventLedger?: () => EventLedger;
48
+ initGovernorLedger?: () => GovernorLedger;
49
+ initPortfolioQueue?: () => PortfolioQueueStore;
50
+ initRunStateStore?: () => RunStateStore;
51
+ runDiscover?: (args: string[], options?: Record<string, unknown>) => Promise<number>;
52
+ runAttempt?: (args: string[], options?: Record<string, unknown>) => Promise<number>;
53
+ resolveAmsPolicy?: (repoFullName: string, options?: Record<string, unknown>) => Promise<{ spec: Record<string, unknown>; source: string; warnings: string[] }>;
54
+ checkMinerKillSwitch?: (input?: { env?: Record<string, string | undefined>; repoPaused?: boolean }) => { scope: "global" | "repo" | "none"; active: boolean };
55
+ evaluateRunLoopBoundaryGate?: (input: unknown, options?: unknown) => { verdict: { reason: string }; canClaimNext: boolean };
56
+ pollPrDisposition?: (repoFullName: string, prNumber: number, options?: PollPrDispositionOptions) => Promise<{ state: "open" | "closed"; merged: boolean; closedAt: string | null; attempts: number }>;
57
+ pollCheckRuns?: (repoFullName: string, prNumber: number, options?: PollCheckRunsOptions) => Promise<{ conclusion: CheckRunConclusion; checks: unknown[]; headSha: string; attempts: number }>;
58
+ recordPrOutcomeSnapshot?: (input: unknown, options?: unknown) => unknown;
59
+ buildLoopClosureSummary?: (sources: unknown, options?: unknown) => { sinceSeq: number | null; lastSeq: number };
60
+ attemptLoopReentry?: (candidate: unknown, deps: unknown) => { decision: { reenter: boolean; reasons: string[] }; dequeued: { repoFullName: string; identifier: string; priority: number; status: string; enqueuedAt: string } | null };
61
+ attemptOptions?: Record<string, unknown>;
62
+ prDispositionOptions?: PollPrDispositionOptions;
63
+ ciPollOptions?: PollCheckRunsOptions;
64
+ };
65
+
66
+ export function runLoop(args: string[], options?: RunLoopOptions): Promise<number>;