@bluewombat/runtime 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 (151) hide show
  1. package/README.md +473 -0
  2. package/SPECS.md +303 -0
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +172 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/config/defaults.d.ts +17 -0
  8. package/dist/config/defaults.d.ts.map +1 -0
  9. package/dist/config/defaults.js +17 -0
  10. package/dist/config/defaults.js.map +1 -0
  11. package/dist/config/find-config.d.ts +9 -0
  12. package/dist/config/find-config.d.ts.map +1 -0
  13. package/dist/config/find-config.js +25 -0
  14. package/dist/config/find-config.js.map +1 -0
  15. package/dist/config/home.d.ts +17 -0
  16. package/dist/config/home.d.ts.map +1 -0
  17. package/dist/config/home.js +23 -0
  18. package/dist/config/home.js.map +1 -0
  19. package/dist/config/load-config.d.ts +13 -0
  20. package/dist/config/load-config.d.ts.map +1 -0
  21. package/dist/config/load-config.js +537 -0
  22. package/dist/config/load-config.js.map +1 -0
  23. package/dist/config/parse-args.d.ts +25 -0
  24. package/dist/config/parse-args.d.ts.map +1 -0
  25. package/dist/config/parse-args.js +478 -0
  26. package/dist/config/parse-args.js.map +1 -0
  27. package/dist/config/types.d.ts +144 -0
  28. package/dist/config/types.d.ts.map +1 -0
  29. package/dist/config/types.js +2 -0
  30. package/dist/config/types.js.map +1 -0
  31. package/dist/index.d.ts +30 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +16 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/loop/authority.d.ts +51 -0
  36. package/dist/loop/authority.d.ts.map +1 -0
  37. package/dist/loop/authority.js +166 -0
  38. package/dist/loop/authority.js.map +1 -0
  39. package/dist/loop/context.d.ts +44 -0
  40. package/dist/loop/context.d.ts.map +1 -0
  41. package/dist/loop/context.js +2 -0
  42. package/dist/loop/context.js.map +1 -0
  43. package/dist/loop/cursor.d.ts +4 -0
  44. package/dist/loop/cursor.d.ts.map +1 -0
  45. package/dist/loop/cursor.js +20 -0
  46. package/dist/loop/cursor.js.map +1 -0
  47. package/dist/loop/deliveries.d.ts +22 -0
  48. package/dist/loop/deliveries.d.ts.map +1 -0
  49. package/dist/loop/deliveries.js +240 -0
  50. package/dist/loop/deliveries.js.map +1 -0
  51. package/dist/loop/describe.d.ts +40 -0
  52. package/dist/loop/describe.d.ts.map +1 -0
  53. package/dist/loop/describe.js +48 -0
  54. package/dist/loop/describe.js.map +1 -0
  55. package/dist/loop/drive.d.ts +15 -0
  56. package/dist/loop/drive.d.ts.map +1 -0
  57. package/dist/loop/drive.js +42 -0
  58. package/dist/loop/drive.js.map +1 -0
  59. package/dist/loop/journal.d.ts +22 -0
  60. package/dist/loop/journal.d.ts.map +1 -0
  61. package/dist/loop/journal.js +49 -0
  62. package/dist/loop/journal.js.map +1 -0
  63. package/dist/loop/lock.d.ts +11 -0
  64. package/dist/loop/lock.d.ts.map +1 -0
  65. package/dist/loop/lock.js +60 -0
  66. package/dist/loop/lock.js.map +1 -0
  67. package/dist/loop/message.d.ts +34 -0
  68. package/dist/loop/message.d.ts.map +1 -0
  69. package/dist/loop/message.js +48 -0
  70. package/dist/loop/message.js.map +1 -0
  71. package/dist/loop/open-host.d.ts +13 -0
  72. package/dist/loop/open-host.d.ts.map +1 -0
  73. package/dist/loop/open-host.js +180 -0
  74. package/dist/loop/open-host.js.map +1 -0
  75. package/dist/loop/probe.d.ts +9 -0
  76. package/dist/loop/probe.d.ts.map +1 -0
  77. package/dist/loop/probe.js +57 -0
  78. package/dist/loop/probe.js.map +1 -0
  79. package/dist/loop/report.d.ts +26 -0
  80. package/dist/loop/report.d.ts.map +1 -0
  81. package/dist/loop/report.js +328 -0
  82. package/dist/loop/report.js.map +1 -0
  83. package/dist/loop/tick.d.ts +24 -0
  84. package/dist/loop/tick.d.ts.map +1 -0
  85. package/dist/loop/tick.js +169 -0
  86. package/dist/loop/tick.js.map +1 -0
  87. package/dist/loop/trace.d.ts +16 -0
  88. package/dist/loop/trace.d.ts.map +1 -0
  89. package/dist/loop/trace.js +49 -0
  90. package/dist/loop/trace.js.map +1 -0
  91. package/dist/loop/transformers.d.ts +27 -0
  92. package/dist/loop/transformers.d.ts.map +1 -0
  93. package/dist/loop/transformers.js +229 -0
  94. package/dist/loop/transformers.js.map +1 -0
  95. package/dist/loop/work-line.d.ts +73 -0
  96. package/dist/loop/work-line.d.ts.map +1 -0
  97. package/dist/loop/work-line.js +109 -0
  98. package/dist/loop/work-line.js.map +1 -0
  99. package/dist/operator/board.d.ts +31 -0
  100. package/dist/operator/board.d.ts.map +1 -0
  101. package/dist/operator/board.js +67 -0
  102. package/dist/operator/board.js.map +1 -0
  103. package/dist/operator/cancel.d.ts +19 -0
  104. package/dist/operator/cancel.d.ts.map +1 -0
  105. package/dist/operator/cancel.js +70 -0
  106. package/dist/operator/cancel.js.map +1 -0
  107. package/dist/operator/doctor.d.ts +15 -0
  108. package/dist/operator/doctor.d.ts.map +1 -0
  109. package/dist/operator/doctor.js +416 -0
  110. package/dist/operator/doctor.js.map +1 -0
  111. package/dist/operator/git-remote.d.ts +39 -0
  112. package/dist/operator/git-remote.d.ts.map +1 -0
  113. package/dist/operator/git-remote.js +78 -0
  114. package/dist/operator/git-remote.js.map +1 -0
  115. package/dist/operator/init.d.ts +28 -0
  116. package/dist/operator/init.d.ts.map +1 -0
  117. package/dist/operator/init.js +522 -0
  118. package/dist/operator/init.js.map +1 -0
  119. package/dist/operator/live.d.ts +19 -0
  120. package/dist/operator/live.d.ts.map +1 -0
  121. package/dist/operator/live.js +149 -0
  122. package/dist/operator/live.js.map +1 -0
  123. package/dist/operator/prompt.d.ts +35 -0
  124. package/dist/operator/prompt.d.ts.map +1 -0
  125. package/dist/operator/prompt.js +125 -0
  126. package/dist/operator/prompt.js.map +1 -0
  127. package/dist/operator/setup.d.ts +18 -0
  128. package/dist/operator/setup.d.ts.map +1 -0
  129. package/dist/operator/setup.js +62 -0
  130. package/dist/operator/setup.js.map +1 -0
  131. package/dist/plugins/discover.d.ts +13 -0
  132. package/dist/plugins/discover.d.ts.map +1 -0
  133. package/dist/plugins/discover.js +81 -0
  134. package/dist/plugins/discover.js.map +1 -0
  135. package/dist/plugins/isolation.d.ts +78 -0
  136. package/dist/plugins/isolation.d.ts.map +1 -0
  137. package/dist/plugins/isolation.js +64 -0
  138. package/dist/plugins/isolation.js.map +1 -0
  139. package/dist/plugins/load.d.ts +35 -0
  140. package/dist/plugins/load.d.ts.map +1 -0
  141. package/dist/plugins/load.js +109 -0
  142. package/dist/plugins/load.js.map +1 -0
  143. package/dist/plugins/manager.d.ts +43 -0
  144. package/dist/plugins/manager.d.ts.map +1 -0
  145. package/dist/plugins/manager.js +47 -0
  146. package/dist/plugins/manager.js.map +1 -0
  147. package/dist/plugins/persist.d.ts +33 -0
  148. package/dist/plugins/persist.d.ts.map +1 -0
  149. package/dist/plugins/persist.js +26 -0
  150. package/dist/plugins/persist.js.map +1 -0
  151. package/package.json +66 -0
