looply-cli 0.5.4 → 0.5.5

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 (89) hide show
  1. package/dist/.src-hash +1 -1
  2. package/dist/autonomy-controller.d.ts +14 -1
  3. package/dist/autonomy-controller.d.ts.map +1 -1
  4. package/dist/autonomy-controller.js +55 -2
  5. package/dist/autonomy-controller.js.map +1 -1
  6. package/dist/autonomy-store.d.ts +35 -2
  7. package/dist/autonomy-store.d.ts.map +1 -1
  8. package/dist/autonomy-store.js +27 -2
  9. package/dist/autonomy-store.js.map +1 -1
  10. package/dist/autonomy-tick.d.ts +25 -2
  11. package/dist/autonomy-tick.d.ts.map +1 -1
  12. package/dist/autonomy-tick.js +122 -4
  13. package/dist/autonomy-tick.js.map +1 -1
  14. package/dist/bin.d.ts.map +1 -1
  15. package/dist/bin.js +2 -0
  16. package/dist/bin.js.map +1 -1
  17. package/dist/checkout-carry.d.ts.map +1 -1
  18. package/dist/checkout-carry.js +12 -0
  19. package/dist/checkout-carry.js.map +1 -1
  20. package/dist/config.d.ts +41 -0
  21. package/dist/config.d.ts.map +1 -1
  22. package/dist/config.js +40 -7
  23. package/dist/config.js.map +1 -1
  24. package/dist/coordinator-state.d.ts +14 -0
  25. package/dist/coordinator-state.d.ts.map +1 -1
  26. package/dist/coordinator-state.js +29 -0
  27. package/dist/coordinator-state.js.map +1 -1
  28. package/dist/daemon-cmd.d.ts +1 -1
  29. package/dist/daemon-cmd.d.ts.map +1 -1
  30. package/dist/daemon-cmd.js +56 -33
  31. package/dist/daemon-cmd.js.map +1 -1
  32. package/dist/git-driver.d.ts +6 -0
  33. package/dist/git-driver.d.ts.map +1 -1
  34. package/dist/git-driver.js +12 -0
  35. package/dist/git-driver.js.map +1 -1
  36. package/dist/index-for-head.js +1 -1
  37. package/dist/index-for-head.js.map +1 -1
  38. package/dist/machine-run-slots.d.ts +59 -0
  39. package/dist/machine-run-slots.d.ts.map +1 -0
  40. package/dist/machine-run-slots.js +140 -0
  41. package/dist/machine-run-slots.js.map +1 -0
  42. package/dist/programme-mode.d.ts +6 -0
  43. package/dist/programme-mode.d.ts.map +1 -1
  44. package/dist/programme-mode.js +23 -0
  45. package/dist/programme-mode.js.map +1 -1
  46. package/dist/project-index-store.d.ts +19 -1
  47. package/dist/project-index-store.d.ts.map +1 -1
  48. package/dist/project-index-store.js +40 -5
  49. package/dist/project-index-store.js.map +1 -1
  50. package/dist/project-terminal.d.ts +25 -0
  51. package/dist/project-terminal.d.ts.map +1 -0
  52. package/dist/project-terminal.js +46 -0
  53. package/dist/project-terminal.js.map +1 -0
  54. package/dist/pursuit-ending.d.ts +57 -0
  55. package/dist/pursuit-ending.d.ts.map +1 -0
  56. package/dist/pursuit-ending.js +128 -0
  57. package/dist/pursuit-ending.js.map +1 -0
  58. package/dist/run-base.d.ts +84 -0
  59. package/dist/run-base.d.ts.map +1 -0
  60. package/dist/run-base.js +142 -0
  61. package/dist/run-base.js.map +1 -0
  62. package/dist/run-cmd.d.ts.map +1 -1
  63. package/dist/run-cmd.js +46 -5
  64. package/dist/run-cmd.js.map +1 -1
  65. package/dist/run-ended.d.ts +16 -0
  66. package/dist/run-ended.d.ts.map +1 -1
  67. package/dist/run-ended.js +30 -0
  68. package/dist/run-ended.js.map +1 -1
  69. package/dist/run-ending-locator.d.ts +10 -0
  70. package/dist/run-ending-locator.d.ts.map +1 -1
  71. package/dist/run-ending-locator.js +45 -0
  72. package/dist/run-ending-locator.js.map +1 -1
  73. package/dist/run-launcher.d.ts +17 -1
  74. package/dist/run-launcher.d.ts.map +1 -1
  75. package/dist/run-launcher.js +36 -5
  76. package/dist/run-launcher.js.map +1 -1
  77. package/dist/server-client.d.ts +5 -1
  78. package/dist/server-client.d.ts.map +1 -1
  79. package/dist/server-client.js +1 -0
  80. package/dist/server-client.js.map +1 -1
  81. package/dist/setup.d.ts.map +1 -1
  82. package/dist/setup.js +17 -0
  83. package/dist/setup.js.map +1 -1
  84. package/dist/workspace-provisioner.d.ts +2 -0
  85. package/dist/workspace-provisioner.d.ts.map +1 -1
  86. package/dist/workspace-provisioner.js +27 -1
  87. package/dist/workspace-provisioner.js.map +1 -1
  88. package/package.json +54 -54
  89. package/win/HandleProbe.cs +116 -116
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.programmeIsOn = programmeIsOn;
4
4
  exports.describeProgramme = describeProgramme;
