@indigoai-us/hq-cli 5.125.0 → 5.127.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 (108) hide show
  1. package/CHANGELOG.md +329 -0
  2. package/assets/bot-workers/setup/skills/joining-a-team.md +125 -0
  3. package/assets/bot-workers/setup/skills/your-business.md +270 -0
  4. package/assets/bot-workers/setup/worker.yaml +189 -58
  5. package/assets/lanes-hooks/hq-lanes-drain.json +15 -0
  6. package/assets/lanes-hooks/hq-lanes-drain.mjs +254 -0
  7. package/assets/lanes-hooks/hq-lanes-drain.sh +21 -0
  8. package/assets/lanes-reconcile/hq-lanes-reconcile.service +11 -0
  9. package/assets/lanes-reconcile/hq-lanes-reconcile.timer +12 -0
  10. package/dist/command-catalog.generated.d.ts +643 -6
  11. package/dist/command-catalog.generated.js +836 -6
  12. package/dist/command-registration-plan.d.ts +7 -0
  13. package/dist/command-registration-plan.js +11 -1
  14. package/dist/commands/agents.d.ts +12 -0
  15. package/dist/commands/agents.js +46 -2
  16. package/dist/commands/bot.d.ts +10 -0
  17. package/dist/commands/bot.js +6 -0
  18. package/dist/commands/lanes.d.ts +114 -0
  19. package/dist/commands/lanes.js +2969 -0
  20. package/dist/commands/mesh.js +287 -24
  21. package/dist/commands/onboard-create-identity.d.ts +26 -0
  22. package/dist/commands/onboard-create-identity.js +23 -0
  23. package/dist/commands/onboard.js +13 -4
  24. package/dist/lib/bot/progress.d.ts +6 -0
  25. package/dist/lib/bot/progress.js +16 -0
  26. package/dist/lib/bot/runtime/grok.d.ts +30 -7
  27. package/dist/lib/bot/runtime/grok.js +86 -8
  28. package/dist/lib/bot/runtime/index.js +15 -8
  29. package/dist/lib/bot/runtime/messages-stream.d.ts +12 -3
  30. package/dist/lib/bot/runtime/messages-stream.js +49 -3
  31. package/dist/lib/lanes/accounts.d.ts +103 -0
  32. package/dist/lib/lanes/accounts.js +318 -0
  33. package/dist/lib/lanes/compaction.d.ts +96 -0
  34. package/dist/lib/lanes/compaction.js +197 -0
  35. package/dist/lib/lanes/config.d.ts +71 -0
  36. package/dist/lib/lanes/config.js +408 -0
  37. package/dist/lib/lanes/delivery.d.ts +151 -0
  38. package/dist/lib/lanes/delivery.js +354 -0
  39. package/dist/lib/lanes/dropbox.d.ts +96 -0
  40. package/dist/lib/lanes/dropbox.js +408 -0
  41. package/dist/lib/lanes/effort.d.ts +50 -0
  42. package/dist/lib/lanes/effort.js +109 -0
  43. package/dist/lib/lanes/errors.d.ts +39 -0
  44. package/dist/lib/lanes/errors.js +72 -0
  45. package/dist/lib/lanes/hooks-install.d.ts +81 -0
  46. package/dist/lib/lanes/hooks-install.js +326 -0
  47. package/dist/lib/lanes/hq-root.d.ts +19 -0
  48. package/dist/lib/lanes/hq-root.js +28 -0
  49. package/dist/lib/lanes/index.d.ts +49 -0
  50. package/dist/lib/lanes/index.js +27 -0
  51. package/dist/lib/lanes/liveness.d.ts +95 -0
  52. package/dist/lib/lanes/liveness.js +332 -0
  53. package/dist/lib/lanes/machine-identity.d.ts +34 -0
  54. package/dist/lib/lanes/machine-identity.js +92 -0
  55. package/dist/lib/lanes/mesh-events.d.ts +109 -0
  56. package/dist/lib/lanes/mesh-events.js +275 -0
  57. package/dist/lib/lanes/outpost-dispatch.d.ts +65 -0
  58. package/dist/lib/lanes/outpost-dispatch.js +90 -0
  59. package/dist/lib/lanes/questions.d.ts +75 -0
  60. package/dist/lib/lanes/questions.js +243 -0
  61. package/dist/lib/lanes/quota.d.ts +95 -0
  62. package/dist/lib/lanes/quota.js +320 -0
  63. package/dist/lib/lanes/reconcile-install.d.ts +69 -0
  64. package/dist/lib/lanes/reconcile-install.js +221 -0
  65. package/dist/lib/lanes/reconcile.d.ts +102 -0
  66. package/dist/lib/lanes/reconcile.js +985 -0
  67. package/dist/lib/lanes/registry.d.ts +116 -0
  68. package/dist/lib/lanes/registry.js +521 -0
  69. package/dist/lib/lanes/spawn.d.ts +274 -0
  70. package/dist/lib/lanes/spawn.js +1363 -0
  71. package/dist/lib/lanes/store.d.ts +68 -0
  72. package/dist/lib/lanes/store.js +745 -0
  73. package/dist/lib/lanes/throttle.d.ts +89 -0
  74. package/dist/lib/lanes/throttle.js +297 -0
  75. package/dist/lib/lanes/types.d.ts +535 -0
  76. package/dist/lib/lanes/types.js +350 -0
  77. package/dist/lib/lanes/watcher-main.d.ts +9 -0
  78. package/dist/lib/lanes/watcher-main.js +22 -0
  79. package/dist/lib/lanes/watcher.d.ts +216 -0
  80. package/dist/lib/lanes/watcher.js +859 -0
  81. package/dist/lib/mesh/api.d.ts +71 -7
  82. package/dist/lib/mesh/api.js +167 -28
  83. package/dist/lib/mesh/live/backfill-held.d.ts +18 -7
  84. package/dist/lib/mesh/live/backfill-held.js +66 -21
  85. package/dist/lib/mesh/live/daemon/config.d.ts +27 -0
  86. package/dist/lib/mesh/live/daemon/config.js +75 -0
  87. package/dist/lib/mesh/live/daemon/index.d.ts +4 -3
  88. package/dist/lib/mesh/live/daemon/index.js +3 -3
  89. package/dist/lib/mesh/live/daemon/install.d.ts +143 -1
  90. package/dist/lib/mesh/live/daemon/install.js +444 -2
  91. package/dist/lib/mesh/live/daemon/paths.d.ts +2 -0
  92. package/dist/lib/mesh/live/daemon/paths.js +2 -0
  93. package/dist/lib/mesh/live/daemon/run.d.ts +2 -0
  94. package/dist/lib/mesh/live/daemon/run.js +111 -54
  95. package/dist/lib/mesh/live/daemon/state.d.ts +2 -0
  96. package/dist/lib/mesh/live/daemon/transcript-watch.d.ts +3 -0
  97. package/dist/lib/mesh/live/daemon/transcript-watch.js +31 -8
  98. package/dist/lib/scan-packages/index.d.ts +2 -0
  99. package/dist/lib/scan-packages/index.js +18 -13
  100. package/dist/lib/work-context/config.d.ts +20 -0
  101. package/dist/lib/work-context/config.js +26 -5
  102. package/dist/lib/work-context/reconcile.js +28 -7
  103. package/dist/lib/work-context/state.d.ts +12 -0
  104. package/dist/lib/work-context/state.js +131 -3
  105. package/dist/lib/work-context/windows-acl.d.ts +123 -0
  106. package/dist/lib/work-context/windows-acl.js +425 -0
  107. package/dist/utils/pack-contributions.js +5 -4
  108. package/package.json +3 -1
