looply-cli 0.5.4 → 0.5.6

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 (110) 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 +2 -0
  18. package/dist/checkout-carry.d.ts.map +1 -1
  19. package/dist/checkout-carry.js +37 -2
  20. package/dist/checkout-carry.js.map +1 -1
  21. package/dist/config.d.ts +41 -0
  22. package/dist/config.d.ts.map +1 -1
  23. package/dist/config.js +40 -7
  24. package/dist/config.js.map +1 -1
  25. package/dist/coordinator-state.d.ts +14 -0
  26. package/dist/coordinator-state.d.ts.map +1 -1
  27. package/dist/coordinator-state.js +29 -0
  28. package/dist/coordinator-state.js.map +1 -1
  29. package/dist/daemon-cmd.d.ts +1 -1
  30. package/dist/daemon-cmd.d.ts.map +1 -1
  31. package/dist/daemon-cmd.js +56 -33
  32. package/dist/daemon-cmd.js.map +1 -1
  33. package/dist/git-driver.d.ts +6 -0
  34. package/dist/git-driver.d.ts.map +1 -1
  35. package/dist/git-driver.js +12 -0
  36. package/dist/git-driver.js.map +1 -1
  37. package/dist/goal-adaptive.d.ts +12 -0
  38. package/dist/goal-adaptive.d.ts.map +1 -1
  39. package/dist/goal-adaptive.js +19 -4
  40. package/dist/goal-adaptive.js.map +1 -1
  41. package/dist/goal-compile.d.ts +7 -0
  42. package/dist/goal-compile.d.ts.map +1 -1
  43. package/dist/goal-compile.js +3 -0
  44. package/dist/goal-compile.js.map +1 -1
  45. package/dist/goal-execution-evidence.d.ts +28 -2
  46. package/dist/goal-execution-evidence.d.ts.map +1 -1
  47. package/dist/goal-execution-evidence.js +30 -5
  48. package/dist/goal-execution-evidence.js.map +1 -1
  49. package/dist/goal-reproof.d.ts +42 -0
  50. package/dist/goal-reproof.d.ts.map +1 -0
  51. package/dist/goal-reproof.js +35 -0
  52. package/dist/goal-reproof.js.map +1 -0
  53. package/dist/index-for-head.js +1 -1
  54. package/dist/index-for-head.js.map +1 -1
  55. package/dist/machine-run-slots.d.ts +59 -0
  56. package/dist/machine-run-slots.d.ts.map +1 -0
  57. package/dist/machine-run-slots.js +140 -0
  58. package/dist/machine-run-slots.js.map +1 -0
  59. package/dist/plan-recovery.d.ts +70 -0
  60. package/dist/plan-recovery.d.ts.map +1 -0
  61. package/dist/plan-recovery.js +131 -0
  62. package/dist/plan-recovery.js.map +1 -0
  63. package/dist/programme-mode.d.ts +6 -0
  64. package/dist/programme-mode.d.ts.map +1 -1
  65. package/dist/programme-mode.js +23 -0
  66. package/dist/programme-mode.js.map +1 -1
  67. package/dist/project-index-store.d.ts +19 -1
  68. package/dist/project-index-store.d.ts.map +1 -1
  69. package/dist/project-index-store.js +40 -5
  70. package/dist/project-index-store.js.map +1 -1
  71. package/dist/project-terminal.d.ts +25 -0
  72. package/dist/project-terminal.d.ts.map +1 -0
  73. package/dist/project-terminal.js +46 -0
  74. package/dist/project-terminal.js.map +1 -0
  75. package/dist/pursuit-ending.d.ts +57 -0
  76. package/dist/pursuit-ending.d.ts.map +1 -0
  77. package/dist/pursuit-ending.js +128 -0
  78. package/dist/pursuit-ending.js.map +1 -0
  79. package/dist/run-base.d.ts +84 -0
  80. package/dist/run-base.d.ts.map +1 -0
  81. package/dist/run-base.js +142 -0
  82. package/dist/run-base.js.map +1 -0
  83. package/dist/run-cmd.d.ts.map +1 -1
  84. package/dist/run-cmd.js +110 -14
  85. package/dist/run-cmd.js.map +1 -1
  86. package/dist/run-ended.d.ts +16 -0
  87. package/dist/run-ended.d.ts.map +1 -1
  88. package/dist/run-ended.js +30 -0
  89. package/dist/run-ended.js.map +1 -1
  90. package/dist/run-ending-locator.d.ts +10 -0
  91. package/dist/run-ending-locator.d.ts.map +1 -1
  92. package/dist/run-ending-locator.js +45 -0
  93. package/dist/run-ending-locator.js.map +1 -1
  94. package/dist/run-launcher.d.ts +17 -1
  95. package/dist/run-launcher.d.ts.map +1 -1
  96. package/dist/run-launcher.js +36 -5
  97. package/dist/run-launcher.js.map +1 -1
  98. package/dist/server-client.d.ts +5 -1
  99. package/dist/server-client.d.ts.map +1 -1
  100. package/dist/server-client.js +1 -0
  101. package/dist/server-client.js.map +1 -1
  102. package/dist/setup.d.ts.map +1 -1
  103. package/dist/setup.js +17 -0
  104. package/dist/setup.js.map +1 -1
  105. package/dist/workspace-provisioner.d.ts +2 -0
  106. package/dist/workspace-provisioner.d.ts.map +1 -1
  107. package/dist/workspace-provisioner.js +27 -1
  108. package/dist/workspace-provisioner.js.map +1 -1
  109. package/package.json +54 -54
  110. package/win/HandleProbe.cs +116 -116