5
+ exports.describeParallel = describeParallel;
5
6
  /**
6
7
  * Is this machine running as a programme at all?
7
8
  *
@@ -47,4 +48,26 @@ function describeProgramme(cfg) {
47
48
  return 'programme mode: continuation only (machine.programme: true)';
48
49
  return 'programme mode: off (manual defaults)';
49
50
  }
51
+ /**
52
+ * PARALLEL TICKETS, IN ONE SENTENCE — `looply doctor`, `looply status` and the
53
+ * daemon's first lines. Says what the parser made of `machine.max_parallel_runs`
54
+ * and its companions, including the ceilings a person did not write.
55
+ */
56
+ function describeParallel(cfg) {
57
+ const m = cfg.machine;
58
+ const machineCap = m?.maxRunsOnMachine ?? 4;
59
+ const onMachine = `at most ${machineCap} autonomous run${machineCap === 1 ? '' : 's'} across this computer (machine.max_runs_on_machine)`;
60
+ if (m?.coordinator !== true) {
61
+ return `parallel: off — one goal at a time in this checkout (machine.max_parallel_runs: ${m?.maxParallelRuns ?? 1}); ${onMachine}`;
62
+ }
63
+ const n = Math.min(m.maxWorkspaces, m.maxAgentsInFlight, cfg.run.maxConcurrentRuns ?? 1);
64
+ const faces = [
65
+ m.provisionWorkspaces === true ? 'makes checkouts' : 'makes no checkouts (provision_workspaces: false)',
66
+ m.reapProvisioned === true ? `retires idle ones after ${m.idleCheckoutMinutes ?? 60} min` : 'never retires them',
67
+ ];
68
+ const carry = cfg.run.carryIntoCheckouts ?? [];
69
+ return (`parallel: up to ${n} goal${n === 1 ? '' : 's'} at once (machine.max_parallel_runs: ${m.maxParallelRuns ?? n}), each in its own checkout — ` +
70
+ `${faces.join(', ')}; runs cut from ${cfg.run.baseBranch ?? 'the default branch'} (or their one dependency's work); ` +
71
+ `carries ${carry.length === 0 ? 'nothing' : carry.join(', ')} into checkouts; ${onMachine}`);
72
+ }
50
73
  //# sourceMappingURL=programme-mode.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"programme-mode.js","sourceRoot":"","sources":["../src/programme-mode.ts"],"names":[],"mappings":";;AA2BA,sCAEC;AAED,8CAoBC;AAxCD;;;;;;;;;;;;;;;GAeG;AACH,SAAgB,aAAa,CAAC,GAAiB;IAC7C,OAAO,GAAG,CAAC,OAAO,EAAE,aAAa,KAAK,SAAS,IAAI,GAAG,CAAC,OAAO,EAAE,SAAS,KAAK,IAAI,CAAC;AACrF,CAAC;AAED,SAAgB,iBAAiB,CAAC,GAAiB;IACjD,MAAM,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC;IACtB,IAAI,CAAC,EAAE,aAAa,KAAK,SAAS,EAAE,CAAC;QACnC,MAAM,CAAC,GAAG,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC;QACjC,MAAM,CAAC,GAAG,CAAC,KAAa,EAAE,IAAY,EAAE,EAAE,CAAC,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;QACvF,MAAM,GAAG,GAAa,EAAE,CAAC;QACzB,IAAI,CAAC,CAAC,WAAW,KAAK,IAAI;YAAE,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACpD,IAAI,CAAC,CAAC,mBAAmB,KAAK,IAAI;YAAE,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC7D,IAAI,CAAC,CAAC,eAAe,KAAK,IAAI;YAAE,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACpD,IAAI,CAAC,CAAC,UAAU,KAAK,IAAI;YAAE,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAClD,IAAI,CAAC,CAAC,SAAS,KAAK,IAAI,IAAI,GAAG,CAAC,GAAG,CAAC,WAAW,KAAK,IAAI;YAAE,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAClF,IAAI,GAAG,CAAC,GAAG,CAAC,KAAK,KAAK,IAAI;YAAE,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC9C,OAAO,CACL,wBAAwB,CAAC,CAAC,CAAC,CAAC,aAAa,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,iBAAiB,EAAE,OAAO,CAAC,cAAc;YACxG,GAAG,CAAC,CAAC,CAAC,CAAC,cAAc,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC,aAAa,iCAAiC,CAAC,CAAC,cAAc,EAAE;YAChH,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,uBAAuB,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAClE,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,EAAE,SAAS,KAAK,IAAI;QAAE,OAAO,6DAA6D,CAAC;IAChG,OAAO,uCAAuC,CAAC;AACjD,CAAC"}
1
+ {"version":3,"file":"programme-mode.js","sourceRoot":"","sources":["../src/programme-mode.ts"],"names":[],"mappings":"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"}
@@ -45,11 +45,28 @@ export declare const MAX_SNAPSHOTS = 4;
45
45
  export declare class ProjectIndexStore {
46
46
  private readonly stateDir;
47
47
  private readonly fs;
48
+ /**
49
+ * PARALLEL CHECKOUTS SHARE ONE INDEX PER REVISION. A snapshot is a function of
50
+ * (tree sha, package set) and nothing about which checkout built it, so a
51
+ * machine-made checkout reads the PROJECT's copy when it has none of its own,
52
+ * and every save lands there too — N checkouts on one revision build it once.
53
+ * Absent (or the same directory): this checkout's own, as before.
54
+ */
55
+ private readonly shared?;
48
56
  private state;
49
57
  constructor(stateDir: string, fs: LedgerFs & {
50
58
  readDir?: (path: string) => Promise<string[]>;
51
- });
59
+ },
60
+ /**
61
+ * PARALLEL CHECKOUTS SHARE ONE INDEX PER REVISION. A snapshot is a function of
62
+ * (tree sha, package set) and nothing about which checkout built it, so a
63
+ * machine-made checkout reads the PROJECT's copy when it has none of its own,
64
+ * and every save lands there too — N checkouts on one revision build it once.
65
+ * Absent (or the same directory): this checkout's own, as before.
66
+ */
67
+ shared?: string | undefined);
52
68
  private pathFor;
69
+ private sharing;
53
70
  status(): IndexStoreState;
