halfcycle 0.4.12 → 0.4.14

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 (54) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/bin/bin.bundle.mjs +9366 -567
  3. package/bin/pre-tool-use-filter.sh +470 -0
  4. package/dist/bin.d.ts +1 -0
  5. package/dist/bin.d.ts.map +1 -1
  6. package/dist/build-record/pair-io.d.ts +49 -0
  7. package/dist/build-record/pair-io.d.ts.map +1 -0
  8. package/dist/build-record/render-change.d.ts +25 -0
  9. package/dist/build-record/render-change.d.ts.map +1 -0
  10. package/dist/build-record/render-v2.d.ts +10 -5
  11. package/dist/build-record/render-v2.d.ts.map +1 -1
  12. package/dist/build-record/write-change.d.ts +63 -0
  13. package/dist/build-record/write-change.d.ts.map +1 -0
  14. package/dist/build-record/write.d.ts +5 -15
  15. package/dist/build-record/write.d.ts.map +1 -1
  16. package/dist/change.d.ts +136 -0
  17. package/dist/change.d.ts.map +1 -0
  18. package/dist/check-tasks.d.ts +71 -0
  19. package/dist/check-tasks.d.ts.map +1 -0
  20. package/dist/claude-plan.d.ts +114 -0
  21. package/dist/claude-plan.d.ts.map +1 -0
  22. package/dist/cli-contract.d.ts +12 -1
  23. package/dist/cli-contract.d.ts.map +1 -1
  24. package/dist/cli.js +9017 -5228
  25. package/dist/cli.js.map +3 -3
  26. package/dist/close-phase.d.ts +113 -10
  27. package/dist/close-phase.d.ts.map +1 -1
  28. package/dist/halfcycle-monorepo.d.ts +26 -0
  29. package/dist/halfcycle-monorepo.d.ts.map +1 -0
  30. package/dist/index.js +1617 -845
  31. package/dist/index.js.map +3 -3
  32. package/dist/install-manifest.d.ts +18 -1
  33. package/dist/install-manifest.d.ts.map +1 -1
  34. package/dist/install.d.ts +225 -3
  35. package/dist/install.d.ts.map +1 -1
  36. package/dist/merge-settings.d.ts +25 -2
  37. package/dist/merge-settings.d.ts.map +1 -1
  38. package/dist/open-phase.d.ts +1 -1
  39. package/dist/open-phase.d.ts.map +1 -1
  40. package/dist/pace.d.ts +138 -0
  41. package/dist/pace.d.ts.map +1 -0
  42. package/dist/phase-work.d.ts +37 -0
  43. package/dist/phase-work.d.ts.map +1 -0
  44. package/dist/plan.d.ts +5 -2
  45. package/dist/plan.d.ts.map +1 -1
  46. package/dist/prove.d.ts +77 -0
  47. package/dist/prove.d.ts.map +1 -0
  48. package/dist/review.d.ts +19 -1
  49. package/dist/review.d.ts.map +1 -1
  50. package/dist/system-report.d.ts +4 -4
  51. package/dist/system-report.d.ts.map +1 -1
  52. package/dist/uninstall.d.ts +4 -1
  53. package/dist/uninstall.d.ts.map +1 -1
  54. package/package.json +1 -1
