wicked-crew 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/audit.d.ts +70 -0
- package/dist/api/audit.d.ts.map +1 -0
- package/dist/api/audit.js +131 -0
- package/dist/api/audit.js.map +1 -0
- package/dist/api/auth.d.ts +192 -0
- package/dist/api/auth.d.ts.map +1 -0
- package/dist/api/auth.js +515 -0
- package/dist/api/auth.js.map +1 -0
- package/dist/api/gate-cache.d.ts +8 -0
- package/dist/api/gate-cache.d.ts.map +1 -1
- package/dist/api/gate-cache.js +10 -0
- package/dist/api/gate-cache.js.map +1 -1
- package/dist/api/guidance-index.d.ts +39 -0
- package/dist/api/guidance-index.d.ts.map +1 -0
- package/dist/api/guidance-index.js +67 -0
- package/dist/api/guidance-index.js.map +1 -0
- package/dist/api/open-path.d.ts +34 -0
- package/dist/api/open-path.d.ts.map +1 -0
- package/dist/api/open-path.js +101 -0
- package/dist/api/open-path.js.map +1 -0
- package/dist/api/retry-index.d.ts +30 -0
- package/dist/api/retry-index.d.ts.map +1 -0
- package/dist/api/retry-index.js +45 -0
- package/dist/api/retry-index.js.map +1 -0
- package/dist/api/routes.d.ts +164 -1
- package/dist/api/routes.d.ts.map +1 -1
- package/dist/api/routes.js +769 -21
- package/dist/api/routes.js.map +1 -1
- package/dist/api/run-files.d.ts +63 -0
- package/dist/api/run-files.d.ts.map +1 -0
- package/dist/api/run-files.js +271 -0
- package/dist/api/run-files.js.map +1 -0
- package/dist/api/seat-health.d.ts +55 -0
- package/dist/api/seat-health.d.ts.map +1 -0
- package/dist/api/seat-health.js +273 -0
- package/dist/api/seat-health.js.map +1 -0
- package/dist/api/seat-signin.d.ts +27 -0
- package/dist/api/seat-signin.d.ts.map +1 -0
- package/dist/api/seat-signin.js +143 -0
- package/dist/api/seat-signin.js.map +1 -0
- package/dist/api/server.d.ts +190 -3
- package/dist/api/server.d.ts.map +1 -1
- package/dist/api/server.js +365 -11
- package/dist/api/server.js.map +1 -1
- package/dist/api/stall-watchdog.d.ts +62 -0
- package/dist/api/stall-watchdog.d.ts.map +1 -0
- package/dist/api/stall-watchdog.js +138 -0
- package/dist/api/stall-watchdog.js.map +1 -0
- package/dist/cli/index.js +171 -12
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/mcp.d.ts +14 -0
- package/dist/cli/mcp.d.ts.map +1 -0
- package/dist/cli/mcp.js +119 -0
- package/dist/cli/mcp.js.map +1 -0
- package/dist/core/adapter.d.ts +87 -10
- package/dist/core/adapter.d.ts.map +1 -1
- package/dist/core/adapter.js +347 -28
- package/dist/core/adapter.js.map +1 -1
- package/dist/core/bridge-reaper.d.ts +134 -0
- package/dist/core/bridge-reaper.d.ts.map +1 -0
- package/dist/core/bridge-reaper.js +286 -0
- package/dist/core/bridge-reaper.js.map +1 -0
- package/dist/core/deliver.d.ts +118 -0
- package/dist/core/deliver.d.ts.map +1 -0
- package/dist/core/deliver.js +241 -0
- package/dist/core/deliver.js.map +1 -0
- package/dist/core/deliverable-floor.d.ts +103 -0
- package/dist/core/deliverable-floor.d.ts.map +1 -0
- package/dist/core/deliverable-floor.js +173 -0
- package/dist/core/deliverable-floor.js.map +1 -0
- package/dist/core/exec.d.ts +2 -0
- package/dist/core/exec.d.ts.map +1 -1
- package/dist/core/exec.js.map +1 -1
- package/dist/core/types.d.ts +92 -352
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +14 -4
- package/dist/core/types.js.map +1 -1
- package/dist/interactive/bridge-pool.d.ts +99 -0
- package/dist/interactive/bridge-pool.d.ts.map +1 -0
- package/dist/interactive/bridge-pool.js +244 -0
- package/dist/interactive/bridge-pool.js.map +1 -0
- package/dist/interactive/bridge-root.d.ts +36 -0
- package/dist/interactive/bridge-root.d.ts.map +1 -0
- package/dist/interactive/bridge-root.js +48 -0
- package/dist/interactive/bridge-root.js.map +1 -0
- package/dist/interactive/chat-events.d.ts +207 -0
- package/dist/interactive/chat-events.d.ts.map +1 -0
- package/dist/interactive/chat-events.js +769 -0
- package/dist/interactive/chat-events.js.map +1 -0
- package/dist/interactive/demo-events.d.ts +283 -0
- package/dist/interactive/demo-events.d.ts.map +1 -0
- package/dist/interactive/demo-events.js +889 -0
- package/dist/interactive/demo-events.js.map +1 -0
- package/dist/interactive/draft-events.d.ts +224 -0
- package/dist/interactive/draft-events.d.ts.map +1 -0
- package/dist/interactive/draft-events.js +793 -0
- package/dist/interactive/draft-events.js.map +1 -0
- package/dist/interactive/edit-events.d.ts +194 -0
- package/dist/interactive/edit-events.d.ts.map +1 -0
- package/dist/interactive/edit-events.js +601 -0
- package/dist/interactive/edit-events.js.map +1 -0
- package/dist/interactive/ledger.d.ts +39 -0
- package/dist/interactive/ledger.d.ts.map +1 -0
- package/dist/interactive/ledger.js +93 -0
- package/dist/interactive/ledger.js.map +1 -0
- package/dist/interactive/proxy-routes.d.ts +39 -0
- package/dist/interactive/proxy-routes.d.ts.map +1 -0
- package/dist/interactive/proxy-routes.js +189 -0
- package/dist/interactive/proxy-routes.js.map +1 -0
- package/dist/interactive/repo-snapshot.d.ts +100 -0
- package/dist/interactive/repo-snapshot.d.ts.map +1 -0
- package/dist/interactive/repo-snapshot.js +289 -0
- package/dist/interactive/repo-snapshot.js.map +1 -0
- package/dist/interactive/ws-relay.d.ts +85 -0
- package/dist/interactive/ws-relay.d.ts.map +1 -0
- package/dist/interactive/ws-relay.js +191 -0
- package/dist/interactive/ws-relay.js.map +1 -0
- package/dist/projects/activity.d.ts +29 -0
- package/dist/projects/activity.d.ts.map +1 -0
- package/dist/projects/activity.js +172 -0
- package/dist/projects/activity.js.map +1 -0
- package/dist/projects/charter.d.ts +28 -0
- package/dist/projects/charter.d.ts.map +1 -0
- package/dist/projects/charter.js +53 -0
- package/dist/projects/charter.js.map +1 -0
- package/dist/projects/events.d.ts +55 -0
- package/dist/projects/events.d.ts.map +1 -0
- package/dist/projects/events.js +141 -0
- package/dist/projects/events.js.map +1 -0
- package/dist/projects/graph-paths.d.ts +92 -0
- package/dist/projects/graph-paths.d.ts.map +1 -0
- package/dist/projects/graph-paths.js +130 -0
- package/dist/projects/graph-paths.js.map +1 -0
- package/dist/projects/graph.d.ts +179 -0
- package/dist/projects/graph.d.ts.map +1 -0
- package/dist/projects/graph.js +775 -0
- package/dist/projects/graph.js.map +1 -0
- package/dist/projects/membership-index.d.ts +25 -0
- package/dist/projects/membership-index.d.ts.map +1 -0
- package/dist/projects/membership-index.js +46 -0
- package/dist/projects/membership-index.js.map +1 -0
- package/dist/projects/routes.d.ts +97 -0
- package/dist/projects/routes.d.ts.map +1 -0
- package/dist/projects/routes.js +510 -0
- package/dist/projects/routes.js.map +1 -0
- package/dist/projects/settings.d.ts +32 -0
- package/dist/projects/settings.d.ts.map +1 -0
- package/dist/projects/settings.js +64 -0
- package/dist/projects/settings.js.map +1 -0
- package/dist/qe/acceptance.d.ts +137 -0
- package/dist/qe/acceptance.d.ts.map +1 -0
- package/dist/qe/acceptance.js +249 -0
- package/dist/qe/acceptance.js.map +1 -0
- package/dist/qe/gate-events.d.ts +111 -0
- package/dist/qe/gate-events.d.ts.map +1 -0
- package/dist/qe/gate-events.js +168 -0
- package/dist/qe/gate-events.js.map +1 -0
- package/dist/qe/ledger.d.ts +100 -0
- package/dist/qe/ledger.d.ts.map +1 -0
- package/dist/qe/ledger.js +154 -0
- package/dist/qe/ledger.js.map +1 -0
- package/dist/studio/assets/index-8p8uwCxG.js +530 -0
- package/dist/studio/assets/index-D6S9zUtO.css +32 -0
- package/dist/studio/index.html +5 -3
- package/package.json +10 -4
- package/dist/studio/assets/index-DaaUU8Ep.css +0 -32
- package/dist/studio/assets/index-Fu5DRC00.js +0 -423
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Opt-in consumption of the QE gate's wicked-bus events.
|
|
3
|
+
*
|
|
4
|
+
* The QE pipeline announces gate results on the bus — the wire contract the
|
|
5
|
+
* retired wicked-testing package's `lib/gate.mjs` established and garden's qe
|
|
6
|
+
* skills now emit (Phase 6c kept these event names and payload fields STABLE
|
|
7
|
+
* by decision — only the emitters' `domain` stamp rebranded to `qe`):
|
|
8
|
+
*
|
|
9
|
+
* wicked.qe.gate.passed | wicked.qe.gate.failed | wicked.qe.gate.conditional
|
|
10
|
+
* payload (8 canonical fields): run_id, context, gate_verdict, exit_code,
|
|
11
|
+
* verdict_summary, mode, completed_at, scenario_count
|
|
12
|
+
* idempotency key: `qe:gate.result:{context}:{sha256(run_id)[0:16]}:0`
|
|
13
|
+
* wicked.qe.deploy.completed
|
|
14
|
+
* payload: run_id, project_id (emitted alongside a PASS)
|
|
15
|
+
*
|
|
16
|
+
* Consumption is OPT-IN behind crew's existing bus seam (like `--bus-db` /
|
|
17
|
+
* `WICKED_BUS_EXEC`): when armed, a durable wicked-bus subscriber folds each
|
|
18
|
+
* event into this in-memory cache so acceptance reads see gate results the
|
|
19
|
+
* moment they happen; when the bus is absent, nothing here runs and the
|
|
20
|
+
* acceptance route's lazy ledger read is the (always-correct) fallback. The
|
|
21
|
+
* cache is a freshness signal — the ledger stays the system of record for the
|
|
22
|
+
* gate decision, so a lost or replayed event can never flip a verdict.
|
|
23
|
+
*/
|
|
24
|
+
/** The gate-result event types (the old gate.mjs wire contract, verbatim). */
|
|
25
|
+
export const QE_GATE_EVENT_TYPES = [
|
|
26
|
+
'wicked.qe.gate.passed',
|
|
27
|
+
'wicked.qe.gate.failed',
|
|
28
|
+
'wicked.qe.gate.conditional',
|
|
29
|
+
];
|
|
30
|
+
/** The cross-product deploy signal emitted alongside a PASS. */
|
|
31
|
+
export const QE_DEPLOY_EVENT_TYPE = 'wicked.qe.deploy.completed';
|
|
32
|
+
/**
|
|
33
|
+
* One durable-subscription filter covering both families above
|
|
34
|
+
* (`prefix.**` = one or more remaining segments in wicked-bus filter grammar).
|
|
35
|
+
*/
|
|
36
|
+
export const QE_BUS_FILTER = 'wicked.qe.**';
|
|
37
|
+
/** Subscriber identity on the bus (registration + cursor resume key). */
|
|
38
|
+
export const QE_BUS_PLUGIN = 'wicked-crew';
|
|
39
|
+
function str(v) {
|
|
40
|
+
return typeof v === 'string' ? v : null;
|
|
41
|
+
}
|
|
42
|
+
function num(v) {
|
|
43
|
+
return typeof v === 'number' && Number.isFinite(v) ? v : null;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Latest-gate-result cache, keyed by QE run id and by context.
|
|
47
|
+
*
|
|
48
|
+
* At-least-once delivery means the same logical event may arrive more than
|
|
49
|
+
* once; folding is idempotent by construction (same event ⇒ same entry). No
|
|
50
|
+
* eviction: entries are one small record per QE run/context and the daemon is
|
|
51
|
+
* local-first — a restart simply starts empty and the ledger read covers it.
|
|
52
|
+
*/
|
|
53
|
+
export class QeGateCache {
|
|
54
|
+
byRun = new Map();
|
|
55
|
+
byContext = new Map();
|
|
56
|
+
latestEntry;
|
|
57
|
+
/**
|
|
58
|
+
* Fold one bus event. Returns `true` when the event was a recognized
|
|
59
|
+
* `wicked.qe.*` gate/deploy frame and was cached; unknown types are ignored
|
|
60
|
+
* (the durable filter is a prefix, so future qe events pass through here).
|
|
61
|
+
*/
|
|
62
|
+
ingest(eventType, payload, observedAt = new Date().toISOString()) {
|
|
63
|
+
const isGate = QE_GATE_EVENT_TYPES.includes(eventType);
|
|
64
|
+
const isDeploy = eventType === QE_DEPLOY_EVENT_TYPE;
|
|
65
|
+
if (!isGate && !isDeploy)
|
|
66
|
+
return false;
|
|
67
|
+
if (typeof payload !== 'object' || payload === null)
|
|
68
|
+
return false;
|
|
69
|
+
const p = payload;
|
|
70
|
+
const runId = str(p['run_id']);
|
|
71
|
+
if (runId === null)
|
|
72
|
+
return false; // both contracts require run_id
|
|
73
|
+
const entry = {
|
|
74
|
+
eventType,
|
|
75
|
+
runId,
|
|
76
|
+
// Gate events carry `context`; the deploy signal spells it `project_id`.
|
|
77
|
+
context: str(p['context']) ?? str(p['project_id']),
|
|
78
|
+
gateVerdict: isGate ? str(p['gate_verdict']) : null,
|
|
79
|
+
exitCode: isGate ? num(p['exit_code']) : null,
|
|
80
|
+
verdictSummary: isGate ? str(p['verdict_summary']) : null,
|
|
81
|
+
mode: isGate ? str(p['mode']) : null,
|
|
82
|
+
completedAt: isGate ? str(p['completed_at']) : null,
|
|
83
|
+
scenarioCount: isGate ? num(p['scenario_count']) : null,
|
|
84
|
+
observedAt,
|
|
85
|
+
};
|
|
86
|
+
// The deploy signal must not shadow the gate result it accompanies: for the
|
|
87
|
+
// same run, a gate event always wins the byRun/byContext slots; the deploy
|
|
88
|
+
// frame only fills them when no gate result was seen (e.g. cursor_init
|
|
89
|
+
// 'latest' catching the tail of an emission pair).
|
|
90
|
+
const existing = this.byRun.get(runId);
|
|
91
|
+
if (!(isDeploy && existing !== undefined && existing.gateVerdict !== null)) {
|
|
92
|
+
this.byRun.set(runId, entry);
|
|
93
|
+
if (entry.context !== null)
|
|
94
|
+
this.byContext.set(entry.context, entry);
|
|
95
|
+
}
|
|
96
|
+
this.latestEntry = entry;
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
/** The latest cached result for a QE run id. */
|
|
100
|
+
forRun(runId) {
|
|
101
|
+
return this.byRun.get(runId);
|
|
102
|
+
}
|
|
103
|
+
/** The latest cached result for a context (QE project id). */
|
|
104
|
+
forContext(context) {
|
|
105
|
+
return this.byContext.get(context);
|
|
106
|
+
}
|
|
107
|
+
/** The most recently observed event, whatever it was keyed by. */
|
|
108
|
+
latest() {
|
|
109
|
+
return this.latestEntry;
|
|
110
|
+
}
|
|
111
|
+
/** Number of distinct QE runs with a cached result (diagnostics / tests). */
|
|
112
|
+
size() {
|
|
113
|
+
return this.byRun.size;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Start the durable `wicked.qe.**` subscriber and fold events into `cache`.
|
|
118
|
+
*
|
|
119
|
+
* Graceful degradation, matching how other wicked consumers subscribe
|
|
120
|
+
* (wicked-brain's memory subscriber): wicked-bus is dynamically imported, and
|
|
121
|
+
* a missing package / unopenable db returns `null` instead of throwing — the
|
|
122
|
+
* caller opted in, so the degradation is LOGGED, but a daemon must still boot
|
|
123
|
+
* on a machine whose bus is broken (acceptance falls back to lazy ledger
|
|
124
|
+
* reads, which never needed the bus).
|
|
125
|
+
*
|
|
126
|
+
* `cursor_init: 'latest'`: the cache is a live freshness signal, not history —
|
|
127
|
+
* replaying an old bus backlog into it would let a stale event masquerade as
|
|
128
|
+
* fresh. History belongs to the ledger.
|
|
129
|
+
*/
|
|
130
|
+
export async function startQeGateSubscriber(cache, opts = {}) {
|
|
131
|
+
const log = opts.log ?? ((m) => console.error(m));
|
|
132
|
+
let bus;
|
|
133
|
+
try {
|
|
134
|
+
bus = await import('wicked-bus');
|
|
135
|
+
}
|
|
136
|
+
catch (err) {
|
|
137
|
+
log(`[qe-gate-events] wicked-bus is not importable — gate events disabled, acceptance stays on lazy ledger reads: ${err instanceof Error ? err.message : String(err)}`);
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
let db;
|
|
141
|
+
try {
|
|
142
|
+
db = bus.openDb(opts.dbPath !== undefined ? { db_path: opts.dbPath } : {});
|
|
143
|
+
}
|
|
144
|
+
catch (err) {
|
|
145
|
+
log(`[qe-gate-events] could not open the bus db${opts.dbPath !== undefined ? ` at ${opts.dbPath}` : ''} — gate events disabled: ${err instanceof Error ? err.message : String(err)}`);
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
const sub = bus.subscribe({
|
|
149
|
+
db,
|
|
150
|
+
plugin: QE_BUS_PLUGIN,
|
|
151
|
+
filter: QE_BUS_FILTER,
|
|
152
|
+
cursor_init: 'latest',
|
|
153
|
+
pollIntervalMs: opts.pollIntervalMs ?? 5000,
|
|
154
|
+
// The handler only folds into an in-memory map; a retry loop or DLQ entry
|
|
155
|
+
// for it would be noise. It never throws by construction.
|
|
156
|
+
maxRetries: 0,
|
|
157
|
+
handler: (event) => {
|
|
158
|
+
cache.ingest(event.event_type, event.payload);
|
|
159
|
+
},
|
|
160
|
+
onError: (err, event) => {
|
|
161
|
+
log(`[qe-gate-events] handler error on event ${String(event?.event_id ?? '?')}: ${err.message}`);
|
|
162
|
+
},
|
|
163
|
+
});
|
|
164
|
+
return {
|
|
165
|
+
stop: () => sub.stop(),
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=gate-events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gate-events.js","sourceRoot":"","sources":["../../src/qe/gate-events.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read-only view over a repo's QE evidence ledger (wicked-ledger).
|
|
3
|
+
*
|
|
4
|
+
* The ledger is the data contract between the QE pipeline (wicked-garden's qe
|
|
5
|
+
* skills, formerly the retired wicked-testing package) and the acceptance gate
|
|
6
|
+
* this daemon owns: a DomainStore rooted at `<repo>/.wicked-qe/` (legacy
|
|
7
|
+
* `<repo>/.wicked-testing/` — see qeLedgerRoot) holding `runs` and
|
|
8
|
+
* `verdicts`, plus the public evidence manifest at
|
|
9
|
+
* `<root>/evidence/<run-id>/manifest.json`. This module reads that state
|
|
10
|
+
* through the wicked-ledger package API (public entry, no deep imports) and
|
|
11
|
+
* never writes a domain record — the QE pipeline is the only writer.
|
|
12
|
+
*
|
|
13
|
+
* ONE deliberate mutation is allowed: `rebuildIndex()`, which regenerates the
|
|
14
|
+
* store's DERIVED SQLite index from the canonical JSON files when the two
|
|
15
|
+
* disagree (see `readAcceptanceState`). Canonical JSON is authoritative by the
|
|
16
|
+
* ledger's own schema contract; the index is a cache, and rebuilding a cache
|
|
17
|
+
* is not a write to the ledger's record of what happened.
|
|
18
|
+
*/
|
|
19
|
+
import type { EvidenceManifest, RunRecord, VerdictRecord } from 'wicked-ledger';
|
|
20
|
+
/**
|
|
21
|
+
* The ledger root directory name under a repo root.
|
|
22
|
+
*
|
|
23
|
+
* Phase 6c (the wicked-testing retirement) renamed the wire contract to
|
|
24
|
+
* `.wicked-qe`; `.wicked-testing` is the legacy dirname repos written by the
|
|
25
|
+
* retired package (and pre-6c garden qe skills) still carry. Resolution is
|
|
26
|
+
* dual-read and mirrors wicked-ledger's `resolveLedgerRoot`: the new name
|
|
27
|
+
* wins, an existing legacy root is honored, fresh repos get the new name.
|
|
28
|
+
*/
|
|
29
|
+
export declare const DEFAULT_QE_LEDGER_DIRNAME = ".wicked-qe";
|
|
30
|
+
export declare const LEGACY_QE_LEDGER_DIRNAME = ".wicked-testing";
|
|
31
|
+
/** The configured ledger dir name: `WICKED_QE_LEDGER_DIR` env override, else the default. */
|
|
32
|
+
export declare function qeLedgerDirName(): string;
|
|
33
|
+
/**
|
|
34
|
+
* Absolute ledger root for a repo (dual-read, Phase 6c).
|
|
35
|
+
*
|
|
36
|
+
* An explicit `WICKED_QE_LEDGER_DIR` pins the dirname exactly — the operator
|
|
37
|
+
* is driving, no fallback probing. Otherwise: `<repo>/.wicked-qe` when it
|
|
38
|
+
* exists; else an existing legacy `<repo>/.wicked-testing` (that ledger keeps
|
|
39
|
+
* its root — a store must never split across two dirs); else `.wicked-qe`.
|
|
40
|
+
*/
|
|
41
|
+
export declare function qeLedgerRoot(repoRoot: string): string;
|
|
42
|
+
/**
|
|
43
|
+
* The acceptance-relevant slice of a repo's ledger.
|
|
44
|
+
*
|
|
45
|
+
* `found: false` means the repo has no ledger at all (the dir is absent) —
|
|
46
|
+
* a distinct fact from "a ledger with no verdicts", and the gate treats both
|
|
47
|
+
* as a deny with different reasons. `error` carries a read-layer failure
|
|
48
|
+
* (store threw); it is never set on an ordinary empty ledger.
|
|
49
|
+
*/
|
|
50
|
+
export interface QeAcceptanceState {
|
|
51
|
+
/** Absolute ledger root that was read (or probed). */
|
|
52
|
+
root: string;
|
|
53
|
+
/** Whether the ledger root exists on disk. */
|
|
54
|
+
found: boolean;
|
|
55
|
+
/** The QE run the verdict belongs to, when resolvable. */
|
|
56
|
+
run: RunRecord | null;
|
|
57
|
+
/** The governing verdict row — newest first, the ledger's system of record. */
|
|
58
|
+
verdict: VerdictRecord | null;
|
|
59
|
+
/** The public evidence manifest for that run, when present and parseable. */
|
|
60
|
+
manifest: EvidenceManifest | null;
|
|
61
|
+
/** Absolute path the manifest was read from (null when absent). */
|
|
62
|
+
manifestPath: string | null;
|
|
63
|
+
/** Read-layer failure detail (store open/read threw). */
|
|
64
|
+
error?: string;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Read the ledger's current acceptance state for a repo.
|
|
68
|
+
*
|
|
69
|
+
* The newest verdict row governs (`opts.qeRunId` narrows to one QE run's
|
|
70
|
+
* newest verdict instead). The verdicts TABLE is the system of record — the
|
|
71
|
+
* manifest is the public artifact built from it at run finalization, returned
|
|
72
|
+
* here as display evidence, never as a gate input: a run can legitimately be
|
|
73
|
+
* re-reviewed after its manifest was built, and the newer verdict row wins.
|
|
74
|
+
*
|
|
75
|
+
* Index-drift healing: the store is dual-write (canonical JSON + a derived
|
|
76
|
+
* SQLite index) and a writer that degraded to JSON-only leaves the index
|
|
77
|
+
* behind. When the index answers "no verdicts" but canonical verdict files
|
|
78
|
+
* exist, the index is provably stale, so it is rebuilt from JSON once and
|
|
79
|
+
* re-read — otherwise a ledger full of evidence would read as "missing
|
|
80
|
+
* evidence ⇒ deny", a wrong answer in the honest direction but still wrong.
|
|
81
|
+
*/
|
|
82
|
+
export declare function readAcceptanceState(repoRoot: string, opts?: {
|
|
83
|
+
qeRunId?: string;
|
|
84
|
+
}): Promise<QeAcceptanceState>;
|
|
85
|
+
/** The summary of a manifest the acceptance route serves (never the full artifact list). */
|
|
86
|
+
export interface QeManifestSummary {
|
|
87
|
+
manifestVersion: string;
|
|
88
|
+
runId: string;
|
|
89
|
+
scenarioName: string | null;
|
|
90
|
+
status: string;
|
|
91
|
+
artifactCount: number;
|
|
92
|
+
verdict: {
|
|
93
|
+
value: string;
|
|
94
|
+
reviewer: string;
|
|
95
|
+
recordedAt: string | null;
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
/** Reduce a manifest to the route's summary shape. */
|
|
99
|
+
export declare function summarizeManifest(manifest: EvidenceManifest): QeManifestSummary;
|
|
100
|
+
//# sourceMappingURL=ledger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ledger.d.ts","sourceRoot":"","sources":["../../src/qe/ledger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAMH,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEhF;;;;;;;;GAQG;AACH,eAAO,MAAM,yBAAyB,eAAe,CAAC;AACtD,eAAO,MAAM,wBAAwB,oBAAoB,CAAC;AAE1D,6FAA6F;AAC7F,wBAAgB,eAAe,IAAI,MAAM,CAGxC;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQrD;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAiB;IAChC,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,8CAA8C;IAC9C,KAAK,EAAE,OAAO,CAAC;IACf,0DAA0D;IAC1D,GAAG,EAAE,SAAS,GAAG,IAAI,CAAC;IACtB,+EAA+E;IAC/E,OAAO,EAAE,aAAa,GAAG,IAAI,CAAC;IAC9B,6EAA6E;IAC7E,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAClC,mEAAmE;IACnE,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,yDAAyD;IACzD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAaD;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAC1B,OAAO,CAAC,iBAAiB,CAAC,CAqC5B;AAgBD,4FAA4F;AAC5F,MAAM,WAAW,iBAAiB;IAChC,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;CACzE;AAED,sDAAsD;AACtD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,iBAAiB,CAa/E"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read-only view over a repo's QE evidence ledger (wicked-ledger).
|
|
3
|
+
*
|
|
4
|
+
* The ledger is the data contract between the QE pipeline (wicked-garden's qe
|
|
5
|
+
* skills, formerly the retired wicked-testing package) and the acceptance gate
|
|
6
|
+
* this daemon owns: a DomainStore rooted at `<repo>/.wicked-qe/` (legacy
|
|
7
|
+
* `<repo>/.wicked-testing/` — see qeLedgerRoot) holding `runs` and
|
|
8
|
+
* `verdicts`, plus the public evidence manifest at
|
|
9
|
+
* `<root>/evidence/<run-id>/manifest.json`. This module reads that state
|
|
10
|
+
* through the wicked-ledger package API (public entry, no deep imports) and
|
|
11
|
+
* never writes a domain record — the QE pipeline is the only writer.
|
|
12
|
+
*
|
|
13
|
+
* ONE deliberate mutation is allowed: `rebuildIndex()`, which regenerates the
|
|
14
|
+
* store's DERIVED SQLite index from the canonical JSON files when the two
|
|
15
|
+
* disagree (see `readAcceptanceState`). Canonical JSON is authoritative by the
|
|
16
|
+
* ledger's own schema contract; the index is a cache, and rebuilding a cache
|
|
17
|
+
* is not a write to the ledger's record of what happened.
|
|
18
|
+
*/
|
|
19
|
+
import { existsSync, readdirSync } from 'node:fs';
|
|
20
|
+
import { readFile } from 'node:fs/promises';
|
|
21
|
+
import { join } from 'node:path';
|
|
22
|
+
import { createDomainStore } from 'wicked-ledger';
|
|
23
|
+
/**
|
|
24
|
+
* The ledger root directory name under a repo root.
|
|
25
|
+
*
|
|
26
|
+
* Phase 6c (the wicked-testing retirement) renamed the wire contract to
|
|
27
|
+
* `.wicked-qe`; `.wicked-testing` is the legacy dirname repos written by the
|
|
28
|
+
* retired package (and pre-6c garden qe skills) still carry. Resolution is
|
|
29
|
+
* dual-read and mirrors wicked-ledger's `resolveLedgerRoot`: the new name
|
|
30
|
+
* wins, an existing legacy root is honored, fresh repos get the new name.
|
|
31
|
+
*/
|
|
32
|
+
export const DEFAULT_QE_LEDGER_DIRNAME = '.wicked-qe';
|
|
33
|
+
export const LEGACY_QE_LEDGER_DIRNAME = '.wicked-testing';
|
|
34
|
+
/** The configured ledger dir name: `WICKED_QE_LEDGER_DIR` env override, else the default. */
|
|
35
|
+
export function qeLedgerDirName() {
|
|
36
|
+
const env = process.env['WICKED_QE_LEDGER_DIR']?.trim();
|
|
37
|
+
return env !== undefined && env !== '' ? env : DEFAULT_QE_LEDGER_DIRNAME;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Absolute ledger root for a repo (dual-read, Phase 6c).
|
|
41
|
+
*
|
|
42
|
+
* An explicit `WICKED_QE_LEDGER_DIR` pins the dirname exactly — the operator
|
|
43
|
+
* is driving, no fallback probing. Otherwise: `<repo>/.wicked-qe` when it
|
|
44
|
+
* exists; else an existing legacy `<repo>/.wicked-testing` (that ledger keeps
|
|
45
|
+
* its root — a store must never split across two dirs); else `.wicked-qe`.
|
|
46
|
+
*/
|
|
47
|
+
export function qeLedgerRoot(repoRoot) {
|
|
48
|
+
const env = process.env['WICKED_QE_LEDGER_DIR']?.trim();
|
|
49
|
+
if (env !== undefined && env !== '')
|
|
50
|
+
return join(repoRoot, env);
|
|
51
|
+
const current = join(repoRoot, DEFAULT_QE_LEDGER_DIRNAME);
|
|
52
|
+
if (existsSync(current))
|
|
53
|
+
return current;
|
|
54
|
+
const legacy = join(repoRoot, LEGACY_QE_LEDGER_DIRNAME);
|
|
55
|
+
if (existsSync(legacy))
|
|
56
|
+
return legacy;
|
|
57
|
+
return current;
|
|
58
|
+
}
|
|
59
|
+
/** True when the canonical JSON dir for a table has at least one record file. */
|
|
60
|
+
function hasCanonicalRows(root, table) {
|
|
61
|
+
try {
|
|
62
|
+
return readdirSync(join(root, table)).some((f) => f.endsWith('.json') && !f.includes('.tmp.'));
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Read the ledger's current acceptance state for a repo.
|
|
70
|
+
*
|
|
71
|
+
* The newest verdict row governs (`opts.qeRunId` narrows to one QE run's
|
|
72
|
+
* newest verdict instead). The verdicts TABLE is the system of record — the
|
|
73
|
+
* manifest is the public artifact built from it at run finalization, returned
|
|
74
|
+
* here as display evidence, never as a gate input: a run can legitimately be
|
|
75
|
+
* re-reviewed after its manifest was built, and the newer verdict row wins.
|
|
76
|
+
*
|
|
77
|
+
* Index-drift healing: the store is dual-write (canonical JSON + a derived
|
|
78
|
+
* SQLite index) and a writer that degraded to JSON-only leaves the index
|
|
79
|
+
* behind. When the index answers "no verdicts" but canonical verdict files
|
|
80
|
+
* exist, the index is provably stale, so it is rebuilt from JSON once and
|
|
81
|
+
* re-read — otherwise a ledger full of evidence would read as "missing
|
|
82
|
+
* evidence ⇒ deny", a wrong answer in the honest direction but still wrong.
|
|
83
|
+
*/
|
|
84
|
+
export async function readAcceptanceState(repoRoot, opts) {
|
|
85
|
+
const root = qeLedgerRoot(repoRoot);
|
|
86
|
+
const state = {
|
|
87
|
+
root,
|
|
88
|
+
found: false,
|
|
89
|
+
run: null,
|
|
90
|
+
verdict: null,
|
|
91
|
+
manifest: null,
|
|
92
|
+
manifestPath: null,
|
|
93
|
+
};
|
|
94
|
+
// Probe before opening: createDomainStore CREATES its root when absent, and
|
|
95
|
+
// a read must not install an empty ledger into a repo that never had one.
|
|
96
|
+
if (!existsSync(root))
|
|
97
|
+
return state;
|
|
98
|
+
state.found = true;
|
|
99
|
+
try {
|
|
100
|
+
const store = createDomainStore({ root });
|
|
101
|
+
const filter = opts?.qeRunId !== undefined ? { run_id: opts.qeRunId } : undefined;
|
|
102
|
+
let verdicts = store.list('verdicts', filter);
|
|
103
|
+
if (verdicts.length === 0 && store.mode === 'sqlite+json' && hasCanonicalRows(root, 'verdicts')) {
|
|
104
|
+
store.rebuildIndex();
|
|
105
|
+
verdicts = store.list('verdicts', filter);
|
|
106
|
+
}
|
|
107
|
+
const verdict = verdicts[0] ?? null;
|
|
108
|
+
state.verdict = verdict;
|
|
109
|
+
if (verdict !== null) {
|
|
110
|
+
state.run = store.get('runs', verdict.run_id);
|
|
111
|
+
state.manifestPath = join(root, 'evidence', verdict.run_id, 'manifest.json');
|
|
112
|
+
state.manifest = await readManifest(state.manifestPath);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
// A ledger that exists but cannot be read is NOT "no evidence" — the gate
|
|
117
|
+
// still denies (deny-dominates), but the reason must name the read failure
|
|
118
|
+
// so an operator fixes the store instead of hunting for a missing run.
|
|
119
|
+
state.error = err instanceof Error ? err.message : String(err);
|
|
120
|
+
}
|
|
121
|
+
return state;
|
|
122
|
+
}
|
|
123
|
+
/** Parse the public manifest, or null when absent/malformed (display evidence only). */
|
|
124
|
+
async function readManifest(path) {
|
|
125
|
+
try {
|
|
126
|
+
const raw = await readFile(path, 'utf8');
|
|
127
|
+
const parsed = JSON.parse(raw);
|
|
128
|
+
// Minimal shape check — enough to know this is a manifest and not stray JSON.
|
|
129
|
+
if (typeof parsed !== 'object' || parsed === null)
|
|
130
|
+
return null;
|
|
131
|
+
if (typeof parsed.run_id !== 'string' || typeof parsed.manifest_version !== 'string')
|
|
132
|
+
return null;
|
|
133
|
+
return parsed;
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/** Reduce a manifest to the route's summary shape. */
|
|
140
|
+
export function summarizeManifest(manifest) {
|
|
141
|
+
return {
|
|
142
|
+
manifestVersion: manifest.manifest_version,
|
|
143
|
+
runId: manifest.run_id,
|
|
144
|
+
scenarioName: typeof manifest.scenario_name === 'string' ? manifest.scenario_name : null,
|
|
145
|
+
status: manifest.status,
|
|
146
|
+
artifactCount: Array.isArray(manifest.artifacts) ? manifest.artifacts.length : 0,
|
|
147
|
+
verdict: {
|
|
148
|
+
value: manifest.verdict?.value ?? 'INCONCLUSIVE',
|
|
149
|
+
reviewer: manifest.verdict?.reviewer ?? '',
|
|
150
|
+
recordedAt: manifest.verdict?.recorded_at ?? null,
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=ledger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ledger.js","sourceRoot":"","sources":["../../src/qe/ledger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAGlD;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,YAAY,CAAC;AACtD,MAAM,CAAC,MAAM,wBAAwB,GAAG,iBAAiB,CAAC;AAE1D,6FAA6F;AAC7F,MAAM,UAAU,eAAe;IAC7B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,EAAE,IAAI,EAAE,CAAC;IACxD,OAAO,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,yBAAyB,CAAC;AAC3E,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,QAAgB;IAC3C,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,EAAE,IAAI,EAAE,CAAC;IACxD,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IAChE,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,EAAE,yBAAyB,CAAC,CAAC;IAC1D,IAAI,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,OAAO,CAAC;IACxC,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,EAAE,wBAAwB,CAAC,CAAC;IACxD,IAAI,UAAU,CAAC,MAAM,CAAC;QAAE,OAAO,MAAM,CAAC;IACtC,OAAO,OAAO,CAAC;AACjB,CAAC;AA2BD,iFAAiF;AACjF,SAAS,gBAAgB,CAAC,IAAY,EAAE,KAAa;IACnD,IAAI,CAAC;QACH,OAAO,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CACxC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CACnD,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,QAAgB,EAChB,IAA2B;IAE3B,MAAM,IAAI,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;IACpC,MAAM,KAAK,GAAsB;QAC/B,IAAI;QACJ,KAAK,EAAE,KAAK;QACZ,GAAG,EAAE,IAAI;QACT,OAAO,EAAE,IAAI;QACb,QAAQ,EAAE,IAAI;QACd,YAAY,EAAE,IAAI;KACnB,CAAC;IACF,4EAA4E;IAC5E,0EAA0E;IAC1E,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACpC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC;IAEnB,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,iBAAiB,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1C,MAAM,MAAM,GAAG,IAAI,EAAE,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;QAClF,IAAI,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QAC9C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa,IAAI,gBAAgB,CAAC,IAAI,EAAE,UAAU,CAAC,EAAE,CAAC;YAChG,KAAK,CAAC,YAAY,EAAE,CAAC;YACrB,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QAC5C,CAAC;QACD,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;QACpC,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC;QACxB,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YACrB,KAAK,CAAC,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;YAC9C,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;YAC7E,KAAK,CAAC,QAAQ,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,0EAA0E;QAC1E,2EAA2E;QAC3E,uEAAuE;QACvE,KAAK,CAAC,KAAK,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACjE,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,wFAAwF;AACxF,KAAK,UAAU,YAAY,CAAC,IAAY;IACtC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACzC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAqB,CAAC;QACnD,8EAA8E;QAC9E,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QAC/D,IAAI,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,IAAI,OAAO,MAAM,CAAC,gBAAgB,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC;QAClG,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAYD,sDAAsD;AACtD,MAAM,UAAU,iBAAiB,CAAC,QAA0B;IAC1D,OAAO;QACL,eAAe,EAAE,QAAQ,CAAC,gBAAgB;QAC1C,KAAK,EAAE,QAAQ,CAAC,MAAM;QACtB,YAAY,EAAE,OAAO,QAAQ,CAAC,aAAa,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI;QACxF,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,aAAa,EAAE,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAChF,OAAO,EAAE;YACP,KAAK,EAAE,QAAQ,CAAC,OAAO,EAAE,KAAK,IAAI,cAAc;YAChD,QAAQ,EAAE,QAAQ,CAAC,OAAO,EAAE,QAAQ,IAAI,EAAE;YAC1C,UAAU,EAAE,QAAQ,CAAC,OAAO,EAAE,WAAW,IAAI,IAAI;SAClD;KACF,CAAC;AACJ,CAAC"}
|