wyrm-mcp 3.7.1 → 4.0.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/README.md +17 -1
- package/dist/audit.d.ts +82 -0
- package/dist/audit.d.ts.map +1 -0
- package/dist/audit.js +151 -0
- package/dist/audit.js.map +1 -0
- package/dist/causality.d.ts +76 -0
- package/dist/causality.d.ts.map +1 -0
- package/dist/causality.js +115 -0
- package/dist/causality.js.map +1 -0
- package/dist/database.d.ts.map +1 -1
- package/dist/database.js +5 -0
- package/dist/database.js.map +1 -1
- package/dist/failure-patterns.d.ts +60 -0
- package/dist/failure-patterns.d.ts.map +1 -0
- package/dist/failure-patterns.js +117 -0
- package/dist/failure-patterns.js.map +1 -0
- package/dist/federation.d.ts +82 -0
- package/dist/federation.d.ts.map +1 -0
- package/dist/federation.js +220 -0
- package/dist/federation.js.map +1 -0
- package/dist/hours.d.ts +82 -0
- package/dist/hours.d.ts.map +1 -0
- package/dist/hours.js +162 -0
- package/dist/hours.js.map +1 -0
- package/dist/http-fast.d.ts.map +1 -1
- package/dist/http-fast.js +183 -1
- package/dist/http-fast.js.map +1 -1
- package/dist/http-server.js +1 -1
- package/dist/http-server.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1000 -99
- package/dist/index.js.map +1 -1
- package/dist/indexer.d.ts +2 -0
- package/dist/indexer.d.ts.map +1 -1
- package/dist/indexer.js +4 -0
- package/dist/indexer.js.map +1 -1
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +265 -1
- package/dist/migrations.js.map +1 -1
- package/dist/presence.d.ts +71 -0
- package/dist/presence.d.ts.map +1 -0
- package/dist/presence.js +133 -0
- package/dist/presence.js.map +1 -0
- package/dist/rehydration.d.ts +39 -0
- package/dist/rehydration.d.ts.map +1 -0
- package/dist/rehydration.js +178 -0
- package/dist/rehydration.js.map +1 -0
- package/dist/setup.js +0 -0
- package/dist/sub-agent.d.ts +58 -0
- package/dist/sub-agent.d.ts.map +1 -0
- package/dist/sub-agent.js +292 -0
- package/dist/sub-agent.js.map +1 -0
- package/dist/symbols.d.ts +65 -0
- package/dist/symbols.d.ts.map +1 -0
- package/dist/symbols.js +291 -0
- package/dist/symbols.js.map +1 -0
- package/dist/tool-analytics.d.ts +85 -0
- package/dist/tool-analytics.d.ts.map +1 -0
- package/dist/tool-analytics.js +161 -0
- package/dist/tool-analytics.js.map +1 -0
- package/dist/wyrm-cli.js +0 -0
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -177,7 +177,23 @@ Add to `~/.codeium/windsurf/mcp_config.json`:
|
|
|
177
177
|
|
|
178
178
|
Or run **`wyrm-setup`** to auto-detect and configure all installed AI clients at once.
|
|
179
179
|
|
|
180
|
-
### 3.
|
|
180
|
+
### 3. Enable Semantic Search (Optional but Recommended)
|
|
181
|
+
|
|
182
|
+
Wyrm uses hybrid search (FTS5 + semantic vectors) when [Ollama](https://ollama.com) is running locally. No configuration needed — Wyrm auto-detects it.
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
# Install Ollama: https://ollama.com
|
|
186
|
+
ollama pull nomic-embed-text
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
That's it. Once `nomic-embed-text` is available, `wyrm_search` automatically upgrades from keyword-only to hybrid semantic+keyword search using Reciprocal Rank Fusion. If Ollama isn't running, Wyrm falls back to FTS5 silently — no errors, no config changes required.
|
|
190
|
+
|
|
191
|
+
To use OpenAI embeddings instead:
|
|
192
|
+
```bash
|
|
193
|
+
WYRM_VECTOR_PROVIDER=openai OPENAI_API_KEY=sk-... wyrm-mcp
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### 4. Use It
|
|
181
197
|
|
|
182
198
|
Once connected, your AI has access to all Wyrm tools. Try:
|
|
183
199
|
|
package/dist/audit.d.ts
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compliance audit trail (Tier 3.9).
|
|
3
|
+
*
|
|
4
|
+
* Hash-chained event log: each row records sha256(prev_hash || payload ||
|
|
5
|
+
* timestamp). Tampering with any historical entry breaks the chain.
|
|
6
|
+
* Optional Ed25519 signing layered on top provides a SOC2 / HIPAA-grade
|
|
7
|
+
* audit surface — every AI decision, prompt, tool call, code edit, with
|
|
8
|
+
* the prompt that caused it.
|
|
9
|
+
*
|
|
10
|
+
* `wyrm_audit_export(range)` produces a tamper-evident JSON bundle that
|
|
11
|
+
* an external auditor can verify offline:
|
|
12
|
+
* 1. Recompute the hash chain from genesis through the range.
|
|
13
|
+
* 2. Verify Ed25519 signatures against the operator's public key.
|
|
14
|
+
* 3. Confirm no gaps in IDs.
|
|
15
|
+
*
|
|
16
|
+
* @copyright 2026 Ghost Protocol (Pvt) Ltd. All Rights Reserved.
|
|
17
|
+
* @license Proprietary
|
|
18
|
+
*/
|
|
19
|
+
import type Database from 'better-sqlite3';
|
|
20
|
+
export interface AuditEntry {
|
|
21
|
+
id: number;
|
|
22
|
+
event_kind: string;
|
|
23
|
+
actor: string | null;
|
|
24
|
+
project_id: number | null;
|
|
25
|
+
payload_json: string;
|
|
26
|
+
prev_hash: string;
|
|
27
|
+
row_hash: string;
|
|
28
|
+
signature: string | null;
|
|
29
|
+
logged_at: string;
|
|
30
|
+
}
|
|
31
|
+
export interface LogInput {
|
|
32
|
+
event_kind: string;
|
|
33
|
+
actor?: string | null;
|
|
34
|
+
project_id?: number | null;
|
|
35
|
+
payload: Record<string, unknown>;
|
|
36
|
+
signature?: string | null;
|
|
37
|
+
}
|
|
38
|
+
export interface AuditBundle {
|
|
39
|
+
version: 1;
|
|
40
|
+
range: {
|
|
41
|
+
start: string;
|
|
42
|
+
end: string;
|
|
43
|
+
};
|
|
44
|
+
exported_at: string;
|
|
45
|
+
entry_count: number;
|
|
46
|
+
first_id: number | null;
|
|
47
|
+
last_id: number | null;
|
|
48
|
+
genesis_prev_hash: string;
|
|
49
|
+
final_row_hash: string;
|
|
50
|
+
entries: AuditEntry[];
|
|
51
|
+
}
|
|
52
|
+
export interface VerificationResult {
|
|
53
|
+
ok: boolean;
|
|
54
|
+
total: number;
|
|
55
|
+
verified: number;
|
|
56
|
+
first_invalid_id?: number;
|
|
57
|
+
reason?: string;
|
|
58
|
+
}
|
|
59
|
+
export declare class AuditLog {
|
|
60
|
+
private db;
|
|
61
|
+
constructor(db: Database.Database);
|
|
62
|
+
/** Get the hash of the most recent entry (or 'genesis' if empty). */
|
|
63
|
+
private latestHash;
|
|
64
|
+
/** Append a hash-chained event. Returns the inserted row. */
|
|
65
|
+
log(input: LogInput): AuditEntry;
|
|
66
|
+
get(id: number): AuditEntry | null;
|
|
67
|
+
/** Verify the entire chain from the first row through the latest.
|
|
68
|
+
* Useful for periodic self-audits. */
|
|
69
|
+
verify(): VerificationResult;
|
|
70
|
+
/** Export a date-ranged tamper-evident bundle. Range is inclusive on
|
|
71
|
+
* both ends. Verification still walks from genesis to ensure no gaps. */
|
|
72
|
+
export(opts: {
|
|
73
|
+
range_start?: string;
|
|
74
|
+
range_end?: string;
|
|
75
|
+
}): AuditBundle;
|
|
76
|
+
/** Statically verify a previously-exported bundle (no DB required).
|
|
77
|
+
* Useful for the external auditor who only has the JSON file. */
|
|
78
|
+
static verifyBundle(bundle: AuditBundle): VerificationResult;
|
|
79
|
+
/** Slim query for recent entries — UI / dashboards. */
|
|
80
|
+
recent(limit?: number, kind?: string): AuditEntry[];
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=audit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../src/audit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAG3C,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,QAAQ;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,CAAC,CAAC;IACX,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,UAAU,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAID,qBAAa,QAAQ;IACP,OAAO,CAAC,EAAE;gBAAF,EAAE,EAAE,QAAQ,CAAC,QAAQ;IAEzC,qEAAqE;IACrE,OAAO,CAAC,UAAU;IAOlB,6DAA6D;IAC7D,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,UAAU;IAwBhC,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;IAMlC;0CACsC;IACtC,MAAM,IAAI,kBAAkB;IA8B5B;6EACyE;IACzE,MAAM,CAAC,IAAI,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,WAAW;IA+BvE;qEACiE;IACjE,MAAM,CAAC,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,kBAAkB;IAoC5D,uDAAuD;IACvD,MAAM,CAAC,KAAK,SAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,UAAU,EAAE;CAUjD"}
|
package/dist/audit.js
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compliance audit trail (Tier 3.9).
|
|
3
|
+
*
|
|
4
|
+
* Hash-chained event log: each row records sha256(prev_hash || payload ||
|
|
5
|
+
* timestamp). Tampering with any historical entry breaks the chain.
|
|
6
|
+
* Optional Ed25519 signing layered on top provides a SOC2 / HIPAA-grade
|
|
7
|
+
* audit surface — every AI decision, prompt, tool call, code edit, with
|
|
8
|
+
* the prompt that caused it.
|
|
9
|
+
*
|
|
10
|
+
* `wyrm_audit_export(range)` produces a tamper-evident JSON bundle that
|
|
11
|
+
* an external auditor can verify offline:
|
|
12
|
+
* 1. Recompute the hash chain from genesis through the range.
|
|
13
|
+
* 2. Verify Ed25519 signatures against the operator's public key.
|
|
14
|
+
* 3. Confirm no gaps in IDs.
|
|
15
|
+
*
|
|
16
|
+
* @copyright 2026 Ghost Protocol (Pvt) Ltd. All Rights Reserved.
|
|
17
|
+
* @license Proprietary
|
|
18
|
+
*/
|
|
19
|
+
import { createHash } from 'crypto';
|
|
20
|
+
const GENESIS_HASH = 'genesis';
|
|
21
|
+
export class AuditLog {
|
|
22
|
+
db;
|
|
23
|
+
constructor(db) {
|
|
24
|
+
this.db = db;
|
|
25
|
+
}
|
|
26
|
+
/** Get the hash of the most recent entry (or 'genesis' if empty). */
|
|
27
|
+
latestHash() {
|
|
28
|
+
const row = this.db.prepare('SELECT row_hash FROM audit_log ORDER BY id DESC LIMIT 1').get();
|
|
29
|
+
return row?.row_hash ?? GENESIS_HASH;
|
|
30
|
+
}
|
|
31
|
+
/** Append a hash-chained event. Returns the inserted row. */
|
|
32
|
+
log(input) {
|
|
33
|
+
const payloadJson = JSON.stringify(input.payload);
|
|
34
|
+
const loggedAt = new Date().toISOString();
|
|
35
|
+
const prevHash = this.latestHash();
|
|
36
|
+
const hashInput = `${prevHash}|${input.event_kind}|${payloadJson}|${loggedAt}`;
|
|
37
|
+
const rowHash = createHash('sha256').update(hashInput).digest('hex');
|
|
38
|
+
const info = this.db.prepare(`
|
|
39
|
+
INSERT INTO audit_log
|
|
40
|
+
(event_kind, actor, project_id, payload_json, prev_hash, row_hash, signature, logged_at)
|
|
41
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
42
|
+
`).run(input.event_kind, input.actor ?? null, input.project_id ?? null, payloadJson, prevHash, rowHash, input.signature ?? null, loggedAt);
|
|
43
|
+
return this.get(info.lastInsertRowid);
|
|
44
|
+
}
|
|
45
|
+
get(id) {
|
|
46
|
+
return this.db.prepare('SELECT * FROM audit_log WHERE id = ?').get(id) ?? null;
|
|
47
|
+
}
|
|
48
|
+
/** Verify the entire chain from the first row through the latest.
|
|
49
|
+
* Useful for periodic self-audits. */
|
|
50
|
+
verify() {
|
|
51
|
+
const rows = this.db.prepare('SELECT * FROM audit_log ORDER BY id ASC').all();
|
|
52
|
+
if (rows.length === 0)
|
|
53
|
+
return { ok: true, total: 0, verified: 0 };
|
|
54
|
+
let expectedPrev = GENESIS_HASH;
|
|
55
|
+
for (const row of rows) {
|
|
56
|
+
if (row.prev_hash !== expectedPrev) {
|
|
57
|
+
return {
|
|
58
|
+
ok: false, total: rows.length, verified: row.id - 1,
|
|
59
|
+
first_invalid_id: row.id,
|
|
60
|
+
reason: `prev_hash mismatch: expected ${expectedPrev}, got ${row.prev_hash}`,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
const recomputed = createHash('sha256')
|
|
64
|
+
.update(`${row.prev_hash}|${row.event_kind}|${row.payload_json}|${row.logged_at}`)
|
|
65
|
+
.digest('hex');
|
|
66
|
+
if (recomputed !== row.row_hash) {
|
|
67
|
+
return {
|
|
68
|
+
ok: false, total: rows.length, verified: row.id - 1,
|
|
69
|
+
first_invalid_id: row.id,
|
|
70
|
+
reason: `row_hash mismatch at id ${row.id}: recomputed ${recomputed}, stored ${row.row_hash}`,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
expectedPrev = row.row_hash;
|
|
74
|
+
}
|
|
75
|
+
return { ok: true, total: rows.length, verified: rows.length };
|
|
76
|
+
}
|
|
77
|
+
/** Export a date-ranged tamper-evident bundle. Range is inclusive on
|
|
78
|
+
* both ends. Verification still walks from genesis to ensure no gaps. */
|
|
79
|
+
export(opts) {
|
|
80
|
+
const params = [];
|
|
81
|
+
let where = '';
|
|
82
|
+
if (opts.range_start) {
|
|
83
|
+
where += ' AND logged_at >= ?';
|
|
84
|
+
params.push(opts.range_start);
|
|
85
|
+
}
|
|
86
|
+
if (opts.range_end) {
|
|
87
|
+
where += ' AND logged_at <= ?';
|
|
88
|
+
params.push(opts.range_end);
|
|
89
|
+
}
|
|
90
|
+
const entries = this.db.prepare(`SELECT * FROM audit_log WHERE 1=1 ${where} ORDER BY id ASC`).all(...params);
|
|
91
|
+
return {
|
|
92
|
+
version: 1,
|
|
93
|
+
range: {
|
|
94
|
+
start: opts.range_start ?? entries[0]?.logged_at ?? new Date(0).toISOString(),
|
|
95
|
+
end: opts.range_end ?? entries[entries.length - 1]?.logged_at ?? new Date().toISOString(),
|
|
96
|
+
},
|
|
97
|
+
exported_at: new Date().toISOString(),
|
|
98
|
+
entry_count: entries.length,
|
|
99
|
+
first_id: entries[0]?.id ?? null,
|
|
100
|
+
last_id: entries[entries.length - 1]?.id ?? null,
|
|
101
|
+
genesis_prev_hash: entries[0]?.prev_hash ?? GENESIS_HASH,
|
|
102
|
+
final_row_hash: entries[entries.length - 1]?.row_hash ?? GENESIS_HASH,
|
|
103
|
+
entries,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
/** Statically verify a previously-exported bundle (no DB required).
|
|
107
|
+
* Useful for the external auditor who only has the JSON file. */
|
|
108
|
+
static verifyBundle(bundle) {
|
|
109
|
+
if (bundle.version !== 1) {
|
|
110
|
+
return { ok: false, total: bundle.entry_count, verified: 0, reason: `Unknown bundle version ${bundle.version}` };
|
|
111
|
+
}
|
|
112
|
+
let expectedPrev = bundle.genesis_prev_hash;
|
|
113
|
+
let verified = 0;
|
|
114
|
+
for (const row of bundle.entries) {
|
|
115
|
+
if (row.prev_hash !== expectedPrev) {
|
|
116
|
+
return {
|
|
117
|
+
ok: false, total: bundle.entries.length, verified,
|
|
118
|
+
first_invalid_id: row.id,
|
|
119
|
+
reason: `prev_hash mismatch: expected ${expectedPrev}, got ${row.prev_hash}`,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
const recomputed = createHash('sha256')
|
|
123
|
+
.update(`${row.prev_hash}|${row.event_kind}|${row.payload_json}|${row.logged_at}`)
|
|
124
|
+
.digest('hex');
|
|
125
|
+
if (recomputed !== row.row_hash) {
|
|
126
|
+
return {
|
|
127
|
+
ok: false, total: bundle.entries.length, verified,
|
|
128
|
+
first_invalid_id: row.id,
|
|
129
|
+
reason: `row_hash mismatch at id ${row.id}`,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
expectedPrev = row.row_hash;
|
|
133
|
+
verified++;
|
|
134
|
+
}
|
|
135
|
+
if (bundle.entries.length > 0 && bundle.final_row_hash !== expectedPrev) {
|
|
136
|
+
return {
|
|
137
|
+
ok: false, total: bundle.entries.length, verified,
|
|
138
|
+
reason: `final_row_hash mismatch`,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
return { ok: true, total: bundle.entries.length, verified };
|
|
142
|
+
}
|
|
143
|
+
/** Slim query for recent entries — UI / dashboards. */
|
|
144
|
+
recent(limit = 100, kind) {
|
|
145
|
+
if (kind) {
|
|
146
|
+
return this.db.prepare('SELECT * FROM audit_log WHERE event_kind = ? ORDER BY id DESC LIMIT ?').all(kind, limit);
|
|
147
|
+
}
|
|
148
|
+
return this.db.prepare('SELECT * FROM audit_log ORDER BY id DESC LIMIT ?').all(limit);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=audit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.js","sourceRoot":"","sources":["../src/audit.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Causality — decision chains + downstream invalidation.
|
|
3
|
+
*
|
|
4
|
+
* "We chose Postgres because Y" → "Y turned out to be wrong" → flag every
|
|
5
|
+
* downstream decision built on Y for re-evaluation.
|
|
6
|
+
*
|
|
7
|
+
* Edges link a `(kind, id)` pair to another `(kind, id)` pair with a
|
|
8
|
+
* relation (`because_of`, `supersedes`, `refutes`, `verifies`). When a
|
|
9
|
+
* ground truth flips to stale or gets superseded, the invalidation
|
|
10
|
+
* cascade walks the edge graph and flags downstream decisions.
|
|
11
|
+
*
|
|
12
|
+
* @copyright 2026 Ghost Protocol (Pvt) Ltd. All Rights Reserved.
|
|
13
|
+
* @license Proprietary
|
|
14
|
+
*/
|
|
15
|
+
import type Database from 'better-sqlite3';
|
|
16
|
+
export type EdgeKind = 'truth' | 'artifact' | 'quest' | 'session' | 'data';
|
|
17
|
+
export type EdgeRelation = 'because_of' | 'supersedes' | 'refutes' | 'verifies';
|
|
18
|
+
export interface DecisionEdge {
|
|
19
|
+
id: number;
|
|
20
|
+
project_id: number;
|
|
21
|
+
from_kind: EdgeKind;
|
|
22
|
+
from_id: number;
|
|
23
|
+
to_kind: EdgeKind;
|
|
24
|
+
to_id: number;
|
|
25
|
+
relation: EdgeRelation;
|
|
26
|
+
rationale: string | null;
|
|
27
|
+
confidence: number;
|
|
28
|
+
created_at: string;
|
|
29
|
+
invalidated_at: string | null;
|
|
30
|
+
}
|
|
31
|
+
export interface LinkInput {
|
|
32
|
+
project_id: number;
|
|
33
|
+
from_kind: EdgeKind;
|
|
34
|
+
from_id: number;
|
|
35
|
+
to_kind: EdgeKind;
|
|
36
|
+
to_id: number;
|
|
37
|
+
relation?: EdgeRelation;
|
|
38
|
+
rationale?: string;
|
|
39
|
+
confidence?: number;
|
|
40
|
+
}
|
|
41
|
+
export interface InvalidationResult {
|
|
42
|
+
invalidated: number;
|
|
43
|
+
affected: Array<{
|
|
44
|
+
kind: EdgeKind;
|
|
45
|
+
id: number;
|
|
46
|
+
edge_id: number;
|
|
47
|
+
rationale: string | null;
|
|
48
|
+
}>;
|
|
49
|
+
}
|
|
50
|
+
export declare class Causality {
|
|
51
|
+
private db;
|
|
52
|
+
constructor(db: Database.Database);
|
|
53
|
+
/** Record that `from` was decided BECAUSE OF `to` (or other relation). */
|
|
54
|
+
link(input: LinkInput): DecisionEdge;
|
|
55
|
+
get(id: number): DecisionEdge | null;
|
|
56
|
+
/** All decisions that depend on the given source (outgoing edges from source). */
|
|
57
|
+
downstreamOf(kind: EdgeKind, id: number): DecisionEdge[];
|
|
58
|
+
/** All sources that the given decision was based on (incoming edges to decision). */
|
|
59
|
+
upstreamOf(kind: EdgeKind, id: number): DecisionEdge[];
|
|
60
|
+
/** Walk downstream from a source, depth-first, marking dependent decisions.
|
|
61
|
+
* Returns the set of (kind, id) pairs affected. Idempotent — already-
|
|
62
|
+
* invalidated edges are skipped. */
|
|
63
|
+
invalidateDownstream(kind: EdgeKind, id: number, reason?: string): InvalidationResult;
|
|
64
|
+
/** Path query: list edges forming the decision chain from `from` back to `to`,
|
|
65
|
+
* walking upstream up to maxDepth. Returns empty if no path. */
|
|
66
|
+
pathTo(from: {
|
|
67
|
+
kind: EdgeKind;
|
|
68
|
+
id: number;
|
|
69
|
+
}, to: {
|
|
70
|
+
kind: EdgeKind;
|
|
71
|
+
id: number;
|
|
72
|
+
}, maxDepth?: number): DecisionEdge[];
|
|
73
|
+
/** List all currently-invalidated edges that touch a project. */
|
|
74
|
+
invalidatedInProject(projectId: number, limit?: number): DecisionEdge[];
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=causality.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"causality.d.ts","sourceRoot":"","sources":["../src/causality.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAE3C,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,UAAU,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AAC3E,MAAM,MAAM,YAAY,GAAG,YAAY,GAAG,YAAY,GAAG,SAAS,GAAG,UAAU,CAAC;AAEhF,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,QAAQ,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,QAAQ,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,YAAY,CAAC;IACvB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,SAAS;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,QAAQ,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,QAAQ,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,QAAQ,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;CAC5F;AAED,qBAAa,SAAS;IACR,OAAO,CAAC,EAAE;gBAAF,EAAE,EAAE,QAAQ,CAAC,QAAQ;IAEzC,0EAA0E;IAC1E,IAAI,CAAC,KAAK,EAAE,SAAS,GAAG,YAAY;IAgBpC,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI;IAMpC,kFAAkF;IAClF,YAAY,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,GAAG,YAAY,EAAE;IAQxD,qFAAqF;IACrF,UAAU,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,GAAG,YAAY,EAAE;IAQtD;;wCAEoC;IACpC,oBAAoB,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,kBAAkB;IAkCrF;oEACgE;IAChE,MAAM,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,QAAQ,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,EAAE,EAAE,EAAE;QAAE,IAAI,EAAE,QAAQ,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,EAAE,QAAQ,SAAI,GAAG,YAAY,EAAE;IAqB9G,iEAAiE;IACjE,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,YAAY,EAAE;CAQpE"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Causality — decision chains + downstream invalidation.
|
|
3
|
+
*
|
|
4
|
+
* "We chose Postgres because Y" → "Y turned out to be wrong" → flag every
|
|
5
|
+
* downstream decision built on Y for re-evaluation.
|
|
6
|
+
*
|
|
7
|
+
* Edges link a `(kind, id)` pair to another `(kind, id)` pair with a
|
|
8
|
+
* relation (`because_of`, `supersedes`, `refutes`, `verifies`). When a
|
|
9
|
+
* ground truth flips to stale or gets superseded, the invalidation
|
|
10
|
+
* cascade walks the edge graph and flags downstream decisions.
|
|
11
|
+
*
|
|
12
|
+
* @copyright 2026 Ghost Protocol (Pvt) Ltd. All Rights Reserved.
|
|
13
|
+
* @license Proprietary
|
|
14
|
+
*/
|
|
15
|
+
export class Causality {
|
|
16
|
+
db;
|
|
17
|
+
constructor(db) {
|
|
18
|
+
this.db = db;
|
|
19
|
+
}
|
|
20
|
+
/** Record that `from` was decided BECAUSE OF `to` (or other relation). */
|
|
21
|
+
link(input) {
|
|
22
|
+
const info = this.db.prepare(`
|
|
23
|
+
INSERT INTO decision_edges
|
|
24
|
+
(project_id, from_kind, from_id, to_kind, to_id, relation, rationale, confidence)
|
|
25
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
26
|
+
`).run(input.project_id, input.from_kind, input.from_id, input.to_kind, input.to_id, input.relation ?? 'because_of', input.rationale ?? null, input.confidence ?? 1.0);
|
|
27
|
+
return this.get(info.lastInsertRowid);
|
|
28
|
+
}
|
|
29
|
+
get(id) {
|
|
30
|
+
return this.db.prepare('SELECT * FROM decision_edges WHERE id = ?').get(id) ?? null;
|
|
31
|
+
}
|
|
32
|
+
/** All decisions that depend on the given source (outgoing edges from source). */
|
|
33
|
+
downstreamOf(kind, id) {
|
|
34
|
+
return this.db.prepare(`
|
|
35
|
+
SELECT * FROM decision_edges
|
|
36
|
+
WHERE to_kind = ? AND to_id = ? AND invalidated_at IS NULL
|
|
37
|
+
ORDER BY created_at DESC
|
|
38
|
+
`).all(kind, id);
|
|
39
|
+
}
|
|
40
|
+
/** All sources that the given decision was based on (incoming edges to decision). */
|
|
41
|
+
upstreamOf(kind, id) {
|
|
42
|
+
return this.db.prepare(`
|
|
43
|
+
SELECT * FROM decision_edges
|
|
44
|
+
WHERE from_kind = ? AND from_id = ? AND invalidated_at IS NULL
|
|
45
|
+
ORDER BY created_at DESC
|
|
46
|
+
`).all(kind, id);
|
|
47
|
+
}
|
|
48
|
+
/** Walk downstream from a source, depth-first, marking dependent decisions.
|
|
49
|
+
* Returns the set of (kind, id) pairs affected. Idempotent — already-
|
|
50
|
+
* invalidated edges are skipped. */
|
|
51
|
+
invalidateDownstream(kind, id, reason) {
|
|
52
|
+
const affected = [];
|
|
53
|
+
const seen = new Set();
|
|
54
|
+
const queue = [{ kind, id }];
|
|
55
|
+
const markEdge = this.db.prepare(`
|
|
56
|
+
UPDATE decision_edges
|
|
57
|
+
SET invalidated_at = datetime('now'),
|
|
58
|
+
rationale = COALESCE(?, rationale)
|
|
59
|
+
WHERE id = ?
|
|
60
|
+
`);
|
|
61
|
+
while (queue.length > 0) {
|
|
62
|
+
const node = queue.shift();
|
|
63
|
+
const key = `${node.kind}:${node.id}`;
|
|
64
|
+
if (seen.has(key))
|
|
65
|
+
continue;
|
|
66
|
+
seen.add(key);
|
|
67
|
+
const edges = this.downstreamOf(node.kind, node.id);
|
|
68
|
+
for (const edge of edges) {
|
|
69
|
+
markEdge.run(reason ?? null, edge.id);
|
|
70
|
+
affected.push({
|
|
71
|
+
kind: edge.from_kind,
|
|
72
|
+
id: edge.from_id,
|
|
73
|
+
edge_id: edge.id,
|
|
74
|
+
rationale: edge.rationale,
|
|
75
|
+
});
|
|
76
|
+
queue.push({ kind: edge.from_kind, id: edge.from_id });
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return { invalidated: affected.length, affected };
|
|
80
|
+
}
|
|
81
|
+
/** Path query: list edges forming the decision chain from `from` back to `to`,
|
|
82
|
+
* walking upstream up to maxDepth. Returns empty if no path. */
|
|
83
|
+
pathTo(from, to, maxDepth = 6) {
|
|
84
|
+
const visited = new Set();
|
|
85
|
+
const stack = [
|
|
86
|
+
{ node: from, path: [] },
|
|
87
|
+
];
|
|
88
|
+
while (stack.length > 0) {
|
|
89
|
+
const { node, path } = stack.pop();
|
|
90
|
+
const key = `${node.kind}:${node.id}`;
|
|
91
|
+
if (visited.has(key) || path.length > maxDepth)
|
|
92
|
+
continue;
|
|
93
|
+
visited.add(key);
|
|
94
|
+
if (node.kind === to.kind && node.id === to.id)
|
|
95
|
+
return path;
|
|
96
|
+
for (const edge of this.upstreamOf(node.kind, node.id)) {
|
|
97
|
+
stack.push({
|
|
98
|
+
node: { kind: edge.to_kind, id: edge.to_id },
|
|
99
|
+
path: [...path, edge],
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return [];
|
|
104
|
+
}
|
|
105
|
+
/** List all currently-invalidated edges that touch a project. */
|
|
106
|
+
invalidatedInProject(projectId, limit = 50) {
|
|
107
|
+
return this.db.prepare(`
|
|
108
|
+
SELECT * FROM decision_edges
|
|
109
|
+
WHERE project_id = ? AND invalidated_at IS NOT NULL
|
|
110
|
+
ORDER BY invalidated_at DESC
|
|
111
|
+
LIMIT ?
|
|
112
|
+
`).all(projectId, limit);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=causality.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"causality.js","sourceRoot":"","sources":["../src/causality.ts"],"names":[],"mappings":"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"}
|
package/dist/database.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,QAAQ,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"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"}
|
package/dist/database.js
CHANGED
|
@@ -20,6 +20,7 @@ import { spawnSync } from 'child_process';
|
|
|
20
20
|
import { getResilienceManager } from './resilience.js';
|
|
21
21
|
import { WyrmLogger } from './logger.js';
|
|
22
22
|
import { runMigrations, getSchemaVersion } from './migrations.js';
|
|
23
|
+
import { validateProjectPath } from './security.js';
|
|
23
24
|
export class WyrmDB {
|
|
24
25
|
db;
|
|
25
26
|
BATCH_SIZE = 1000;
|
|
@@ -94,6 +95,8 @@ export class WyrmDB {
|
|
|
94
95
|
}
|
|
95
96
|
// ==================== WATCH DIRECTORIES ====================
|
|
96
97
|
addWatchDir(path, recursive = true) {
|
|
98
|
+
// Validate path is within allowed directories to prevent directory traversal
|
|
99
|
+
validateProjectPath(path);
|
|
97
100
|
return this.db.prepare(`
|
|
98
101
|
INSERT INTO watch_dirs (path, recursive)
|
|
99
102
|
VALUES (?, ?)
|
|
@@ -109,6 +112,8 @@ export class WyrmDB {
|
|
|
109
112
|
}
|
|
110
113
|
// ==================== AUTO-DISCOVERY ====================
|
|
111
114
|
scanForProjects(rootPath, recursive = true) {
|
|
115
|
+
// Validate path is within allowed directories to prevent directory traversal
|
|
116
|
+
validateProjectPath(rootPath);
|
|
112
117
|
const discovered = [];
|
|
113
118
|
const scan = (dir, depth = 0) => {
|
|
114
119
|
if (depth > 3 && recursive)
|