wicked-crew 0.7.27 → 0.7.29

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 (135) hide show
  1. package/README.md +9 -1
  2. package/dist/api/chat-scope.d.ts +210 -0
  3. package/dist/api/chat-scope.d.ts.map +1 -0
  4. package/dist/api/chat-scope.js +724 -0
  5. package/dist/api/chat-scope.js.map +1 -0
  6. package/dist/api/diagnostics.d.ts +30 -2
  7. package/dist/api/diagnostics.d.ts.map +1 -1
  8. package/dist/api/diagnostics.js +73 -5
  9. package/dist/api/diagnostics.js.map +1 -1
  10. package/dist/api/governance-health.d.ts +163 -0
  11. package/dist/api/governance-health.d.ts.map +1 -0
  12. package/dist/api/governance-health.js +348 -0
  13. package/dist/api/governance-health.js.map +1 -0
  14. package/dist/api/open-path.d.ts.map +1 -1
  15. package/dist/api/open-path.js +2 -1
  16. package/dist/api/open-path.js.map +1 -1
  17. package/dist/api/post-hoc-deliver.d.ts +9 -5
  18. package/dist/api/post-hoc-deliver.d.ts.map +1 -1
  19. package/dist/api/post-hoc-deliver.js +21 -7
  20. package/dist/api/post-hoc-deliver.js.map +1 -1
  21. package/dist/api/routes.d.ts +56 -12
  22. package/dist/api/routes.d.ts.map +1 -1
  23. package/dist/api/routes.js +318 -50
  24. package/dist/api/routes.js.map +1 -1
  25. package/dist/api/seat-health.d.ts.map +1 -1
  26. package/dist/api/seat-health.js +25 -5
  27. package/dist/api/seat-health.js.map +1 -1
  28. package/dist/api/seat-signin.d.ts.map +1 -1
  29. package/dist/api/seat-signin.js +49 -23
  30. package/dist/api/seat-signin.js.map +1 -1
  31. package/dist/api/server.d.ts +13 -0
  32. package/dist/api/server.d.ts.map +1 -1
  33. package/dist/api/server.js +34 -0
  34. package/dist/api/server.js.map +1 -1
  35. package/dist/campaigns/routes.d.ts +4 -4
  36. package/dist/cli/governance.d.ts +131 -0
  37. package/dist/cli/governance.d.ts.map +1 -0
  38. package/dist/cli/governance.js +354 -0
  39. package/dist/cli/governance.js.map +1 -0
  40. package/dist/cli/index.js +114 -19
  41. package/dist/cli/index.js.map +1 -1
  42. package/dist/core/adapter.d.ts +89 -1
  43. package/dist/core/adapter.d.ts.map +1 -1
  44. package/dist/core/adapter.js +145 -25
  45. package/dist/core/adapter.js.map +1 -1
  46. package/dist/core/bridge-reaper.d.ts.map +1 -1
  47. package/dist/core/bridge-reaper.js +4 -1
  48. package/dist/core/bridge-reaper.js.map +1 -1
  49. package/dist/core/deliver-text.d.ts +184 -0
  50. package/dist/core/deliver-text.d.ts.map +1 -0
  51. package/dist/core/deliver-text.js +434 -0
  52. package/dist/core/deliver-text.js.map +1 -0
  53. package/dist/core/deliver-triage.d.ts +90 -0
  54. package/dist/core/deliver-triage.d.ts.map +1 -0
  55. package/dist/core/deliver-triage.js +106 -0
  56. package/dist/core/deliver-triage.js.map +1 -0
  57. package/dist/core/deliver.d.ts +129 -19
  58. package/dist/core/deliver.d.ts.map +1 -1
  59. package/dist/core/deliver.js +271 -57
  60. package/dist/core/deliver.js.map +1 -1
  61. package/dist/core/deliverable-floor.d.ts.map +1 -1
  62. package/dist/core/deliverable-floor.js +5 -4
  63. package/dist/core/deliverable-floor.js.map +1 -1
  64. package/dist/core/estate-mcp-client.d.ts.map +1 -1
  65. package/dist/core/estate-mcp-client.js +7 -2
  66. package/dist/core/estate-mcp-client.js.map +1 -1
  67. package/dist/core/exec.d.ts.map +1 -1
  68. package/dist/core/exec.js +11 -1
  69. package/dist/core/exec.js.map +1 -1
  70. package/dist/core/governance-store.d.ts +197 -0
  71. package/dist/core/governance-store.d.ts.map +1 -0
  72. package/dist/core/governance-store.js +283 -0
  73. package/dist/core/governance-store.js.map +1 -0
  74. package/dist/core/repoPaths.d.ts +36 -5
  75. package/dist/core/repoPaths.d.ts.map +1 -1
  76. package/dist/core/repoPaths.js +46 -4
  77. package/dist/core/repoPaths.js.map +1 -1
  78. package/dist/interactive/bridge-pool.d.ts +130 -2
  79. package/dist/interactive/bridge-pool.d.ts.map +1 -1
  80. package/dist/interactive/bridge-pool.js +286 -8
  81. package/dist/interactive/bridge-pool.js.map +1 -1
  82. package/dist/interactive/bus-location.d.ts +65 -0
  83. package/dist/interactive/bus-location.d.ts.map +1 -0
  84. package/dist/interactive/bus-location.js +75 -0
  85. package/dist/interactive/bus-location.js.map +1 -0
  86. package/dist/interactive/chat-events.d.ts.map +1 -1
  87. package/dist/interactive/chat-events.js +29 -23
  88. package/dist/interactive/chat-events.js.map +1 -1
  89. package/dist/interactive/demo-events.d.ts +16 -1
  90. package/dist/interactive/demo-events.d.ts.map +1 -1
  91. package/dist/interactive/demo-events.js +262 -43
  92. package/dist/interactive/demo-events.js.map +1 -1
  93. package/dist/interactive/doc-grounding.d.ts +202 -0
  94. package/dist/interactive/doc-grounding.d.ts.map +1 -0
  95. package/dist/interactive/doc-grounding.js +647 -0
  96. package/dist/interactive/doc-grounding.js.map +1 -0
  97. package/dist/interactive/draft-events.d.ts +54 -1
  98. package/dist/interactive/draft-events.d.ts.map +1 -1
  99. package/dist/interactive/draft-events.js +234 -117
  100. package/dist/interactive/draft-events.js.map +1 -1
  101. package/dist/interactive/edit-events.d.ts.map +1 -1
  102. package/dist/interactive/edit-events.js +27 -21
  103. package/dist/interactive/edit-events.js.map +1 -1
  104. package/dist/interactive/proxy-routes.d.ts +78 -0
  105. package/dist/interactive/proxy-routes.d.ts.map +1 -1
  106. package/dist/interactive/proxy-routes.js +355 -14
  107. package/dist/interactive/proxy-routes.js.map +1 -1
  108. package/dist/interactive/repo-snapshot.d.ts +31 -0
  109. package/dist/interactive/repo-snapshot.d.ts.map +1 -1
  110. package/dist/interactive/repo-snapshot.js +56 -1
  111. package/dist/interactive/repo-snapshot.js.map +1 -1
  112. package/dist/projects/graph-paths.d.ts +4 -2
  113. package/dist/projects/graph-paths.d.ts.map +1 -1
  114. package/dist/projects/graph-paths.js +4 -2
  115. package/dist/projects/graph-paths.js.map +1 -1
  116. package/dist/projects/graph.d.ts +5 -4
  117. package/dist/projects/graph.d.ts.map +1 -1
  118. package/dist/projects/graph.js +22 -5
  119. package/dist/projects/graph.js.map +1 -1
  120. package/dist/projects/routes.d.ts.map +1 -1
  121. package/dist/projects/routes.js +18 -9
  122. package/dist/projects/routes.js.map +1 -1
  123. package/dist/qe/conformance.d.ts +10 -1
  124. package/dist/qe/conformance.d.ts.map +1 -1
  125. package/dist/qe/conformance.js +57 -4
  126. package/dist/qe/conformance.js.map +1 -1
  127. package/dist/skills/plugin-source.d.ts.map +1 -1
  128. package/dist/skills/plugin-source.js +3 -0
  129. package/dist/skills/plugin-source.js.map +1 -1
  130. package/dist/studio/assets/index-CeJTutxP.js +540 -0
  131. package/dist/studio/index.html +1 -1
  132. package/dist/studio/testid-inventory.json +333 -7
  133. package/endpoint-manifest.json +75 -12
  134. package/package.json +3 -3
  135. package/dist/studio/assets/index-FcZg3WDR.js +0 -539
