agentic-qe 3.6.19 → 3.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/.claude/skills/skills-manifest.json +1 -1
- package/README.md +29 -1
- package/package.json +2 -1
- package/scripts/rvf-baseline-benchmark.ts +843 -0
- package/v3/CHANGELOG.md +30 -0
- package/v3/dist/audit/witness-chain.d.ts +148 -0
- package/v3/dist/audit/witness-chain.d.ts.map +1 -0
- package/v3/dist/audit/witness-chain.js +269 -0
- package/v3/dist/audit/witness-chain.js.map +1 -0
- package/v3/dist/cli/brain-commands.d.ts +39 -0
- package/v3/dist/cli/brain-commands.d.ts.map +1 -0
- package/v3/dist/cli/brain-commands.js +60 -0
- package/v3/dist/cli/brain-commands.js.map +1 -0
- package/v3/dist/cli/bundle.js +4509 -2452
- package/v3/dist/cli/command-registry.d.ts.map +1 -1
- package/v3/dist/cli/command-registry.js +3 -1
- package/v3/dist/cli/command-registry.js.map +1 -1
- package/v3/dist/cli/handlers/brain-handler.d.ts +22 -0
- package/v3/dist/cli/handlers/brain-handler.d.ts.map +1 -0
- package/v3/dist/cli/handlers/brain-handler.js +148 -0
- package/v3/dist/cli/handlers/brain-handler.js.map +1 -0
- package/v3/dist/cli/handlers/index.d.ts +1 -0
- package/v3/dist/cli/handlers/index.d.ts.map +1 -1
- package/v3/dist/cli/handlers/index.js +1 -0
- package/v3/dist/cli/handlers/index.js.map +1 -1
- package/v3/dist/domains/coverage-analysis/services/hnsw-index.d.ts +31 -44
- package/v3/dist/domains/coverage-analysis/services/hnsw-index.d.ts.map +1 -1
- package/v3/dist/domains/coverage-analysis/services/hnsw-index.js +73 -178
- package/v3/dist/domains/coverage-analysis/services/hnsw-index.js.map +1 -1
- package/v3/dist/domains/quality-assessment/coordinator.d.ts.map +1 -1
- package/v3/dist/domains/quality-assessment/coordinator.js +8 -0
- package/v3/dist/domains/quality-assessment/coordinator.js.map +1 -1
- package/v3/dist/domains/test-execution/coordinator.d.ts +14 -0
- package/v3/dist/domains/test-execution/coordinator.d.ts.map +1 -1
- package/v3/dist/domains/test-execution/coordinator.js +18 -0
- package/v3/dist/domains/test-execution/coordinator.js.map +1 -1
- package/v3/dist/domains/test-execution/services/index.d.ts +1 -0
- package/v3/dist/domains/test-execution/services/index.d.ts.map +1 -1
- package/v3/dist/domains/test-execution/services/index.js +1 -0
- package/v3/dist/domains/test-execution/services/index.js.map +1 -1
- package/v3/dist/domains/test-execution/services/mincut-test-optimizer.d.ts +118 -0
- package/v3/dist/domains/test-execution/services/mincut-test-optimizer.d.ts.map +1 -0
- package/v3/dist/domains/test-execution/services/mincut-test-optimizer.js +358 -0
- package/v3/dist/domains/test-execution/services/mincut-test-optimizer.js.map +1 -0
- package/v3/dist/integrations/ruvector/brain-exporter.d.ts +66 -0
- package/v3/dist/integrations/ruvector/brain-exporter.d.ts.map +1 -0
- package/v3/dist/integrations/ruvector/brain-exporter.js +537 -0
- package/v3/dist/integrations/ruvector/brain-exporter.js.map +1 -0
- package/v3/dist/integrations/ruvector/index.d.ts +4 -0
- package/v3/dist/integrations/ruvector/index.d.ts.map +1 -1
- package/v3/dist/integrations/ruvector/index.js +5 -0
- package/v3/dist/integrations/ruvector/index.js.map +1 -1
- package/v3/dist/integrations/ruvector/mincut-wrapper.d.ts +204 -0
- package/v3/dist/integrations/ruvector/mincut-wrapper.d.ts.map +1 -0
- package/v3/dist/integrations/ruvector/mincut-wrapper.js +310 -0
- package/v3/dist/integrations/ruvector/mincut-wrapper.js.map +1 -0
- package/v3/dist/integrations/ruvector/rvf-dual-writer.d.ts +141 -0
- package/v3/dist/integrations/ruvector/rvf-dual-writer.d.ts.map +1 -0
- package/v3/dist/integrations/ruvector/rvf-dual-writer.js +367 -0
- package/v3/dist/integrations/ruvector/rvf-dual-writer.js.map +1 -0
- package/v3/dist/integrations/ruvector/rvf-native-adapter.d.ts +60 -0
- package/v3/dist/integrations/ruvector/rvf-native-adapter.d.ts.map +1 -0
- package/v3/dist/integrations/ruvector/rvf-native-adapter.js +240 -0
- package/v3/dist/integrations/ruvector/rvf-native-adapter.js.map +1 -0
- package/v3/dist/kernel/hnsw-adapter.d.ts +99 -0
- package/v3/dist/kernel/hnsw-adapter.d.ts.map +1 -0
- package/v3/dist/kernel/hnsw-adapter.js +218 -0
- package/v3/dist/kernel/hnsw-adapter.js.map +1 -0
- package/v3/dist/kernel/hnsw-index-provider.d.ts +90 -0
- package/v3/dist/kernel/hnsw-index-provider.d.ts.map +1 -0
- package/v3/dist/kernel/hnsw-index-provider.js +23 -0
- package/v3/dist/kernel/hnsw-index-provider.js.map +1 -0
- package/v3/dist/kernel/progressive-hnsw-backend.d.ts +67 -0
- package/v3/dist/kernel/progressive-hnsw-backend.d.ts.map +1 -0
- package/v3/dist/kernel/progressive-hnsw-backend.js +266 -0
- package/v3/dist/kernel/progressive-hnsw-backend.js.map +1 -0
- package/v3/dist/kernel/unified-memory-hnsw.d.ts +71 -0
- package/v3/dist/kernel/unified-memory-hnsw.d.ts.map +1 -1
- package/v3/dist/kernel/unified-memory-hnsw.js +87 -0
- package/v3/dist/kernel/unified-memory-hnsw.js.map +1 -1
- package/v3/dist/kernel/unified-memory-schemas.d.ts +1 -0
- package/v3/dist/kernel/unified-memory-schemas.d.ts.map +1 -1
- package/v3/dist/kernel/unified-memory-schemas.js +16 -0
- package/v3/dist/kernel/unified-memory-schemas.js.map +1 -1
- package/v3/dist/learning/dream/dream-engine.d.ts +16 -0
- package/v3/dist/learning/dream/dream-engine.d.ts.map +1 -1
- package/v3/dist/learning/dream/dream-engine.js +70 -0
- package/v3/dist/learning/dream/dream-engine.js.map +1 -1
- package/v3/dist/learning/dream/index.d.ts +2 -0
- package/v3/dist/learning/dream/index.d.ts.map +1 -1
- package/v3/dist/learning/dream/index.js +8 -0
- package/v3/dist/learning/dream/index.js.map +1 -1
- package/v3/dist/learning/dream/rvcow-branch-manager.d.ts +170 -0
- package/v3/dist/learning/dream/rvcow-branch-manager.d.ts.map +1 -0
- package/v3/dist/learning/dream/rvcow-branch-manager.js +263 -0
- package/v3/dist/learning/dream/rvcow-branch-manager.js.map +1 -0
- package/v3/dist/learning/dream/speculative-dreamer.d.ts +129 -0
- package/v3/dist/learning/dream/speculative-dreamer.d.ts.map +1 -0
- package/v3/dist/learning/dream/speculative-dreamer.js +214 -0
- package/v3/dist/learning/dream/speculative-dreamer.js.map +1 -0
- package/v3/dist/learning/qe-reasoning-bank.d.ts +9 -0
- package/v3/dist/learning/qe-reasoning-bank.d.ts.map +1 -1
- package/v3/dist/learning/qe-reasoning-bank.js +50 -1
- package/v3/dist/learning/qe-reasoning-bank.js.map +1 -1
- package/v3/dist/mcp/bundle.js +8900 -7163
- package/v3/dist/mcp/services/mincut-routing-service.d.ts +148 -0
- package/v3/dist/mcp/services/mincut-routing-service.d.ts.map +1 -0
- package/v3/dist/mcp/services/mincut-routing-service.js +198 -0
- package/v3/dist/mcp/services/mincut-routing-service.js.map +1 -0
- package/v3/dist/mcp/services/task-router.d.ts +4 -0
- package/v3/dist/mcp/services/task-router.d.ts.map +1 -1
- package/v3/dist/mcp/services/task-router.js +57 -15
- package/v3/dist/mcp/services/task-router.js.map +1 -1
- package/v3/dist/monitoring/structural-health.d.ts +142 -0
- package/v3/dist/monitoring/structural-health.d.ts.map +1 -0
- package/v3/dist/monitoring/structural-health.js +201 -0
- package/v3/dist/monitoring/structural-health.js.map +1 -0
- package/v3/package.json +1 -1
package/v3/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,36 @@ All notable changes to Agentic QE will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [3.7.0] - 2026-02-23
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **RVF Cognitive Container integration** — 12 of 16 planned integration tasks completed across 4 workstreams: MinCut routing, dream cycle branching, witness chain attestation, and HNSW unification
|
|
13
|
+
- **MinCut-based task routing** — Lambda (vertex connectivity) analysis models task complexity as a graph problem for the 3-tier model router; shadow mode collects comparison data against the production heuristic router
|
|
14
|
+
- **RVCOW dream cycle branching** — Copy-on-write branching for dream cycle experimentation using SQLite savepoints and in-memory overlays; speculative insights are isolated until merged
|
|
15
|
+
- **Cryptographic witness chain** — SHA-256 hash-chained append-only audit trail for quality gate decisions, pattern promotions, test suite completions, and routing decisions; tamper-evident with chain verification
|
|
16
|
+
- **HNSW unification** — Consolidated 3 fragmented HNSW implementations behind a unified progressive adapter with 2-state search (fast flat scan vs full HNSW) based on collection size
|
|
17
|
+
- **Brain export/import CLI** — `aqe brain export`, `aqe brain import --dry-run`, and `aqe brain info` commands for portable QE intelligence containers (.aqe-brain format with JSONL + binary vectors)
|
|
18
|
+
- **MinCut test suite optimizer** — Models test suites as coverage graphs, computes minimum cut to identify critical tests, skippable tests, and optimal execution order; wired into test-execution domain
|
|
19
|
+
- **RVF dual-writer** — Best-effort dual-write from QEReasoningBank to both SQLite and RVF containers, preparing for future RVF promotion as primary storage
|
|
20
|
+
- **RVF native adapter** — Direct N-API bindings to @ruvector/rvf-node bypassing SDK wrapper bugs; graceful fallback when native binaries unavailable
|
|
21
|
+
- **Stoer-Wagner structural health monitor** — Computes exact mincut of swarm and codebase dependency graphs as a normalized connectivity health score
|
|
22
|
+
- **MinCut wrapper** — Unified interface over TypeScript MinCutCalculator with native @ruvector/mincut-node fallback detection
|
|
23
|
+
- **246 new tests** across all RVF integration modules (unit + integration)
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
|
|
27
|
+
- **Dead module wiring** — MinCut test optimizer, brain CLI handler, and RVF dual-writer were implemented but not reachable from production code paths; all three now wired into their respective domains
|
|
28
|
+
- **Benchmark baseline integrity** — Original pre-RVF baseline (Feb 22) restored after being accidentally overwritten by post-integration rerun; Feb 23 rerun preserved separately
|
|
29
|
+
- **Dual-writer test honesty** — 21 mock-only tests that verified call counts without checking behavior replaced with assertions that verify argument content and response shape
|
|
30
|
+
- **HNSW unification test stability** — Fixed non-deterministic vector ordering caused by cosine similarity scale-invariance (`v * 0.9` has identical cosine similarity to `v`); replaced with directionally different vector
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
|
|
34
|
+
- **Benchmark report transparency** — All "Live" status claims corrected to "Wired" or "Internal"; added honest "Modules Not Yet Wired" section; recommendations expanded from 5 to 9
|
|
35
|
+
- **QEReasoningBank extensibility** — Added optional `setRvfDualWriter()` injection point for best-effort dual-write during `storePattern()` and `promotePattern()`
|
|
36
|
+
- **Test execution coordinator** — Added `optimizeTestSuite()` method delegating to MinCut test optimizer
|
|
37
|
+
|
|
8
38
|
## [3.6.19] - 2026-02-22
|
|
9
39
|
|
|
10
40
|
### Fixed
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Witness Chain - Cryptographic Audit Trail for QE Decisions
|
|
3
|
+
* ADR-070: Witness Chain Audit Compliance
|
|
4
|
+
*
|
|
5
|
+
* Implements a SHA-256 hash-chained append-only log for audit compliance.
|
|
6
|
+
* Every quality gate decision, pattern mutation, and dream cycle action
|
|
7
|
+
* is recorded with cryptographic integrity guarantees.
|
|
8
|
+
*
|
|
9
|
+
* The chain is tamper-evident: modifying any entry breaks the hash chain,
|
|
10
|
+
* detectable by verify().
|
|
11
|
+
*/
|
|
12
|
+
import { type Database as DatabaseType } from 'better-sqlite3';
|
|
13
|
+
/**
|
|
14
|
+
* Actions that can be recorded in the witness chain
|
|
15
|
+
*/
|
|
16
|
+
export type WitnessActionType = 'PATTERN_CREATE' | 'PATTERN_UPDATE' | 'PATTERN_PROMOTE' | 'PATTERN_QUARANTINE' | 'DREAM_MERGE' | 'DREAM_DISCARD' | 'QUALITY_GATE_PASS' | 'QUALITY_GATE_FAIL' | 'ROUTING_DECISION';
|
|
17
|
+
/**
|
|
18
|
+
* A single entry in the witness chain
|
|
19
|
+
*/
|
|
20
|
+
export interface WitnessEntry {
|
|
21
|
+
/** Auto-incrementing ID */
|
|
22
|
+
id: number;
|
|
23
|
+
/** SHA-256 hash of the previous entry (64 hex chars, all zeros for genesis) */
|
|
24
|
+
prev_hash: string;
|
|
25
|
+
/** SHA-256 hash of the action data */
|
|
26
|
+
action_hash: string;
|
|
27
|
+
/** Type of action recorded */
|
|
28
|
+
action_type: WitnessActionType;
|
|
29
|
+
/** JSON-serialized action data */
|
|
30
|
+
action_data: string;
|
|
31
|
+
/** ISO 8601 timestamp */
|
|
32
|
+
timestamp: string;
|
|
33
|
+
/** Actor identifier (agent ID, system, dream engine, etc.) */
|
|
34
|
+
actor: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Filter options for querying witness entries
|
|
38
|
+
*/
|
|
39
|
+
export interface WitnessFilter {
|
|
40
|
+
/** Filter by action type */
|
|
41
|
+
action_type?: WitnessActionType;
|
|
42
|
+
/** Filter entries after this timestamp (inclusive) */
|
|
43
|
+
since?: string;
|
|
44
|
+
/** Filter entries before this timestamp (inclusive) */
|
|
45
|
+
until?: string;
|
|
46
|
+
/** Filter by actor */
|
|
47
|
+
actor?: string;
|
|
48
|
+
/** Maximum number of entries to return */
|
|
49
|
+
limit?: number;
|
|
50
|
+
/** Offset for pagination */
|
|
51
|
+
offset?: number;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Result of chain integrity verification
|
|
55
|
+
*/
|
|
56
|
+
export interface VerifyResult {
|
|
57
|
+
/** Whether the entire chain is valid */
|
|
58
|
+
valid: boolean;
|
|
59
|
+
/** The entry ID where the chain broke (undefined if valid) */
|
|
60
|
+
brokenAt?: number;
|
|
61
|
+
/** Total entries checked */
|
|
62
|
+
entriesChecked: number;
|
|
63
|
+
}
|
|
64
|
+
/** Genesis previous hash: 64 zero characters */
|
|
65
|
+
declare const GENESIS_PREV_HASH: string;
|
|
66
|
+
/**
|
|
67
|
+
* SHA-256 hash-chained append-only audit log.
|
|
68
|
+
*
|
|
69
|
+
* Each entry's prev_hash is the SHA-256 of the serialized previous entry,
|
|
70
|
+
* creating an immutable chain. Any modification to a past entry will cause
|
|
71
|
+
* verify() to detect the break.
|
|
72
|
+
*/
|
|
73
|
+
export declare class WitnessChain {
|
|
74
|
+
private readonly externalDb?;
|
|
75
|
+
private db;
|
|
76
|
+
private initialized;
|
|
77
|
+
/**
|
|
78
|
+
* Create a WitnessChain instance.
|
|
79
|
+
*
|
|
80
|
+
* @param externalDb - Optional external database connection (for testing
|
|
81
|
+
* with in-memory SQLite). When omitted, uses UnifiedMemoryManager.
|
|
82
|
+
*/
|
|
83
|
+
constructor(externalDb?: DatabaseType | undefined);
|
|
84
|
+
/**
|
|
85
|
+
* Initialize the witness chain.
|
|
86
|
+
* Creates the witness_chain table if it does not exist.
|
|
87
|
+
*/
|
|
88
|
+
initialize(): Promise<void>;
|
|
89
|
+
/**
|
|
90
|
+
* Create the witness_chain table (additive, does not touch other tables).
|
|
91
|
+
*/
|
|
92
|
+
private ensureTable;
|
|
93
|
+
/**
|
|
94
|
+
* Append a new entry to the witness chain.
|
|
95
|
+
*
|
|
96
|
+
* @param actionType - The type of action being recorded
|
|
97
|
+
* @param actionData - Arbitrary data describing the action
|
|
98
|
+
* @param actor - Who performed the action
|
|
99
|
+
* @returns The newly created WitnessEntry
|
|
100
|
+
*/
|
|
101
|
+
append(actionType: WitnessActionType, actionData: Record<string, unknown>, actor: string): WitnessEntry;
|
|
102
|
+
/**
|
|
103
|
+
* Verify the integrity of the entire witness chain.
|
|
104
|
+
*
|
|
105
|
+
* Walks through every entry in order and checks that each entry's
|
|
106
|
+
* prev_hash matches the SHA-256 of the previous entry's serialized form.
|
|
107
|
+
*
|
|
108
|
+
* @returns Verification result with validity status and break point
|
|
109
|
+
*/
|
|
110
|
+
verify(): VerifyResult;
|
|
111
|
+
/**
|
|
112
|
+
* Query witness chain entries with optional filters.
|
|
113
|
+
*
|
|
114
|
+
* @param filter - Optional filter criteria
|
|
115
|
+
* @returns Array of matching WitnessEntry records
|
|
116
|
+
*/
|
|
117
|
+
getEntries(filter?: WitnessFilter): WitnessEntry[];
|
|
118
|
+
/**
|
|
119
|
+
* Cross-verify our SQLite witness chain against an RVF native witness.
|
|
120
|
+
*
|
|
121
|
+
* Calls rvfAdapter.status() to get witnessValid and witnessEntries,
|
|
122
|
+
* then compares with our own verify() result.
|
|
123
|
+
*
|
|
124
|
+
* @param rvfAdapter - An RvfNativeAdapter instance with a status() method
|
|
125
|
+
* @returns Cross-verification result from both chains
|
|
126
|
+
*/
|
|
127
|
+
crossVerifyWithRvf(rvfAdapter: any): {
|
|
128
|
+
sqliteValid: boolean;
|
|
129
|
+
rvfValid: boolean;
|
|
130
|
+
rvfEntries: number;
|
|
131
|
+
bothValid: boolean;
|
|
132
|
+
};
|
|
133
|
+
/**
|
|
134
|
+
* Get the total number of entries in the chain.
|
|
135
|
+
*/
|
|
136
|
+
getChainLength(): number;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Get or create the singleton WitnessChain instance.
|
|
140
|
+
* Uses UnifiedMemoryManager for storage.
|
|
141
|
+
*/
|
|
142
|
+
export declare function getWitnessChain(): Promise<WitnessChain>;
|
|
143
|
+
/**
|
|
144
|
+
* Create a WitnessChain with an external database (for testing).
|
|
145
|
+
*/
|
|
146
|
+
export declare function createWitnessChain(db: DatabaseType): WitnessChain;
|
|
147
|
+
export { GENESIS_PREV_HASH };
|
|
148
|
+
//# sourceMappingURL=witness-chain.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"witness-chain.d.ts","sourceRoot":"","sources":["../../src/audit/witness-chain.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EAAE,KAAK,QAAQ,IAAI,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAQ/D;;GAEG;AACH,MAAM,MAAM,iBAAiB,GACzB,gBAAgB,GAChB,gBAAgB,GAChB,iBAAiB,GACjB,oBAAoB,GACpB,aAAa,GACb,eAAe,GACf,mBAAmB,GACnB,mBAAmB,GACnB,kBAAkB,CAAC;AAEvB;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,2BAA2B;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,+EAA+E;IAC/E,SAAS,EAAE,MAAM,CAAC;IAClB,sCAAsC;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,8BAA8B;IAC9B,WAAW,EAAE,iBAAiB,CAAC;IAC/B,kCAAkC;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,yBAAyB;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,8DAA8D;IAC9D,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,4BAA4B;IAC5B,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC,sDAAsD;IACtD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uDAAuD;IACvD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sBAAsB;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4BAA4B;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,wCAAwC;IACxC,KAAK,EAAE,OAAO,CAAC;IACf,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4BAA4B;IAC5B,cAAc,EAAE,MAAM,CAAC;CACxB;AAMD,gDAAgD;AAChD,QAAA,MAAM,iBAAiB,QAAiB,CAAC;AAMzC;;;;;;GAMG;AACH,qBAAa,YAAY;IAUX,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC;IATxC,OAAO,CAAC,EAAE,CAA6B;IACvC,OAAO,CAAC,WAAW,CAAS;IAE5B;;;;;OAKG;gBAC0B,UAAU,CAAC,EAAE,YAAY,YAAA;IAEtD;;;OAGG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAejC;;OAEG;IACH,OAAO,CAAC,WAAW;IAkBnB;;;;;;;OAOG;IACH,MAAM,CACJ,UAAU,EAAE,iBAAiB,EAC7B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,KAAK,EAAE,MAAM,GACZ,YAAY;IAkCf;;;;;;;OAOG;IACH,MAAM,IAAI,YAAY;IAyCtB;;;;;OAKG;IACH,UAAU,CAAC,MAAM,CAAC,EAAE,aAAa,GAAG,YAAY,EAAE;IA+BlD;;;;;;;;OAQG;IAEH,kBAAkB,CAAC,UAAU,EAAE,GAAG,GAAG;QACnC,WAAW,EAAE,OAAO,CAAC;QACrB,QAAQ,EAAE,OAAO,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,OAAO,CAAC;KACpB;IAcD;;OAEG;IACH,cAAc,IAAI,MAAM;CAQzB;AAmCD;;;GAGG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,YAAY,CAAC,CAM7D;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,YAAY,GAAG,YAAY,CAEjE;AAGD,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Witness Chain - Cryptographic Audit Trail for QE Decisions
|
|
3
|
+
* ADR-070: Witness Chain Audit Compliance
|
|
4
|
+
*
|
|
5
|
+
* Implements a SHA-256 hash-chained append-only log for audit compliance.
|
|
6
|
+
* Every quality gate decision, pattern mutation, and dream cycle action
|
|
7
|
+
* is recorded with cryptographic integrity guarantees.
|
|
8
|
+
*
|
|
9
|
+
* The chain is tamper-evident: modifying any entry breaks the hash chain,
|
|
10
|
+
* detectable by verify().
|
|
11
|
+
*/
|
|
12
|
+
import { createHash } from 'crypto';
|
|
13
|
+
import { getUnifiedMemory } from '../kernel/unified-memory.js';
|
|
14
|
+
// ============================================================================
|
|
15
|
+
// Constants
|
|
16
|
+
// ============================================================================
|
|
17
|
+
/** Genesis previous hash: 64 zero characters */
|
|
18
|
+
const GENESIS_PREV_HASH = '0'.repeat(64);
|
|
19
|
+
// ============================================================================
|
|
20
|
+
// WitnessChain Implementation
|
|
21
|
+
// ============================================================================
|
|
22
|
+
/**
|
|
23
|
+
* SHA-256 hash-chained append-only audit log.
|
|
24
|
+
*
|
|
25
|
+
* Each entry's prev_hash is the SHA-256 of the serialized previous entry,
|
|
26
|
+
* creating an immutable chain. Any modification to a past entry will cause
|
|
27
|
+
* verify() to detect the break.
|
|
28
|
+
*/
|
|
29
|
+
export class WitnessChain {
|
|
30
|
+
externalDb;
|
|
31
|
+
db = null;
|
|
32
|
+
initialized = false;
|
|
33
|
+
/**
|
|
34
|
+
* Create a WitnessChain instance.
|
|
35
|
+
*
|
|
36
|
+
* @param externalDb - Optional external database connection (for testing
|
|
37
|
+
* with in-memory SQLite). When omitted, uses UnifiedMemoryManager.
|
|
38
|
+
*/
|
|
39
|
+
constructor(externalDb) {
|
|
40
|
+
this.externalDb = externalDb;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Initialize the witness chain.
|
|
44
|
+
* Creates the witness_chain table if it does not exist.
|
|
45
|
+
*/
|
|
46
|
+
async initialize() {
|
|
47
|
+
if (this.initialized)
|
|
48
|
+
return;
|
|
49
|
+
if (this.externalDb) {
|
|
50
|
+
this.db = this.externalDb;
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
const unified = getUnifiedMemory();
|
|
54
|
+
await unified.initialize();
|
|
55
|
+
this.db = unified.getDatabase();
|
|
56
|
+
}
|
|
57
|
+
this.ensureTable();
|
|
58
|
+
this.initialized = true;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Create the witness_chain table (additive, does not touch other tables).
|
|
62
|
+
*/
|
|
63
|
+
ensureTable() {
|
|
64
|
+
if (!this.db)
|
|
65
|
+
throw new Error('Database not initialized');
|
|
66
|
+
this.db.exec(`
|
|
67
|
+
CREATE TABLE IF NOT EXISTS witness_chain (
|
|
68
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
69
|
+
prev_hash TEXT NOT NULL,
|
|
70
|
+
action_hash TEXT NOT NULL,
|
|
71
|
+
action_type TEXT NOT NULL,
|
|
72
|
+
action_data TEXT,
|
|
73
|
+
timestamp TEXT NOT NULL,
|
|
74
|
+
actor TEXT NOT NULL
|
|
75
|
+
);
|
|
76
|
+
CREATE INDEX IF NOT EXISTS idx_witness_action_type ON witness_chain(action_type);
|
|
77
|
+
CREATE INDEX IF NOT EXISTS idx_witness_timestamp ON witness_chain(timestamp);
|
|
78
|
+
`);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Append a new entry to the witness chain.
|
|
82
|
+
*
|
|
83
|
+
* @param actionType - The type of action being recorded
|
|
84
|
+
* @param actionData - Arbitrary data describing the action
|
|
85
|
+
* @param actor - Who performed the action
|
|
86
|
+
* @returns The newly created WitnessEntry
|
|
87
|
+
*/
|
|
88
|
+
append(actionType, actionData, actor) {
|
|
89
|
+
if (!this.db)
|
|
90
|
+
throw new Error('WitnessChain not initialized');
|
|
91
|
+
const timestamp = new Date().toISOString();
|
|
92
|
+
const actionDataStr = JSON.stringify(actionData);
|
|
93
|
+
const actionHash = sha256(actionDataStr);
|
|
94
|
+
// Get the previous entry's hash
|
|
95
|
+
const lastEntry = this.db
|
|
96
|
+
.prepare('SELECT * FROM witness_chain ORDER BY id DESC LIMIT 1')
|
|
97
|
+
.get();
|
|
98
|
+
const prevHash = lastEntry ? sha256(serializeEntry(lastEntry)) : GENESIS_PREV_HASH;
|
|
99
|
+
const result = this.db
|
|
100
|
+
.prepare(`INSERT INTO witness_chain (prev_hash, action_hash, action_type, action_data, timestamp, actor)
|
|
101
|
+
VALUES (?, ?, ?, ?, ?, ?)`)
|
|
102
|
+
.run(prevHash, actionHash, actionType, actionDataStr, timestamp, actor);
|
|
103
|
+
const entry = {
|
|
104
|
+
id: result.lastInsertRowid,
|
|
105
|
+
prev_hash: prevHash,
|
|
106
|
+
action_hash: actionHash,
|
|
107
|
+
action_type: actionType,
|
|
108
|
+
action_data: actionDataStr,
|
|
109
|
+
timestamp,
|
|
110
|
+
actor,
|
|
111
|
+
};
|
|
112
|
+
return entry;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Verify the integrity of the entire witness chain.
|
|
116
|
+
*
|
|
117
|
+
* Walks through every entry in order and checks that each entry's
|
|
118
|
+
* prev_hash matches the SHA-256 of the previous entry's serialized form.
|
|
119
|
+
*
|
|
120
|
+
* @returns Verification result with validity status and break point
|
|
121
|
+
*/
|
|
122
|
+
verify() {
|
|
123
|
+
if (!this.db)
|
|
124
|
+
throw new Error('WitnessChain not initialized');
|
|
125
|
+
const entries = this.db
|
|
126
|
+
.prepare('SELECT * FROM witness_chain ORDER BY id ASC')
|
|
127
|
+
.all();
|
|
128
|
+
if (entries.length === 0) {
|
|
129
|
+
return { valid: true, entriesChecked: 0 };
|
|
130
|
+
}
|
|
131
|
+
// Check genesis entry
|
|
132
|
+
if (entries[0].prev_hash !== GENESIS_PREV_HASH) {
|
|
133
|
+
return { valid: false, brokenAt: entries[0].id, entriesChecked: 1 };
|
|
134
|
+
}
|
|
135
|
+
// Check action_hash for first entry
|
|
136
|
+
if (entries[0].action_hash !== sha256(entries[0].action_data)) {
|
|
137
|
+
return { valid: false, brokenAt: entries[0].id, entriesChecked: 1 };
|
|
138
|
+
}
|
|
139
|
+
// Walk the chain
|
|
140
|
+
for (let i = 1; i < entries.length; i++) {
|
|
141
|
+
const current = entries[i];
|
|
142
|
+
const previous = entries[i - 1];
|
|
143
|
+
// Verify action_hash
|
|
144
|
+
if (current.action_hash !== sha256(current.action_data)) {
|
|
145
|
+
return { valid: false, brokenAt: current.id, entriesChecked: i + 1 };
|
|
146
|
+
}
|
|
147
|
+
// Verify prev_hash links to previous entry
|
|
148
|
+
const expectedPrevHash = sha256(serializeEntry(previous));
|
|
149
|
+
if (current.prev_hash !== expectedPrevHash) {
|
|
150
|
+
return { valid: false, brokenAt: current.id, entriesChecked: i + 1 };
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return { valid: true, entriesChecked: entries.length };
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Query witness chain entries with optional filters.
|
|
157
|
+
*
|
|
158
|
+
* @param filter - Optional filter criteria
|
|
159
|
+
* @returns Array of matching WitnessEntry records
|
|
160
|
+
*/
|
|
161
|
+
getEntries(filter) {
|
|
162
|
+
if (!this.db)
|
|
163
|
+
throw new Error('WitnessChain not initialized');
|
|
164
|
+
const conditions = [];
|
|
165
|
+
const params = [];
|
|
166
|
+
if (filter?.action_type) {
|
|
167
|
+
conditions.push('action_type = ?');
|
|
168
|
+
params.push(filter.action_type);
|
|
169
|
+
}
|
|
170
|
+
if (filter?.since) {
|
|
171
|
+
conditions.push('timestamp >= ?');
|
|
172
|
+
params.push(filter.since);
|
|
173
|
+
}
|
|
174
|
+
if (filter?.until) {
|
|
175
|
+
conditions.push('timestamp <= ?');
|
|
176
|
+
params.push(filter.until);
|
|
177
|
+
}
|
|
178
|
+
if (filter?.actor) {
|
|
179
|
+
conditions.push('actor = ?');
|
|
180
|
+
params.push(filter.actor);
|
|
181
|
+
}
|
|
182
|
+
const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
|
|
183
|
+
const limit = filter?.limit ? `LIMIT ${filter.limit}` : '';
|
|
184
|
+
const offset = filter?.offset ? `OFFSET ${filter.offset}` : '';
|
|
185
|
+
const sql = `SELECT * FROM witness_chain ${where} ORDER BY id ASC ${limit} ${offset}`;
|
|
186
|
+
return this.db.prepare(sql).all(...params);
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Cross-verify our SQLite witness chain against an RVF native witness.
|
|
190
|
+
*
|
|
191
|
+
* Calls rvfAdapter.status() to get witnessValid and witnessEntries,
|
|
192
|
+
* then compares with our own verify() result.
|
|
193
|
+
*
|
|
194
|
+
* @param rvfAdapter - An RvfNativeAdapter instance with a status() method
|
|
195
|
+
* @returns Cross-verification result from both chains
|
|
196
|
+
*/
|
|
197
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
198
|
+
crossVerifyWithRvf(rvfAdapter) {
|
|
199
|
+
const sqliteResult = this.verify();
|
|
200
|
+
const rvfStatus = rvfAdapter.status();
|
|
201
|
+
const rvfValid = rvfStatus.witnessValid === true;
|
|
202
|
+
const rvfEntries = typeof rvfStatus.witnessEntries === 'number' ? rvfStatus.witnessEntries : 0;
|
|
203
|
+
return {
|
|
204
|
+
sqliteValid: sqliteResult.valid,
|
|
205
|
+
rvfValid,
|
|
206
|
+
rvfEntries,
|
|
207
|
+
bothValid: sqliteResult.valid && rvfValid,
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Get the total number of entries in the chain.
|
|
212
|
+
*/
|
|
213
|
+
getChainLength() {
|
|
214
|
+
if (!this.db)
|
|
215
|
+
throw new Error('WitnessChain not initialized');
|
|
216
|
+
const row = this.db
|
|
217
|
+
.prepare('SELECT COUNT(*) as count FROM witness_chain')
|
|
218
|
+
.get();
|
|
219
|
+
return row.count;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
// ============================================================================
|
|
223
|
+
// Helper Functions
|
|
224
|
+
// ============================================================================
|
|
225
|
+
/**
|
|
226
|
+
* Compute SHA-256 hex digest of a string.
|
|
227
|
+
*/
|
|
228
|
+
function sha256(data) {
|
|
229
|
+
return createHash('sha256').update(data, 'utf-8').digest('hex');
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Serialize a WitnessEntry to a deterministic string for hashing.
|
|
233
|
+
* Uses a fixed field order to ensure consistency.
|
|
234
|
+
*/
|
|
235
|
+
function serializeEntry(entry) {
|
|
236
|
+
return JSON.stringify({
|
|
237
|
+
id: entry.id,
|
|
238
|
+
prev_hash: entry.prev_hash,
|
|
239
|
+
action_hash: entry.action_hash,
|
|
240
|
+
action_type: entry.action_type,
|
|
241
|
+
action_data: entry.action_data,
|
|
242
|
+
timestamp: entry.timestamp,
|
|
243
|
+
actor: entry.actor,
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
// ============================================================================
|
|
247
|
+
// Singleton / Factory
|
|
248
|
+
// ============================================================================
|
|
249
|
+
let _instance = null;
|
|
250
|
+
/**
|
|
251
|
+
* Get or create the singleton WitnessChain instance.
|
|
252
|
+
* Uses UnifiedMemoryManager for storage.
|
|
253
|
+
*/
|
|
254
|
+
export async function getWitnessChain() {
|
|
255
|
+
if (!_instance) {
|
|
256
|
+
_instance = new WitnessChain();
|
|
257
|
+
await _instance.initialize();
|
|
258
|
+
}
|
|
259
|
+
return _instance;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Create a WitnessChain with an external database (for testing).
|
|
263
|
+
*/
|
|
264
|
+
export function createWitnessChain(db) {
|
|
265
|
+
return new WitnessChain(db);
|
|
266
|
+
}
|
|
267
|
+
// Re-export for convenience
|
|
268
|
+
export { GENESIS_PREV_HASH };
|
|
269
|
+
//# sourceMappingURL=witness-chain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"witness-chain.js","sourceRoot":"","sources":["../../src/audit/witness-chain.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Brain CLI Commands
|
|
3
|
+
*
|
|
4
|
+
* Exported functions for brain export/import that can be wired into
|
|
5
|
+
* the CLI command registry. These are thin wrappers around the core
|
|
6
|
+
* brain-exporter module, handling database connection lifecycle.
|
|
7
|
+
*/
|
|
8
|
+
import { type BrainExportManifest, type BrainExportOptions, type BrainImportOptions, type BrainImportResult } from '../integrations/ruvector/brain-exporter.js';
|
|
9
|
+
/**
|
|
10
|
+
* Export the QE brain state from a database to a portable directory.
|
|
11
|
+
*
|
|
12
|
+
* Opens the database in read-only WAL mode to avoid write locks,
|
|
13
|
+
* then delegates to the core export function.
|
|
14
|
+
*
|
|
15
|
+
* @param dbPath - Path to the source SQLite database
|
|
16
|
+
* @param options - Export options including output path and filters
|
|
17
|
+
* @returns The export manifest with stats and checksum
|
|
18
|
+
*/
|
|
19
|
+
export declare function exportBrain(dbPath: string, options: BrainExportOptions): Promise<BrainExportManifest>;
|
|
20
|
+
/**
|
|
21
|
+
* Import a brain export directory into a target database.
|
|
22
|
+
*
|
|
23
|
+
* Opens the database in read-write mode, validates the manifest
|
|
24
|
+
* checksum, then merges data using the specified strategy.
|
|
25
|
+
*
|
|
26
|
+
* @param dbPath - Path to the target SQLite database
|
|
27
|
+
* @param containerPath - Path to the brain export directory
|
|
28
|
+
* @param options - Import options including merge strategy
|
|
29
|
+
* @returns Import result with counts of imported, skipped, and conflicting records
|
|
30
|
+
*/
|
|
31
|
+
export declare function importBrain(dbPath: string, containerPath: string, options: BrainImportOptions): Promise<BrainImportResult>;
|
|
32
|
+
/**
|
|
33
|
+
* Read the manifest from a brain export directory.
|
|
34
|
+
*
|
|
35
|
+
* @param containerPath - Path to the brain export directory
|
|
36
|
+
* @returns The export manifest
|
|
37
|
+
*/
|
|
38
|
+
export declare function brainInfo(containerPath: string): Promise<BrainExportManifest>;
|
|
39
|
+
//# sourceMappingURL=brain-commands.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brain-commands.d.ts","sourceRoot":"","sources":["../../src/cli/brain-commands.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAIL,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACvB,MAAM,4CAA4C,CAAC;AAEpD;;;;;;;;;GASG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,mBAAmB,CAAC,CAS9B;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,iBAAiB,CAAC,CAS5B;AAED;;;;;GAKG;AACH,wBAAsB,SAAS,CAC7B,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,mBAAmB,CAAC,CAE9B"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Brain CLI Commands
|
|
3
|
+
*
|
|
4
|
+
* Exported functions for brain export/import that can be wired into
|
|
5
|
+
* the CLI command registry. These are thin wrappers around the core
|
|
6
|
+
* brain-exporter module, handling database connection lifecycle.
|
|
7
|
+
*/
|
|
8
|
+
import Database from 'better-sqlite3';
|
|
9
|
+
import { exportBrain as coreExportBrain, importBrain as coreImportBrain, brainInfo as coreBrainInfo, } from '../integrations/ruvector/brain-exporter.js';
|
|
10
|
+
/**
|
|
11
|
+
* Export the QE brain state from a database to a portable directory.
|
|
12
|
+
*
|
|
13
|
+
* Opens the database in read-only WAL mode to avoid write locks,
|
|
14
|
+
* then delegates to the core export function.
|
|
15
|
+
*
|
|
16
|
+
* @param dbPath - Path to the source SQLite database
|
|
17
|
+
* @param options - Export options including output path and filters
|
|
18
|
+
* @returns The export manifest with stats and checksum
|
|
19
|
+
*/
|
|
20
|
+
export async function exportBrain(dbPath, options) {
|
|
21
|
+
const db = new Database(dbPath, { readonly: true });
|
|
22
|
+
db.pragma('journal_mode = WAL');
|
|
23
|
+
try {
|
|
24
|
+
return coreExportBrain(db, options, dbPath);
|
|
25
|
+
}
|
|
26
|
+
finally {
|
|
27
|
+
db.close();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Import a brain export directory into a target database.
|
|
32
|
+
*
|
|
33
|
+
* Opens the database in read-write mode, validates the manifest
|
|
34
|
+
* checksum, then merges data using the specified strategy.
|
|
35
|
+
*
|
|
36
|
+
* @param dbPath - Path to the target SQLite database
|
|
37
|
+
* @param containerPath - Path to the brain export directory
|
|
38
|
+
* @param options - Import options including merge strategy
|
|
39
|
+
* @returns Import result with counts of imported, skipped, and conflicting records
|
|
40
|
+
*/
|
|
41
|
+
export async function importBrain(dbPath, containerPath, options) {
|
|
42
|
+
const db = new Database(dbPath);
|
|
43
|
+
db.pragma('journal_mode = WAL');
|
|
44
|
+
try {
|
|
45
|
+
return coreImportBrain(db, containerPath, options);
|
|
46
|
+
}
|
|
47
|
+
finally {
|
|
48
|
+
db.close();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Read the manifest from a brain export directory.
|
|
53
|
+
*
|
|
54
|
+
* @param containerPath - Path to the brain export directory
|
|
55
|
+
* @returns The export manifest
|
|
56
|
+
*/
|
|
57
|
+
export async function brainInfo(containerPath) {
|
|
58
|
+
return coreBrainInfo(containerPath);
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=brain-commands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brain-commands.js","sourceRoot":"","sources":["../../src/cli/brain-commands.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,EACL,WAAW,IAAI,eAAe,EAC9B,WAAW,IAAI,eAAe,EAC9B,SAAS,IAAI,aAAa,GAK3B,MAAM,4CAA4C,CAAC;AAEpD;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAAc,EACd,OAA2B;IAE3B,MAAM,EAAE,GAAG,IAAI,QAAQ,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IACpD,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;IAEhC,IAAI,CAAC;QACH,OAAO,eAAe,CAAC,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAC9C,CAAC;YAAS,CAAC;QACT,EAAE,CAAC,KAAK,EAAE,CAAC;IACb,CAAC;AACH,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAAc,EACd,aAAqB,EACrB,OAA2B;IAE3B,MAAM,EAAE,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC;IAChC,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;IAEhC,IAAI,CAAC;QACH,OAAO,eAAe,CAAC,EAAE,EAAE,aAAa,EAAE,OAAO,CAAC,CAAC;IACrD,CAAC;YAAS,CAAC;QACT,EAAE,CAAC,KAAK,EAAE,CAAC;IACb,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,aAAqB;IAErB,OAAO,aAAa,CAAC,aAAa,CAAC,CAAC;AACtC,CAAC"}
|