@@ -0,0 +1,63 @@
1
+ /**
2
+ * The small-change record pair writer (feature `three-paths`, *The writer*).
3
+ *
4
+ * A small change's record is not a phase's Build Record, so it never goes through
5
+ * `writeRecordPair`: it has its own folder, `docs/build-records/changes/`, its own
6
+ * renderer (`render-change.ts`) and a narrower replace rule.
7
+ *
8
+ * THE FILENAME COMES FROM THE CALLER'S `sortingId` ARGUMENT, never from the record
9
+ * (INV-023). The argument is checked as a UUID (`sortingIdSchema`, the contracts' one
10
+ * home of a change id) here, where every caller converges, before any path is made,
11
+ * so the CLI's own check is not the only one. `record.sortingId` is never read for a
12
+ * path: a record naming another change, or `../x`, still lands at the argument's name.
13
+ * After the join, every path, temporary ones included, is checked to be a plain file
14
+ * directly inside the folder, comparing two operands that move independently: the
15
+ * folder (from `repoRoot` and a constant) and the candidate (from the argument).
16
+ *
17
+ * WRITE-ONCE, SO NEVER REPLACED. The service freezes a small change's record once, so
18
+ * the same `.json` bytes already there are up to date (the `.md` is rendered again,
19
+ * so a renderer change never refuses the CLI's own pair), and anything else in the way
20
+ * is refused, naming the file. The exclusive create and the no-half-pair rule are the
21
+ * shared ones in `pair-io.ts`.
22
+ *
23
+ * All-or-nothing: the id is checked, every path asserted and both texts rendered
24
+ * before the folder is made or the first file created.
25
+ */
26
+ import { type SmallChangeRecord } from '@halfcycle/events';
27
+ import { type RecordPairIo } from './pair-io.js';
28
+ /** The one output folder for small-change records, relative to the project root. */
29
+ export declare const CHANGE_RECORD_DIR: string;
30
+ /** A change id that cannot name a record file: refused before any path is made. */
31
+ export declare class InvalidChangeIdError extends Error {
32
+ readonly id: unknown;
33
+ constructor(id: unknown);
34
+ }
35
+ /**
36
+ * Assert that a joined path is still a plain file directly inside `outDir`. Exported
37
+ * so a test can hand it a candidate outside the folder: no id that passes the UUID
38
+ * check can produce one, so only a direct call can tell this guard from a deleted one.
39
+ */
40
+ export declare function assertInsideChangeDir(outDir: string, candidate: string, id: unknown): void;
41
+ /**
42
+ * What `writeChangeRecordPair` did. `created`: neither file existed. `up-to-date`: the
43
+ * `.json` already held these exact bytes, and the `.md` was rendered again.
44
+ * `in-the-way`: something else is at one of the two paths; nothing was written and
45
+ * `path` names it.
46
+ */
47
+ export type ChangeRecordPairResult = {
48
+ kind: 'created' | 'up-to-date';
49
+ jsonPath: string;
50
+ mdPath: string;
51
+ } | {
52
+ kind: 'in-the-way';
53
+ path: string;
54
+ };
55
+ /**
56
+ * Write a small change's record pair into `docs/build-records/changes/`: the `.json`
57
+ * as the service sent it, the `.md` rendered from the parsed record.
58
+ *
59
+ * @throws InvalidChangeIdError when `sortingId` is not a change id.
60
+ * @throws the file system's own error when a write fails; nothing is left behind.
61
+ */
62
+ export declare function writeChangeRecordPair(repoRoot: string, sortingId: string, rawRecord: unknown, record: SmallChangeRecord, io?: RecordPairIo): ChangeRecordPairResult;
63
+ //# sourceMappingURL=write-change.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write-change.d.ts","sourceRoot":"","sources":["../../src/build-record/write-change.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAIH,OAAO,EAAmB,KAAK,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE5E,OAAO,EAML,KAAK,YAAY,EAClB,MAAM,cAAc,CAAC;AAEtB,oFAAoF;AACpF,eAAO,MAAM,iBAAiB,QAA2C,CAAC;AAE1E,mFAAmF;AACnF,qBAAa,oBAAqB,SAAQ,KAAK;IACjC,QAAQ,CAAC,EAAE,EAAE,OAAO;gBAAX,EAAE,EAAE,OAAO;CAIjC;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,GAAG,IAAI,CAI1F;AAED;;;;;GAKG;AACH,MAAM,MAAM,sBAAsB,GAC9B;IAAE,IAAI,EAAE,SAAS,GAAG,YAAY,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACpE;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzC;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,OAAO,EAClB,MAAM,EAAE,iBAAiB,EACzB,EAAE,GAAE,YAAkC,GACrC,sBAAsB,CA0BxB"}
@@ -25,6 +25,7 @@
25
25
  * before the `mkdirSync` and the first create, so a refused record leaves no file
26
26
  * and no empty directory behind.
27
27
  */
28
+ import { NODE_RECORD_PAIR_IO, serialiseServedRecord, type RecordPairIo } from './pair-io.js';
28
29
  import { type BuildRecord } from '@halfcycle/events';
29
30
  /** The one and only output directory (relative to the target repo root). */
30
31
  export declare const BUILD_RECORD_DIR: string;
@@ -43,20 +44,11 @@ export declare const BUILD_RECORD_DIR: string;
43
44
  */
44
45
  export declare function assertInsideOutDir(outDir: string, candidate: string, identity: unknown): void;
45
46
  /**
46
- * The file operations `writeRecordPair` makes, behind one seam so a test can make
47
- * the SECOND write fail and watch the first come back out. `createExclusive` opens
48
- * with `wx` (never truncates an existing file) and removes what it created if the
49
- * write itself fails; `rename` replaces in one step on the same filesystem.
50
- *
51
- * ONE SEAM FOR TEXT AND BYTES. `draw`'s three-file writer (`../draw/write.ts`) goes
52
- * through this same seam with a PNG's bytes, so a string is written as UTF-8 and a
53
- * byte array as itself, and there is one exclusive-create on disk, not two.
47
+ * The shared file discipline (`pair-io.ts`): one exclusive-create, one replace and one
48
+ * no-half-pair create for this writer and the small-change writer. Re-exported so the
49
+ * callers that have always imported them from here keep doing so.
54
50
  */