@@ -0,0 +1,416 @@
1
+ import { existsSync, statSync } from "node:fs";
2
+ import { delimiter, dirname, isAbsolute, join } from "node:path";
3
+ import { PRODUCT } from "@bluewombat/manager-kit";
4
+ import { ISOLATION_COPY, ISOLATION_GIT } from "../config/defaults.js";
5
+ import { CONFIG_FILENAME, findConfig } from "../config/find-config.js";
6
+ import { parseArgs } from "../config/parse-args.js";
7
+ import { inspectWorkLine, resolveWorkLine } from "../loop/work-line.js";
8
+ import { resolveIsolationStrategy } from "../plugins/isolation.js";
9
+ import { contextOf, loadManagerModule } from "../plugins/manager.js";
10
+ import { remoteNames } from "./git-remote.js";
11
+ const REQUIRED_NODE_MAJOR = 24;
12
+ /**
13
+ * Say what is missing before a run says it. Nothing here uses the network:
14
+ * the answer must be the same offline, and a manager's own check is held to
15
+ * the same rule.
16
+ */
17
+ export async function runDoctor(input) {
18
+ const findings = [nodeFinding(input.nodeVersion ?? process.versions.node)];
19
+ const configPath = configPathOf(input);
20
+ findings.push(configPath === undefined
21
+ ? { level: "warn", label: "config", detail: `no ${CONFIG_FILENAME} found; using flags only` }
22
+ : { level: "ok", label: "config", detail: configPath });
23
+ const parsed = parseArgs(input.argv, { cwd: input.cwd, checkPaths: false });
24
+ if (!parsed.ok) {
25
+ findings.push({ level: "fail", label: "invocation", detail: parsed.reason });
26
+ return report(findings, input.write);
27
+ }
28
+ const invocation = parsed.invocation;
29
+ findings.push({ level: "ok", label: "invocation", detail: "every required field is set" });
30
+ findings.push({ level: "ok", label: "home", detail: invocation.home });
31
+ const request = {
32
+ manager: invocation.manager,
33
+ managerOptions: invocation.managerOptions,
34
+ configDir: invocation.configDir,
35
+ durationMs: invocation.timeoutMs,
36
+ interruptFlag: { interrupted: false },
37
+ env: input.env,
38
+ };
39
+ const loaded = await loadManagerModule(request);
40
+ const workLine = await workLineOf(invocation, loaded.ok ? loaded.module : undefined);
41
+ findings.push(...workLineFindings(workLine));
42
+ // Whose the directory is decides which checks apply: Host's copy of a
43
+ // reference was already held against it, and may not exist yet.
44
+ const stable = workLine.kind === "invalid" ? undefined : workLine.stable;
45
+ const target = workLine.kind === "copy" ? workLine.target : invocation.workLineBranch;
46
+ findings.push(...isolationFindings(invocation, workLine));
47
+ findings.push(...authorityFindings(invocation, workLine, target, input.env));
48
+ const judged = assemblyFinding(invocation);
49
+ if (judged !== undefined) {
50
+ findings.push(judged);
51
+ }
52
+ if (stable !== undefined && workLine.kind !== "copy") {
53
+ const onBranch = workLineBranchFinding(stable, target);
54
+ if (onBranch !== undefined) {
55
+ findings.push(onBranch);
56
+ }
57
+ }
58
+ findings.push(writableFinding("workspace root", invocation.workspaceRoot));
59
+ findings.push(writableFinding("ledger root", invocation.ledgerRoot));
60
+ findings.push(commandFinding("Planner", invocation.planner.cmd, input.env));
61
+ for (const stage of ["builder", "assembly"]) {
62
+ if (stage === "builder") {
63
+ for (const pass of ["producer", "repair"]) {
64
+ findings.push(commandFinding(`${label(stage)} ${pass}`, invocation.builder[pass].cmd, input.env));
65
+ }
66
+ }
67
+ else if (invocation.assembly.fix !== undefined) {
68
+ findings.push(commandFinding("Assembly fix", invocation.assembly.fix.cmd, input.env));
69
+ }
70
+ for (const gate of invocation[stage].gates) {
71
+ findings.push(commandFinding(`${label(stage)} gate ${gate.id}`, gate.argv, input.env));
72
+ }
73
+ }
74
+ findings.push(...assemblyFixFindings(invocation));
75
+ if (!loaded.ok) {
76
+ findings.push({ level: "fail", label: "manager", detail: loaded.reason });
77
+ return report(findings, input.write);
78
+ }
79
+ findings.push({ level: "ok", label: "manager", detail: invocation.manager });
80
+ if (loaded.module.checkManager !== undefined) {
81
+ findings.push(...(await loaded.module.checkManager(contextOf(request))));
82
+ }
83
+ return report(findings, input.write);
84
+ }
85
+ /**
86
+ * Whether the Project offers its work to somebody outside, and how.
87
+ *
88
+ * The block is a declaration, so this is where the declaration meets reality:
89
+ * an Authority needs a work line to offer the work to, and a command that puts
90
+ * the work in front of it.
91
+ */
92
+ function authorityFindings(invocation, workLine, target, env) {
93
+ const authority = invocation.authority;
94
+ if (authority === undefined) {
95
+ return [
96
+ {
97
+ level: "warn",
98
+ label: "authority",
99
+ detail: 'not declared — the fold is local and final. Add "authority": { "enabled": false } to say so, or true to offer the work',
100
+ },
101
+ ];
102
+ }
103
+ if (!authority.enabled) {
104
+ return [
105
+ { level: "ok", label: "authority", detail: "none — the fold into WorkLineStable is final" },
106
+ ];
107
+ }
108
+ const findings = [];
109
+ if (target === undefined) {
110
+ findings.push({
111
+ level: "fail",
112
+ label: "authority",
113
+ detail: 'enabled, but "workLine.branch" does not say which work line the work is offered to',
114
+ });
115
+ }
116
+ else {
117
+ findings.push({
118
+ level: "ok",
119
+ label: "authority",
120
+ detail: `offers the assembled feature on "${target}"`,
121
+ });
122
+ }
123
+ findings.push(commandFinding("Publisher", authority.publishArgv, env));
124
+ findings.push(commandFinding("Refresher", authority.refreshArgv, env));
125
+ if (authority.describeArgv !== undefined) {
126
+ findings.push(commandFinding("Describer", authority.describeArgv, env));
127
+ }
128
+ // An accepted Submission moves the work line where the Authority is, and Host
129
+ // reads that back from `origin` before the next Isolation. Without that
130
+ // remote the fetch fails on every tick and the run starts nothing at all —
131
+ // silently, because a skipped tick looks exactly like an idle one. A copy of
132
+ // a reference has its `origin` by construction.
133
+ if (target !== undefined &&
134
+ (workLine.kind === "operators" || workLine.kind === "unchecked") &&
135
+ inspectWorkLine(workLine.stable).kind === "git" &&
136
+ !remoteNames(workLine.stable).includes("origin")) {
137
+ findings.push({
138
+ level: "fail",
139
+ label: "work line remote",
140
+ detail: 'no "origin" — after the Authority folds, Host reads the work line back from it, and every run would start nothing until it exists',
141
+ });
142
+ }
143
+ return findings;
144
+ }
145
+ function configPathOf(input) {
146
+ const flagged = input.argv.indexOf("--config");
147
+ if (flagged >= 0) {
148
+ return input.argv[flagged + 1];
149
+ }
150
+ return findConfig(input.cwd);
151
+ }
152
+ function nodeFinding(version) {
153
+ const major = Number(version.split(".")[0]);
154
+ return major >= REQUIRED_NODE_MAJOR
155
+ ? { level: "ok", label: "Node.js", detail: version }
156
+ : {
157
+ level: "fail",
158
+ label: "Node.js",
159
+ detail: `${version} — ${PRODUCT} needs ${REQUIRED_NODE_MAJOR} or later`,
160
+ };
161
+ }
162
+ /**
163
+ * The same decision `mason run` makes at boot, without the fetch. A manager
164
+ * that does not load names no reference; the failure is reported where the
165
+ * manager is.
166
+ */
167
+ async function workLineOf(invocation, module) {
168
+ const strategy = await resolveIsolationStrategy(invocation.workLineIsolation, invocation.configDir, invocation.workLineIsolationOptions);
169
+ if (!strategy.ok) {
170
+ return { kind: "invalid", reason: strategy.reason };
171
+ }
172
+ const context = contextOf({
173
+ manager: invocation.manager,
174
+ managerOptions: invocation.managerOptions,
175
+ configDir: invocation.configDir,
176
+ durationMs: invocation.timeoutMs,
177
+ interruptFlag: { interrupted: false },
178
+ env: {},
179
+ });
180
+ return resolveWorkLine({
181
+ home: invocation.home,
182
+ stable: invocation.workLineStable,
183
+ branch: invocation.workLineBranch,
184
+ manager: invocation.manager,
185
+ wantsAuthority: invocation.authority?.enabled === true,
186
+ reference: module?.referenceManager?.(context),
187
+ strategy: strategy.strategy,
188
+ strategyName: strategy.specifier,
189
+ });
190
+ }
191
+ function workLineFindings(workLine) {
192
+ switch (workLine.kind) {
193
+ case "invalid":
194
+ return [{ level: "fail", label: "work line", detail: workLine.reason }];
195
+ case "operators":
196
+ return [workLineFinding(workLine.stable)];
197
+ case "unchecked":
198
+ return [
199
+ workLineFinding(workLine.stable),
200
+ { level: "warn", label: "work line", detail: `${workLine.reason} Taken as is.` },
201
+ ];
202
+ case "copy": {
203
+ const findings = [
204
+ { level: "ok", label: "reference", detail: workLine.reference.summary },
205
+ ];
206
+ switch (workLine.state.kind) {
207
+ case "matches":
208
+ findings.push({ level: "ok", label: "work line", detail: `${workLine.stable} (copy)` });
209
+ break;
210
+ case "missing":
211
+ findings.push({
212
+ level: "ok",
213
+ label: "work line",
214
+ detail: `${workLine.stable} — copied from the reference on the first run`,
215
+ });
216
+ break;
217
+ case "mismatch":
218
+ findings.push({
219
+ level: "fail",
220
+ label: "work line",
221
+ detail: `${workLine.stable} is not a copy of the reference: ${workLine.state.reason}`,
222
+ });
223
+ break;
224
+ }
225
+ return findings;
226
+ }
227
+ }
228
+ }
229
+ function workLineFinding(path) {
230
+ if (!existsSync(path) || !statSync(path).isDirectory()) {
231
+ return { level: "fail", label: "WorkLineStable", detail: `not a directory: ${path}` };
232
+ }
233
+ if (!existsSync(join(path, ".git"))) {
234
+ return {
235
+ level: "ok",
236
+ label: "WorkLineStable",
237
+ detail: `${path} (plain directory)`,
238
+ };
239
+ }
240
+ return { level: "ok", label: "WorkLineStable", detail: `${path} (git)` };
241
+ }
242
+ /**
243
+ * Whether `workLine.isolation` matches what is on disk, and what Authority needs.
244
+ *
245
+ * Isolator does not choose a strategy; the config does. A mismatch here is a Project that will
246
+ * fail on the first Isolation, or one that cannot publish a Submission.
247
+ */
248
+ function isolationFindings(invocation, workLine) {
249
+ const findings = [
250
+ {
251
+ level: "ok",
252
+ label: "workLine.isolation",
253
+ detail: invocation.workLineIsolation,
254
+ },
255
+ ];
256
+ const isGitStrategy = invocation.workLineIsolation === ISOLATION_GIT;
257
+ const isCopyStrategy = invocation.workLineIsolation === ISOLATION_COPY;
258
+ // A copy of a reference is git by construction, fetched or not yet.
259
+ const operatorsTree = workLine.kind === "operators" || workLine.kind === "unchecked"
260
+ ? inspectWorkLine(workLine.stable)
261
+ : undefined;
262
+ if (isGitStrategy && operatorsTree !== undefined && operatorsTree.kind !== "git") {
263
+ findings.push({
264
+ level: "warn",
265
+ label: "workLine.isolation",
266
+ detail: `"${ISOLATION_GIT}", but WorkLineStable has no .git — the first Isolation will fail until the directory is a git tree`,
267
+ });
268
+ }
269
+ if (isCopyStrategy && invocation.authority?.enabled === true) {
270
+ findings.push({
271
+ level: "warn",
272
+ label: "workLine.isolation",
273
+ detail: `"${ISOLATION_COPY}" with authority.enabled — the git Publisher needs a git work line; Submissions will refuse`,
274
+ });
275
+ }
276
+ return findings;
277
+ }
278
+ /**
279
+ * Whether anything judges the assembled feature.
280
+ *
281
+ * With a work line to offer the work to, the assembled feature is published and
282
+ * then folded on the Gate sequence's word. An empty sequence is a Project that
283
+ * publishes and merges with nothing looking at the whole.
284
+ */
285
+ function assemblyFinding(invocation) {
286
+ // Only an Authority publishes and merges. With the fold staying local there
287
+ // is nothing outside to guard, and the unit Gates already judged every part.
288
+ if (invocation.authority?.enabled !== true) {
289
+ return undefined;
290
+ }
291
+ if (invocation.assembly.gates.length > 0) {
292
+ return {
293
+ level: "ok",
294
+ label: "assembly gates",
295
+ detail: invocation.assembly.gates.map((gate) => gate.id).join(", "),
296
+ };
297
+ }
298
+ return {
299
+ level: "warn",
300
+ label: "assembly gates",
301
+ detail: 'none — the assembled feature is published and merged with nothing judging it. Add "assembly.gates" (ci-green reads the work line\'s own checks)',
302
+ };
303
+ }
304
+ function label(stage) {
305
+ return stage === "builder" ? "Builder" : "Assembly";
306
+ }
307
+ /**
308
+ * A Submission that comes back needs a command that can fix what the judgement
309
+ * named. Nothing sends one back where no Authority ever took it.
310
+ */
311
+ function assemblyFixFindings(invocation) {
312
+ const declared = invocation.assembly.fix !== undefined;
313
+ const offering = invocation.authority?.enabled === true;
314
+ if (offering && !declared) {
315
+ return [
316
+ {
317
+ level: "fail",
318
+ label: "assembly fix",
319
+ detail: 'authority.enabled is true, so a Submission can come back. Name "assembly.fix"',
320
+ },
321
+ ];
322
+ }
323
+ if (declared && !offering) {
324
+ return [
325
+ {
326
+ level: "warn",
327
+ label: "assembly fix",
328
+ detail: "declared, but nothing sends a Submission back without an Authority — it will never run",
329
+ },
330
+ ];
331
+ }
332
+ return [];
333
+ }
334
+ /**
335
+ * Which work line a fold would land on.
336
+ *
337
+ * Without `workLine.branch` the answer is "whatever is checked out", which is
338
+ * nobody's decision: leave that tree on another branch and a feature lands
339
+ * there without a word.
340
+ */
341
+ function workLineBranchFinding(path, wanted) {
342
+ const state = inspectWorkLine(path);
343
+ if (state.kind !== "git") {
344
+ return undefined;
345
+ }
346
+ if (wanted === undefined) {
347
+ return {
348
+ level: "warn",
349
+ label: "work line",
350
+ detail: `on "${state.branch}" — set "workLine.branch" to say which one a fold must land on`,
351
+ };
352
+ }
353
+ if (state.branch !== wanted) {
354
+ return {
355
+ level: "fail",
356
+ label: "work line",
357
+ detail: `on "${state.branch}", but the config wants "${wanted}"`,
358
+ };
359
+ }
360
+ return { level: "ok", label: "work line", detail: wanted };
361
+ }
362
+ /** Host creates the whole chain, so the nearest existing ancestor is the answer. */
363
+ function writableFinding(label, path) {
364
+ if (existsSync(path)) {
365
+ return statSync(path).isDirectory()
366
+ ? { level: "ok", label, detail: path }
367
+ : { level: "fail", label, detail: `not a directory: ${path}` };
368
+ }
369
+ let ancestor = dirname(path);
370
+ for (;;) {
371
+ if (existsSync(ancestor)) {
372
+ return statSync(ancestor).isDirectory()
373
+ ? { level: "ok", label, detail: `${path} (created on run)` }
374
+ : { level: "fail", label, detail: `not a directory: ${ancestor}` };
375
+ }
376
+ const parent = dirname(ancestor);
377
+ if (parent === ancestor) {
378
+ return { level: "fail", label, detail: `no existing parent for ${path}` };
379
+ }
380
+ ancestor = parent;
381
+ }
382
+ }
383
+ function commandFinding(label, argv, env) {
384
+ const command = argv[0];
385
+ if (command === undefined) {
386
+ return { level: "fail", label, detail: "empty command" };
387
+ }
388
+ return locate(command, env) === undefined
389
+ ? { level: "fail", label, detail: `command not found: ${command}` }
390
+ : { level: "ok", label, detail: argv.join(" ") };
391
+ }
392
+ /** An explicit path must exist; a bare word must sit on PATH. */
393
+ function locate(command, env) {
394
+ if (isAbsolute(command) || command.includes("/")) {
395
+ return existsSync(command) ? command : undefined;
396
+ }
397
+ for (const dir of (env.PATH ?? "").split(delimiter)) {
398
+ if (dir.length > 0 && existsSync(join(dir, command))) {
399
+ return join(dir, command);
400
+ }
401
+ }
402
+ return undefined;
403
+ }
404
+ function report(findings, write) {
405
+ let failed = 0;
406
+ for (const finding of findings) {
407
+ if (finding.level === "fail") {
408
+ failed += 1;
409
+ }
410
+ const mark = finding.level === "ok" ? "ok " : finding.level === "warn" ? "warn" : "FAIL";
411
+ write(`${mark} ${finding.label}${finding.detail === undefined ? "" : ` — ${finding.detail}`}\n`);
412
+ }
413
+ write(failed === 0 ? "\nReady to run.\n" : `\n${failed} check(s) failed.\n`);
414
+ return failed === 0 ? 0 : 1;
415
+ }
416
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/operator/doctor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Git remotes, for `init` and `doctor`: what a copy points at, what a remote
3
+ * holds, and a clone of one branch. Whether a path *is* a work line is the
4
+ * loop's question — `inspectWorkLine` in `loop/work-line.ts`.
5
+ */
6
+ /**
7
+ * The remotes that work line copy knows, by name.
8
+ *
9
+ * Offline on purpose: the question here is whether the name is configured at
10
+ * all, which is the one that turns a run that silently does nothing into a
11
+ * refusal at startup. Whether that remote answers is the network's business.
12
+ */
13
+ export declare function remoteNames(path: string): string[];
14
+ /**
15
+ * Whether the remote really carries that branch.
16
+ *
17
+ * Cheap, and it is the check that turns "cloned the wrong thing" into a
18
+ * question asked before anything is written to disk.
19
+ */
20
+ export declare function remoteBranches(remote: string): {
21
+ ok: true;
22
+ names: string[];
23
+ } | {
24
+ ok: false;
25
+ reason: string;
26
+ };
27
+ /**
28
+ * The branch a bare `git clone` would land on. `ls-remote --symref` answers it
29
+ * without fetching anything, so `--clone` needs no `--branch` to do the
30
+ * obvious thing.
31
+ */
32
+ export declare function remoteHead(remote: string): string | undefined;
33
+ export declare function cloneWorkLine(remote: string, branch: string, path: string): {
34
+ ok: true;
35
+ } | {
36
+ ok: false;
37
+ reason: string;
38
+ };
39
+ //# sourceMappingURL=git-remote.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-remote.d.ts","sourceRoot":"","sources":["../../src/operator/git-remote.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AAEH;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAQlD;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,MAAM,GACb;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAa/D;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAY7D;AAED,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GACX;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAK9C"}
@@ -0,0 +1,78 @@
1
+ import { spawnSync } from "node:child_process";
2
+ /**
3
+ * Git remotes, for `init` and `doctor`: what a copy points at, what a remote
4
+ * holds, and a clone of one branch. Whether a path *is* a work line is the
5
+ * loop's question — `inspectWorkLine` in `loop/work-line.ts`.
6
+ */
7
+ /**
8
+ * The remotes that work line copy knows, by name.
9
+ *
10
+ * Offline on purpose: the question here is whether the name is configured at
11
+ * all, which is the one that turns a run that silently does nothing into a
12
+ * refusal at startup. Whether that remote answers is the network's business.
13
+ */
14
+ export function remoteNames(path) {
15
+ const listed = git(["remote"], path);
16
+ return listed.ok
17
+ ? listed.stdout
18
+ .split("\n")
19
+ .map((line) => line.trim())
20
+ .filter((line) => line.length > 0)
21
+ : [];
22
+ }
23
+ /**
24
+ * Whether the remote really carries that branch.
25
+ *
26
+ * Cheap, and it is the check that turns "cloned the wrong thing" into a
27
+ * question asked before anything is written to disk.
28
+ */
29
+ export function remoteBranches(remote) {
30
+ const listed = git(["ls-remote", "--heads", remote]);
31
+ if (!listed.ok) {
32
+ return { ok: false, reason: listed.stderr.trim() || `Cannot reach ${remote}` };
33
+ }
34
+ const names = [];
35
+ for (const line of listed.stdout.split("\n")) {
36
+ const ref = line.split("\t")[1];
37
+ if (ref?.startsWith("refs/heads/")) {
38
+ names.push(ref.slice("refs/heads/".length));
39
+ }
40
+ }
41
+ return { ok: true, names };
42
+ }
43
+ /**
44
+ * The branch a bare `git clone` would land on. `ls-remote --symref` answers it
45
+ * without fetching anything, so `--clone` needs no `--branch` to do the
46
+ * obvious thing.
47
+ */
48
+ export function remoteHead(remote) {
49
+ const listed = git(["ls-remote", "--symref", remote, "HEAD"]);
50
+ if (!listed.ok) {
51
+ return undefined;
52
+ }
53
+ for (const line of listed.stdout.split("\n")) {
54
+ const matched = /^ref:\s+refs\/heads\/(\S+)\s+HEAD$/.exec(line.trim());
55
+ if (matched?.[1] !== undefined) {
56
+ return matched[1];
57
+ }
58
+ }
59
+ return undefined;
60
+ }
61
+ export function cloneWorkLine(remote, branch, path) {
62
+ const cloned = git(["clone", "--branch", branch, "--single-branch", remote, path]);
63
+ return cloned.ok
64
+ ? { ok: true }
65
+ : { ok: false, reason: cloned.stderr.trim() || "git clone failed" };
66
+ }
67
+ function git(argv, cwd) {
68
+ const result = spawnSync("git", argv, {
69
+ encoding: "utf8",
70
+ ...(cwd === undefined ? {} : { cwd }),
71
+ });
72
+ return {
73
+ ok: result.status === 0,
74
+ stdout: result.stdout ?? "",
75
+ stderr: result.stderr ?? String(result.error ?? ""),
76
+ };
77
+ }
78
+ //# sourceMappingURL=git-remote.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-remote.js","sourceRoot":"","sources":["../../src/operator/git-remote.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import { type Ask } from "./prompt.js";
2
+ export type InitInput = {
3
+ cwd: string;
4
+ argv: string[];
5
+ write: (line: string) => void;
6
+ env?: Record<string, string | undefined>;
7
+ /** Present: the wizard runs and asks. Absent: flags only, nothing is asked. */
8
+ ask?: Ask;
9
+ };
10
+ export type InitResult = {
11
+ ok: true;
12
+ path: string;
13
+ exitCode: number;
14
+ } | {
15
+ ok: false;
16
+ reason: string;
17
+ exitCode?: number;
18
+ };
19
+ /**
20
+ * Set a working directory up, in one pass.
21
+ *
22
+ * With `ask`, it walks the questions — which manager, what that manager needs,
23
+ * where WorkLineStable is — then writes the files and carries straight on into
24
+ * `setup`, so nothing has to be re-run by hand. With flags only, it writes the
25
+ * same files and asks nothing, which is what a script wants.
26
+ */
27
+ export declare function runInit(input: InitInput): Promise<InitResult>;
28
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/operator/init.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,KAAK,GAAG,EAAiD,MAAM,aAAa,CAAC;AAGtF,MAAM,MAAM,SAAS,GAAG;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACzC,+EAA+E;IAC/E,GAAG,CAAC,EAAE,GAAG,CAAC;CACX,CAAC;AAEF,MAAM,MAAM,UAAU,GAClB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAC5C;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAsBrD;;;;;;;GAOG;AACH,wBAAsB,OAAO,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CASnE"}