@@ -1,4 +1,4 @@
1
- import { type Item, type RunScope } from '@looply/core';
1
+ import { type GateStepResult, type Item, type RunScope } from '@looply/core';
2
2
  import type { RoundRecord } from './round-records';
3
3
  /**
4
4
  * KEY 2 — THE HALF OF "THIS GOAL IS MET" THAT CANNOT BE TALKED INTO AN ANSWER.
@@ -96,6 +96,24 @@ export interface GoalExecutionInput {
96
96
  * a person's own `git commit` can never qualify.
97
97
  */
98
98
  countManualWork?: boolean;
99
+ /**
100
+ * THE GATES, RUN AGAIN AT THE CURRENT HEAD, when the tree moved on since this
101
+ * plan was delivered (`goal-reproof.ts`).
102
+ *
103
+ * 🔴 WHY: TAB-B-57, 63 and 64 (2026-10-15) delivered every step of their plans,
104
+ * and the next Start found another ticket's run had moved this checkout's HEAD
105
+ * in between — stacked on top of their own commits. KEY 2 answered "the code
106
+ * has moved on … what is here now was never checked", which was TRUE, and the
107
+ * goal went back to a person for it. The honest repair is not to relax (2)
108
+ * above but to do the checking: run every required step at the tree that is
109
+ * here now. Accepted only when a committed round of this plan is CONTAINED in
110
+ * that tree (`contains`: the plan's committed shas that are ancestors of HEAD),
111
+ * so a re-proof can never vouch for a tree that lacks the work.
112
+ */
113
+ rechecked?: {
114
+ readonly contains: ReadonlySet<string>;
115
+ readonly steps: readonly GateStepResult[];
116
+ };
99
117
  }