55
- export interface RecordPairIo {
56
- createExclusive(path: string, data: string | Uint8Array): void;
57
- rename(from: string, to: string): void;
58
- }
59
- export declare const NODE_RECORD_PAIR_IO: RecordPairIo;
51
+ export { NODE_RECORD_PAIR_IO, serialiseServedRecord, type RecordPairIo };
60
52
  /**
61
53
  * What `writeRecordPair` did. `created`: neither file existed. `up-to-date`: the
62
54
  * `.json` already held these exact bytes, and the `.md` was rendered again.
@@ -72,8 +64,6 @@ export type RecordPairResult = {
72
64
  kind: 'in-the-way';
73
65
  path: string;
74
66
  };
75
- /** Serialise a served record for the `.json`: 2-space indent, trailing newline. */
76
- export declare function serialiseServedRecord(rawRecord: unknown): string;
77
67
  /**
78
68
  * Write a phase's Build Record pair into `docs/build-records/`: the `.json` as the
79
69
  * service sent it, and the `.md` rendered from the parsed record.
@@ -1 +1 @@
1
- {"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../src/build-record/write.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAcH,OAAO,EAKL,KAAK,WAAW,EACjB,MAAM,mBAAmB,CAAC;AAE3B,4EAA4E;AAC5E,eAAO,MAAM,gBAAgB,QAAgC,CAAC;AAE9D;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,IAAI,CAM7F;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,YAAY;IAC3B,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAAC;IAC/D,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;CACxC;AA2BD,eAAO,MAAM,mBAAmB,EAAE,YAGjC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,gBAAgB,GACxB;IAAE,IAAI,EAAE,SAAS,GAAG,YAAY,GAAG,UAAU,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACjF;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzC,mFAAmF;AACnF,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,OAAO,GAAG,MAAM,CAEhE;AA0CD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,OAAO,EAClB,MAAM,EAAE,WAAW,EACnB,EAAE,GAAE,YAAkC,GACrC,gBAAgB,CAyDlB"}
1
+ {"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../src/build-record/write.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAKH,OAAO,EACL,mBAAmB,EAInB,qBAAqB,EACrB,KAAK,YAAY,EAClB,MAAM,cAAc,CAAC;AACtB,OAAO,EAKL,KAAK,WAAW,EACjB,MAAM,mBAAmB,CAAC;AAE3B,4EAA4E;AAC5E,eAAO,MAAM,gBAAgB,QAAgC,CAAC;AAE9D;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,IAAI,CAM7F;AAED;;;;GAIG;AACH,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,KAAK,YAAY,EAAE,CAAC;AAEzE;;;;;;GAMG;AACH,MAAM,MAAM,gBAAgB,GACxB;IAAE,IAAI,EAAE,SAAS,GAAG,YAAY,GAAG,UAAU,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACjF;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AA8BzC;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,OAAO,EAClB,MAAM,EAAE,WAAW,EACnB,EAAE,GAAE,YAAkC,GACrC,gBAAgB,CAkDlB"}
@@ -0,0 +1,136 @@
1
+ /**
2
+ * `npx halfcycle@latest change` — sorting a change, moving it up, and ending a small
3
+ * change (Safe, lean, fast · E3, feature `three-paths` AC2–AC4, AC6's writer, AC8's
4
+ * missing route; `mini-phase` *The CLI*).
5
+ *
6
+ * THREE FORMS, required flags declared once in `cli-contract.ts` (`missingRequirements`
7
+ * enforces them, and the remedy-string seam test reads the same table):
8
+ * - `change sort --request "<line>" --touches <path>… [--contract <from>:<to>]…
9
+ * [--stored-data] [--standing-rule] [--new-part]` checks `docs/system.json` exactly as
10
+ * `system` does (`checkAndReportDescription`, the one path), reads HEAD as the start
11
+ * commit (a project with no commit cannot sort), sends the description, then the
12
+ * sort, and prints control's answer: its sentence, the sorting's id, what to say next.
13
+ * The path is never worked out here: control re-runs the one rule (`sortChange`) and
14
+ * records its own answer. The request is checked locally with the contracts' own
15
+ * `checkChangeSortRequest` first, so a request control would refuse costs no request.
16
+ * - `change up <mini|full> --change <id>` moves an unfinished small change up and, the
17
+ * change now being finished, writes its record pair; `--phase <phase>` moves a mini
18
+ * phase up instead. A move down is refused here with the contracts' own sentence,
19
+ * before anything is sent; control refuses it again, as it refuses every move down.
20
+ * - `change done <id>` reads the record FIRST. A record found means the change has
21
+ * ended: the pair is written, the outcome printed, and nothing else happens — no
22
+ * runner is started, no report is sent. Only when the service says the change has
23
+ * not ended does it start the runner's `observe --change <id>`, which reads the
24
+ * basis, counts or finishes by the work standing, and prints one line this module
25
+ * parses with `observeChangeRunResultSchema` (one home, shared with the runner).
26
+ *
27
+ * THE RECORD'S FILENAME COMES FROM THE `<id>` ARGUMENT, checked as a change id here and
28
+ * again by the writer, never from a field of the record (INV-023).
29
+ *
30
+ * A SMALL CHANGE IS NOT A PHASE (INV-024): no line here asks for, mentions or marks an
31
+ * approval. Every sentence about a path is the contracts' `CHANGE_PATH_WORDS` or
32
+ * control's own answer; none is restated here (INV-003). Nothing a step id; the next
33
+ * thing to say is the phrase control's answer carries (INV-016).
34
+ *
35
+ * TOPOLOGY. Every route here takes the project credential alone: no GitHub
36
+ * installation, no open phase, no portal session (INV-022). A service without a route
37
+ * is told apart by `isMissingRoute`, and the CLI says so and exits 1.
38
+ *
39
+ * INV-001: Node builtins, the global `fetch`, `@halfcycle/events` and `@halfcycle/core`
40
+ * only; the runner is spawned, never imported. SHIPS TO CLIENT DISK inside the CLI: no
41
+ * comment sits beside an object member, and every string is a sentence a person reads.
42
+ */
43
+ import { type ChangeContract, type ObserveChangeRunResult, type SmallChangeRecord } from '@halfcycle/events';
44
+ import { type HeadCommitOutcome } from './close-phase.js';
45
+ import type { RepoCredential } from './open-phase.js';
46
+ import { type SystemDeps, type SystemRun } from './system-report.js';
47
+ import { type ChangeRecordPairResult } from './build-record/write-change.js';
48
+ /** The verb's usage, one home: printed by `--help` and by a usage error. */
49
+ export declare const CHANGE_USAGE: string;
50
+ /** What one invocation asks for, once its words have been read. */
51
+ export type ChangeArgs = {
52
+ readonly form: 'sort';
53
+ readonly request: string;
54
+ readonly touches: readonly string[];
55
+ readonly contracts: readonly ChangeContract[];
56
+ readonly storedData: boolean;
57
+ readonly standingRule: boolean;
58
+ readonly newPart: boolean;
59
+ readonly repoRoot?: string;
60
+ } | {
61
+ readonly form: 'up';
62
+ readonly to: 'mini' | 'full';
63
+ readonly target: {
64
+ readonly kind: 'change';
65
+ readonly sortingId: string;
66
+ } | {
67
+ readonly kind: 'phase';
68
+ readonly phase: string;
69
+ };
70
+ readonly repoRoot?: string;
71
+ } | {
72
+ readonly form: 'done';
73
+ readonly sortingId: string;
74
+ readonly repoRoot?: string;
75
+ };
76
+ /** The words read, or the line to print and the code to exit with. Nothing was sent. */
77
+ export type ParsedChange = {
78
+ ok: true;
79
+ args: ChangeArgs;
80
+ } | {
81
+ ok: false;
82
+ line: string;
83
+ exitCode: 1 | 2;
84
+ };
85
+ /**
86
+ * Read `rest` (the words after `change`). The required flags are the contract's
87
+ * (`missingRequirements`), refused first with the contract's own sentence; then each
88
+ * form's own words are read, and anything else is a usage error. Nothing is read from
89
+ * disk and nothing is sent.
90
+ */
91
+ export declare function parseChangeArgs(rest: readonly string[]): ParsedChange;
92
+ /** The pieces the verb reaches outside itself through; replaced in tests. */
93
+ export interface ChangeDeps extends SystemDeps {
94
+ readonly readHead: (repoRoot: string) => HeadCommitOutcome;
95
+ readonly fetch: typeof fetch;
96
+ readonly observeChange: (credential: RepoCredential, repoRoot: string, sortingId: string) => Promise<ObserveChangeRunResult>;
97
+ readonly writePair: (repoRoot: string, sortingId: string, rawRecord: unknown, record: SmallChangeRecord) => ChangeRecordPairResult;
98
+ }
99
+ /**
100
+ * The one line the `observe --change` child printed, read through the shared
101
+ * `observeChangeRunResultSchema`, or `unreachable` when stdout holds no such line.
102
+ */
103
+ export declare function readObserveChangeLine(stdout: string): ObserveChangeRunResult;
104
+ /**
105
+ * End a small change through the runner's `observe --change <id>`, spawned the way the
106
+ * close step spawns the runner's verbs (`runRunnerChild`), with the same credential.
107
+ * The id is the checked argument. Never throws.
108
+ */
109
+ export declare function runObserveChangeChild(binary: string | Error, credential: RepoCredential, repoRoot: string, sortingId: string): Promise<ObserveChangeRunResult>;
110
+ /** The line naming what to say next: the phrase the service's answer carries. */
111
+ export declare function nextSayLine(say: string): string;
112
+ /** The command that ends a small change, or writes its record again: the one remedy. */
113
+ export declare function changeDoneCommand(sortingId: string): string;
114
+ /** What a finished change's record says about how it ended, in the contracts' words. */
115
+ export declare function recordOutcomeLines(record: SmallChangeRecord): string;
116
+ /**
117
+ * `change sort`. The local check runs with the description that just passed and the
118
+ * HEAD just read; the description version is not known until the service answers, so
119
+ * the local check is given the lowest version there is, which no rule reads beyond its
120
+ * shape. The request that leaves carries the version the service gave.
121
+ */
122
+ export declare function runChangeSort(repoRoot: string, args: Extract<ChangeArgs, {
123
+ form: 'sort';
124
+ }>, deps: ChangeDeps): Promise<SystemRun>;
125
+ /** `change up`: a small change by its id, or a mini phase by its name. */
126
+ export declare function runChangeUp(repoRoot: string, args: Extract<ChangeArgs, {
127
+ form: 'up';
128
+ }>, deps: ChangeDeps): Promise<SystemRun>;
129
+ /**
130
+ * `change done <id>`. The record is read first; the runner is started only when the
131
+ * service says the change has not ended (three-paths AC4).
132
+ */
133
+ export declare function runChangeDone(repoRoot: string, sortingId: string, deps: ChangeDeps): Promise<SystemRun>;
134
+ /** The whole verb, once its words are read: the form's run. */
135
+ export declare function runChange(repoRoot: string, args: ChangeArgs, deps: ChangeDeps): Promise<SystemRun>;
136
+ //# sourceMappingURL=change.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"change.d.ts","sourceRoot":"","sources":["../src/change.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * `npx halfcycle@latest check-tasks <phase> [--with-task-list] [--repo <root>]`
3
+ * (`collision-free-parallel-work` AC3; `checks-as-work-lands` AC3, AC6).
4
+ *
5
+ * OFFLINE, ALWAYS. This verb reads at most two files on the person's own machine —
6
+ * `docs/build-records/task-plan.json` and, with `--with-task-list`,
7
+ * `docs/build-records/build-tasks.json` — and nothing else. It opens no credential
8
+ * file, makes no network call, and needs no sign-in. Everything it prints comes from
9
+ * `checkTaskPlan` (`@halfcycle/core`), which is pure: this module's whole job is
10
+ * reading the two files, handing them to that function, and printing what it
11
+ * returns.
12
+ *
13
+ * ONE HOME FOR THE PLAN'S SHAPE AND ITS RULES (INV-003): `taskPlanSchema`,
14
+ * `taskListFileSchema`, `checkTaskPlan` and every line it prints live in
15
+ * `@halfcycle/core`'s `task-plan.ts`. This file restates none of them — it only
16
+ * turns a missing or unparsable file into the one kind of answer this verb gives for
17
+ * that (exit 2, naming the file), and turns the function's lines into the exit code
18
+ * the spec pins (0 clean, 1 any refusal).
19
+ *
20
+ * THE TASK LIST IS READ ONLY WHEN ASKED. Without `--with-task-list` this verb never
21
+ * opens `build-tasks.json`, so a stale or disagreeing list on disk from an earlier
22
+ * phase changes nothing about a planning run — the one case
23
+ * `collision-free-parallel-work`'s *Decisions taken* exists to prevent.
24
+ *
25
+ * A MISSING TASK LIST IS NOT AN ERROR. Only the plan file is required input; a task
26
+ * list that is missing, names another phase, or carries no phase at all (the shape
27
+ * written before this release) reads as `checkTaskPlan`'s note N1 and exits 0 on an
28
+ * otherwise clean plan. A plan file in the same state is always a hard failure (exit
29
+ * 2), because the plan is this verb's one required input.
30
+ *
31
+ * SHIPS TO CLIENT DISK inside the CLI (INV-001: Node builtins, `@halfcycle/core`
32
+ * only — no network, so no `@halfcycle/events` and no `fetch`). Every string here is
33
+ * a sentence a person reads in their own terminal, so none names an internal
34
+ * register, a route, or this project's own tooling; no comment sits beside an
35
+ * object member.
36
+ */
37
+ /** The usage line, printed for no phase, an extra argument or an unknown flag. */
38
+ export declare const CHECK_TASKS_USAGE = "npx halfcycle@latest check-tasks <phase> [--with-task-list] [--repo <root>]";
39
+ /**
40
+ * What the arguments after `check-tasks` came to. Exactly one positional (the
41
+ * phase), at most one `--with-task-list` and at most one `--repo <root>`; anything
42
+ * else, no phase included, is usage.
43
+ */
44
+ export type CheckTasksArgs = {
45
+ ok: true;
46
+ phase: string;
47
+ withTaskList: boolean;
48
+ repoRoot: string | undefined;
49
+ } | {
50
+ ok: false;
51
+ };
52
+ export declare function parseCheckTasksArgs(argv: readonly string[]): CheckTasksArgs;
53
+ /** What a run of the verb came to. */
54
+ export interface CheckTasksRun {
55
+ readonly stdout: string;
56
+ readonly stderr: string;
57
+ readonly exitCode: number;
58
+ }
59
+ /**
60
+ * The whole verb. Reads `docs/build-records/task-plan.json` under `repoRoot`, and,
61
+ * with `withTaskList`, `docs/build-records/build-tasks.json`; hands both to
62
+ * `checkTaskPlan` and prints its lines, one per line, in the order it returns them,
63
+ * or `checkTaskPlan`'s own clear line when there is nothing to report. Never throws.
64
+ *
65
+ * Exit 0 when nothing refuses, 1 when anything does, 2 when the plan file is
66
+ * missing or either file cannot be read or parsed as JSON or does not match the
67
+ * shape this tool reads (naming which file, and where). A missing task list is not
68
+ * an error (see the module header) and never changes the exit code on its own.
69
+ */
70
+ export declare function runCheckTasks(repoRoot: string, phase: string, withTaskList: boolean): CheckTasksRun;
71
+ //# sourceMappingURL=check-tasks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check-tasks.d.ts","sourceRoot":"","sources":["../src/check-tasks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAgBH,kFAAkF;AAClF,eAAO,MAAM,iBAAiB,gFAAgF,CAAC;AAE/G;;;;GAIG;AACH,MAAM,MAAM,cAAc,GACtB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,GAChF;IAAE,EAAE,EAAE,KAAK,CAAA;CAAE,CAAC;AAElB,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,cAAc,CAuB3E;AA2CD,sCAAsC;AACtC,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,GAAG,aAAa,CA4BnG"}
@@ -0,0 +1,114 @@
1
+ /**
2
+ * SETUP ASKS THE CLAUDE PLAN ONCE (`builds-paced-to-plan` AC2, setup half).
3
+ *
4
+ * `bin.ts`'s setup arm calls `setupClaudePlan` after the project is created or found.
5
+ * In order:
6
+ *
7
+ * 1. NOBODY IS ASKED, AND NOTHING IS SENT, unless this account owns the project
8
+ * and a person is there (`isInteractiveRun`: a terminal on standard input and no
9
+ * `CI`). That one gate covers a script, CI, an agent running `npx halfcycle` from
10
+ * its own shell (no terminal on standard input) and a guest. A remembered answer
11
+ * is not sent either: the spec's "a setup with no person there sends nothing".
12
+ * 2. A COMPUTER THAT WAS TOLD BEFORE is not asked again: the remembered plan is
13
+ * sent, and, once control has taken it, the remembered line says so.
14
+ * 3. OTHERWISE the question is asked (`askLine`), the answer remembered on this
15
+ * computer and sent. An answer that names no plan is asked again, up to
16
+ * `PLAN_QUESTION_TRIES` times in all; after that nothing is remembered or sent,
17
+ * and the plan stays unknown until the owner sets it in the console.
18
+ *
19
+ * ONE HOME FOR EVERY WORD AND SHAPE, AND IT IS NOT HERE. The question, the answer's
20
+ * reading, the remembered line, the seven plans and the request body are
21
+ * `@halfcycle/events`' `pacing.ts`; the remembered file's shape IS the request body
22
+ * (`claudePlanRequestSchema`), so the file and the wire cannot drift apart. This
23
+ * module holds only the order above and the file and network I/O.
24
+ *
25
+ * THE CREDENTIAL IS THE MACHINE'S ACCOUNT CREDENTIAL, read the way the create route's
26
+ * is (`HALFCYCLE_TOKEN` in the environment first, else this machine's saved sign-in),
27
+ * and never a browser sign-in: the project is already set up, and a sign-in for a
28
+ * question about pacing would be out of all proportion. The engagement credential is
29
+ * never sent; control refuses it on this route. With no account credential the answer
30
+ * is still remembered, so the next setup sends it.
31
+ *
32
+ * BEST EFFORT, NEVER A FAILURE. The install has already succeeded when this runs. A
33
+ * network error, a timeout, a refusal (control not yet carrying the route, or a
34
+ * project this account does not own after all) or a file that cannot be written is
35
+ * silent: the remembered answer is re-sent by the next setup, and the owner can set
36
+ * the plan in the console. Nothing here throws.
37
+ *
38
+ * A REMEMBERED ANSWER IS RE-SENT ON EVERY LATER SETUP, as the spec says, so a plan the
39
+ * owner changed in the console is set back by their next `npx halfcycle` on this
40
+ * computer. That is the spec's rule, written down here so it is not mistaken for a
41
+ * defect of this module.
42
+ *
43
+ * INV-001: Node builtins, `@halfcycle/core`, `@halfcycle/events` and this package's
44
+ * own modules. Nothing about usage crosses (ADR-015): only the plan's id.
45
+ */
46
+ import { type ClaudePlanId } from '@halfcycle/events';
47
+ /** The remembered answer's file name, under `~/.halfcycle/`. Machine-level, never in a project (INV-016). */
48
+ export declare const CLAUDE_PLAN_FILENAME = "claude-plan.json";
49
+ /** How many times the question is put before an answer that names no plan is given up on. */
50
+ export declare const PLAN_QUESTION_TRIES = 3;
51
+ /** `~/.halfcycle/claude-plan.json`. */
52
+ export declare function claudePlanPath(home?: string): string;
53
+ /**
54
+ * The plan this computer was told before, or `undefined` when it was never told or
55
+ * the file does not read as one: a file that does not parse is asked about again and
56
+ * overwritten, never an error.
57
+ */
58
+ export declare function readRememberedClaudePlan(home?: string): ClaudePlanId | undefined;
59
+ /**
60
+ * Remember the plan on this computer, owner-only, the account store's posture
61
+ * (`account-credential.ts`). Returns false when it could not be written.
62
+ */
63
+ export declare function rememberClaudePlan(plan: ClaudePlanId, home?: string): boolean;
64
+ /**
65
+ * The owner's settings page, under the project's console address, or `undefined` when
66
+ * this run has no console address (an older control, or none configured). No address
67
+ * is guessed: `bin.ts` passes the same address it prints as the project's console.
68
+ */
69
+ export declare function settingsPageUrl(consoleUrl: string | undefined): string | undefined;
70
+ /**
71
+ * Send the plan to `PUT /engagements/:engagementId/claude-plan` with the account
72
+ * credential. True only when control took it (a 2xx). Never throws.
73
+ */
74
+ export declare function sendClaudePlan(serviceUrl: string, engagementId: string, credential: string, plan: ClaudePlanId, fetchImpl?: typeof fetch): Promise<boolean>;
75
+ /** What `setupClaudePlan` did, for the caller's tests; `bin.ts` reads none of it. */
76
+ export type ClaudePlanSetupOutcome = {
77
+ readonly kind: 'not-owner';
78
+ } | {
79
+ readonly kind: 'no-person';
80
+ } | {
81
+ readonly kind: 'no-answer';
82
+ } | {
83
+ readonly kind: 'failed';
84
+ } | {
85
+ readonly kind: 'remembered';
86
+ readonly plan: ClaudePlanId;
87
+ readonly sent: boolean;
88
+ } | {
89
+ readonly kind: 'answered';
90
+ readonly plan: ClaudePlanId;
91
+ readonly sent: boolean;
92
+ };
93
+ export interface ClaudePlanSetupInput {
94
+ readonly serviceUrl: string;
95
+ readonly engagementId: string;
96
+ /** True when this run's account owns the project; false for a guest, or when ownership is not known. */
97
+ readonly ownsProject: boolean;
98
+ /** The project's console address this run prints, if any; the settings page is under it. */
99
+ readonly consoleUrl: string | undefined;
100
+ }
101
+ export interface ClaudePlanSetupDeps {
102
+ readonly interactive: () => boolean;
103
+ readonly ask: (question: string) => Promise<string>;
104
+ readonly write: (text: string) => void;
105
+ readonly env?: NodeJS.ProcessEnv;
106
+ readonly home?: string;
107
+ readonly fetchImpl?: typeof fetch;
108
+ }
109
+ /**
110
+ * The setup arm's one call: ask the plan once, remember it, send it (module
111
+ * docblock). Never throws; the outcome is for tests.
112
+ */
113
+ export declare function setupClaudePlan(input: ClaudePlanSetupInput, deps: ClaudePlanSetupDeps): Promise<ClaudePlanSetupOutcome>;
114
+ //# sourceMappingURL=claude-plan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-plan.d.ts","sourceRoot":"","sources":["../src/claude-plan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AAKH,OAAO,EAKL,KAAK,YAAY,EAClB,MAAM,mBAAmB,CAAC;AAG3B,6GAA6G;AAC7G,eAAO,MAAM,oBAAoB,qBAAqB,CAAC;AAEvD,6FAA6F;AAC7F,eAAO,MAAM,mBAAmB,IAAI,CAAC;AAQrC,uCAAuC;AACvC,wBAAgB,cAAc,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAOhF;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,YAAY,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAU7E;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAGlF;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAClC,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,YAAY,EAClB,SAAS,GAAE,OAAO,KAAa,GAC9B,OAAO,CAAC,OAAO,CAAC,CAiBlB;AAED,qFAAqF;AACrF,MAAM,MAAM,sBAAsB,GAC9B;IAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAA;CAAE,GAC9B;IAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAA;CAAE,GAC9B;IAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAA;CAAE,GAC9B;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,GAC3B;IAAE,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GACpF;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC;AAEvF,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,wGAAwG;IACxG,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,4FAA4F;IAC5F,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;CACzC;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,OAAO,CAAC;IACpC,QAAQ,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACpD,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACjC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CACnC;AASD;;;GAGG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,oBAAoB,EAC3B,IAAI,EAAE,mBAAmB,GACxB,OAAO,CAAC,sBAAsB,CAAC,CA+BjC"}
@@ -62,7 +62,7 @@
62
62
  * home is the failure mode it exists to prevent.