@@ -0,0 +1,69 @@
1
+ /**
2
+ * systemd user timer install for the lanes reconcile pass.
3
+ *
4
+ * Policy: hq-infra-watchdogs-systemd-not-session. The pass is a oneshot
5
+ * invoked by a timer, never a session-bound background job. Install writes
6
+ * unit files under a systemd user dir and is idempotent and reversible.
7
+ * Enabling the timer is optional — the CLI pass works without it.
8
+ */
9
+ export declare const RECONCILE_TIMER_INTERVAL = "1min";
10
+ export interface ProviderPathEnv {
11
+ /** PATH for the systemd unit: resolved provider dirs, systemd defaults, then the shell PATH. */
12
+ path: string;
13
+ /** Providers whose binary resolved on the installing shell's PATH. */
14
+ resolved: string[];
15
+ /** Providers whose binary did not resolve. Reported, never fatal on their own. */
16
+ unresolved: string[];
17
+ }
18
+ /**
19
+ * Resolve provider commands with the installing shell's PATH. The resulting
20
+ * directories are carried into the systemd unit, whose default PATH is too
21
+ * narrow for per-user provider installations.
22
+ *
23
+ * A default config enables one account per provider, so `providers` usually
24
+ * names every provider even on a box with one installed. A provider that does
25
+ * not resolve is reported in `unresolved`; the install only refuses when none
26
+ * of the requested providers resolves, because then the timer has nothing to
27
+ * run.
28
+ */
29
+ export declare function providerPathEnv(providers: readonly string[], pathEnv?: string | undefined): ProviderPathEnv;
30
+ export interface RunCommandResult {
31
+ status: number;
32
+ stdout?: string;
33
+ stderr?: string;
34
+ }
35
+ export type RunCommand = (command: string, args: string[]) => RunCommandResult;
36
+ export interface ReconcileInstallOpts {
37
+ systemdRoot: string;
38
+ hqRoot: string;
39
+ nodeBinary?: string;
40
+ hqBinary?: string;
41
+ pathEnv?: string;
42
+ home?: string;
43
+ enable?: boolean;
44
+ runCommand?: RunCommand;
45
+ }
46
+ export interface ReconcileInstallResult {
47
+ ok: true;
48
+ action: "reconcile.install" | "reconcile.uninstall";
49
+ systemd_root: string;
50
+ unit: string;
51
+ timer: string;
52
+ written?: boolean;
53
+ enabled?: boolean;
54
+ removed?: boolean;
55
+ }
56
+ export declare function renderReconcileService(opts: {
57
+ nodeBinary: string;
58
+ hqBinary: string;
59
+ hqRoot: string;
60
+ home?: string;
61
+ pathEnv?: string;
62
+ }): string;
63
+ export declare function renderReconcileTimer(): string;
64
+ export declare function defaultSystemdUserDir(home?: string): string;
65
+ export declare function installReconcileTimer(opts: ReconcileInstallOpts): ReconcileInstallResult;
66
+ export declare function uninstallReconcileTimer(opts: Pick<ReconcileInstallOpts, "systemdRoot" | "runCommand"> & {
67
+ disable?: boolean;
68
+ }): ReconcileInstallResult;
69
+ //# sourceMappingURL=reconcile-install.d.ts.map
@@ -0,0 +1,221 @@
1
+ /**
2
+ * systemd user timer install for the lanes reconcile pass.
3
+ *
4
+ * Policy: hq-infra-watchdogs-systemd-not-session. The pass is a oneshot
5
+ * invoked by a timer, never a session-bound background job. Install writes
6
+ * unit files under a systemd user dir and is idempotent and reversible.
7
+ * Enabling the timer is optional — the CLI pass works without it.
8
+ */
9
+ import * as fs from "node:fs";
10
+ import * as os from "node:os";
11
+ import * as path from "node:path";
12
+ import { LanesError } from "./errors.js";
13
+ import { RECONCILE_TIMER_NAME, RECONCILE_UNIT_NAME } from "./reconcile.js";
14
+ import { resolveHqBinary, resolveNodeBinary, } from "../mesh/live/daemon/install.js";
15
+ import { SYSTEMD_PATH_ENV } from "../service-manager/systemd.js";
16
+ export const RECONCILE_TIMER_INTERVAL = "1min";
17
+ /**
18
+ * Resolve provider commands with the installing shell's PATH. The resulting
19
+ * directories are carried into the systemd unit, whose default PATH is too
20
+ * narrow for per-user provider installations.
21
+ *
22
+ * A default config enables one account per provider, so `providers` usually
23
+ * names every provider even on a box with one installed. A provider that does
24
+ * not resolve is reported in `unresolved`; the install only refuses when none
25
+ * of the requested providers resolves, because then the timer has nothing to
26
+ * run.
27
+ */
28
+ export function providerPathEnv(providers, pathEnv = process.env.PATH) {
29
+ const searched = pathEnv ?? "";
30
+ const directories = searched.split(path.delimiter).filter(Boolean);
31
+ const resolvedDirs = [];
32
+ const resolved = [];
33
+ const unresolved = [];
34
+ for (const provider of providers) {
35
+ const found = directories.find((directory) => {
36
+ try {
37
+ fs.accessSync(path.join(directory, provider), fs.constants.X_OK);
38
+ return true;
39
+ }
40
+ catch {
41
+ return false;
42
+ }
43
+ });
44
+ if (!found) {
45
+ unresolved.push(provider);
46
+ continue;
47
+ }
48
+ resolved.push(provider);
49
+ // Keep the real binary's directory, not only a wrapper directory that
50
+ // happened to be on the installing shell's PATH. Systemd must be able to
51
+ // invoke the resolved provider after it starts with its own environment.
52
+ resolvedDirs.push(path.dirname(fs.realpathSync(path.join(found, provider))));
53
+ }
54
+ if (providers.length > 0 && resolved.length === 0) {
55
+ throw new LanesError("provider_binary_unresolved", `Cannot resolve any provider binary (${providers.join(", ")}) from PATH`, { providers: [...providers], searched_path: searched });
56
+ }
57
+ return {
58
+ path: [...new Set([...resolvedDirs, ...SYSTEMD_PATH_ENV.split(":"), ...directories])]
59
+ .filter(Boolean)
60
+ .join(":"),
61
+ resolved,
62
+ unresolved,
63
+ };
64
+ }
65
+ function shellQuote(v) {
66
+ return /^[A-Za-z0-9_./:-]+$/.test(v) ? v : `'${v.replace(/'/g, `'\\''`)}'`;
67
+ }
68
+ export function renderReconcileService(opts) {
69
+ const exec = [opts.nodeBinary, opts.hqBinary, "lanes", "reconcile"]
70
+ .map(shellQuote)
71
+ .join(" ");
72
+ const home = opts.home ?? os.homedir();
73
+ const pathEnv = opts.pathEnv ?? SYSTEMD_PATH_ENV;
74
+ return `[Unit]
75
+ Description=HQ lanes reconcile pass
76
+ Documentation=file://personal/projects/hq-cli-lanes/SPEC.md
77
+
78
+ [Service]
79
+ Type=oneshot
80
+ ExecStart=${exec}
81
+ WorkingDirectory=${shellQuote(opts.hqRoot)}
82
+ Nice=10
83
+ Environment=HOME=${shellQuote(home)}
84
+ Environment=PATH=${shellQuote(pathEnv)}
85
+ Environment=HQ_ROOT=${shellQuote(opts.hqRoot)}
86
+ Environment=HQ_NO_UPDATE_CHECK=1
87
+ KillMode=process
88
+
89
+ [Install]
90
+ WantedBy=default.target
91
+ `;
92
+ }
93
+ export function renderReconcileTimer() {
94
+ return `[Unit]
95
+ Description=Periodic HQ lanes reconcile pass
96
+
97
+ [Timer]
98
+ OnBootSec=30s
99
+ OnUnitActiveSec=${RECONCILE_TIMER_INTERVAL}
100
+ AccuracySec=10s
101
+ Persistent=true
102
+ Unit=${RECONCILE_UNIT_NAME}
103
+
104
+ [Install]
105
+ WantedBy=timers.target
106
+ `;
107
+ }
108
+ export function defaultSystemdUserDir(home = os.homedir()) {
109
+ return path.join(home, ".config", "systemd", "user");
110
+ }
111
+ function writeIfChanged(filePath, contents) {
112
+ try {
113
+ const existing = fs.readFileSync(filePath, "utf8");
114
+ if (existing === contents)
115
+ return false;
116
+ }
117
+ catch (err) {
118
+ const code = err.code;
119
+ if (code !== "ENOENT")
120
+ throw err;
121
+ }
122
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
123
+ const tmp = `${filePath}.${process.pid}.${Date.now()}.tmp`;
124
+ try {
125
+ fs.writeFileSync(tmp, contents, { encoding: "utf8", mode: 0o644 });
126
+ fs.renameSync(tmp, filePath);
127
+ }
128
+ catch (err) {
129
+ try {
130
+ fs.unlinkSync(tmp);
131
+ }
132
+ catch (unlinkErr) {
133
+ const unlinkCode = unlinkErr.code;
134
+ if (unlinkCode !== "ENOENT") {
135
+ process.stderr.write(`hq lanes reconcile install: unlink tmp failed for ${tmp}: ${unlinkErr instanceof Error ? unlinkErr.message : String(unlinkErr)}\n`);
136
+ }
137
+ }
138
+ throw err;
139
+ }
140
+ return true;
141
+ }
142
+ function unlinkIfExists(filePath) {
143
+ try {
144
+ fs.unlinkSync(filePath);
145
+ return true;
146
+ }
147
+ catch (err) {
148
+ const code = err.code;
149
+ if (code === "ENOENT")
150
+ return false;
151
+ throw err;
152
+ }
153
+ }
154
+ function runSystemctl(args, runCommand) {
155
+ const result = runCommand("systemctl", args);
156
+ if (result.status !== 0) {
157
+ throw new LanesError("systemd_failed", `systemctl ${args.join(" ")} failed: ${(result.stderr ?? "").trim() || `exit ${result.status}`}`, { args, status: result.status, stderr: result.stderr });
158
+ }
159
+ }
160
+ export function installReconcileTimer(opts) {
161
+ const nodeBinary = opts.nodeBinary ?? resolveNodeBinary();
162
+ const hqBinary = opts.hqBinary ?? resolveHqBinary();
163
+ const unitPath = path.join(opts.systemdRoot, RECONCILE_UNIT_NAME);
164
+ const timerPath = path.join(opts.systemdRoot, RECONCILE_TIMER_NAME);
165
+ const unitChanged = writeIfChanged(unitPath, renderReconcileService({
166
+ nodeBinary,
167
+ hqBinary,
168
+ hqRoot: opts.hqRoot,
169
+ home: opts.home,
170
+ pathEnv: opts.pathEnv,
171
+ }));
172
+ const timerChanged = writeIfChanged(timerPath, renderReconcileTimer());
173
+ let enabled = false;
174
+ if (opts.enable) {
175
+ if (!opts.runCommand) {
176
+ throw new LanesError("systemd_enable_requires_runner", "--enable needs a systemctl runner; pass runCommand or omit --enable to write unit files only", {});
177
+ }
178
+ runSystemctl(["--user", "daemon-reload"], opts.runCommand);
179
+ runSystemctl(["--user", "enable", "--now", RECONCILE_TIMER_NAME], opts.runCommand);
180
+ enabled = true;
181
+ }
182
+ return {
183
+ ok: true,
184
+ action: "reconcile.install",
185
+ systemd_root: opts.systemdRoot,
186
+ unit: unitPath,
187
+ timer: timerPath,
188
+ written: unitChanged || timerChanged,
189
+ enabled,
190
+ };
191
+ }
192
+ export function uninstallReconcileTimer(opts) {
193
+ if (opts.disable) {
194
+ if (!opts.runCommand) {
195
+ throw new LanesError("systemd_enable_requires_runner", "--disable needs a systemctl runner", {});
196
+ }
197
+ const disable = opts.runCommand("systemctl", [
198
+ "--user",
199
+ "disable",
200
+ "--now",
201
+ RECONCILE_TIMER_NAME,
202
+ ]);
203
+ if (disable.status !== 0) {
204
+ process.stderr.write(`hq lanes reconcile uninstall: systemctl disable exited ${disable.status}: ${(disable.stderr ?? "").trim()}\n`);
205
+ }
206
+ opts.runCommand("systemctl", ["--user", "daemon-reload"]);
207
+ }
208
+ const unitPath = path.join(opts.systemdRoot, RECONCILE_UNIT_NAME);
209
+ const timerPath = path.join(opts.systemdRoot, RECONCILE_TIMER_NAME);
210
+ const removedUnit = unlinkIfExists(unitPath);
211
+ const removedTimer = unlinkIfExists(timerPath);
212
+ return {
213
+ ok: true,
214
+ action: "reconcile.uninstall",
215
+ systemd_root: opts.systemdRoot,
216
+ unit: unitPath,
217
+ timer: timerPath,
218
+ removed: removedUnit || removedTimer,
219
+ };
220
+ }
221
+ //# sourceMappingURL=reconcile-install.js.map
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Periodic reconcile pass (spec §5.7, §6.8, §9).
3
+ *
4
+ * Owned by the machine, not by any lane. Reads never mutate; every write is a
5
+ * compare-and-set. The per-lane watcher owns progress/terminal/silence of a
6
+ * live process — this pass owns the transitions no single lane can own.
7
+ */
8
+ import { type LivenessDeps } from "./liveness.js";
9
+ import { type EnvelopeRepairSpawnInput, type SpawnLaneDeps } from "./spawn.js";
10
+ import { type ThrottleDeps } from "./throttle.js";
11
+ import type { LaneRecord, LivenessState, QuestionRecord, SeniorRef } from "./types.js";
12
+ import { type LaneMesh } from "./mesh-events.js";
13
+ /** Spec §9: unanswered at the current hop for 60 minutes → one hop. */
14
+ export declare const QUESTION_AGE_MS: number;
15
+ /** Spec §6.6 + §9: v1 permits exactly one aged advance. */
16
+ export declare const MAX_AGED_ADVANCES = 1;
17
+ /** Aligns with watcher silence: a host that has not reported for this long is dead. */
18
+ export declare const DEAD_HOST_MS: number;
19
+ export declare const RECONCILE_LOCK_STALE_MS = 30000;
20
+ export declare const RECONCILE_LOCK_TIMEOUT_MS = 5000;
21
+ export declare const RECONCILE_UNIT_NAME = "hq-lanes-reconcile.service";
22
+ export declare const RECONCILE_TIMER_NAME = "hq-lanes-reconcile.timer";
23
+ export interface ReconcileSkip {
24
+ kind: "lane" | "question" | "store" | "throttle" | "liveness";
25
+ id?: string;
26
+ why: string;
27
+ }
28
+ export interface ReconcileChange {
29
+ id: string;
30
+ from?: string;
31
+ to?: string;
32
+ reason?: string;
33
+ /** The attempted provider PATH when admission found no executable. */
34
+ searched_path?: string;
35
+ }
36
+ export interface ReconcileSummary {
37
+ ok: boolean;
38
+ action: "reconcile";
39
+ dry_run: boolean;
40
+ admitted: ReconcileChange[];
41
+ overdue: ReconcileChange[];
42
+ aged: ReconcileChange[];
43
+ advanced: ReconcileChange[];
44
+ resumed: ReconcileChange[];
45
+ dead_host: ReconcileChange[];
46
+ heartbeats: string[];
47
+ skipped: ReconcileSkip[];
48
+ errors: Array<{
49
+ message: string;
50
+ code?: string;
51
+ }>;
52
+ heartbeat_at: string | null;
53
+ }
54
+ export interface ReconcileHost {
55
+ hostname: string;
56
+ outpostId: string | null;
57
+ }
58
+ export interface ReconcileDeps {
59
+ now: () => Date;
60
+ host: ReconcileHost;
61
+ dryRun: boolean;
62
+ spawn?: (hqRoot: string, lane: LaneRecord) => LaneRecord;
63
+ spawnRepair?: (hqRoot: string, lane: LaneRecord, input: EnvelopeRepairSpawnInput) => number;
64
+ spawnLaneDeps?: SpawnLaneDeps;
65
+ throttleDeps?: ThrottleDeps;
66
+ livenessDeps?: LivenessDeps;
67
+ isAlive?: (pid: number) => boolean;
68
+ readSessionSenior?: (sessionId: string) => SeniorRef;
69
+ presenceConnected?: boolean;
70
+ env?: NodeJS.ProcessEnv;
71
+ /** Detached mesh seam for dead-watcher recovery. */
72
+ mesh?: LaneMesh | null;
73
+ /** Bound on one terminal mesh emit during dead-host recovery. Default 10 s. */
74
+ meshEmitTimeoutMs?: number;
75
+ /**
76
+ * Awaited after lane/question records and liveness are loaded, before any
77
+ * CAS write. Test seam so two in-process passes can share a snapshot.
78
+ */
79
+ afterLoad?: () => Promise<void>;
80
+ }
81
+ export declare function reconcileHeartbeatPath(hqRoot: string): string;
82
+ export declare function timeoutPath(hqRoot: string, laneId: string): string;
83
+ export declare function laneRunsHere(lane: LaneRecord, host: ReconcileHost): boolean;
84
+ export declare function agedAdvanceCount(question: QuestionRecord): number;
85
+ export declare function currentHopStartedAtMs(question: QuestionRecord): number;
86
+ export declare function shouldAgeQuestion(question: QuestionRecord, audience: SeniorRef, nowMs: number): boolean;
87
+ export declare function shouldAdvanceAudienceEnded(audience: SeniorRef, liveness: LivenessState | null): boolean;
88
+ export declare function readTimeoutDeadline(hqRoot: string, laneId: string): {
89
+ deadline_at: string;
90
+ timeout_secs?: number;
91
+ } | null;
92
+ export declare function isDeadlinePassed(deadlineAt: string, nowMs: number): boolean;
93
+ export declare function resolveQuestionAudience(question: QuestionRecord, readLaneSenior: (laneId: string) => SeniorRef, readSessionSenior: (sessionId: string) => SeniorRef): SeniorRef;
94
+ /** Unlocked pass body. `runReconcilePass` takes the process lock around this. */
95
+ export declare function runPassBody(hqRoot: string, deps: ReconcileDeps): Promise<ReconcileSummary>;
96
+ /**
97
+ * One idempotent reconcile pass. Throws only when the store directory itself
98
+ * cannot be listed; per-record failures are logged onto the summary and set
99
+ * `ok: false` rather than being swallowed.
100
+ */
101
+ export declare function runReconcilePass(hqRoot: string, deps: ReconcileDeps): Promise<ReconcileSummary>;
102
+ //# sourceMappingURL=reconcile.d.ts.map