looply-cli 0.5.11 → 0.5.12
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.
- package/dist/.src-hash +1 -1
- package/dist/bin.d.ts.map +1 -1
- package/dist/bin.js +9 -0
- package/dist/bin.js.map +1 -1
- package/dist/branch-delivery-wiring.d.ts +4 -1
- package/dist/branch-delivery-wiring.d.ts.map +1 -1
- package/dist/branch-delivery-wiring.js +34 -12
- package/dist/branch-delivery-wiring.js.map +1 -1
- package/dist/branch-delivery.d.ts +23 -3
- package/dist/branch-delivery.d.ts.map +1 -1
- package/dist/branch-delivery.js +40 -2
- package/dist/branch-delivery.js.map +1 -1
- package/dist/coordinator-state.d.ts.map +1 -1
- package/dist/coordinator-state.js +2 -0
- package/dist/coordinator-state.js.map +1 -1
- package/dist/daemon-cmd.d.ts.map +1 -1
- package/dist/daemon-cmd.js +23 -1
- package/dist/daemon-cmd.js.map +1 -1
- package/dist/machine-run-slots.d.ts +10 -2
- package/dist/machine-run-slots.d.ts.map +1 -1
- package/dist/machine-run-slots.js +15 -4
- package/dist/machine-run-slots.js.map +1 -1
- package/dist/maintenance-cmd.d.ts +44 -0
- package/dist/maintenance-cmd.d.ts.map +1 -0
- package/dist/maintenance-cmd.js +132 -0
- package/dist/maintenance-cmd.js.map +1 -0
- package/dist/maintenance-facts.d.ts +52 -0
- package/dist/maintenance-facts.d.ts.map +1 -0
- package/dist/maintenance-facts.js +256 -0
- package/dist/maintenance-facts.js.map +1 -0
- package/dist/maintenance-tick.d.ts +51 -0
- package/dist/maintenance-tick.d.ts.map +1 -0
- package/dist/maintenance-tick.js +156 -0
- package/dist/maintenance-tick.js.map +1 -0
- package/dist/run-launcher.d.ts +3 -0
- package/dist/run-launcher.d.ts.map +1 -1
- package/dist/run-launcher.js +3 -2
- package/dist/run-launcher.js.map +1 -1
- package/dist/server-client.d.ts +24 -0
- package/dist/server-client.d.ts.map +1 -1
- package/dist/server-client.js +11 -0
- package/dist/server-client.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.findPackageRoots = findPackageRoots;
|
|
4
|
+
exports.shipsNativeCode = shipsNativeCode;
|
|
5
|
+
exports.unusedDependencies = unusedDependencies;
|
|
6
|
+
exports.gatherRootFacts = gatherRootFacts;
|
|
7
|
+
exports.gatherFacts = gatherFacts;
|
|
8
|
+
exports.nodeFactsDeps = nodeFactsDeps;
|
|
9
|
+
const node_child_process_1 = require("node:child_process");
|
|
10
|
+
const node_fs_1 = require("node:fs");
|
|
11
|
+
const node_path_1 = require("node:path");
|
|
12
|
+
const core_1 = require("@looply/core");
|
|
13
|
+
const LOCKFILES = ['package-lock.json', 'npm-shrinkwrap.json', 'pnpm-lock.yaml', 'yarn.lock', 'bun.lockb', 'bun.lock'];
|
|
14
|
+
const SKIP_DIRS = new Set(['node_modules', 'dist', 'build', 'coverage', 'out', 'vendor', 'android', 'ios', 'tmp', 'temp']);
|
|
15
|
+
const MAX_ROOTS = 12;
|
|
16
|
+
/** Package roots: the repository root when it has a package.json, then folders up to two levels down with a package.json and a lockfile. */
|
|
17
|
+
function findPackageRoots(repo, deps) {
|
|
18
|
+
const roots = [];
|
|
19
|
+
if (deps.exists((0, node_path_1.join)(repo, 'package.json')))
|
|
20
|
+
roots.push('.');
|
|
21
|
+
const walk = (dir, depth) => {
|
|
22
|
+
if (depth > 2 || roots.length >= MAX_ROOTS)
|
|
23
|
+
return;
|
|
24
|
+
for (const e of deps.list(dir).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
25
|
+
if (!e.dir || e.name.startsWith('.') || SKIP_DIRS.has(e.name))
|
|
26
|
+
continue;
|
|
27
|
+
const sub = (0, node_path_1.join)(dir, e.name);
|
|
28
|
+
if (deps.exists((0, node_path_1.join)(sub, 'package.json')) && LOCKFILES.some((l) => deps.exists((0, node_path_1.join)(sub, l)))) {
|
|
29
|
+
roots.push((0, node_path_1.relative)(repo, sub).split(node_path_1.sep).join('/'));
|
|
30
|
+
if (roots.length >= MAX_ROOTS)
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
walk(sub, depth + 1);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
walk(repo, 1);
|
|
37
|
+
return roots;
|
|
38
|
+
}
|
|
39
|
+
function json(text) {
|
|
40
|
+
if (text === null)
|
|
41
|
+
return null;
|
|
42
|
+
try {
|
|
43
|
+
const v = JSON.parse(text);
|
|
44
|
+
return typeof v === 'object' && v !== null && !Array.isArray(v) ? v : null;
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function depNames(pkg, field) {
|
|
51
|
+
const d = pkg[field];
|
|
52
|
+
return typeof d === 'object' && d !== null ? Object.keys(d) : [];
|
|
53
|
+
}
|
|
54
|
+
/** The first JSON value in a tool's output — npm can print a warning line before it. */
|
|
55
|
+
function jsonPart(out) {
|
|
56
|
+
const i = out.search(/[{[]/);
|
|
57
|
+
return i < 0 ? '' : out.slice(i);
|
|
58
|
+
}
|
|
59
|
+
const outdatedArgs = (pm) => pm === 'npm' ? ['outdated', '--json', '--long'] : pm === 'pnpm' ? ['outdated', '--format', 'json'] : null;
|
|
60
|
+
const auditArgs = (pm) => (pm === 'npm' ? ['audit', '--json'] : pm === 'pnpm' ? ['audit', '--json'] : null);
|
|
61
|
+
/** Does this installed package ship native code an Expo app must rebuild for? */
|
|
62
|
+
function shipsNativeCode(pkgDir, deps) {
|
|
63
|
+
if (['expo-module.config.json', 'react-native.config.js', 'android', 'ios'].some((f) => deps.exists((0, node_path_1.join)(pkgDir, f))))
|
|
64
|
+
return true;
|
|
65
|
+
const pkg = json(deps.readFile((0, node_path_1.join)(pkgDir, 'package.json')));
|
|
66
|
+
return pkg !== null && pkg['codegenConfig'] !== undefined;
|
|
67
|
+
}
|
|
68
|
+
const SOURCE = /\.(ts|tsx|js|jsx|mjs|cjs|mts|cts|vue|svelte|json|ya?ml)$/;
|
|
69
|
+
const MAX_FILES = 20_000;
|
|
70
|
+
const MAX_BYTES = 1_000_000;
|
|
71
|
+
/** Used through a config, a CLI or by convention, not by an import. Never proposed for removal. */
|
|
72
|
+
const IMPLICIT = /^(@types\/.+|typescript|ts-node|tsx|eslint.*|@eslint\/.+|@typescript-eslint\/.+|prettier.*|jest.*|ts-jest|babel-.+|@babel\/.+|vite|vitest|@vitejs\/.+|postcss.*|tailwindcss|autoprefixer|nodemon|husky|lint-staged|concurrently|cross-env|rimraf|npm-run-all.*|prisma|@prisma\/client|expo|react-native|metro.*|patch-package|dotenv-cli)$/;
|
|
73
|
+
/**
|
|
74
|
+
* Dependencies nothing under `root` mentions by name in a quote — a plain text
|
|
75
|
+
* search, so a candidate list for a goal to CONFIRM, never a removal list.
|
|
76
|
+
*/
|
|
77
|
+
function unusedDependencies(rootDir, pkg, deps) {
|
|
78
|
+
const candidates = [...depNames(pkg, 'dependencies'), ...depNames(pkg, 'devDependencies')].filter((n) => !IMPLICIT.test(n));
|
|
79
|
+
if (candidates.length === 0)
|
|
80
|
+
return [];
|
|
81
|
+
const scripts = JSON.stringify(pkg['scripts'] ?? {});
|
|
82
|
+
const remaining = new Set(candidates.filter((n) => !scripts.includes(n)));
|
|
83
|
+
let files = 0;
|
|
84
|
+
const walk = (dir) => {
|
|
85
|
+
if (remaining.size === 0 || files >= MAX_FILES)
|
|
86
|
+
return;
|
|
87
|
+
for (const e of deps.list(dir)) {
|
|
88
|
+
if (remaining.size === 0 || files >= MAX_FILES)
|
|
89
|
+
return;
|
|
90
|
+
if (e.dir) {
|
|
91
|
+
if (e.name.startsWith('.') || SKIP_DIRS.has(e.name))
|
|
92
|
+
continue;
|
|
93
|
+
walk((0, node_path_1.join)(dir, e.name));
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
if (!SOURCE.test(e.name) || e.name === 'package.json' || LOCKFILES.includes(e.name))
|
|
97
|
+
continue;
|
|
98
|
+
files += 1;
|
|
99
|
+
const text = deps.readFile((0, node_path_1.join)(dir, e.name));
|
|
100
|
+
if (text === null || text.length > MAX_BYTES)
|
|
101
|
+
continue;
|
|
102
|
+
for (const n of [...remaining]) {
|
|
103
|
+
if (text.includes(`'${n}`) || text.includes(`"${n}`) || text.includes(`\`${n}`))
|
|
104
|
+
remaining.delete(n);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
walk(rootDir);
|
|
109
|
+
return [...remaining].sort();
|
|
110
|
+
}
|
|
111
|
+
/** Every fact for one package root. Never throws: a tool that failed is a sentence on the root. */
|
|
112
|
+
async function gatherRootFacts(repo, root, opts, deps) {
|
|
113
|
+
const dir = root === '.' ? repo : (0, node_path_1.join)(repo, ...root.split('/'));
|
|
114
|
+
const pkg = json(deps.readFile((0, node_path_1.join)(dir, 'package.json'))) ?? {};
|
|
115
|
+
const lockfiles = LOCKFILES.filter((l) => deps.exists((0, node_path_1.join)(dir, l)));
|
|
116
|
+
const { pm, problem } = (0, core_1.packageManagerOf)(pkg['packageManager'], lockfiles);
|
|
117
|
+
const names = [...depNames(pkg, 'dependencies'), ...depNames(pkg, 'devDependencies')];
|
|
118
|
+
const expo = names.includes('expo');
|
|
119
|
+
const facts = {
|
|
120
|
+
root,
|
|
121
|
+
packageManager: pm,
|
|
122
|
+
packageManagerProblem: problem,
|
|
123
|
+
expo,
|
|
124
|
+
outdated: null,
|
|
125
|
+
outdatedProblem: null,
|
|
126
|
+
audit: null,
|
|
127
|
+
auditProblem: null,
|
|
128
|
+
unused: [],
|
|
129
|
+
nativePackages: [],
|
|
130
|
+
changelogs: {},
|
|
131
|
+
};
|
|
132
|
+
if (pm === null)
|
|
133
|
+
return facts;
|
|
134
|
+
const installed = deps.exists((0, node_path_1.join)(dir, 'node_modules'));
|
|
135
|
+
const oArgs = outdatedArgs(pm);
|
|
136
|
+
if (oArgs === null)
|
|
137
|
+
facts.outdatedProblem = `Looply does not read ${pm} outdated reports yet`;
|
|
138
|
+
else if (!installed)
|
|
139
|
+
facts.outdatedProblem = 'its dependencies are not installed (no node_modules), so the installed versions are unknown';
|
|
140
|
+
else {
|
|
141
|
+
const r = await deps.run(pm, oArgs, dir);
|
|
142
|
+
// `outdated` exits 1 when something is outdated; only unreadable output is a failure.
|
|
143
|
+
try {
|
|
144
|
+
// Nothing outdated is `{}`; no JSON at all is a failure, not "nothing to do".
|
|
145
|
+
const body = jsonPart(r.stdout);
|
|
146
|
+
if (body === '')
|
|
147
|
+
throw new Error('no report');
|
|
148
|
+
facts.outdated = (0, core_1.parseOutdatedJson)(body);
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
facts.outdatedProblem = `${pm} outdated failed (exit ${r.code}): ${(r.stderr || r.stdout).trim().split(/\r?\n/)[0] ?? ''}`.slice(0, 300);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
const aArgs = auditArgs(pm);
|
|
155
|
+
if (aArgs === null)
|
|
156
|
+
facts.auditProblem = `Looply does not read ${pm} audit reports yet`;
|
|
157
|
+
else {
|
|
158
|
+
const r = await deps.run(pm, aArgs, dir);
|
|
159
|
+
try {
|
|
160
|
+
const body = jsonPart(r.stdout);
|
|
161
|
+
if (body === '')
|
|
162
|
+
throw new Error('no report');
|
|
163
|
+
const raw = json(body);
|
|
164
|
+
if (raw !== null && raw['error'] !== undefined)
|
|
165
|
+
throw new Error(JSON.stringify(raw['error']).slice(0, 200));
|
|
166
|
+
facts.audit = (0, core_1.parseAuditJson)(body, names);
|
|
167
|
+
}
|
|
168
|
+
catch (e) {
|
|
169
|
+
facts.auditProblem = `${pm} audit failed (exit ${r.code}): ${e.message || (r.stderr || '').trim().split(/\r?\n/)[0] || ''}`.slice(0, 300);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
if (installed) {
|
|
173
|
+
for (const o of facts.outdated ?? []) {
|
|
174
|
+
const p = json(deps.readFile((0, node_path_1.join)(dir, 'node_modules', ...o.name.split('/'), 'package.json')));
|
|
175
|
+
const url = p === null ? null : (0, core_1.changelogUrlOf)(p['repository']);
|
|
176
|
+
if (url !== null)
|
|
177
|
+
facts.changelogs[o.name] = url;
|
|
178
|
+
}
|
|
179
|
+
if (expo)
|
|
180
|
+
facts.nativePackages = names.filter((n) => shipsNativeCode((0, node_path_1.join)(dir, 'node_modules', ...n.split('/')), deps)).sort();
|
|
181
|
+
}
|
|
182
|
+
if (opts.deadCode)
|
|
183
|
+
facts.unused = unusedDependencies(dir, pkg, deps);
|
|
184
|
+
return facts;
|
|
185
|
+
}
|
|
186
|
+
async function gatherFacts(repo, opts, deps) {
|
|
187
|
+
const out = [];
|
|
188
|
+
for (const root of findPackageRoots(repo, deps))
|
|
189
|
+
out.push(await gatherRootFacts(repo, root, opts, deps));
|
|
190
|
+
return out;
|
|
191
|
+
}
|
|
192
|
+
const RUN_TIMEOUT_MS = 3 * 60_000;
|
|
193
|
+
/** The real thing: hidden, bounded, no prompts, nothing written. */
|
|
194
|
+
function nodeFactsDeps() {
|
|
195
|
+
return {
|
|
196
|
+
run: (command, args, cwd) => new Promise((resolve) => {
|
|
197
|
+
let stdout = '';
|
|
198
|
+
let stderr = '';
|
|
199
|
+
let settled = false;
|
|
200
|
+
const done = (r) => {
|
|
201
|
+
if (settled)
|
|
202
|
+
return;
|
|
203
|
+
settled = true;
|
|
204
|
+
clearTimeout(timer);
|
|
205
|
+
resolve(r);
|
|
206
|
+
};
|
|
207
|
+
// A `.cmd` on Windows needs the shell; every argument here is a fixed word from this file.
|
|
208
|
+
const child = (0, node_child_process_1.spawn)(command, [...args], {
|
|
209
|
+
cwd,
|
|
210
|
+
shell: process.platform === 'win32',
|
|
211
|
+
windowsHide: true,
|
|
212
|
+
env: { ...process.env, NO_UPDATE_NOTIFIER: '1', npm_config_update_notifier: 'false', COREPACK_ENABLE_DOWNLOAD_PROMPT: '0' },
|
|
213
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
214
|
+
});
|
|
215
|
+
const timer = setTimeout(() => {
|
|
216
|
+
child.kill();
|
|
217
|
+
done({ code: null, stdout, stderr: `${stderr}\ntimed out after ${RUN_TIMEOUT_MS / 1000}s` });
|
|
218
|
+
}, RUN_TIMEOUT_MS);
|
|
219
|
+
child.stdout.on('data', (b) => {
|
|
220
|
+
if (stdout.length < 20_000_000)
|
|
221
|
+
stdout += b.toString('utf8');
|
|
222
|
+
});
|
|
223
|
+
child.stderr.on('data', (b) => {
|
|
224
|
+
if (stderr.length < 100_000)
|
|
225
|
+
stderr += b.toString('utf8');
|
|
226
|
+
});
|
|
227
|
+
child.on('error', (e) => done({ code: null, stdout, stderr: e.message }));
|
|
228
|
+
child.on('close', (code) => done({ code, stdout, stderr }));
|
|
229
|
+
}),
|
|
230
|
+
readFile: (path) => {
|
|
231
|
+
try {
|
|
232
|
+
return (0, node_fs_1.readFileSync)(path, 'utf8');
|
|
233
|
+
}
|
|
234
|
+
catch {
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
},
|
|
238
|
+
list: (path) => {
|
|
239
|
+
try {
|
|
240
|
+
return (0, node_fs_1.readdirSync)(path, { withFileTypes: true }).map((d) => ({ name: d.name, dir: d.isDirectory() }));
|
|
241
|
+
}
|
|
242
|
+
catch {
|
|
243
|
+
return [];
|
|
244
|
+
}
|
|
245
|
+
},
|
|
246
|
+
exists: (path) => {
|
|
247
|
+
try {
|
|
248
|
+
return (0, node_fs_1.existsSync)(path) && ((0, node_fs_1.statSync)(path).isFile() || (0, node_fs_1.statSync)(path).isDirectory());
|
|
249
|
+
}
|
|
250
|
+
catch {
|
|
251
|
+
return false;
|
|
252
|
+
}
|
|
253
|
+
},
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
//# sourceMappingURL=maintenance-facts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"maintenance-facts.js","sourceRoot":"","sources":["../src/maintenance-facts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { type MaintenancePlan, type MaintenanceSettings, type PackageRootFacts } from '@looply/core';
|
|
2
|
+
/**
|
|
3
|
+
* THE WEEKLY MAINTENANCE PLAN, MADE BY THE DAEMON THAT DRIVES THE REPOSITORY.
|
|
4
|
+
*
|
|
5
|
+
* On the daemon's five-minute settings cadence: pull the project's maintenance
|
|
6
|
+
* setting (set in AutoRyn or the console) into `maintenance-settings.json`, and
|
|
7
|
+
* when the weekly slot has passed and no plan was made since, read the repository
|
|
8
|
+
* (`maintenance-facts.ts`), plan (`planMaintenance`), and propose the plan to the
|
|
9
|
+
* server. AutoRyn turns proposals into tickets and goals; this machine never
|
|
10
|
+
* creates a goal by itself.
|
|
11
|
+
*
|
|
12
|
+
* ⚠️ ONE PLAN PER SLOT. `maintenance-state.json` records when the last plan was
|
|
13
|
+
* proposed; a failure to reach the server leaves it unrecorded, so the next
|
|
14
|
+
* cadence tries again — but reading the repository again costs a few `npm`
|
|
15
|
+
* calls, so a failed plan waits 30 minutes before the next try.
|
|
16
|
+
*
|
|
17
|
+
* ⚠️ NEVER TWO AT ONCE, AND NEVER BLOCKING. The plan runs in the background of
|
|
18
|
+
* the cadence; a second cadence that finds one going does nothing.
|
|
19
|
+
*/
|
|
20
|
+
export declare const MAINTENANCE_SETTINGS_FILE = "maintenance-settings.json";
|
|
21
|
+
export declare const MAINTENANCE_STATE_FILE = "maintenance-state.json";
|
|
22
|
+
export interface MaintenanceState {
|
|
23
|
+
/** When the last plan reached the server (ms). */
|
|
24
|
+
lastPlannedAt: number | null;
|
|
25
|
+
week: string | null;
|
|
26
|
+
proposed: number;
|
|
27
|
+
skipped: string[];
|
|
28
|
+
/** The last failure and when, for a retry delay and a person reading the file. */
|
|
29
|
+
lastFailureAt: number | null;
|
|
30
|
+
lastFailure: string | null;
|
|
31
|
+
}
|
|
32
|
+
/** The project's maintenance setting as this machine last heard it; null when off or never heard. */
|
|
33
|
+
export declare function readMaintenanceSettings(stateDir: string): MaintenanceSettings | null;
|
|
34
|
+
export declare function readMaintenanceState(stateDir: string): MaintenanceState;
|
|
35
|
+
export interface MaintenanceTickDeps {
|
|
36
|
+
stateDir: string;
|
|
37
|
+
fetchSettings(): Promise<unknown>;
|
|
38
|
+
propose(body: {
|
|
39
|
+
week: string;
|
|
40
|
+
items: MaintenancePlan['items'];
|
|
41
|
+
}): Promise<unknown>;
|
|
42
|
+
gather(opts: {
|
|
43
|
+
deadCode: boolean;
|
|
44
|
+
}): Promise<PackageRootFacts[]>;
|
|
45
|
+
log(line: string): void;
|
|
46
|
+
now(): number;
|
|
47
|
+
}
|
|
48
|
+
export type MaintenanceTickOutcome = 'off' | 'not-due' | 'busy' | 'waiting-retry' | 'proposed' | 'failed';
|
|
49
|
+
/** One cadence: refresh the setting, plan when due. Never throws. Returns what happened (tests). */
|
|
50
|
+
export declare function makeMaintenanceTick(deps: MaintenanceTickDeps): () => Promise<MaintenanceTickOutcome>;
|
|
51
|
+
//# sourceMappingURL=maintenance-tick.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"maintenance-tick.d.ts","sourceRoot":"","sources":["../src/maintenance-tick.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACtB,MAAM,cAAc,CAAC;AAGtB;;;;;;;;;;;;;;;;;GAiBG;AAEH,eAAO,MAAM,yBAAyB,8BAA8B,CAAC;AACrE,eAAO,MAAM,sBAAsB,2BAA2B,CAAC;AAG/D,MAAM,WAAW,gBAAgB;IAC/B,kDAAkD;IAClD,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,kFAAkF;IAClF,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAkBD,qGAAqG;AACrG,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,mBAAmB,GAAG,IAAI,CAKpF;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,CAWvE;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAClC,OAAO,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,eAAe,CAAC,OAAO,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACnF,MAAM,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC;IACjE,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,GAAG,IAAI,MAAM,CAAC;CACf;AAED,MAAM,MAAM,sBAAsB,GAAG,KAAK,GAAG,SAAS,GAAG,MAAM,GAAG,eAAe,GAAG,UAAU,GAAG,QAAQ,CAAC;AAE1G,oGAAoG;AACpG,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,mBAAmB,GAAG,MAAM,OAAO,CAAC,sBAAsB,CAAC,CA+EpG"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MAINTENANCE_STATE_FILE = exports.MAINTENANCE_SETTINGS_FILE = void 0;
|
|
4
|
+
exports.readMaintenanceSettings = readMaintenanceSettings;
|
|
5
|
+
exports.readMaintenanceState = readMaintenanceState;
|
|
6
|
+
exports.makeMaintenanceTick = makeMaintenanceTick;
|
|
7
|
+
const node_fs_1 = require("node:fs");
|
|
8
|
+
const node_path_1 = require("node:path");
|
|
9
|
+
const core_1 = require("@looply/core");
|
|
10
|
+
const server_client_1 = require("./server-client");
|
|
11
|
+
/**
|
|
12
|
+
* THE WEEKLY MAINTENANCE PLAN, MADE BY THE DAEMON THAT DRIVES THE REPOSITORY.
|
|
13
|
+
*
|
|
14
|
+
* On the daemon's five-minute settings cadence: pull the project's maintenance
|
|
15
|
+
* setting (set in AutoRyn or the console) into `maintenance-settings.json`, and
|
|
16
|
+
* when the weekly slot has passed and no plan was made since, read the repository
|
|
17
|
+
* (`maintenance-facts.ts`), plan (`planMaintenance`), and propose the plan to the
|
|
18
|
+
* server. AutoRyn turns proposals into tickets and goals; this machine never
|
|
19
|
+
* creates a goal by itself.
|
|
20
|
+
*
|
|
21
|
+
* ⚠️ ONE PLAN PER SLOT. `maintenance-state.json` records when the last plan was
|
|
22
|
+
* proposed; a failure to reach the server leaves it unrecorded, so the next
|
|
23
|
+
* cadence tries again — but reading the repository again costs a few `npm`
|
|
24
|
+
* calls, so a failed plan waits 30 minutes before the next try.
|
|
25
|
+
*
|
|
26
|
+
* ⚠️ NEVER TWO AT ONCE, AND NEVER BLOCKING. The plan runs in the background of
|
|
27
|
+
* the cadence; a second cadence that finds one going does nothing.
|
|
28
|
+
*/
|
|
29
|
+
exports.MAINTENANCE_SETTINGS_FILE = 'maintenance-settings.json';
|
|
30
|
+
exports.MAINTENANCE_STATE_FILE = 'maintenance-state.json';
|
|
31
|
+
const RETRY_AFTER_MS = 30 * 60_000;
|
|
32
|
+
function readJson(path) {
|
|
33
|
+
try {
|
|
34
|
+
const v = JSON.parse((0, node_fs_1.readFileSync)(path, 'utf8'));
|
|
35
|
+
return typeof v === 'object' && v !== null && !Array.isArray(v) ? v : null;
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function writeJson(path, dir, value) {
|
|
42
|
+
(0, node_fs_1.mkdirSync)(dir, { recursive: true });
|
|
43
|
+
const tmp = `${path}.${process.pid}.tmp`;
|
|
44
|
+
(0, node_fs_1.writeFileSync)(tmp, JSON.stringify(value, null, 2) + '\n', 'utf8');
|
|
45
|
+
(0, node_fs_1.renameSync)(tmp, path);
|
|
46
|
+
}
|
|
47
|
+
/** The project's maintenance setting as this machine last heard it; null when off or never heard. */
|
|
48
|
+
function readMaintenanceSettings(stateDir) {
|
|
49
|
+
const raw = readJson((0, node_path_1.join)(stateDir, exports.MAINTENANCE_SETTINGS_FILE));
|
|
50
|
+
if (raw === null || raw['settings'] === null || raw['settings'] === undefined)
|
|
51
|
+
return null;
|
|
52
|
+
const v = (0, core_1.validateMaintenanceSettings)(raw['settings']);
|
|
53
|
+
return v.ok ? v.settings : null;
|
|
54
|
+
}
|
|
55
|
+
function readMaintenanceState(stateDir) {
|
|
56
|
+
const raw = readJson((0, node_path_1.join)(stateDir, exports.MAINTENANCE_STATE_FILE)) ?? {};
|
|
57
|
+
const num = (k) => (typeof raw[k] === 'number' && Number.isFinite(raw[k]) ? raw[k] : null);
|
|
58
|
+
return {
|
|
59
|
+
lastPlannedAt: num('lastPlannedAt'),
|
|
60
|
+
week: typeof raw['week'] === 'string' ? raw['week'] : null,
|
|
61
|
+
proposed: num('proposed') ?? 0,
|
|
62
|
+
skipped: Array.isArray(raw['skipped']) ? raw['skipped'].filter((s) => typeof s === 'string') : [],
|
|
63
|
+
lastFailureAt: num('lastFailureAt'),
|
|
64
|
+
lastFailure: typeof raw['lastFailure'] === 'string' ? raw['lastFailure'] : null,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/** One cadence: refresh the setting, plan when due. Never throws. Returns what happened (tests). */
|
|
68
|
+
function makeMaintenanceTick(deps) {
|
|
69
|
+
let running = false;
|
|
70
|
+
let reportedPullFailure = false;
|
|
71
|
+
const pull = async () => {
|
|
72
|
+
let body;
|
|
73
|
+
try {
|
|
74
|
+
body = await deps.fetchSettings();
|
|
75
|
+
}
|
|
76
|
+
catch (e) {
|
|
77
|
+
if (!(e instanceof server_client_1.ServerError && (e.isOffline || e.isAuth)) && !reportedPullFailure) {
|
|
78
|
+
reportedPullFailure = true;
|
|
79
|
+
deps.log(`maint : could not refresh the maintenance setting — ${e.message}`);
|
|
80
|
+
}
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
reportedPullFailure = false;
|
|
84
|
+
const b = body;
|
|
85
|
+
if (typeof b !== 'object' || b === null || !('settings' in b))
|
|
86
|
+
return;
|
|
87
|
+
let settings = null;
|
|
88
|
+
if (b.settings !== null) {
|
|
89
|
+
const v = (0, core_1.validateMaintenanceSettings)(b.settings);
|
|
90
|
+
if (!v.ok) {
|
|
91
|
+
deps.log(`maint : the server sent a maintenance setting this build refuses (${v.key}: ${v.because})`);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
settings = v.settings;
|
|
95
|
+
}
|
|
96
|
+
const path = (0, node_path_1.join)(deps.stateDir, exports.MAINTENANCE_SETTINGS_FILE);
|
|
97
|
+
const before = readJson(path);
|
|
98
|
+
if (before !== null && JSON.stringify(before['settings'] ?? null) === JSON.stringify(settings))
|
|
99
|
+
return;
|
|
100
|
+
try {
|
|
101
|
+
writeJson(path, deps.stateDir, { settings, updatedAt: typeof b.updatedAt === 'string' ? b.updatedAt : null, fetchedAt: new Date(deps.now()).toISOString() });
|
|
102
|
+
deps.log(`maint : maintenance is ${settings?.enabled ? 'on' : 'off'} for this project`);
|
|
103
|
+
}
|
|
104
|
+
catch (e) {
|
|
105
|
+
deps.log(`maint : could not write the maintenance setting (${e.message})`);
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
const plan = async (settings, week) => {
|
|
109
|
+
const state = readMaintenanceState(deps.stateDir);
|
|
110
|
+
const save = (patch) => {
|
|
111
|
+
try {
|
|
112
|
+
writeJson((0, node_path_1.join)(deps.stateDir, exports.MAINTENANCE_STATE_FILE), deps.stateDir, { ...state, ...patch });
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
/* the next cadence plans again; a duplicate plan is upserted, not doubled */
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
try {
|
|
119
|
+
deps.log(`maint : making this week's maintenance plan (${week})`);
|
|
120
|
+
const facts = await deps.gather({ deadCode: settings.deadCode.enabled });
|
|
121
|
+
const result = (0, core_1.planMaintenance)({ settings, week, roots: facts });
|
|
122
|
+
await deps.propose({ week, items: result.items });
|
|
123
|
+
save({ lastPlannedAt: deps.now(), week, proposed: result.items.length, skipped: result.skipped.slice(0, 50), lastFailure: null, lastFailureAt: null });
|
|
124
|
+
deps.log(`maint : proposed ${result.items.length} maintenance goal(s) for ${week}${result.skipped.length ? `; ${result.skipped.length} thing(s) left for later (${exports.MAINTENANCE_STATE_FILE})` : ''}`);
|
|
125
|
+
return 'proposed';
|
|
126
|
+
}
|
|
127
|
+
catch (e) {
|
|
128
|
+
const why = e.message.slice(0, 300);
|
|
129
|
+
save({ lastFailureAt: deps.now(), lastFailure: why });
|
|
130
|
+
deps.log(`maint : the maintenance plan failed — ${why}; trying again in 30 minutes`);
|
|
131
|
+
return 'failed';
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
return async () => {
|
|
135
|
+
await pull();
|
|
136
|
+
const settings = readMaintenanceSettings(deps.stateDir);
|
|
137
|
+
const state = readMaintenanceState(deps.stateDir);
|
|
138
|
+
const due = (0, core_1.maintenanceDue)(settings, state.lastPlannedAt, deps.now());
|
|
139
|
+
if (settings === null || !settings.enabled)
|
|
140
|
+
return 'off';
|
|
141
|
+
if (!due.due)
|
|
142
|
+
return 'not-due';
|
|
143
|
+
if (running)
|
|
144
|
+
return 'busy';
|
|
145
|
+
if (state.lastFailureAt !== null && deps.now() - state.lastFailureAt < RETRY_AFTER_MS)
|
|
146
|
+
return 'waiting-retry';
|
|
147
|
+
running = true;
|
|
148
|
+
try {
|
|
149
|
+
return await plan(settings, due.week);
|
|
150
|
+
}
|
|
151
|
+
finally {
|
|
152
|
+
running = false;
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=maintenance-tick.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"maintenance-tick.js","sourceRoot":"","sources":["../src/maintenance-tick.ts"],"names":[],"mappings":"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"}
|
package/dist/run-launcher.d.ts
CHANGED
|
@@ -89,6 +89,8 @@ export interface RunLauncherDeps {
|
|
|
89
89
|
* it — a person's Start is that person's decision about their own machine.
|
|
90
90
|
*/
|
|
91
91
|
machineSlots?: MachineRunSlots;
|
|
92
|
+
/** Is this goal a scheduled maintenance goal? Its machine-wide slot follows maintenance rules. */
|
|
93
|
+
isMaintenance?: (goalId: string | undefined) => boolean;
|
|
92
94
|
}
|
|
93
95
|
export type LaunchResult =
|
|
94
96
|
/**
|
|
@@ -484,6 +486,7 @@ export declare function readStartPayload(payload: unknown): StartRead;
|
|
|
484
486
|
export declare function hoursFromPayload(payload: unknown): number | undefined;
|
|
485
487
|
export declare function nodeRunLauncher(cwd: string, stateDir?: string, extra?: {
|
|
486
488
|
readonly machineSlots?: MachineRunSlots;
|
|
489
|
+
readonly isMaintenance?: (goalId: string | undefined) => boolean;
|
|
487
490
|
}): RunLauncher;
|
|
488
491
|
/**
|
|
489
492
|
* Where one launched run's stdout and stderr go: `<state>/run-logs/<when>-<request>.log`, appended. Null when the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-launcher.d.ts","sourceRoot":"","sources":["../src/run-launcher.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAA6C,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAKzF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D;;;;;;;;;;;;GAYG;AAEH,wFAAwF;AACxF,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;IACxB,4EAA4E;IAC5E,MAAM,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,GAAG,IAAI,CAAC;IAChD,gEAAgE;IAChE,OAAO,CAAC,EAAE,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI,CAAC;IACxC,gFAAgF;IAChF,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,YAAY,CAAC;IAC7C,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,yEAAyE;IACzE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;;OAOG;IACH,WAAW,CAAC,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IACnE;;;;;;;;OAQG;IACH,SAAS,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,CAAC;IAClC;;;;;;;;;;;OAWG;IACH,WAAW,CAAC,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACrD;;;;;;;;;;;;;;OAcG;IACH,SAAS,CAAC,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,cAAc,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IACzF;;;;;OAKG;IACH,YAAY,CAAC,EAAE,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"run-launcher.d.ts","sourceRoot":"","sources":["../src/run-launcher.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAA6C,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAKzF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D;;;;;;;;;;;;GAYG;AAEH,wFAAwF;AACxF,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;IACxB,4EAA4E;IAC5E,MAAM,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,GAAG,IAAI,CAAC;IAChD,gEAAgE;IAChE,OAAO,CAAC,EAAE,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI,CAAC;IACxC,gFAAgF;IAChF,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,YAAY,CAAC;IAC7C,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,yEAAyE;IACzE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;;OAOG;IACH,WAAW,CAAC,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IACnE;;;;;;;;OAQG;IACH,SAAS,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,CAAC;IAClC;;;;;;;;;;;OAWG;IACH,WAAW,CAAC,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACrD;;;;;;;;;;;;;;OAcG;IACH,SAAS,CAAC,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,cAAc,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IACzF;;;;;OAKG;IACH,YAAY,CAAC,EAAE,eAAe,CAAC;IAC/B,kGAAkG;IAClG,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,KAAK,OAAO,CAAC;CACzD;AAED,MAAM,MAAM,YAAY;AACtB;;;;;;;;GAQG;AACD;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE;AAC9E;;;;;;;GAOG;GACD;IACE,OAAO,EAAE,KAAK,CAAC;IACf,OAAO,EAAE,IAAI,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;;;OAQG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,GACD;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE;AACpC;;;;;;;;;;;;GAYG;GACD;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,IAAI,CAAC;IAAC,IAAI,CAAC,EAAE,cAAc,CAAA;CAAE,CAAC;AAE9E;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,WAAW;AACrB;;;;;;GAMG;AACD;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE;AAC9C;;;;;;;;;GASG;GACD;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjF;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,YAAa,SAAQ,YAAY;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,WAAW,CAAC;IACpB;;;;;;;;;;;;;;;OAeG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,WAAW;AACrB,qFAAqF;AACnF;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE;AACxC,+EAA+E;GAC7E;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE;AACrC,2EAA2E;GACzE;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,cAAc,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE;AAC3D,4EAA4E;GAC1E;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE;AACrC,mFAAmF;GACjF;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,YAAY,GAAG,WAAW,CAa1D;AAED,4EAA4E;AAC5E,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAChD;;;;;OAKG;IACH,OAAO,CAAC,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACpD;;;;OAIG;IACH,IAAI,CAAC,IAAI,OAAO,CAAC,YAAY,CAAC,CAAC;CAChC;AAED;;;GAGG;AACH,eAAO,MAAM,iBAAiB,MAAM,CAAC;AA2BrC,qBAAa,WAAY,YAAW,UAAU;IA0BhC,OAAO,CAAC,QAAQ,CAAC,IAAI;IAzBjC;;;;;;;OAOG;IACH,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAkE;IAEvF;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA4D;gBAErD,IAAI,EAAE,eAAe;IAElD;;;;;;;;;;;;OAYG;YACW,WAAW;IAczB;;;;;;OAMG;IACH,SAAS,IAAI,OAAO;IAId,KAAK,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;IAqIrD;;;;OAIG;IACG,OAAO,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAsBxD;;;;OAIG;IACH,OAAO,CAAC,WAAW;IAKnB;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,YAAY,CAAC;YAUrB,MAAM;CA4JrB;AAoCD;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC5B,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAiBnF;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB;;;;;;;;;;;;;OAaG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,MAAM,CAAC;AAErC;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,SAAS,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,YAAY,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3F,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,CAqD5D;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAKrE;AAGD,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,EACX,QAAQ,CAAC,EAAE,MAAM,EACjB,KAAK,GAAE;IAAE,QAAQ,CAAC,YAAY,CAAC,EAAE,eAAe,CAAC;IAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,KAAK,OAAO,CAAA;CAAO,GACxH,WAAW,CA4Gb;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,GAAG,GAAE,IAAiB,GAAG,MAAM,CAK/F"}
|
package/dist/run-launcher.js
CHANGED
|
@@ -208,7 +208,7 @@ class RunLauncher {
|
|
|
208
208
|
*/
|
|
209
209
|
const slots = req.origin.kind === 'autonomy' ? this.deps.machineSlots : undefined;
|
|
210
210
|
if (slots !== undefined) {
|
|
211
|
-
const full = slots.claim(requestId);
|
|
211
|
+
const full = slots.claim(requestId, { maintenance: this.deps.isMaintenance?.(req.goalId) === true });
|
|
212
212
|
if (full !== null)
|
|
213
213
|
return { started: false, reason: full };
|
|
214
214
|
}
|
|
@@ -306,7 +306,7 @@ class RunLauncher {
|
|
|
306
306
|
machineFull(req) {
|
|
307
307
|
if (req.origin.kind !== 'autonomy' || this.deps.machineSlots === undefined)
|
|
308
308
|
return null;
|
|
309
|
-
return this.deps.machineSlots.claim(req.requestId);
|
|
309
|
+
return this.deps.machineSlots.claim(req.requestId, { maintenance: this.deps.isMaintenance?.(req.goalId) === true });
|
|
310
310
|
}
|
|
311
311
|
/**
|
|
312
312
|
* `looply scan`, as a child, so the lens passes stream into the ledger and
|
|
@@ -644,6 +644,7 @@ function nodeRunLauncher(cwd, stateDir, extra = {}) {
|
|
|
644
644
|
const refusals = new run_refusal_marks_1.RunRefusalMarks(project, ledger_store_1.nodeLedgerFs);
|
|
645
645
|
return new RunLauncher({
|
|
646
646
|
...(extra.machineSlots === undefined ? {} : { machineSlots: extra.machineSlots }),
|
|
647
|
+
...(extra.isMaintenance === undefined ? {} : { isMaintenance: extra.isMaintenance }),
|
|
647
648
|
...(leases ? { peekLease: () => leases.inspect() } : {}),
|
|
648
649
|
/**
|
|
649
650
|
* 🔴 THE LEASE OF THE CHECKOUT BEING LAUNCHED INTO.
|