54
71
  /**
55
72
  * The snapshot for a tree, or null.
@@ -84,6 +101,7 @@ export declare class ProjectIndexStore {
84
101
  * nobody compared. The two production callers both pass it.
85
102
  */
86
103
  expectedPackages?: readonly string[]): Promise<ProjectIndexSnapshot | null>;
104
+ private loadAt;
87
105
  /**
88
106
  * Write a snapshot for its own tree.
89
107
  *
@@ -1 +1 @@
1
- {"version":3,"file":"project-index-store.d.ts","sourceRoot":"","sources":["../src/project-index-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,oBAAoB,EAC1B,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,MAAM,MAAM,eAAe,GAAG,IAAI,GAAG,YAAY,CAAC;AAElD;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,IAAI,CAAC;AAE/B,qBAAa,iBAAiB;IAI1B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,EAAE;IAJrB,OAAO,CAAC,KAAK,CAAyB;gBAGnB,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,QAAQ,GAAG;QAAE,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;KAAE;IAGnF,OAAO,CAAC,OAAO;IAIf,MAAM,IAAI,eAAe;IAIzB;;;;;;;;OAQG;IACG,IAAI,CACR,OAAO,EAAE,MAAM;IACf;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,GACnC,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;IA2CvC;;;;;;;OAOG;IACG,IAAI,CAAC,QAAQ,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;CAsB1D"}
1
+ {"version":3,"file":"project-index-store.d.ts","sourceRoot":"","sources":["../src/project-index-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,oBAAoB,EAC1B,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,MAAM,MAAM,eAAe,GAAG,IAAI,GAAG,YAAY,CAAC;AAElD;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,IAAI,CAAC;AAE/B,qBAAa,iBAAiB;IAI1B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,EAAE;IACnB;;;;;;OAMG;IACH,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;IAZ1B,OAAO,CAAC,KAAK,CAAyB;gBAGnB,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,QAAQ,GAAG;QAAE,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;KAAE;IACjF;;;;;;OAMG;IACc,MAAM,CAAC,EAAE,MAAM,YAAA;IAGlC,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,OAAO;IAIf,MAAM,IAAI,eAAe;IAIzB;;;;;;;;OAQG;IACG,IAAI,CACR,OAAO,EAAE,MAAM;IACf;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,GACnC,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;YAQzB,MAAM;IAgDpB;;;;;;;OAOG;IACG,IAAI,CAAC,QAAQ,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;CAkC1D"}
@@ -14,13 +14,26 @@ exports.MAX_SNAPSHOTS = 4;
14
14
  class ProjectIndexStore {
15
15
  stateDir;
16
16
  fs;
17
+ shared;
17
18
  state = 'ok';
18
- constructor(stateDir, fs) {
19
+ constructor(stateDir, fs,
20
+ /**
21
+ * PARALLEL CHECKOUTS SHARE ONE INDEX PER REVISION. A snapshot is a function of
22
+ * (tree sha, package set) and nothing about which checkout built it, so a
23
+ * machine-made checkout reads the PROJECT's copy when it has none of its own,
24
+ * and every save lands there too — N checkouts on one revision build it once.
25
+ * Absent (or the same directory): this checkout's own, as before.
26
+ */
27
+ shared) {
19
28
  this.stateDir = stateDir;
20
29
  this.fs = fs;
30
+ this.shared = shared;
31
+ }
32
+ pathFor(treeSha, dir = this.stateDir) {
33
+ return `${dir}/project-index-${treeSha}.json`;
21
34
  }