@@ -0,0 +1,131 @@
1
+ /**
2
+ * `wicked-crew governance replay <outbox> [--governance-db <path> | --db <core db>] [--dry-run]`
3
+ * (crew#495, F-022): drain a dead-letter outbox back into the governance store.
4
+ *
5
+ * The engine spools every `wicked.*` event it could not store as one NDJSON line (`emit.rs`
6
+ * `spool_record`: the envelope plus `deadletter_reason`, and — on engines carrying crew#495's
7
+ * companion — `ts`, `pid`, `origin`). This command hands that file to the engine, which writes
8
+ * each record as the EVENT node it should have been, restoring the original `ts` where the record
9
+ * carries one so an id-ordered scan of the store is still chronological.
10
+ *
11
+ * Drain order matters, because the daemon may be appending to the SAME file while this runs:
12
+ * 1. RENAME the outbox to `<outbox>.replayed-<ISO>` first — atomic, so the daemon's next spool
13
+ * recreates a fresh file and no entry is lost between the read and the archive;
14
+ * 2. replay from the archived file;
15
+ * 3. APPEND the entries that failed to land back onto the live outbox — they stay dead letters,
16
+ * visible on `/diagnostics`, and the archive keeps the full record of what was attempted.
17
+ * `--dry-run` folds the outbox in place (count, types, reasons, timestamp range) and moves nothing.
18
+ *
19
+ * Target store resolution is `serve`'s (`core/governance-store.ts`): `--governance-db` ›
20
+ * `WICKED_CREW_GOVERNANCE_DB` › an inherited `WICKED_ESTATE_DB` › `<core db>.governance/
21
+ * governance.db`, with `--db` naming the core db (default: the state home's `core.db`).
22
+ *
23
+ * Exit codes: 0 every entry landed (or dry run); 1 some entries failed (they are back on the
24
+ * outbox); 2 the installed engine cannot replay (`Core.replayEmitOutbox` absent — upgrade
25
+ * wicked-core-ts), or the arguments are wrong.
26
+ */
27
+ import { Transform, type TransformCallback } from 'node:stream';
28
+ import { type GovernanceStoreLocation } from '../core/governance-store.js';
29
+ import { foldDeadletters, type DeadletterFold } from '../api/governance-health.js';
30
+ export declare const GOVERNANCE_USAGE: string;
31
+ /** crew's own package version, for the origin stamp the engine copies onto dead-letter records. */
32
+ export declare function crewPackageVersion(): string;
33
+ export declare class UsageError extends Error {
34
+ constructor(message: string);
35
+ }
36
+ /** The non-flag arguments, in order (`--dry-run` takes no value; `--db` / `--governance-db` do). */
37
+ export declare function positionalArgs(args: string[]): string[];
38
+ /** Resolve the target store for a replay — `serve`'s rule, over the core db named (or defaulted),
39
+ * with the cross-product bus resolved the way `serve` resolves it (`WICKED_BUS_DB` ›
40
+ * `WICKED_BUS_DATA_DIR` › `<core db>.bus/bus.db`) so the bus db is refused as a target here too. */
41
+ export declare function replayTarget(args: string[], env?: NodeJS.ProcessEnv): GovernanceStoreLocation;
42
+ /** The archive name a drained outbox is renamed to: timestamp + pid + a random nonce, so two replays
43
+ * of the same outbox in the same millisecond (or two processes) can never pick one name and have a
44
+ * later rename replace the earlier archive — the full recovery/audit copy. */
45
+ export declare function archiveNameFor(outbox: string, now?: Date, nonce?: string): string;
46
+ /**
47
+ * Put the lines that did not land back onto the live outbox — and if THAT write fails (permissions,
48
+ * a full disk), say exactly where they are: the archive is retained (nothing is lost on disk), but
49
+ * `/diagnostics` folds only the live path, so without this the operator would see fewer dead letters
50
+ * than exist.
51
+ */
52
+ export declare function appendFailedLines(outbox: string, archive: string, lines: string[]): void;
53
+ /**
54
+ * The caveat a replay that found entries `already_present` must state when the outbox holds
55
+ * UNTIMESTAMPED (pre-stamp) entries: replay ids are content-addressed, and with no stamp to tell
56
+ * them apart, byte-identical unstamped lines share one id — two dead letters of the same event land
57
+ * once. `null` when there is nothing to say.
58
+ */
59
+ export declare function conflationNote(alreadyPresent: number, fold: Pick<DeadletterFold, 'untimestamped'>): string | null;
60
+ /**
61
+ * Keep every NDJSON record whole while streaming one file onto another that a concurrent writer may
62
+ * also be appending to. Every chunk this transform emits is a whole number of records — it buffers
63
+ * up to the last `\n` it has seen and holds the partial tail until more arrives — so an `O_APPEND`
64
+ * write from the other writer landing between two of our writes can only ever sit BETWEEN records,
65
+ * never inside one (read-stream chunks are 64 KiB and not line-aligned; forwarding them raw would
66
+ * let a fresh record be spliced into the middle of an archived one). Two repairs ride INSIDE the
67
+ * data writes, never as separate writes a concurrent spool could slip in front of: a leading `\n`
68
+ * always opens the first emitted chunk (the live file may gain a torn tail between any look and
69
+ * our first write — a check-then-write cannot close that, an unconditional separator does; an
70
+ * empty NDJSON line is skipped by every reader), and a source whose last record lacks its newline
71
+ * gets one appended to that same final write.
72
+ */
73
+ export declare class LineBoundaryGuard extends Transform {
74
+ private readonly leading;
75
+ private carry;
76
+ private first;
77
+ constructor(leading: boolean);
78
+ /** Push one chunk of whole records, opening the very first with the leading separator. */
79
+ private pushRecords;
80
+ _transform(chunk: Buffer | string, _enc: BufferEncoding, cb: TransformCallback): void;
81
+ _flush(cb: TransformCallback): void;
82
+ }
83
+ /**
84
+ * Append NDJSON lines to a live outbox a daemon may be writing — ONE `write()`, ALWAYS behind a
85
+ * `\n`: the file may be absent, at a boundary, or mid-record at the instant of the write, and no
86
+ * look beforehand can know which (the engine writes a record and its newline as two syscalls), so
87
+ * an unconditional separator is the only race-free choice. At worst it is an empty line, which
88
+ * every reader — the fold, the engine's replay — skips.
89
+ */
90
+ export declare function appendLines(outbox: string, lines: string[]): void;
91
+ /**
92
+ * Put an archived outbox back after a replay that threw — APPEND-ONLY, never a rename over the
93
+ * live path: a daemon can create a fresh outbox at any instant, and an `exists`-then-`rename` would
94
+ * replace it and lose what it had just spooled. Appending (`O_APPEND`, so a concurrent spool is
95
+ * never clobbered — the file is created if absent) is loss-free in every interleaving; the cost is
96
+ * the two batches' relative order when the daemon did spool meanwhile (each entry carries its own
97
+ * `ts` on a stamping engine). Streamed, never the whole archive in memory, through
98
+ * {@link LineBoundaryGuard}: whole records per write, the live tail separated first, a torn last
99
+ * record terminated in its own write. The archive is removed only after its last byte is on the
100
+ * live outbox.
101
+ */
102
+ export declare function restoreOutbox(outbox: string, archive: string): Promise<void>;
103
+ export interface ReplayOutcome {
104
+ outbox: string;
105
+ store: {
106
+ path: string;
107
+ source: string;
108
+ };
109
+ archive: string | null;
110
+ read: number;
111
+ replayed: number;
112
+ /** Entries an earlier replay had already landed (a re-replay is a no-op); `null` on an engine that does not report it. */
113
+ alreadyPresent: number | null;
114
+ failed: number;
115
+ dryRun: boolean;
116
+ /** The conflation caveat (see `conflationNote`), or `null`. */
117
+ note: string | null;
118
+ fold?: Awaited<ReturnType<typeof foldDeadletters>>;
119
+ }
120
+ /**
121
+ * The command body, separated from process I/O so a test can drive it. Returns the outcome and the
122
+ * exit code; throws {@link UsageError} for bad arguments and {@link GovernanceReplayUnsupportedError}
123
+ * on an addon without the binding (the CLI maps both to exit 2).
124
+ */
125
+ export declare function replayOutbox(args: string[], env?: NodeJS.ProcessEnv): Promise<{
126
+ outcome: ReplayOutcome;
127
+ exitCode: 0 | 1;
128
+ }>;
129
+ /** The `wicked-crew governance …` entry: prints a JSON outcome and exits with the documented code. */
130
+ export declare function runGovernance(argv: string[]): Promise<void>;
131
+ //# sourceMappingURL=governance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"governance.d.ts","sourceRoot":"","sources":["../../src/cli/governance.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,354 @@
1
+ /**
2
+ * `wicked-crew governance replay <outbox> [--governance-db <path> | --db <core db>] [--dry-run]`
3
+ * (crew#495, F-022): drain a dead-letter outbox back into the governance store.
4
+ *
5
+ * The engine spools every `wicked.*` event it could not store as one NDJSON line (`emit.rs`
6
+ * `spool_record`: the envelope plus `deadletter_reason`, and — on engines carrying crew#495's
7
+ * companion — `ts`, `pid`, `origin`). This command hands that file to the engine, which writes
8
+ * each record as the EVENT node it should have been, restoring the original `ts` where the record
9
+ * carries one so an id-ordered scan of the store is still chronological.
10
+ *
11
+ * Drain order matters, because the daemon may be appending to the SAME file while this runs:
12
+ * 1. RENAME the outbox to `<outbox>.replayed-<ISO>` first — atomic, so the daemon's next spool
13
+ * recreates a fresh file and no entry is lost between the read and the archive;
14
+ * 2. replay from the archived file;
15
+ * 3. APPEND the entries that failed to land back onto the live outbox — they stay dead letters,
16
+ * visible on `/diagnostics`, and the archive keeps the full record of what was attempted.
17
+ * `--dry-run` folds the outbox in place (count, types, reasons, timestamp range) and moves nothing.
18
+ *
19
+ * Target store resolution is `serve`'s (`core/governance-store.ts`): `--governance-db` ›
20
+ * `WICKED_CREW_GOVERNANCE_DB` › an inherited `WICKED_ESTATE_DB` › `<core db>.governance/
21
+ * governance.db`, with `--db` naming the core db (default: the state home's `core.db`).
22
+ *
23
+ * Exit codes: 0 every entry landed (or dry run); 1 some entries failed (they are back on the
24
+ * outbox); 2 the installed engine cannot replay (`Core.replayEmitOutbox` absent — upgrade
25
+ * wicked-core-ts), or the arguments are wrong.
26
+ */
27
+ import { appendFileSync, createReadStream, createWriteStream, existsSync, mkdirSync, readFileSync, renameSync, rmSync, statSync, } from 'node:fs';
28
+ import { dirname, join, resolve } from 'node:path';
29
+ import { Transform } from 'node:stream';
30
+ import { pipeline } from 'node:stream/promises';
31
+ import { fileURLToPath } from 'node:url';
32
+ import { randomBytes } from 'node:crypto';
33
+ import { CoreAdapter, GovernanceReplayUnsupportedError } from '../core/adapter.js';
34
+ import { CrewBusError, resolveCrewBus } from '../interactive/bus-location.js';
35
+ import { EMIT_DEADLETTER_ENGINE_ENV, ESTATE_DB_ENGINE_ENV, GOVERNANCE_DB_ENV, GOVERNANCE_DB_FLAG, GovernanceStoreError, isStoreSpec, resolveGovernanceStore, } from '../core/governance-store.js';
36
+ import { foldDeadletters } from '../api/governance-health.js';
37
+ import { crewStateHome } from '../projects/state-home.js';
38
+ export const GOVERNANCE_USAGE = 'Usage: wicked-crew governance replay <outbox.ndjson> [--governance-db <path> | --db <core db>] [--dry-run]\n' +
39
+ '\n' +
40
+ 'Replay a dead-letter outbox (the engine\'s NDJSON spool of governance events it could not store)\n' +
41
+ 'into the governance store. Resolution of the store matches `serve`:\n' +
42
+ ` ${GOVERNANCE_DB_FLAG} <path> explicit store (env: ${GOVERNANCE_DB_ENV}; an inherited ${ESTATE_DB_ENGINE_ENV} is honoured next)\n` +
43
+ ' --db <path> the core db whose sidecar store is the default target (<core db>.governance/governance.db;\n' +
44
+ ' default core db: ~/.wicked-crew/core.db)\n' +
45
+ ' --dry-run fold the outbox (count, types, reasons, timestamp range) and move nothing\n' +
46
+ '\n' +
47
+ 'The outbox is archived to <outbox>.replayed-<timestamp> BEFORE replay (so a running daemon\'s next\n' +
48
+ 'spool starts a fresh file); entries that fail to land are appended back onto the outbox.\n' +
49
+ `A daemon's own outbox is <core db>.governance/emit-outbox.ndjson (env: ${EMIT_DEADLETTER_ENGINE_ENV});\n` +
50
+ 'a pre-fix engine wrote ~/.something-wicked/wicked-apps/emit-outbox.ndjson.';
51
+ /** crew's own package version, for the origin stamp the engine copies onto dead-letter records. */
52
+ export function crewPackageVersion() {
53
+ try {
54
+ const raw = readFileSync(fileURLToPath(new URL('../../package.json', import.meta.url)), 'utf8');
55
+ return JSON.parse(raw).version ?? '0.0.0';
56
+ }
57
+ catch {
58
+ return '0.0.0';
59
+ }
60
+ }
61
+ function flag(args, name) {
62
+ const i = args.indexOf(name);
63
+ return i >= 0 ? args[i + 1] : undefined;
64
+ }
65
+ /** A flag that was given must carry a value, and the value must not be another flag. */
66
+ function flagValue(args, name) {
67
+ if (!args.includes(name))
68
+ return undefined;
69
+ const value = flag(args, name);
70
+ if (value === undefined || value.startsWith('-')) {
71
+ throw new UsageError(`${name} requires a value (got: ${value ?? '(missing)'})`);
72
+ }
73
+ return value;
74
+ }
75
+ export class UsageError extends Error {
76
+ constructor(message) {
77
+ super(message);
78
+ this.name = 'UsageError';
79
+ }
80
+ }
81
+ /** The flags that take a value — their value is never a positional. */
82
+ const VALUE_FLAGS = new Set(['--db', GOVERNANCE_DB_FLAG]);
83
+ /** The non-flag arguments, in order (`--dry-run` takes no value; `--db` / `--governance-db` do). */
84
+ export function positionalArgs(args) {
85
+ const out = [];
86
+ for (let i = 0; i < args.length; i += 1) {
87
+ const a = args[i];
88
+ if (VALUE_FLAGS.has(a)) {
89
+ i += 1; // skip the flag's value
90
+ continue;
91
+ }
92
+ if (a.startsWith('-'))
93
+ continue;
94
+ out.push(a);
95
+ }
96
+ return out;
97
+ }
98
+ /** Resolve the target store for a replay — `serve`'s rule, over the core db named (or defaulted),
99
+ * with the cross-product bus resolved the way `serve` resolves it (`WICKED_BUS_DB` ›
100
+ * `WICKED_BUS_DATA_DIR` › `<core db>.bus/bus.db`) so the bus db is refused as a target here too. */
101
+ export function replayTarget(args, env = process.env) {
102
+ const coreDbPath = flagValue(args, '--db') ?? join(crewStateHome(), 'core.db');
103
+ const bus = resolveCrewBus({ explicitDb: env['WICKED_BUS_DB'], envDataDir: env['WICKED_BUS_DATA_DIR'], coreDbPath });
104
+ return resolveGovernanceStore({
105
+ flagDb: flagValue(args, GOVERNANCE_DB_FLAG),
106
+ envCrewDb: env[GOVERNANCE_DB_ENV],
107
+ envEstateDb: env[ESTATE_DB_ENGINE_ENV],
108
+ coreDbPath,
109
+ busDbPath: bus.dbPath,
110
+ });
111
+ }
112
+ /** The archive name a drained outbox is renamed to: timestamp + pid + a random nonce, so two replays
113
+ * of the same outbox in the same millisecond (or two processes) can never pick one name and have a
114
+ * later rename replace the earlier archive — the full recovery/audit copy. */
115
+ export function archiveNameFor(outbox, now = new Date(), nonce = randomBytes(3).toString('hex')) {
116
+ return `${outbox}.replayed-${now.toISOString().replace(/[:.]/g, '-')}-${process.pid}-${nonce}`;
117
+ }
118
+ /** A fresh archive name that does not exist yet (the nonce makes a collision astronomically
119
+ * unlikely; the check makes it impossible to rename over an existing archive). */
120
+ function reserveArchiveName(outbox) {
121
+ for (;;) {
122
+ const candidate = archiveNameFor(outbox);
123
+ if (!existsSync(candidate))
124
+ return candidate;
125
+ }
126
+ }
127
+ /**
128
+ * Put the lines that did not land back onto the live outbox — and if THAT write fails (permissions,
129
+ * a full disk), say exactly where they are: the archive is retained (nothing is lost on disk), but
130
+ * `/diagnostics` folds only the live path, so without this the operator would see fewer dead letters
131
+ * than exist.
132
+ */
133
+ export function appendFailedLines(outbox, archive, lines) {
134
+ try {
135
+ appendLines(outbox, lines);
136
+ }
137
+ catch (err) {
138
+ const reason = err instanceof Error ? err.message : String(err);
139
+ throw new Error(`${lines.length} line(s) that failed to replay could not be written back to ${outbox} — they remain in the ` +
140
+ `retained archive ${archive} (nothing is lost; /diagnostics does not fold the archive): ${reason}`);
141
+ }
142
+ }
143
+ /**
144
+ * The caveat a replay that found entries `already_present` must state when the outbox holds
145
+ * UNTIMESTAMPED (pre-stamp) entries: replay ids are content-addressed, and with no stamp to tell
146
+ * them apart, byte-identical unstamped lines share one id — two dead letters of the same event land
147
+ * once. `null` when there is nothing to say.
148
+ */
149
+ export function conflationNote(alreadyPresent, fold) {
150
+ if (alreadyPresent <= 0 || fold.untimestamped <= 0)
151
+ return null;
152
+ return (`${alreadyPresent} entr${alreadyPresent === 1 ? 'y was' : 'ies were'} already on the store. This outbox holds ` +
153
+ `${fold.untimestamped} untimestamped (pre-stamp) entr${fold.untimestamped === 1 ? 'y' : 'ies'}: byte-identical ` +
154
+ 'unstamped lines share one replay id, so two dead letters of the same event land once (stamped lines never conflate ' +
155
+ 'unless their ts and content both match).');
156
+ }
157
+ const NL = 0x0a;
158
+ /**
159
+ * Keep every NDJSON record whole while streaming one file onto another that a concurrent writer may
160
+ * also be appending to. Every chunk this transform emits is a whole number of records — it buffers
161
+ * up to the last `\n` it has seen and holds the partial tail until more arrives — so an `O_APPEND`
162
+ * write from the other writer landing between two of our writes can only ever sit BETWEEN records,
163
+ * never inside one (read-stream chunks are 64 KiB and not line-aligned; forwarding them raw would
164
+ * let a fresh record be spliced into the middle of an archived one). Two repairs ride INSIDE the
165
+ * data writes, never as separate writes a concurrent spool could slip in front of: a leading `\n`
166
+ * always opens the first emitted chunk (the live file may gain a torn tail between any look and
167
+ * our first write — a check-then-write cannot close that, an unconditional separator does; an
168
+ * empty NDJSON line is skipped by every reader), and a source whose last record lacks its newline
169
+ * gets one appended to that same final write.
170
+ */
171
+ export class LineBoundaryGuard extends Transform {
172
+ leading;
173
+ carry = Buffer.alloc(0);
174
+ first = true;
175
+ constructor(leading) {
176
+ super();
177
+ this.leading = leading;
178
+ }
179
+ /** Push one chunk of whole records, opening the very first with the leading separator. */
180
+ pushRecords(data) {
181
+ let out = data;
182
+ if (this.first) {
183
+ this.first = false;
184
+ if (this.leading)
185
+ out = Buffer.concat([Buffer.from('\n'), out]);
186
+ }
187
+ this.push(out);
188
+ }
189
+ _transform(chunk, _enc, cb) {
190
+ const data = Buffer.concat([this.carry, Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)]);
191
+ const lastNl = data.lastIndexOf(NL);
192
+ if (lastNl < 0) {
193
+ this.carry = data; // no complete record yet — hold everything
194
+ }
195
+ else {
196
+ this.pushRecords(data.subarray(0, lastNl + 1)); // whole records only
197
+ this.carry = data.subarray(lastNl + 1); // the partial tail, if any
198
+ }
199
+ cb();
200
+ }
201
+ _flush(cb) {
202
+ if (this.carry.length > 0) {
203
+ this.pushRecords(Buffer.concat([this.carry, Buffer.from('\n')])); // the torn last record, terminated in the same write
204
+ this.carry = Buffer.alloc(0);
205
+ }
206
+ cb();
207
+ }
208
+ }
209
+ /**
210
+ * Append NDJSON lines to a live outbox a daemon may be writing — ONE `write()`, ALWAYS behind a
211
+ * `\n`: the file may be absent, at a boundary, or mid-record at the instant of the write, and no
212
+ * look beforehand can know which (the engine writes a record and its newline as two syscalls), so
213
+ * an unconditional separator is the only race-free choice. At worst it is an empty line, which
214
+ * every reader — the fold, the engine's replay — skips.
215
+ */
216
+ export function appendLines(outbox, lines) {
217
+ if (lines.length === 0)
218
+ return;
219
+ appendFileSync(outbox, `\n${lines.join('\n')}\n`, 'utf8');
220
+ }
221
+ /**
222
+ * Put an archived outbox back after a replay that threw — APPEND-ONLY, never a rename over the
223
+ * live path: a daemon can create a fresh outbox at any instant, and an `exists`-then-`rename` would
224
+ * replace it and lose what it had just spooled. Appending (`O_APPEND`, so a concurrent spool is
225
+ * never clobbered — the file is created if absent) is loss-free in every interleaving; the cost is
226
+ * the two batches' relative order when the daemon did spool meanwhile (each entry carries its own
227
+ * `ts` on a stamping engine). Streamed, never the whole archive in memory, through
228
+ * {@link LineBoundaryGuard}: whole records per write, the live tail separated first, a torn last
229
+ * record terminated in its own write. The archive is removed only after its last byte is on the
230
+ * live outbox.
231
+ */
232
+ export async function restoreOutbox(outbox, archive) {
233
+ if (statSync(archive).size > 0) {
234
+ await pipeline(createReadStream(archive), new LineBoundaryGuard(true), createWriteStream(outbox, { flags: 'a' }));
235
+ }
236
+ rmSync(archive);
237
+ }
238
+ /**
239
+ * The command body, separated from process I/O so a test can drive it. Returns the outcome and the
240
+ * exit code; throws {@link UsageError} for bad arguments and {@link GovernanceReplayUnsupportedError}
241
+ * on an addon without the binding (the CLI maps both to exit 2).
242
+ */
243
+ export async function replayOutbox(args, env = process.env) {
244
+ const outboxArg = positionalArgs(args)[0];
245
+ if (outboxArg === undefined)
246
+ throw new UsageError('missing <outbox.ndjson>');
247
+ const outbox = resolve(outboxArg);
248
+ if (!existsSync(outbox))
249
+ throw new UsageError(`outbox not found: ${outbox}`);
250
+ const dryRun = args.includes('--dry-run');
251
+ const store = replayTarget(args, env);
252
+ if (dryRun) {
253
+ // A dry run folds the FILE and touches no store — so the same target configuration a daemon
254
+ // runs with (`:memory:` included) is inspectable; the refusal below guards only a real replay.
255
+ const fold = await foldDeadletters(outbox);
256
+ return {
257
+ outcome: {
258
+ outbox,
259
+ store: { path: store.displayPath, source: store.source },
260
+ archive: null,
261
+ read: fold.count,
262
+ replayed: 0,
263
+ alreadyPresent: null,
264
+ failed: 0,
265
+ dryRun: true,
266
+ note: null,
267
+ fold,
268
+ },
269
+ exitCode: 0,
270
+ };
271
+ }
272
+ if (store.dbPath === ':memory:') {
273
+ throw new UsageError('refusing to replay into :memory: — name a durable store with --governance-db or --db');
274
+ }
275
+ if (!CoreAdapter.replayEmitOutboxSupported()) {
276
+ throw new GovernanceReplayUnsupportedError('Replaying a dead-letter outbox');
277
+ }
278
+ // The sidecar (or whatever directory the store lives in) must exist before the engine opens it
279
+ // — for a filesystem path, never for an engine spec (`postgres://…`; `:memory:` was refused above).
280
+ if (!isStoreSpec(store.dbPath))
281
+ mkdirSync(dirname(store.dbPath), { recursive: true });
282
+ // 1. Archive first — atomic, so nothing the daemon appends from here on is lost; the name is
283
+ // fresh (timestamp + pid + nonce, checked), so no earlier archive is ever renamed over.
284
+ const archive = reserveArchiveName(outbox);
285
+ renameSync(outbox, archive);
286
+ // 2. Replay from the archive. If the engine THROWS (a store it cannot open, an I/O error
287
+ // mid-file, a permission problem) the archive goes back where the daemon spools and
288
+ // `/diagnostics` looks — an exception must never turn "not replayed" into "0 dead letters".
289
+ // Restored WHOLE: the engine may have landed some records before it threw; a later replay of
290
+ // those is a no-op (replay ids are deterministic per spool line), so nothing is duplicated and
291
+ // nothing is lost.
292
+ let report;
293
+ try {
294
+ report = await CoreAdapter.replayEmitOutbox(archive, store.dbPath);
295
+ }
296
+ catch (err) {
297
+ await restoreOutbox(outbox, archive);
298
+ const reason = err instanceof Error ? err.message : String(err);
299
+ throw new Error(`replay failed and the outbox was restored to ${outbox} (nothing is lost): ${reason}`);
300
+ }
301
+ // 3. What did not land stays a dead letter on the live outbox (append: the daemon may have
302
+ // started a fresh file already — and may be mid-record on it, hence the boundary-safe append);
303
+ // a failed write-back names the archive the lines are still in.
304
+ if (report.failed.length > 0) {
305
+ appendFailedLines(outbox, archive, report.failed.map((f) => f.line));
306
+ }
307
+ const alreadyPresent = report.already_present ?? null;
308
+ const note = alreadyPresent !== null && alreadyPresent > 0 ? conflationNote(alreadyPresent, await foldDeadletters(archive)) : null;
309
+ return {
310
+ outcome: {
311
+ outbox,
312
+ store: { path: store.displayPath, source: store.source },
313
+ archive,
314
+ read: report.read,
315
+ replayed: report.replayed,
316
+ alreadyPresent,
317
+ failed: report.failed.length,
318
+ dryRun: false,
319
+ note,
320
+ },
321
+ exitCode: report.failed.length > 0 ? 1 : 0,
322
+ };
323
+ }
324
+ /** The `wicked-crew governance …` entry: prints a JSON outcome and exits with the documented code. */
325
+ export async function runGovernance(argv) {
326
+ const [sub, ...rest] = argv;
327
+ if (sub !== 'replay' || rest.includes('--help') || rest.includes('-h')) {
328
+ console.error(GOVERNANCE_USAGE);
329
+ process.exit(sub === 'replay' ? 0 : 2);
330
+ }
331
+ try {
332
+ const { outcome, exitCode } = await replayOutbox(rest);
333
+ console.log(JSON.stringify(outcome, null, 2));
334
+ if (outcome.note !== null)
335
+ console.error(`[governance] ${outcome.note}`);
336
+ if (!outcome.dryRun && outcome.failed > 0) {
337
+ console.error(`[governance] ${outcome.failed} entr${outcome.failed === 1 ? 'y' : 'ies'} did not land and were appended back onto ${outcome.outbox}`);
338
+ }
339
+ process.exit(exitCode);
340
+ }
341
+ catch (err) {
342
+ if (err instanceof UsageError || err instanceof GovernanceStoreError || err instanceof CrewBusError) {
343
+ console.error(`[governance] ${err.message}\n\n${GOVERNANCE_USAGE}`);
344
+ process.exit(2);
345
+ }
346
+ if (err instanceof GovernanceReplayUnsupportedError) {
347
+ console.error(`[governance] ${err.message}\n` +
348
+ 'Nothing was moved. Inspect the outbox with --dry-run; replay once the engine is upgraded.');
349
+ process.exit(2);
350
+ }
351
+ throw err;
352
+ }
353
+ }
354
+ //# sourceMappingURL=governance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"governance.js","sourceRoot":"","sources":["../../src/cli/governance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,UAAU,EACV,SAAS,EACT,YAAY,EACZ,UAAU,EACV,MAAM,EACN,QAAQ,GACT,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,SAAS,EAA0B,MAAM,aAAa,CAAC;AAChE,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,EAAE,WAAW,EAAE,gCAAgC,EAA+B,MAAM,oBAAoB,CAAC;AAChH,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAC9E,OAAO,EACL,0BAA0B,EAC1B,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,WAAW,EACX,sBAAsB,GAEvB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,eAAe,EAAuB,MAAM,6BAA6B,CAAC;AACnF,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE1D,MAAM,CAAC,MAAM,gBAAgB,GAC3B,8GAA8G;IAC9G,IAAI;IACJ,oGAAoG;IACpG,uEAAuE;IACvE,KAAK,kBAAkB,iCAAiC,iBAAiB,kBAAkB,oBAAoB,sBAAsB;IACrI,yHAAyH;IACzH,uEAAuE;IACvE,wGAAwG;IACxG,IAAI;IACJ,sGAAsG;IACtG,4FAA4F;IAC5F,0EAA0E,0BAA0B,MAAM;IAC1G,4EAA4E,CAAC;AAE/E,mGAAmG;AACnG,MAAM,UAAU,kBAAkB;IAChC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,aAAa,CAAC,IAAI,GAAG,CAAC,oBAAoB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QAChG,OAAQ,IAAI,CAAC,KAAK,CAAC,GAAG,CAA0B,CAAC,OAAO,IAAI,OAAO,CAAC;IACtE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC;IACjB,CAAC;AACH,CAAC;AAED,SAAS,IAAI,CAAC,IAAc,EAAE,IAAY;IACxC,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC1C,CAAC;AAED,wFAAwF;AACxF,SAAS,SAAS,CAAC,IAAc,EAAE,IAAY;IAC7C,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,SAAS,CAAC;IAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC/B,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACjD,MAAM,IAAI,UAAU,CAAC,GAAG,IAAI,2BAA2B,KAAK,IAAI,WAAW,GAAG,CAAC,CAAC;IAClF,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,OAAO,UAAW,SAAQ,KAAK;IACnC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;IAC3B,CAAC;CACF;AAED,uEAAuE;AACvE,MAAM,WAAW,GAAwB,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC,CAAC;AAE/E,oGAAoG;AACpG,MAAM,UAAU,cAAc,CAAC,IAAc;IAC3C,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACxC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC;QACnB,IAAI,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YACvB,CAAC,IAAI,CAAC,CAAC,CAAC,wBAAwB;YAChC,SAAS;QACX,CAAC;QACD,IAAI,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QAChC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACd,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;qGAEqG;AACrG,MAAM,UAAU,YAAY,CAAC,IAAc,EAAE,MAAyB,OAAO,CAAC,GAAG;IAC/E,MAAM,UAAU,GAAG,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,CAAC,aAAa,EAAE,EAAE,SAAS,CAAC,CAAC;IAC/E,MAAM,GAAG,GAAG,cAAc,CAAC,EAAE,UAAU,EAAE,GAAG,CAAC,eAAe,CAAC,EAAE,UAAU,EAAE,GAAG,CAAC,qBAAqB,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC;IACrH,OAAO,sBAAsB,CAAC;QAC5B,MAAM,EAAE,SAAS,CAAC,IAAI,EAAE,kBAAkB,CAAC;QAC3C,SAAS,EAAE,GAAG,CAAC,iBAAiB,CAAC;QACjC,WAAW,EAAE,GAAG,CAAC,oBAAoB,CAAC;QACtC,UAAU;QACV,SAAS,EAAE,GAAG,CAAC,MAAM;KACtB,CAAC,CAAC;AACL,CAAC;AAED;;+EAE+E;AAC/E,MAAM,UAAU,cAAc,CAAC,MAAc,EAAE,MAAY,IAAI,IAAI,EAAE,EAAE,QAAgB,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;IACnH,OAAO,GAAG,MAAM,aAAa,GAAG,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,IAAI,OAAO,CAAC,GAAG,IAAI,KAAK,EAAE,CAAC;AACjG,CAAC;AAED;mFACmF;AACnF,SAAS,kBAAkB,CAAC,MAAc;IACxC,SAAS,CAAC;QACR,MAAM,SAAS,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;QACzC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;YAAE,OAAO,SAAS,CAAC;IAC/C,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAc,EAAE,OAAe,EAAE,KAAe;IAChF,IAAI,CAAC;QACH,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC7B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,MAAM,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAChE,MAAM,IAAI,KAAK,CACb,GAAG,KAAK,CAAC,MAAM,+DAA+D,MAAM,wBAAwB;YAC1G,oBAAoB,OAAO,+DAA+D,MAAM,EAAE,CACrG,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,cAAsB,EAAE,IAA2C;IAChG,IAAI,cAAc,IAAI,CAAC,IAAI,IAAI,CAAC,aAAa,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAChE,OAAO,CACL,GAAG,cAAc,QAAQ,cAAc,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,2CAA2C;QAC/G,GAAG,IAAI,CAAC,aAAa,kCAAkC,IAAI,CAAC,aAAa,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,mBAAmB;QAChH,qHAAqH;QACrH,0CAA0C,CAC3C,CAAC;AACJ,CAAC;AAED,MAAM,EAAE,GAAG,IAAI,CAAC;AAEhB;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,iBAAkB,SAAQ,SAAS;IAIjB;IAHrB,KAAK,GAAW,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAChC,KAAK,GAAG,IAAI,CAAC;IAErB,YAA6B,OAAgB;QAC3C,KAAK,EAAE,CAAC;QADmB,YAAO,GAAP,OAAO,CAAS;IAE7C,CAAC;IAED,0FAA0F;IAClF,WAAW,CAAC,IAAY;QAC9B,IAAI,GAAG,GAAG,IAAI,CAAC;QACf,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;YACnB,IAAI,IAAI,CAAC,OAAO;gBAAE,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;QAClE,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACjB,CAAC;IAEQ,UAAU,CAAC,KAAsB,EAAE,IAAoB,EAAE,EAAqB;QACrF,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC9F,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QACpC,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;YACf,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,2CAA2C;QAChE,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,qBAAqB;YACrE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,2BAA2B;QACrE,CAAC;QACD,EAAE,EAAE,CAAC;IACP,CAAC;IAEQ,MAAM,CAAC,EAAqB;QACnC,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1B,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,qDAAqD;YACvH,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC/B,CAAC;QACD,EAAE,EAAE,CAAC;IACP,CAAC;CACF;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,MAAc,EAAE,KAAe;IACzD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAC/B,cAAc,CAAC,MAAM,EAAE,KAAK,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAC5D,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,MAAc,EAAE,OAAe;IACjE,IAAI,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;QAC/B,MAAM,QAAQ,CAAC,gBAAgB,CAAC,OAAO,CAAC,EAAE,IAAI,iBAAiB,CAAC,IAAI,CAAC,EAAE,iBAAiB,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;IACpH,CAAC;IACD,MAAM,CAAC,OAAO,CAAC,CAAC;AAClB,CAAC;AAiBD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,IAAc,EACd,MAAyB,OAAO,CAAC,GAAG;IAEpC,MAAM,SAAS,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1C,IAAI,SAAS,KAAK,SAAS;QAAE,MAAM,IAAI,UAAU,CAAC,yBAAyB,CAAC,CAAC;IAC7E,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAClC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,qBAAqB,MAAM,EAAE,CAAC,CAAC;IAC7E,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAC1C,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAEtC,IAAI,MAAM,EAAE,CAAC;QACX,4FAA4F;QAC5F,+FAA+F;QAC/F,MAAM,IAAI,GAAG,MAAM,eAAe,CAAC,MAAM,CAAC,CAAC;QAC3C,OAAO;YACL,OAAO,EAAE;gBACP,MAAM;gBACN,KAAK,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE;gBACxD,OAAO,EAAE,IAAI;gBACb,IAAI,EAAE,IAAI,CAAC,KAAK;gBAChB,QAAQ,EAAE,CAAC;gBACX,cAAc,EAAE,IAAI;gBACpB,MAAM,EAAE,CAAC;gBACT,MAAM,EAAE,IAAI;gBACZ,IAAI,EAAE,IAAI;gBACV,IAAI;aACL;YACD,QAAQ,EAAE,CAAC;SACZ,CAAC;IACJ,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;QAChC,MAAM,IAAI,UAAU,CAAC,sFAAsF,CAAC,CAAC;IAC/G,CAAC;IACD,IAAI,CAAC,WAAW,CAAC,yBAAyB,EAAE,EAAE,CAAC;QAC7C,MAAM,IAAI,gCAAgC,CAAC,gCAAgC,CAAC,CAAC;IAC/E,CAAC;IACD,+FAA+F;IAC/F,oGAAoG;IACpG,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC;QAAE,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEtF,6FAA6F;IAC7F,2FAA2F;IAC3F,MAAM,OAAO,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC3C,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5B,yFAAyF;IACzF,uFAAuF;IACvF,+FAA+F;IAC/F,gGAAgG;IAChG,kGAAkG;IAClG,sBAAsB;IACtB,IAAI,MAA8B,CAAC;IACnC,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,WAAW,CAAC,gBAAgB,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACrE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACrC,MAAM,MAAM,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAChE,MAAM,IAAI,KAAK,CAAC,gDAAgD,MAAM,uBAAuB,MAAM,EAAE,CAAC,CAAC;IACzG,CAAC;IACD,2FAA2F;IAC3F,kGAAkG;IAClG,mEAAmE;IACnE,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,iBAAiB,CACf,MAAM,EACN,OAAO,EACP,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CACjC,CAAC;IACJ,CAAC;IACD,MAAM,cAAc,GAAG,MAAM,CAAC,eAAe,IAAI,IAAI,CAAC;IACtD,MAAM,IAAI,GAAG,cAAc,KAAK,IAAI,IAAI,cAAc,GAAG,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,cAAc,EAAE,MAAM,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACnI,OAAO;QACL,OAAO,EAAE;YACP,MAAM;YACN,KAAK,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE;YACxD,OAAO;YACP,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,cAAc;YACd,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM;YAC5B,MAAM,EAAE,KAAK;YACb,IAAI;SACL;QACD,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;KAC3C,CAAC;AACJ,CAAC;AAED,sGAAsG;AACtG,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAc;IAChD,MAAM,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IAC5B,IAAI,GAAG,KAAK,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACvE,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;QAChC,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACzC,CAAC;IACD,IAAI,CAAC;QACH,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;QACvD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC9C,IAAI,OAAO,CAAC,IAAI,KAAK,IAAI;YAAE,OAAO,CAAC,KAAK,CAAC,gBAAgB,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;QACzE,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1C,OAAO,CAAC,KAAK,CAAC,gBAAgB,OAAO,CAAC,MAAM,QAAQ,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,6CAA6C,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QACvJ,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACzB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,UAAU,IAAI,GAAG,YAAY,oBAAoB,IAAI,GAAG,YAAY,YAAY,EAAE,CAAC;YACpG,OAAO,CAAC,KAAK,CAAC,gBAAgB,GAAG,CAAC,OAAO,OAAO,gBAAgB,EAAE,CAAC,CAAC;YACpE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,IAAI,GAAG,YAAY,gCAAgC,EAAE,CAAC;YACpD,OAAO,CAAC,KAAK,CACX,gBAAgB,GAAG,CAAC,OAAO,IAAI;gBAC7B,2FAA2F,CAC9F,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC"}