63
63
  */
64
64
  /** The verbs the CLI dispatches. Anything else after `halfcycle ` is unknown. */
65
- export declare const CLI_VERBS: readonly ["install", "check-drift", "build-record", "open-phase", "close-phase", "system", "draw", "plan", "review", "uninstall"];
65
+ export declare const CLI_VERBS: readonly ["install", "check-drift", "build-record", "open-phase", "close-phase", "system", "draw", "plan", "review", "check-tasks", "uninstall", "change", "pace", "prove"];
66
66
  export type CliVerb = (typeof CLI_VERBS)[number];
67
67
  /** A flag every invocation of the verb must carry. */
68
68
  export interface RequiredFlag {
@@ -85,10 +85,21 @@ export interface ConditionalFlag {
85
85
  readonly takesValue: boolean;
86
86
  readonly missingMessage: string;
87
87
  }
88
+ /**
89
+ * One form of a verb that has several, chosen by the first word after the verb
90
+ * (`change sort`, `change up`, `change done`). Each form declares its own required
91
+ * flags; the verb's own lists stay empty.
92
+ */
93
+ export interface FormContract {
94
+ readonly form: string;
95
+ readonly required: readonly RequiredFlag[];
96
+ readonly conditional: readonly ConditionalFlag[];
97
+ }
88
98
  export interface VerbContract {
89
99
  readonly verb: CliVerb;
90
100
  readonly required: readonly RequiredFlag[];
91
101
  readonly conditional: readonly ConditionalFlag[];
102
+ readonly forms?: readonly FormContract[];
92
103
  }
93
104
  /** The contract for a verb, or `undefined` when the CLI has no such verb. */
94
105
  export declare function contractFor(verb: string): VerbContract | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"cli-contract.d.ts","sourceRoot":"","sources":["../src/cli-contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8DG;AAIH,iFAAiF;AACjF,eAAO,MAAM,SAAS,mIAAoI,CAAC;AAE3J,MAAM,MAAM,OAAO,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC;AAEjD,sDAAsD;AACtD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,2DAA2D;IAC3D,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,+EAA+E;IAC/E,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAED,iDAAiD;AACjD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,CAAC;IAC3C,QAAQ,CAAC,WAAW,EAAE,SAAS,eAAe,EAAE,CAAC;CAClD;AAiFD,6EAA6E;AAC7E,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAElE;AAED,iDAAiD;AACjD,MAAM,WAAW,SAAS;IACxB,kEAAkE;IAClE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,oCAAoC;IACpC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAmBD;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,EAAE,CAyBxF;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAMtE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAMvE;AASD;;;;GAIG;AACH,eAAO,MAAM,kBAAkB;;CAErB,CAAC;AAyBX;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAa1F"}
1
+ {"version":3,"file":"cli-contract.d.ts","sourceRoot":"","sources":["../src/cli-contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8DG;AAIH,iFAAiF;AACjF,eAAO,MAAM,SAAS,6KAA8K,CAAC;AAErM,MAAM,MAAM,OAAO,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC;AAEjD,sDAAsD;AACtD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,2DAA2D;IAC3D,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,+EAA+E;IAC/E,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAED,iDAAiD;AACjD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAED;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,CAAC;IAC3C,QAAQ,CAAC,WAAW,EAAE,SAAS,eAAe,EAAE,CAAC;CAClD;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,CAAC;IAC3C,QAAQ,CAAC,WAAW,EAAE,SAAS,eAAe,EAAE,CAAC;IACjD,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;CAC1C;AAqID,6EAA6E;AAC7E,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAElE;AAED,iDAAiD;AACjD,MAAM,WAAW,SAAS;IACxB,kEAAkE;IAClE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,oCAAoC;IACpC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAmBD;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,EAAE,CAyBxF;AAuBD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAMtE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAMvE;AASD;;;;GAIG;AACH,eAAO,MAAM,kBAAkB;;CAErB,CAAC;AA0BX;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAa1F"}