22
- pathFor(treeSha) {
23
- return `${this.stateDir}/project-index-${treeSha}.json`;
35
+ sharing() {
36
+ return this.shared !== undefined && this.shared !== this.stateDir ? this.shared : undefined;
24
37
  }
25
38
  status() {
26
39
  return this.state;
@@ -58,12 +71,21 @@ class ProjectIndexStore {
58
71
  * nobody compared. The two production callers both pass it.
59
72
  */
60
73
  expectedPackages) {
74
+ const own = await this.loadAt(this.stateDir, treeSha, expectedPackages);
75
+ const shared = this.sharing();
76
+ if (own !== null || shared === undefined)
77
+ return own;
78
+ // Every check below applies to the shared copy exactly as to this checkout's own.
79
+ return this.loadAt(shared, treeSha, expectedPackages, false);
80
+ }
81
+ async loadAt(dir, treeSha, expectedPackages, mine = true) {
61
82
  let text;
62
83
  try {
63
- text = await this.fs.readFile(this.pathFor(treeSha));
84
+ text = await this.fs.readFile(this.pathFor(treeSha, dir));
64
85
  }
65
86
  catch {
66
- this.state = 'unreadable';
87
+ if (mine)
88
+ this.state = 'unreadable';
67
89
  return null;
68
90
  }
69
91
  if (text === null)
@@ -120,6 +142,19 @@ class ProjectIndexStore {
120
142
  const tmp = `${target}.${process.pid}.tmp`;
121
143
  await this.fs.writeFile(tmp, `${JSON.stringify(snapshot, null, 2)}\n`);
122
144
  await this.fs.rename(tmp, target);
145
+ const shared = this.sharing();
146
+ if (shared !== undefined) {
147
+ try {
148
+ await this.fs.mkdir(shared);
149
+ const there = this.pathFor(snapshot.treeSha, shared);
150
+ const tmpThere = `${there}.${process.pid}.tmp`;
151
+ await this.fs.writeFile(tmpThere, `${JSON.stringify(snapshot, null, 2)}\n`);
152
+ await this.fs.rename(tmpThere, there);
153
+ }
154
+ catch {
155
+ // The shared copy is a convenience for the other checkouts; this one has its own.
156
+ }
157
+ }
123
158
  }
124
159
  }
125
160
  exports.ProjectIndexStore = ProjectIndexStore;
@@ -1 +1 @@
1
- {"version":3,"file":"project-index-store.js","sourceRoot":"","sources":["../src/project-index-store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"project-index-store.js","sourceRoot":"","sources":["../src/project-index-store.ts"],"names":[],"mappings":";;;AAAA,uCAIsB;AAsCtB;;;;;;;GAOG;AACU,QAAA,aAAa,GAAG,CAAC,CAAC;AAE/B,MAAa,iBAAiB;IAIT;IACA;IAQA;IAZX,KAAK,GAAoB,IAAI,CAAC;IAEtC,YACmB,QAAgB,EAChB,EAAgE;IACjF;;;;;;OAMG;IACc,MAAe;QATf,aAAQ,GAAR,QAAQ,CAAQ;QAChB,OAAE,GAAF,EAAE,CAA8D;QAQhE,WAAM,GAAN,MAAM,CAAS;IAC/B,CAAC;IAEI,OAAO,CAAC,OAAe,EAAE,MAAc,IAAI,CAAC,QAAQ;QAC1D,OAAO,GAAG,GAAG,kBAAkB,OAAO,OAAO,CAAC;IAChD,CAAC;IAEO,OAAO;QACb,OAAO,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;IAC9F,CAAC;IAED,MAAM;QACJ,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,IAAI,CACR,OAAe;IACf;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,gBAAoC;QAEpC,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,gBAAgB,CAAC,CAAC;QACxE,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;QAC9B,IAAI,GAAG,KAAK,IAAI,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO,GAAG,CAAC;QACrD,kFAAkF;QAClF,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,gBAAgB,EAAE,KAAK,CAAC,CAAC;IAC/D,CAAC;IAEO,KAAK,CAAC,MAAM,CAClB,GAAW,EACX,OAAe,EACf,gBAA+C,EAC/C,IAAI,GAAG,IAAI;QAEX,IAAI,IAAmB,CAAC;QACxB,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;QAC5D,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,IAAI;gBAAE,IAAI,CAAC,KAAK,GAAG,YAAY,CAAC;YACpC,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,IAAI,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QAE/B,IAAI,MAAe,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC;QAAC,MAAM,CAAC;YACP,yEAAyE;YACzE,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;YAAE,OAAO,IAAI,CAAC;QACrC,IAAI,MAAM,CAAC,MAAM,KAAK,2BAAoB;YAAE,OAAO,IAAI,CAAC;QACxD;;;;;;WAMG;QACH,IAAI,MAAM,CAAC,SAAS,KAAK,8BAAuB;YAAE,OAAO,IAAI,CAAC;QAC9D,2DAA2D;QAC3D,IAAI,MAAM,CAAC,OAAO,KAAK,OAAO;YAAE,OAAO,IAAI,CAAC;QAC5C;;;;;WAKG;QACH,IAAI,gBAAgB,KAAK,SAAS,EAAE,CAAC;YACnC,MAAM,IAAI,GAAG,CAAC,GAAG,gBAAgB,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;YACvE,MAAM,IAAI,GAAG,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;YACtE,IAAI,IAAI,KAAK,IAAI;gBAAE,OAAO,IAAI,CAAC;QACjC,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,IAAI,CAAC,QAA8B;QACvC,MAAM,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACnC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC9C,MAAM,GAAG,GAAG,GAAG,MAAM,IAAI,OAAO,CAAC,GAAG,MAAM,CAAC;QAC3C,MAAM,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;QACvE,MAAM,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAClC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;QAC9B,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;gBAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;gBACrD,MAAM,QAAQ,GAAG,GAAG,KAAK,IAAI,OAAO,CAAC,GAAG,MAAM,CAAC;gBAC/C,MAAM,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;gBAC5E,MAAM,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YACxC,CAAC;YAAC,MAAM,CAAC;gBACP,kFAAkF;YACpF,CAAC;QACH,CAAC;IACH,CAAC;CAgBF;AAhKD,8CAgKC;AAED,SAAS,UAAU,CAAC,CAAU;IAC5B,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IACtD,MAAM,CAAC,GAAG,CAA4B,CAAC;IACvC,OAAO,CACL,OAAO,CAAC,CAAC,QAAQ,CAAC,KAAK,QAAQ;QAC/B,oEAAoE;QACpE,4CAA4C;QAC5C,OAAO,CAAC,CAAC,WAAW,CAAC,KAAK,QAAQ;QAClC,OAAO,CAAC,CAAC,SAAS,CAAC,KAAK,QAAQ;QAChC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAC3B,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAC3B,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAC7B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,25 @@
1
+ import { type GoalAutonomyState, type PursuitEndCode } from '@looply/core';
2
+ import type { AutonomyProgress } from './autonomy-store';
3
+ import type { RunDelivery } from './run-refusal-marks';
4
+ import type { ServerClient } from './server-client';
5
+ /**
6
+ * TELL THE SERVER WHERE A PURSUIT CAME TO REST — AND WHY.
7
+ *
8
+ * The daemon's `projectTerminal`, lifted out of `daemon-cmd` so what it sends
9
+ * can be tested without a daemon. The state alone used to reach the server with
10
+ * a sentence that restated it ("this pursuit ended as human_required"), and a
11
+ * customer's ticket then said exactly that. What goes now is the sentence the
12
+ * tick wrote when the pursuit ended — scrubbed and bounded before it leaves the
13
+ * machine, because it is shown on a ticket and can quote a launcher's or a
14
+ * run's own words — and the code it came from.
15
+ */
16
+ export declare function makeProjectTerminal(deps: {
17
+ client: Pick<ServerClient, 'goalAutonomy' | 'settleGoalAutonomy'>;
18
+ projectId: string;
19
+ /** L4b: what key 2 confirmed for this pursuit, when the run wrote it. */
20
+ deliveryFor: (controllerId: string) => Promise<RunDelivery | null>;
21
+ }): (grant: AutonomyProgress, state: GoalAutonomyState, because: string, code?: PursuitEndCode) => Promise<{
22
+ ok: boolean;
23
+ because?: string;
24
+ }>;
25
+ //# sourceMappingURL=project-terminal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-terminal.d.ts","sourceRoot":"","sources":["../src/project-terminal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,KAAK,iBAAiB,EAAE,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAClG,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpD;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE;IACxC,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE,cAAc,GAAG,oBAAoB,CAAC,CAAC;IAClE,SAAS,EAAE,MAAM,CAAC;IAClB,yEAAyE;IACzE,WAAW,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;CACpE,GAAG,CACF,KAAK,EAAE,gBAAgB,EACvB,KAAK,EAAE,iBAAiB,EACxB,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,cAAc,KAClB,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAyB9C"}
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.makeProjectTerminal = makeProjectTerminal;
4
+ const core_1 = require("@looply/core");
5
+ const grant_reconcile_1 = require("./grant-reconcile");
6
+ /**
7
+ * TELL THE SERVER WHERE A PURSUIT CAME TO REST — AND WHY.
8
+ *
9
+ * The daemon's `projectTerminal`, lifted out of `daemon-cmd` so what it sends
10
+ * can be tested without a daemon. The state alone used to reach the server with
11
+ * a sentence that restated it ("this pursuit ended as human_required"), and a
12
+ * customer's ticket then said exactly that. What goes now is the sentence the
13
+ * tick wrote when the pursuit ended — scrubbed and bounded before it leaves the
14
+ * machine, because it is shown on a ticket and can quote a launcher's or a
15
+ * run's own words — and the code it came from.
16
+ */
17
+ function makeProjectTerminal(deps) {
18
+ return async (grant, state, because, code) => {
19
+ const settlable = (0, grant_reconcile_1.settlableState)(state);
20
+ // Nothing to report. `cancelled` is the case: a person's word, which
21
+ // this machine may observe and stop on but may not write.
22
+ if (settlable === null)
23
+ return { ok: true };
24
+ try {
25
+ const { autonomy } = await deps.client.goalAutonomy(deps.projectId, grant.goalId);
26
+ const mine = autonomy.find((a) => a.controllerId === grant.controllerId);
27
+ if (!mine)
28
+ return { ok: false, because: 'the server has no record of this grant' };
29
+ // L4b: a met goal is settled WITH what key 2 confirmed, when the run wrote it.
30
+ const delivery = settlable === 'satisfied' ? await deps.deliveryFor(grant.controllerId) : null;
31
+ const reason = (0, core_1.cleanPursuitEndReason)(because);
32
+ await deps.client.settleGoalAutonomy(deps.projectId, grant.controllerId, {
33
+ version: mine.version,
34
+ state: settlable,
35
+ ...(reason === '' ? {} : { reason }),
36
+ ...(code === undefined ? {} : { endCode: code }),
37
+ ...(delivery === null ? {} : { delivery }),
38
+ });
39
+ return { ok: true };
40
+ }
41
+ catch (e) {
42
+ return { ok: false, because: e.message };
43
+ }
44
+ };
45
+ }
46
+ //# sourceMappingURL=project-terminal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-terminal.js","sourceRoot":"","sources":["../src/project-terminal.ts"],"names":[],"mappings":";;AAiBA,kDAmCC;AApDD,uCAAkG;AAElG,uDAAmD;AAInD;;;;;;;;;;GAUG;AACH,SAAgB,mBAAmB,CAAC,IAKnC;IAMC,OAAO,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;QAC3C,MAAM,SAAS,GAAG,IAAA,gCAAc,EAAC,KAAK,CAAC,CAAC;QACxC,qEAAqE;QACrE,0DAA0D;QAC1D,IAAI,SAAS,KAAK,IAAI;YAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;QAC5C,IAAI,CAAC;YACH,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;YAClF,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,KAAK,KAAK,CAAC,YAAY,CAAC,CAAC;YACzE,IAAI,CAAC,IAAI;gBAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,wCAAwC,EAAE,CAAC;YACnF,+EAA+E;YAC/E,MAAM,QAAQ,GAAG,SAAS,KAAK,WAAW,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAC/F,MAAM,MAAM,GAAG,IAAA,4BAAqB,EAAC,OAAO,CAAC,CAAC;YAC9C,MAAM,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,YAAY,EAAE;gBACvE,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,KAAK,EAAE,SAAS;gBAChB,GAAG,CAAC,MAAM,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC;gBACpC,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;gBAChD,GAAG,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC;aAC3C,CAAC,CAAC;YACH,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;QACtB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAG,CAAW,CAAC,OAAO,EAAE,CAAC;QACtD,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,57 @@
1
+ import { type GoalAutonomyState, type PursuitEndCode } from '@looply/core';
2
+ /**
3
+ * WHY A PURSUIT ENDED, SAID TO A PERSON WHO IS NOT A DEVELOPER.
4
+ *
5
+ * The controller decides THAT a pursuit is over and which branch ended it (the
6
+ * `end` code on its terminal action). What it hands over is a sentence for a
7
+ * log — "Start 1 was attempted 3 times and never began" — and until this file
8
+ * the server, and through it a customer's ticket, got even less: "this pursuit
9
+ * ended as human_required". A ticket that says it needs a person must say WHY,
10
+ * plainly, and what was tried.
11
+ *
12
+ * So this turns the code, the controller's own sentence and whatever else this
13
+ * machine remembers (what the launcher said, what the last run said on its way
14
+ * out, whether the safety brake or the AI tool was holding it) into one plain
15
+ * paragraph. It decides nothing: every input is already a conclusion.
16
+ *
17
+ * The words a run or a launcher said are QUOTED, never interpreted — except the
18
+ * two compile notes below, which are this repository's own fixed phrases
19
+ * (exported so `run-cmd` writes exactly what is matched here).
20
+ */
21
+ /** What `run-cmd` notes when the planner produced no steps at all. */
22
+ export declare const COMPILE_EMPTY_NOTE = "compile: the plan came back empty";
23
+ /** The start of what `run-cmd` notes when every planned step was refused. */
24
+ export declare const COMPILE_REFUSED_NOTE = "compile: every step was refused";
25
+ /** Everything known about the ending, beside the controller's own words. */
26
+ export interface EndingContext {
27
+ /** The state the pursuit ends in. */
28
+ state: GoalAutonomyState;
29
+ /** Which branch ended it, from the controller. */
30
+ end: PursuitEndCode;
31
+ /** The controller's own sentence. */
32
+ because: string;
33
+ /** This machine's name, as a person would recognise it. */
34
+ machine: string;
35
+ /** How many Starts the grant allowed. */
36
+ maxStarts: number;
37
+ /** For a Start that never began: how many tries were spent. */
38
+ attempts?: number;
39
+ /** The run's own refusal, verbatim, when the ending is a refusal. */
40
+ refusal?: string;
41
+ /** What the last finished Start said on its way out. */
42
+ lastRunNote?: string;
43
+ /** Why the last try to start a Start did not, when the launcher said. */
44
+ lastLaunchNote?: string;
45
+ /** The safety brake's reason, when it was holding the pursuit. */
46
+ safetyBrake?: string;
47
+ /** Why the AI tool was not ready, when it was not. */
48
+ providerNotReady?: string;
49
+ }
50
+ export interface PursuitEnding {
51
+ code: PursuitEndCode;
52
+ /** One plain paragraph, at most `PURSUIT_END_REASON_MAX` characters, scrubbed. */
53
+ because: string;
54
+ }
55
+ /** The sentence and code for an ending. Pure. */
56
+ export declare function describePursuitEnding(ctx: EndingContext): PursuitEnding;
57
+ //# sourceMappingURL=pursuit-ending.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pursuit-ending.d.ts","sourceRoot":"","sources":["../src/pursuit-ending.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,KAAK,iBAAiB,EAAE,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAElG;;;;;;;;;;;;;;;;;;GAkBG;AAEH,sEAAsE;AACtE,eAAO,MAAM,kBAAkB,sCAAsC,CAAC;AACtE,6EAA6E;AAC7E,eAAO,MAAM,oBAAoB,oCAAoC,CAAC;AAEtE,4EAA4E;AAC5E,MAAM,WAAW,aAAa;IAC5B,qCAAqC;IACrC,KAAK,EAAE,iBAAiB,CAAC;IACzB,kDAAkD;IAClD,GAAG,EAAE,cAAc,CAAC;IACpB,qCAAqC;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,2DAA2D;IAC3D,OAAO,EAAE,MAAM,CAAC;IAChB,yCAAyC;IACzC,SAAS,EAAE,MAAM,CAAC;IAClB,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wDAAwD;IACxD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yEAAyE;IACzE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kEAAkE;IAClE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sDAAsD;IACtD,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,cAAc,CAAC;IACrB,kFAAkF;IAClF,OAAO,EAAE,MAAM,CAAC;CACjB;AA8BD,iDAAiD;AACjD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,aAAa,GAAG,aAAa,CAsFvE"}
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.COMPILE_REFUSED_NOTE = exports.COMPILE_EMPTY_NOTE = void 0;
4
+ exports.describePursuitEnding = describePursuitEnding;
5
+ const core_1 = require("@looply/core");
6
+ /**
7
+ * WHY A PURSUIT ENDED, SAID TO A PERSON WHO IS NOT A DEVELOPER.
8
+ *
9
+ * The controller decides THAT a pursuit is over and which branch ended it (the
10
+ * `end` code on its terminal action). What it hands over is a sentence for a
11
+ * log — "Start 1 was attempted 3 times and never began" — and until this file
12
+ * the server, and through it a customer's ticket, got even less: "this pursuit
13
+ * ended as human_required". A ticket that says it needs a person must say WHY,
14
+ * plainly, and what was tried.
15
+ *
16
+ * So this turns the code, the controller's own sentence and whatever else this
17
+ * machine remembers (what the launcher said, what the last run said on its way
18
+ * out, whether the safety brake or the AI tool was holding it) into one plain
19
+ * paragraph. It decides nothing: every input is already a conclusion.
20
+ *
21
+ * The words a run or a launcher said are QUOTED, never interpreted — except the
22
+ * two compile notes below, which are this repository's own fixed phrases
23
+ * (exported so `run-cmd` writes exactly what is matched here).
24
+ */
25
+ /** What `run-cmd` notes when the planner produced no steps at all. */
26
+ exports.COMPILE_EMPTY_NOTE = 'compile: the plan came back empty';
27
+ /** The start of what `run-cmd` notes when every planned step was refused. */
28
+ exports.COMPILE_REFUSED_NOTE = 'compile: every step was refused';
29
+ /** A quoted fragment: one line, scrubbed, short enough to leave room for the advice. */
30
+ function quote(text, max = 220) {
31
+ let s = (0, core_1.cleanPursuitEndReason)(text).replace(/[.\s]+$/, '');
32
+ if (s.length > max)
33
+ s = `${s.slice(0, max - 1).trimEnd()}…`;
34
+ return s;
35
+ }
36
+ const EMPTY_PLAN_ADVICE = 'the planner found nothing to change. If this ticket asks for a change, say plainly what should happen ' +
37
+ '(for example: "the Save button should show a confirmation message"), then start it again.';
38
+ /** What the last run's note says about the plan, when it is one of the two compile notes. */
39
+ function planTrouble(note) {
40
+ if (note === undefined || note === '')
41
+ return null;
42
+ if (note.includes(exports.COMPILE_EMPTY_NOTE))
43
+ return { code: 'plan_empty', sentence: EMPTY_PLAN_ADVICE };
44
+ if (note.includes(exports.COMPILE_REFUSED_NOTE)) {
45
+ const n = /(\d+) step\(s\)/.exec(note)?.[1];
46
+ return {
47
+ code: 'plan_refused',
48
+ sentence: `every step of its plan${n === undefined ? '' : ` (${n} step${n === '1' ? '' : 's'})`} was refused because it ` +
49
+ 'pointed at code that does not exist in this repository as it is now. Describe the change in more detail ' +
50
+ '(which screen or file, what should happen), or check the right repository is connected, then start it again.',
51
+ };
52
+ }
53
+ return null;
54
+ }
55
+ /** The sentence and code for an ending. Pure. */
56
+ function describePursuitEnding(ctx) {
57
+ const out = (code, because) => ({
58
+ code,
59
+ because: (0, core_1.cleanPursuitEndReason)(because),
60
+ });
61
+ const refusal = ctx.refusal === undefined || ctx.refusal === '' ? null : quote(ctx.refusal);
62
+ switch (ctx.end) {
63
+ case 'start_never_began': {
64
+ const n = ctx.attempts ?? 3;
65
+ const why = ctx.lastLaunchNote === undefined || ctx.lastLaunchNote === ''
66
+ ? 'each try was launched but never reported that it had begun'
67
+ : quote(ctx.lastLaunchNote);
68
+ return out('start_never_began', `Looply tried to start this ${n} time${n === 1 ? '' : 's'} on ${ctx.machine} and it never began: ${why}. ` +
69
+ `Someone needs to check that ${ctx.machine} can run Looply (the app is up to date and its AI tool is installed and signed in), then start it again.`);
70
+ }
71
+ case 'plan_limit_reached':
72
+ return out('plan_limit_reached', 'Looply re-planned this goal as many times as it is allowed and it is still not done, so it stopped rather than plan again' +
73
+ (refusal === null ? '. ' : ` (its last check: ${refusal}). `) +
74
+ 'Someone needs to look at what was delivered and say what is still missing.');
75
+ case 'needs_decision':
76
+ return out('needs_decision', `Looply needs a person to decide something before it can go on${refusal === null ? '.' : `: ${refusal}.`}`);
77
+ case 'requirement_uncovered':
78
+ return out('requirement_uncovered', 'The work was delivered, but a required part of this goal is not covered' +
79
+ (refusal === null ? '. ' : `: ${refusal}. `) +
80
+ 'Someone needs to either ask for the missing part or confirm that what is there is enough.');
81
+ case 'repository_changed':
82
+ return out('repository_changed', `The code on ${ctx.machine} changed while Looply was checking the work, so it stopped to be safe. ` +
83
+ 'Someone needs to make sure nobody else is editing that copy of the repository, then start it again.');
84
+ case 'run_refused':
85
+ return out('run_refused', `Looply stopped without the goal being met${refusal === null ? '' : `: ${refusal}`}. Someone needs to look at it and say what should happen next.`);
86
+ case 'records_damaged':
87
+ return out('records_damaged', `Looply's own record of what it has spent on this goal on ${ctx.machine} is damaged, so it stopped rather than guess ` +
88
+ `(${quote(ctx.because, 160)}). Someone needs to check that machine before starting it again.`);
89
+ case 'grant_mismatch':
90
+ return out('grant_mismatch', `The goal no longer matches what ${ctx.machine} was asked to work on (${quote(ctx.because, 160)}). ` +
91
+ 'Someone needs to check the goal and start it again.');
92
+ case 'out_of_time':
93
+ case 'budget_exhausted':
94
+ return exhausted(ctx, out);
95
+ case 'goal_met':
96
+ return out('goal_met', refusal === null ? 'The goal was met.' : `The goal was met: ${refusal}.`);
97
+ case 'superseded':
98
+ return out('superseded', 'The goal was changed, so this pursuit of the earlier wording stopped.');
99
+ case 'abandoned':
100
+ return out('abandoned', 'The goal was given up.');
101
+ case 'cancelled':
102
+ return out('cancelled', 'A person stopped this.');
103
+ default:
104
+ return out(ctx.end, ctx.because);
105
+ }
106
+ }
107
+ /** Ran out of Starts or of time: say what was holding it, or what the last try said. */
108
+ function exhausted(ctx, out) {
109
+ const head = ctx.end === 'out_of_time'
110
+ ? 'The time given for this goal ran out before it was done'
111
+ : `Looply used all ${ctx.maxStarts} of its tries on this goal and it is still not done`;
112
+ if (ctx.providerNotReady !== undefined && ctx.providerNotReady !== '') {
113
+ return out('provider_not_ready', `${head}: the AI tool on ${ctx.machine} was not ready, so no work could start (${quote(ctx.providerNotReady)}). ` +
114
+ `Someone needs to fix that on ${ctx.machine}, then start it again.`);
115
+ }
116
+ if (ctx.safetyBrake !== undefined && ctx.safetyBrake !== '') {
117
+ return out('safety_brake', `${head}: Looply's safety brake had stopped it repeating something that was not working (${quote(ctx.safetyBrake)}). ` +
118
+ 'Someone needs to look at what it was stuck on before starting it again.');
119
+ }
120
+ const plan = planTrouble(ctx.lastRunNote);
121
+ if (plan !== null)
122
+ return out(plan.code, `${head}: ${plan.sentence}`);
123
+ if (ctx.lastRunNote !== undefined && ctx.lastRunNote !== '') {
124
+ return out('repeated_failure', `${head}. Its last try ended: ${quote(ctx.lastRunNote)}. Someone needs to look at that before starting it again.`);
125
+ }
126
+ return out(ctx.end, `${head}. Someone needs to look at what was done and decide whether to start it again.`);
127
+ }
128
+ //# sourceMappingURL=pursuit-ending.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pursuit-ending.js","sourceRoot":"","sources":["../src/pursuit-ending.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,84 @@
1
+ import type { LaneClaimRecord } from './lane-claims';
2
+ /**
3
+ * WHERE A RUN IN A MACHINE-MADE CHECKOUT IS CUT FROM.
4
+ *
5
+ * ─────────────────────────────────────────────────────────────────────────────
6
+ * Without this a run's branch is cut from wherever HEAD is, and in a checkout
7
+ * the machine reuses HEAD is the PREVIOUS run's branch — so ticket N+1 stacked
8
+ * on ticket N, and nothing could be reviewed on its own. Now, in a checkout the
9
+ * machine made (never the person's own checkout), a run is cut from:
10
+ *
11
+ * 1. HEAD, when this checkout's last cut was for THE SAME GOAL — a goal's
12
+ * later Starts continue its own work (the coordinator keeps a goal's plan
13
+ * checkout for it, F28), and the goal-gap / "looks done" checks read this
14
+ * checkout, so they judge that goal's own tree;
15
+ * 1b. the goal's OWN recorded work (its newest delivered commit, else the branch
16
+ * its run claimed) when it lands in a different checkout — a retired home;
17
+ * 2. the delivered tip of the goal it depends on, when it depends on exactly
18
+ * ONE goal — B builds on A's work, not on a base that lacks it;
19
+ * 3. the project's base branch otherwise (`run.base_branch`, else the
20
+ * repository's default branch) — so independent tickets never stack;
21
+ * 4. HEAD as before, said out loud, when no base can be found.
22
+ *
23
+ * ⚠️ THE MARKER IS PER CHECKOUT (`checkout-goal.json` in its own state dir),
24
+ * written at the cut, and it is the only memory this needs: which goal this
25
+ * tree's HEAD belongs to.
26
+ */
27
+ export declare const CHECKOUT_GOAL_MARKER = "checkout-goal.json";
28
+ export interface CheckoutGoal {
29
+ readonly goalId: string | null;
30
+ readonly branch: string;
31
+ readonly at: string;
32
+ }
33
+ export declare function readCheckoutGoal(stateDir: string): CheckoutGoal | null;
34
+ export declare function writeCheckoutGoal(stateDir: string, marker: CheckoutGoal): void;
35
+ /** The slice of git this needs; every verb is a read. */
36
+ export interface BaseGit {
37
+ remoteHeadBranch(): Promise<string | null>;
38
+ refExists(ref: string): Promise<boolean>;
39
+ isAncestor(ancestor: string, of: string): Promise<boolean>;
40
+ listWorktrees(): Promise<Array<{
41
+ path: string;
42
+ head: string;
43
+ branch: string | null;
44
+ }>>;
45
+ }
46
+ /**
47
+ * The project's base branch: `configured` when it names a ref that exists; else
48
+ * the remote's default branch (`origin/HEAD`) — as the LOCAL branch of that name
49
+ * unless the remote one is strictly newer; else the branch the main checkout is
50
+ * on (unless that is one of looply's own). Null when none can be found.
51
+ */
52
+ export declare function resolveBaseBranch(git: BaseGit, configured?: string): Promise<{
53
+ readonly ref: string;
54
+ readonly because: string;
55
+ } | null>;
56
+ export type CutPoint = {
57
+ readonly kind: 'continue';
58
+ readonly because: string;
59
+ } | {
60
+ readonly kind: 'dependency';
61
+ readonly ref: string;
62
+ readonly because: string;
63
+ } | {
64
+ readonly kind: 'base';
65
+ readonly ref: string;
66
+ readonly because: string;
67
+ } | {
68
+ readonly kind: 'head';
69
+ readonly because: string;
70
+ };
71
+ export interface CutInput {
72
+ /** The goal this run is bound to, if any. */
73
+ readonly goalId?: string;
74
+ /** That goal's dependencies, as the mirror holds them. */
75
+ readonly dependsOn?: readonly string[];
76
+ /** Which goal this checkout's HEAD belongs to (`readCheckoutGoal`). */
77
+ readonly checkout: CheckoutGoal | null;
78
+ /** The machine's lane-claim records (`readLaneClaims`). */
79
+ readonly claims: readonly LaneClaimRecord[];
80
+ readonly configuredBase?: string;
81
+ }
82
+ /** Decide where this run's branch starts. Never throws: an unreadable answer degrades to HEAD, said. */
83
+ export declare function cutPointFor(git: BaseGit, input: CutInput): Promise<CutPoint>;
84
+ //# sourceMappingURL=run-base.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-base.d.ts","sourceRoot":"","sources":["../src/run-base.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,eAAO,MAAM,oBAAoB,uBAAuB,CAAC;AAEzD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAQtE;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,IAAI,CAM9E;AAED,yDAAyD;AACzD,MAAM,WAAW,OAAO;IACtB,gBAAgB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC3C,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACzC,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3D,aAAa,IAAI,OAAO,CAAC,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC,CAAC;CACxF;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,OAAO,EACZ,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC;IAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CA6BpE;AAED,MAAM,MAAM,QAAQ,GAChB;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACvD;IAAE,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC/E;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACzE;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAExD,MAAM,WAAW,QAAQ;IACvB,6CAA6C;IAC7C,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,0DAA0D;IAC1D,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,uEAAuE;IACvE,QAAQ,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAC;IACvC,2DAA2D;IAC3D,QAAQ,CAAC,MAAM,EAAE,SAAS,eAAe,EAAE,CAAC;IAC5C,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;CAClC;AAED,wGAAwG;AACxG,wBAAsB,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CA6BlF"}