100
118
  export type GoalExecutionOutcome = {
101
119
  ok: true;
@@ -116,11 +134,19 @@ export type GoalExecutionOutcome = {
116
134
  * gate record is the only one that can speak for it.
117
135
  */
118
136
  delivered: readonly string[];
119
- } | {
137
+ /** Set when the answer rests on a re-proof at HEAD: the steps that ran there, which speak for this tree. */
138
+ reproved?: readonly GateStepResult[];
139
+ }
140
+ /** `moved`: the only refusal a re-proof at the current tree can answer (see `rechecked`). */
141
+ | {
120
142
  ok: false;
121
143
  because: string;
144
+ moved?: true;
122
145
  };
146
+ export declare const CODE_MOVED_ON = "the code has moved on since this plan was delivered, so what is here now was never checked";
123
147
  export declare function confirmGoalExecutionEvidence(input: GoalExecutionInput): GoalExecutionOutcome;
148
+ /** The commits this plan's delivered work made — what a re-proof asks git about (`rechecked.contains`). */
149
+ export declare function committedShasOf(input: Pick<GoalExecutionInput, 'scope' | 'items' | 'rounds' | 'countManualWork'>): string[];
124
150
  /** A committed round, as a goal-met Start locates it: its commit and the run that made it. */
125
151
  export interface DeliveredTip {
126
152
  readonly sha: string;
@@ -1 +1 @@
1
- {"version":3,"file":"goal-execution-evidence.d.ts","sourceRoot":"","sources":["../src/goal-execution-evidence.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,IAAI,EAAE,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAC;AAErF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmEG;AAEH,MAAM,WAAW,kBAAkB;IACjC;;;;;;;;;OASG;IACH,KAAK,EAAE,QAAQ,CAAC;IAChB,KAAK,EAAE,SAAS,IAAI,EAAE,CAAC;IACvB,MAAM,EAAE,SAAS,WAAW,EAAE,CAAC;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,0EAA0E;IAC1E,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC;;;;;;;;;OASG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,MAAM,oBAAoB,GAC5B;IACE,EAAE,EAAE,IAAI,CAAC;IACT,KAAK,EAAE,WAAW,CAAC;IACnB;;;;;;;;;;;;;;OAcG;IACH,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9B,GACD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnC,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,kBAAkB,GAAG,oBAAoB,CAuG5F;AA8CD,8FAA8F;AAC9F,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,IAAI,CAAC,kBAAkB,EAAE,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,iBAAiB,CAAC,GAChF,YAAY,GAAG,IAAI,CAOrB"}
1
+ {"version":3,"file":"goal-execution-evidence.d.ts","sourceRoot":"","sources":["../src/goal-execution-evidence.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,cAAc,EAAE,KAAK,IAAI,EAAE,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAC;AAE1G,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmEG;AAEH,MAAM,WAAW,kBAAkB;IACjC;;;;;;;;;OASG;IACH,KAAK,EAAE,QAAQ,CAAC;IAChB,KAAK,EAAE,SAAS,IAAI,EAAE,CAAC;IACvB,MAAM,EAAE,SAAS,WAAW,EAAE,CAAC;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,0EAA0E;IAC1E,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC;;;;;;;;;OASG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;;;;;;;;;;OAaG;IACH,SAAS,CAAC,EAAE;QACV,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;QACvC,QAAQ,CAAC,KAAK,EAAE,SAAS,cAAc,EAAE,CAAC;KAC3C,CAAC;CACH;AAED,MAAM,MAAM,oBAAoB,GAC5B;IACE,EAAE,EAAE,IAAI,CAAC;IACT,KAAK,EAAE,WAAW,CAAC;IACnB;;;;;;;;;;;;;;OAcG;IACH,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7B,4GAA4G;IAC5G,QAAQ,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;CACtC;AACH,6FAA6F;GAC3F;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,IAAI,CAAA;CAAE,CAAC;AAEjD,eAAO,MAAM,aAAa,+FACoE,CAAC;AAE/F,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,kBAAkB,GAAG,oBAAoB,CAkH5F;AA8CD,2GAA2G;AAC3G,wBAAgB,eAAe,CAAC,KAAK,EAAE,IAAI,CAAC,kBAAkB,EAAE,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,iBAAiB,CAAC,GAAG,MAAM,EAAE,CAM3H;AAED,8FAA8F;AAC9F,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,IAAI,CAAC,kBAAkB,EAAE,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,iBAAiB,CAAC,GAChF,YAAY,GAAG,IAAI,CAOrB"}
@@ -1,9 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CODE_MOVED_ON = void 0;
3
4
  exports.confirmGoalExecutionEvidence = confirmGoalExecutionEvidence;
5
+ exports.committedShasOf = committedShasOf;
4
6
  exports.deliveredTipOf = deliveredTipOf;
5
7
  const core_1 = require("@looply/core");
6
8
  const goal_compile_1 = require("./goal-compile");
9
+ exports.CODE_MOVED_ON = 'the code has moved on since this plan was delivered, so what is here now was never checked';
7
10
  function confirmGoalExecutionEvidence(input) {
8
11
  const { scope, currentHead } = input;
9
12
  if (scope === null)
@@ -49,11 +52,23 @@ function confirmGoalExecutionEvidence(input) {
49
52
  const atHead = committed.filter((r) => r.sha === currentHead);
50
53
  if (atHead.length === 0) {
51
54
  // Deliberately not "close enough". Something has moved the repository since
52
- // this plan landed, and nothing here has checked that the goal survived it.
53
- return {
54
- ok: false,
55
- because: 'the code has moved on since this plan was delivered, so what is here now was never checked',
56
- };
55
+ // this plan landed, and nothing here has checked that the goal survived it —
56
+ // unless the gates were run again at this tree, and the plan's work is in it.
57
+ const rechecked = input.rechecked;
58
+ if (rechecked === undefined)
59
+ return { ok: false, because: exports.CODE_MOVED_ON, moved: true };
60
+ const contained = committed.filter((r) => {
61
+ const item = mineById.get(r.itemId);
62
+ return r.sha !== undefined && rechecked.contains.has(r.sha) && item !== undefined && !(0, goal_compile_1.isPlanMarker)(item);
63
+ });
64
+ if (contained.length === 0) {
65
+ return { ok: false, because: 'the code has moved on since this plan was delivered, and its work is not in the tree that is here now' };
66
+ }
67
+ const permitted = (0, core_1.mayCommit)({ steps: [...rechecked.steps], requiredSteps: input.requiredSteps, proofEnabled: false });
68
+ if (!permitted.ok) {
69
+ return { ok: false, because: `the gates were run again at the current tree, and ${permitted.reason ?? 'they did not pass'}` };
70
+ }
71
+ return { ok: true, round: contained[contained.length - 1], delivered: [...deliveredIds], reproved: rechecked.steps };
57
72
  }
58
73
  // An EXISTS, not a FOR-ALL, and that is the whole reachability argument: a
59
74
  // plan of five steps produces five commits and only the last is HEAD, so
@@ -141,6 +156,16 @@ function committedOfPlan(input, scope) {
141
156
  }
142
157
  return { ok: true, committed, deliveredIds, mineById };
143
158
  }
159
+ /** The commits this plan's delivered work made — what a re-proof asks git about (`rechecked.contains`). */
160
+ function committedShasOf(input) {
161
+ const { scope } = input;
162
+ if (scope === null || scope.planRevision === undefined)
163
+ return [];
164
+ const plan = committedOfPlan(input, scope);
165
+ if (!plan.ok)
166
+ return [];
167
+ return plan.committed.flatMap((r) => (r.sha === undefined ? [] : [r.sha]));
168
+ }
144
169
  /**
145
170
  * The plan's NEWEST committed round — the delivered tree a goal-met Start judges while the
146
171
  * lane has not moved it (F27). Null wherever KEY 2 would find nothing to confirm, and when
@@ -1 +1 @@
1
- {"version":3,"file":"goal-execution-evidence.js","sourceRoot":"","sources":["../src/goal-execution-evidence.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"goal-execution-evidence.js","sourceRoot":"","sources":["../src/goal-execution-evidence.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ import type { GateStepResult } from '@looply/core';
2
+ /**
3
+ * RE-CHECK THE TREE THAT IS HERE NOW, RATHER THAN HAND A DELIVERED GOAL BACK.
4
+ *
5
+ * KEY 2 (`goal-execution-evidence.ts`) refuses a "goal met" verdict when HEAD is
6
+ * not the commit the plan's last round made: nothing has checked the tree that
7
+ * is here now. On 2026-10-15 that refusal ended three Tabsy tickets whose every
8
+ * step had been delivered, gated and proved (TAB-B-57, 63, 64) — another
9
+ * ticket's run had been cut on top of their commits in the same checkout, so
10
+ * HEAD had moved on and the goal went back to a person.
11
+ *
12
+ * This does the missing check instead: when the plan's work is contained in
13
+ * HEAD and the working tree is clean, every gate step runs again at HEAD, and
14
+ * KEY 2 is asked again with what those steps say. A tree without the work, a
15
+ * dirty tree, or a red gate still refuses — with the reason.
16
+ *
17
+ * Every verb is injected, so production and the tests run this same code.
18
+ */
19
+ export interface ReproofDeps {
20
+ /** Uncommitted paths in the working tree. */
21
+ changedPaths(): Promise<readonly string[]>;
22
+ isAncestor(ancestor: string, of: string): Promise<boolean>;
23
+ changedPathsBetween(fromSha: string, toSha: string): Promise<readonly string[]>;
24
+ /** Run the project's gate at the current tree; `changedPaths` feeds the steps' `when:` filters. */
25
+ runGates(changedPaths: readonly string[]): Promise<readonly GateStepResult[]>;
26
+ }
27
+ export type ReproofOutcome = {
28
+ readonly ok: true;
29
+ readonly contains: ReadonlySet<string>;
30
+ readonly steps: readonly GateStepResult[];
31
+ } | {
32
+ readonly ok: false;
33
+ readonly because: string;
34
+ };
35
+ /**
36
+ * `committed` is the plan's committed shas in ledger order (`committedShasOf`).
37
+ * The `when:` paths are everything from the parent of the plan's first
38
+ * contained commit to HEAD, so a step filtered to the files this plan touched
39
+ * still runs.
40
+ */
41
+ export declare function reproveAtHead(head: string, committed: readonly string[], deps: ReproofDeps): Promise<ReproofOutcome>;
42
+ //# sourceMappingURL=goal-reproof.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"goal-reproof.d.ts","sourceRoot":"","sources":["../src/goal-reproof.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,WAAW;IAC1B,6CAA6C;IAC7C,YAAY,IAAI,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAAC;IAC3C,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3D,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAAC;IAChF,mGAAmG;IACnG,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,SAAS,cAAc,EAAE,CAAC,CAAC;CAC/E;AAED,MAAM,MAAM,cAAc,GACtB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,cAAc,EAAE,CAAA;CAAE,GACxG;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAErD;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,CAAC,CAoB1H"}
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.reproveAtHead = reproveAtHead;
4
+ /**
5
+ * `committed` is the plan's committed shas in ledger order (`committedShasOf`).
6
+ * The `when:` paths are everything from the parent of the plan's first
7
+ * contained commit to HEAD, so a step filtered to the files this plan touched
8
+ * still runs.
9
+ */
10
+ async function reproveAtHead(head, committed, deps) {
11
+ if (head === '')
12
+ return { ok: false, because: 'the current commit could not be read' };
13
+ const dirty = await deps.changedPaths();
14
+ if (dirty.length > 0) {
15
+ return { ok: false, because: `the working tree has ${dirty.length} uncommitted change(s), so it is not the tree a gate would check` };
16
+ }
17
+ const contains = [];
18
+ for (const sha of committed) {
19
+ if (sha === head || (await deps.isAncestor(sha, head).catch(() => false)))
20
+ contains.push(sha);
21
+ }
22
+ if (contains.length === 0)
23
+ return { ok: false, because: 'none of this plan’s commits is in the tree that is here now' };
24
+ let paths = [];
25
+ try {
26
+ paths = await deps.changedPathsBetween(`${contains[0]}~1`, head);
27
+ }
28
+ catch {
29
+ // A plan whose first commit is the repository's root has no parent: the plan's own commits still name its files.
30
+ paths = await deps.changedPathsBetween(contains[0], head).catch(() => []);
31
+ }
32
+ const steps = await deps.runGates(paths);
33
+ return { ok: true, contains: new Set(contains), steps };
34
+ }
35
+ //# sourceMappingURL=goal-reproof.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"goal-reproof.js","sourceRoot":"","sources":["../src/goal-reproof.ts"],"names":[],"mappings":";;AAsCA,sCAoBC;AA1BD;;;;;GAKG;AACI,KAAK,UAAU,aAAa,CAAC,IAAY,EAAE,SAA4B,EAAE,IAAiB;IAC/F,IAAI,IAAI,KAAK,EAAE;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,sCAAsC,EAAE,CAAC;IACvF,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;IACxC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,wBAAwB,KAAK,CAAC,MAAM,kEAAkE,EAAE,CAAC;IACxI,CAAC;IACD,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,KAAK,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;QAC5B,IAAI,GAAG,KAAK,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC;YAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChG,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,6DAA6D,EAAE,CAAC;IACxH,IAAI,KAAK,GAAsB,EAAE,CAAC;IAClC,IAAI,CAAC;QACH,KAAK,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IACpE,CAAC;IAAC,MAAM,CAAC;QACP,iHAAiH;QACjH,KAAK,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAAC,CAAE,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;IAC7E,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACzC,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,GAAG,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,CAAC;AAC1D,CAAC"}
@@ -75,7 +75,7 @@ async function indexForHead(cwd) {
75
75
  async function indexForTree(cwd, treeSha) {
76
76
  const git = new git_driver_1.GitDriver((0, git_driver_1.nodeGitExec)(cwd));
77
77
  const packages = packagesFor(cwd);
78
- const store = new project_index_store_1.ProjectIndexStore((0, git_driver_1.executionStateDir)(cwd), ledger_store_1.nodeLedgerFs);
78
+ const store = new project_index_store_1.ProjectIndexStore((0, git_driver_1.executionStateDir)(cwd), ledger_store_1.nodeLedgerFs, (0, git_driver_1.projectStateDir)(cwd));
79
79
  const cached = await store.load(treeSha, packages.map((pkg) => pkg.name));
80
80
  if (cached !== null)
81
81
  return { ok: true, treeSha, snapshot: cached, cached: true };
@@ -1 +1 @@
1
- {"version":3,"file":"index-for-head.js","sourceRoot":"","sources":["../src/index-for-head.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index-for-head.js","sourceRoot":"","sources":["../src/index-for-head.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ import { type ProbeFn } from './run-lease';
2
+ /**
3
+ * HOW MANY AUTONOMOUS RUNS THIS COMPUTER HAS, ACROSS EVERY REPOSITORY IT SERVES.
4
+ *
5
+ * `looply serve` runs one daemon per repository, and each daemon's coordinator
6
+ * bounds only its own project (`machine.max_parallel_runs`). A PC serving 27
7
+ * repositories at 3 each could otherwise launch 81 agent sessions at once. This
8
+ * is the one number they share: `machine.max_runs_on_machine` (default 4).
9
+ *
10
+ * ─────────────────────────────────────────────────────────────────────────────
11
+ * ONE FILE PER SLOT, IN `~/.looply/machine-runs/`.
12
+ *
13
+ * A slot is CLAIMED before a launch (pending, holding the daemon's pid) and
14
+ * BOUND to the child's pid once it is spawned. A slot frees itself: a bound
15
+ * slot whose pid is dead, or a pending slot older than `PENDING_TTL_MS`, is not
16
+ * counted and is swept on the next claim. Nothing has to remember to release,
17
+ * so a crashed run or daemon cannot leak capacity for longer than one probe.
18
+ *
19
+ * Claims are serialised by the shared exclusive lock, so two daemons cannot
20
+ * both see the last free slot and both take it.
21
+ *
22
+ * ⚠️ A CLAIM IS ASKED BEFORE A TRY IS SPENT. The launcher's `busyFor` takes it
23
+ * (see `run-launcher.ts`), and `busyFor` runs before `reserveLaunch` in the
24
+ * tick, so "the machine is full" is a queue — never a failed attempt. A claim
25
+ * is idempotent per request: asking again for the same request refreshes it.
26
+ *
27
+ * ⚠️ AN UNKNOWN LIVENESS COUNTS AS ALIVE, the direction that cannot overshoot.
28
+ */
29
+ /** A claim that never became a run stops holding a slot after this. */
30
+ export declare const PENDING_TTL_MS: number;
31
+ export interface MachineSlot {
32
+ readonly key: string;
33
+ readonly pid: number;
34
+ readonly pending: boolean;
35
+ readonly at: string;
36
+ /** Which repository the run is for — for a person reading the directory. */
37
+ readonly repo?: string;
38
+ }
39
+ export interface MachineRunSlots {
40
+ /** Take (or refresh) a slot for `key`; null when taken, else why the machine is full. */
41
+ claim(key: string): string | null;
42
+ /** The launch happened: the slot now lives as long as `pid` does. */
43
+ bind(key: string, pid: number): void;
44
+ /** The launch did not happen. */
45
+ release(key: string): void;
46
+ /** Live slots right now, `key` excluded when given. */
47
+ inUse(except?: string): number;
48
+ readonly cap: number;
49
+ }
50
+ export interface MachineRunSlotDeps {
51
+ readonly home?: string;
52
+ readonly now?: () => number;
53
+ readonly probe?: ProbeFn;
54
+ readonly pid?: number;
55
+ readonly repo?: string;
56
+ }
57
+ export declare function machineSlotsDir(home?: string): string;
58
+ export declare function machineRunSlots(cap: number, deps?: MachineRunSlotDeps): MachineRunSlots;
59
+ //# sourceMappingURL=machine-run-slots.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"machine-run-slots.d.ts","sourceRoot":"","sources":["../src/machine-run-slots.ts"],"names":[],"mappings":"AAKA,OAAO,EAAa,KAAK,OAAO,EAAE,MAAM,aAAa,CAAC;AAEtD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,uEAAuE;AACvE,eAAO,MAAM,cAAc,QAAa,CAAC;AAEzC,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,4EAA4E;IAC5E,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,yFAAyF;IACzF,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAClC,qEAAqE;IACrE,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,iCAAiC;IACjC,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,uDAAuD;IACvD,KAAK,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,eAAe,CAAC,IAAI,GAAE,MAAkB,GAAG,MAAM,CAEhE;AAID,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE,kBAAuB,GAAG,eAAe,CA8F3F"}
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PENDING_TTL_MS = void 0;
4
+ exports.machineSlotsDir = machineSlotsDir;
5
+ exports.machineRunSlots = machineRunSlots;
6
+ const node_crypto_1 = require("node:crypto");
7
+ const node_fs_1 = require("node:fs");
8
+ const node_os_1 = require("node:os");
9
+ const node_path_1 = require("node:path");
10
+ const exclusive_lock_1 = require("./exclusive-lock");
11
+ const run_lease_1 = require("./run-lease");
12
+ /**
13
+ * HOW MANY AUTONOMOUS RUNS THIS COMPUTER HAS, ACROSS EVERY REPOSITORY IT SERVES.
14
+ *
15
+ * `looply serve` runs one daemon per repository, and each daemon's coordinator
16
+ * bounds only its own project (`machine.max_parallel_runs`). A PC serving 27
17
+ * repositories at 3 each could otherwise launch 81 agent sessions at once. This
18
+ * is the one number they share: `machine.max_runs_on_machine` (default 4).
19
+ *
20
+ * ─────────────────────────────────────────────────────────────────────────────
21
+ * ONE FILE PER SLOT, IN `~/.looply/machine-runs/`.
22
+ *
23
+ * A slot is CLAIMED before a launch (pending, holding the daemon's pid) and
24
+ * BOUND to the child's pid once it is spawned. A slot frees itself: a bound
25
+ * slot whose pid is dead, or a pending slot older than `PENDING_TTL_MS`, is not
26
+ * counted and is swept on the next claim. Nothing has to remember to release,
27
+ * so a crashed run or daemon cannot leak capacity for longer than one probe.
28
+ *
29
+ * Claims are serialised by the shared exclusive lock, so two daemons cannot
30
+ * both see the last free slot and both take it.
31
+ *
32
+ * ⚠️ A CLAIM IS ASKED BEFORE A TRY IS SPENT. The launcher's `busyFor` takes it
33
+ * (see `run-launcher.ts`), and `busyFor` runs before `reserveLaunch` in the
34
+ * tick, so "the machine is full" is a queue — never a failed attempt. A claim
35
+ * is idempotent per request: asking again for the same request refreshes it.
36
+ *
37
+ * ⚠️ AN UNKNOWN LIVENESS COUNTS AS ALIVE, the direction that cannot overshoot.
38
+ */
39
+ /** A claim that never became a run stops holding a slot after this. */
40
+ exports.PENDING_TTL_MS = 3 * 60_000;
41
+ function machineSlotsDir(home = (0, node_os_1.homedir)()) {
42
+ return (0, node_path_1.join)(home, '.looply', 'machine-runs');
43
+ }
44
+ const fileOf = (key) => `${(0, node_crypto_1.createHash)('sha256').update(key).digest('hex').slice(0, 32)}.json`;
45
+ function machineRunSlots(cap, deps = {}) {
46
+ const dir = machineSlotsDir(deps.home);
47
+ const now = deps.now ?? (() => Date.now());
48
+ const probe = deps.probe ?? run_lease_1.nodeProbe;
49
+ const me = deps.pid ?? process.pid;
50
+ const limit = Math.max(1, Math.floor(cap));
51
+ const read = () => {
52
+ let names;
53
+ try {
54
+ names = (0, node_fs_1.readdirSync)(dir).filter((n) => n.endsWith('.json'));
55
+ }
56
+ catch {
57
+ return [];
58
+ }
59
+ const out = [];
60
+ for (const file of names) {
61
+ try {
62
+ const raw = JSON.parse((0, node_fs_1.readFileSync)((0, node_path_1.join)(dir, file), 'utf8'));
63
+ if (typeof raw.key !== 'string' || typeof raw.pid !== 'number' || typeof raw.at !== 'string')
64
+ continue;
65
+ out.push({ file, slot: { key: raw.key, pid: raw.pid, pending: raw.pending === true, at: raw.at, ...(raw.repo === undefined ? {} : { repo: raw.repo }) } });
66
+ }
67
+ catch {
68
+ // A torn write is not a run. The claim that wrote it rewrites it.
69
+ }
70
+ }
71
+ return out;
72
+ };
73
+ const live = (s) => {
74
+ if (s.pending) {
75
+ const at = Date.parse(s.at);
76
+ if (!Number.isFinite(at) || now() - at > exports.PENDING_TTL_MS)
77
+ return false;
78
+ }
79
+ return probe(s.pid) !== 'dead';
80
+ };
81
+ const write = (slot) => {
82
+ (0, node_fs_1.mkdirSync)(dir, { recursive: true });
83
+ const target = (0, node_path_1.join)(dir, fileOf(slot.key));
84
+ const tmp = `${target}.${me}.tmp`;
85
+ (0, node_fs_1.writeFileSync)(tmp, `${JSON.stringify(slot)}\n`, 'utf8');
86
+ (0, node_fs_1.renameSync)(tmp, target);
87
+ };
88
+ const inUse = (except) => read().filter(({ slot }) => slot.key !== except && live(slot)).length;
89
+ return {
90
+ cap: limit,
91
+ inUse,
92
+ claim(key) {
93
+ try {
94
+ (0, node_fs_1.mkdirSync)(dir, { recursive: true });
95
+ }
96
+ catch {
97
+ // Fall through: the lock below refuses, and a refusal is a wait.
98
+ }
99
+ return (0, exclusive_lock_1.withExclusiveLock)((0, node_path_1.join)(dir, 'claim.lock'), () => {
100
+ const all = read();
101
+ for (const { file, slot } of all) {
102
+ if (!live(slot)) {
103
+ try {
104
+ (0, node_fs_1.rmSync)((0, node_path_1.join)(dir, file), { force: true });
105
+ }
106
+ catch {
107
+ /* swept next time */
108
+ }
109
+ }
110
+ }
111
+ const mine = all.find(({ slot }) => slot.key === key);
112
+ if (mine !== undefined && !mine.slot.pending && live(mine.slot))
113
+ return null; // already running
114
+ const others = all.filter(({ slot }) => slot.key !== key && live(slot)).length;
115
+ if (others >= limit) {
116
+ return `this computer already has ${others} autonomous run(s) going across its repositories and its ceiling is ${limit} (machine.max_runs_on_machine)`;
117
+ }
118
+ write({ key, pid: me, pending: true, at: new Date(now()).toISOString(), ...(deps.repo === undefined ? {} : { repo: deps.repo }) });
119
+ return null;
120
+ }, (why) => `the machine-wide run count could not be checked (${why})`);
121
+ },
122
+ bind(key, pid) {
123
+ try {
124
+ write({ key, pid, pending: false, at: new Date(now()).toISOString(), ...(deps.repo === undefined ? {} : { repo: deps.repo }) });
125
+ }
126
+ catch {
127
+ // A slot that cannot be bound expires as pending; the run goes on.
128
+ }
129
+ },
130
+ release(key) {
131
+ try {
132
+ (0, node_fs_1.rmSync)((0, node_path_1.join)(dir, fileOf(key)), { force: true });
133
+ }
134
+ catch {
135
+ /* expires on its own */
136
+ }
137
+ },
138
+ };
139
+ }
140
+ //# sourceMappingURL=machine-run-slots.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"machine-run-slots.js","sourceRoot":"","sources":["../src/machine-run-slots.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ import type { CheckedPlan, CheckedStep } from './compile-check';
2
+ import { type CompileGoalInput, type CompileOutcome, type PlanStep } from './goal-compile';
3
+ /**
4
+ * A PLAN THAT CANNOT BE USED AS IT CAME BACK IS ASKED AGAIN, NOT HANDED TO A PERSON.
5
+ *
6
+ * ─────────────────────────────────────────────────────────────────────────────
7
+ * WHY (Tabsy, 2026-10-15)
8
+ *
9
+ * A ticket pasted into a chat with the same model is fixed nine times in ten.
10
+ * The same tickets given to Looply ended `human_required` for reasons that had
11
+ * nothing to do with the work:
12
+ * - TAB-B-60: the one step of the plan cited `TableBillLink.tsx:201`, the line
13
+ * did not exist at the committed tree, the step was refused, nothing was
14
+ * queued, and the run had nothing to do;
15
+ * - TAB-B-45: "shouldn't a fully paid table automatically become closed? —
16
+ * closing a session is only done manually as of now" was read as a remark,
17
+ * the plan came back empty, and "nothing here can move without you".
18
+ *
19
+ * Neither is a question only a person can answer. So:
20
+ * 1. a step whose citation does not hold is RE-PLANNED: the compiler is asked
21
+ * once more, shown each refusal, and told to read the current tree;
22
+ * 2. a step refused again keeps its place WITHOUT the citation that failed —
23
+ * a citation is a pointer, not the work, and the verify pass still confirms
24
+ * every draft against the code before a round may pick it;
25
+ * 3. an empty plan is asked again with the ticket read as an instruction;
26
+ * 4. an empty plan after that becomes ONE direct step — "do what this ticket
27
+ * asks" — and the implementer is handed the person's full wording (it
28
+ * always is, see `buildImplementerPrompt`). It is gated and proved like
29
+ * every other round, so nothing here lowers the bar for what lands.
30
+ *
31
+ * ⚠️ WHAT IS NOT RECOVERED: a compiler that failed, timed out or answered in a
32
+ * shape nobody could read. Those already spend nothing and the next Start asks
33
+ * again, which is the right answer to a transport problem.
34
+ *
35
+ * PURE apart from the two injected calls, so production and the tests run the
36
+ * same code.
37
+ */
38
+ export interface RecoveryDeps {
39
+ compile(input: CompileGoalInput): Promise<CompileOutcome>;
40
+ check(steps: readonly PlanStep[]): Promise<CheckedPlan>;
41
+ log?(line: string): void;
42
+ }
43
+ export interface RecoveredPlan {
44
+ /** The answer whose steps are the ones to queue (`steps` already recovered). */
45
+ readonly compiled: CompileOutcome;
46
+ /**
47
+ * `admitted` is every step to queue; `refused` is what the FIRST check refused,
48
+ * kept so the compile record shows the claim beside what was there.
49
+ */
50
+ readonly checked: CheckedPlan | null;
51
+ /** What recovery did, for the log; empty when the first answer was used as it came. */
52
+ readonly notes: readonly string[];
53
+ }
54
+ export declare const DIRECT_STEP_PREFIX = "Do what this ticket asks, as written";
55
+ /** The context for a re-plan after refusals: each refused step, and why. */
56
+ export declare function refusalContext(refused: readonly CheckedStep[]): string;
57
+ /** The context for a re-plan after an empty plan: read the ticket as an instruction. */
58
+ export declare const STATEMENT_CONTEXT: string;
59
+ /** The one step a ticket gets when structured planning produced nothing usable. */
60
+ export declare function directFixStep(goalText: string): PlanStep;
61
+ /** A compile answer made of the direct step alone, for a caller that needs a `CompileOutcome`. */
62
+ export declare function directFixOutcome(goalText: string): CompileOutcome;
63
+ /** A refused step with the citations that failed taken off it. */
64
+ export declare function withoutRefuted(r: CheckedStep): PlanStep;
65
+ /**
66
+ * Compile, check, and recover. `maxSteps` bounds what is queued, whatever the
67
+ * recovery added, so a re-plan never makes a plan bigger than the cap it was asked under.
68
+ */
69
+ export declare function compileWithRecovery(input: CompileGoalInput, deps: RecoveryDeps, maxSteps: number): Promise<RecoveredPlan>;
70
+ //# sourceMappingURL=plan-recovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-recovery.d.ts","sourceRoot":"","sources":["../src/plan-recovery.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAW,KAAK,gBAAgB,EAAE,KAAK,cAAc,EAAE,KAAK,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAEpG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAC1D,KAAK,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACxD,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAC5B,gFAAgF;IAChF,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IACrC,uFAAuF;IACvF,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAKD,eAAO,MAAM,kBAAkB,yCAAyC,CAAC;AAEzE,4EAA4E;AAC5E,wBAAgB,cAAc,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,GAAG,MAAM,CAQtE;AAED,wFAAwF;AACxF,eAAO,MAAM,iBAAiB,QAMlB,CAAC;AAOb,mFAAmF;AACnF,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,CAQxD;AAED,kGAAkG;AAClG,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,CAUjE;AAED,kEAAkE;AAClE,wBAAgB,cAAc,CAAC,CAAC,EAAE,WAAW,GAAG,QAAQ,CAGvD;AAcD;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,gBAAgB,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAsD/H"}