smart-claude-memory-mcp 2.1.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-plugin/plugin.json +38 -0
- package/CHANGELOG.md +52 -0
- package/LICENSE +21 -0
- package/README.md +790 -0
- package/dist/chunker.js +33 -0
- package/dist/chunker.js.map +1 -0
- package/dist/config.js +23 -0
- package/dist/config.js.map +1 -0
- package/dist/curriculum/daemon.js +190 -0
- package/dist/curriculum/daemon.js.map +1 -0
- package/dist/curriculum/scanner.js +237 -0
- package/dist/curriculum/scanner.js.map +1 -0
- package/dist/index.js +429 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/migrations.js +128 -0
- package/dist/lib/migrations.js.map +1 -0
- package/dist/ollama.js +59 -0
- package/dist/ollama.js.map +1 -0
- package/dist/project-detect.js +102 -0
- package/dist/project-detect.js.map +1 -0
- package/dist/project.js +26 -0
- package/dist/project.js.map +1 -0
- package/dist/sleep/daemon.js +215 -0
- package/dist/sleep/daemon.js.map +1 -0
- package/dist/sleep/miner.js +285 -0
- package/dist/sleep/miner.js.map +1 -0
- package/dist/supabase.js +405 -0
- package/dist/supabase.js.map +1 -0
- package/dist/telemetry/emit.js +19 -0
- package/dist/telemetry/emit.js.map +1 -0
- package/dist/telemetry/pruner.js +141 -0
- package/dist/telemetry/pruner.js.map +1 -0
- package/dist/telemetry/types.js +2 -0
- package/dist/telemetry/types.js.map +1 -0
- package/dist/tools/backlog.js +599 -0
- package/dist/tools/backlog.js.map +1 -0
- package/dist/tools/batch-freeze-patterns.js +243 -0
- package/dist/tools/batch-freeze-patterns.js.map +1 -0
- package/dist/tools/bloat-audit.js +101 -0
- package/dist/tools/bloat-audit.js.map +1 -0
- package/dist/tools/checkpoint.js +259 -0
- package/dist/tools/checkpoint.js.map +1 -0
- package/dist/tools/compact.js +60 -0
- package/dist/tools/compact.js.map +1 -0
- package/dist/tools/conflict.js +102 -0
- package/dist/tools/conflict.js.map +1 -0
- package/dist/tools/curriculum.js +225 -0
- package/dist/tools/curriculum.js.map +1 -0
- package/dist/tools/frozen-cache.js +106 -0
- package/dist/tools/frozen-cache.js.map +1 -0
- package/dist/tools/health.js +368 -0
- package/dist/tools/health.js.map +1 -0
- package/dist/tools/hygiene.js +309 -0
- package/dist/tools/hygiene.js.map +1 -0
- package/dist/tools/image.js +107 -0
- package/dist/tools/image.js.map +1 -0
- package/dist/tools/list-global-patterns.js +101 -0
- package/dist/tools/list-global-patterns.js.map +1 -0
- package/dist/tools/orchestrator.js +113 -0
- package/dist/tools/orchestrator.js.map +1 -0
- package/dist/tools/policy.js +90 -0
- package/dist/tools/policy.js.map +1 -0
- package/dist/tools/refactor.js +220 -0
- package/dist/tools/refactor.js.map +1 -0
- package/dist/tools/save.js +42 -0
- package/dist/tools/save.js.map +1 -0
- package/dist/tools/search.js +189 -0
- package/dist/tools/search.js.map +1 -0
- package/dist/tools/setup.js +868 -0
- package/dist/tools/setup.js.map +1 -0
- package/dist/tools/shared-schemas.js +24 -0
- package/dist/tools/shared-schemas.js.map +1 -0
- package/dist/tools/skills.js +174 -0
- package/dist/tools/skills.js.map +1 -0
- package/dist/tools/sleep.js +239 -0
- package/dist/tools/sleep.js.map +1 -0
- package/dist/tools/sovereign-constitution.js +319 -0
- package/dist/tools/sovereign-constitution.js.map +1 -0
- package/dist/tools/summarize.js +55 -0
- package/dist/tools/summarize.js.map +1 -0
- package/dist/tools/sync.js +255 -0
- package/dist/tools/sync.js.map +1 -0
- package/dist/tools/system_dashboard.js +181 -0
- package/dist/tools/system_dashboard.js.map +1 -0
- package/dist/tools/update-rule.js +15 -0
- package/dist/tools/update-rule.js.map +1 -0
- package/dist/tools/verification.js +333 -0
- package/dist/tools/verification.js.map +1 -0
- package/dist/trajectory/daemon.js +270 -0
- package/dist/trajectory/daemon.js.map +1 -0
- package/dist/trajectory/stripper.js +124 -0
- package/dist/trajectory/stripper.js.map +1 -0
- package/dist/trajectory/summarizer.js +77 -0
- package/dist/trajectory/summarizer.js.map +1 -0
- package/dist/transactions/checkpoint.js +272 -0
- package/dist/transactions/checkpoint.js.map +1 -0
- package/dist/verification-gate.js +43 -0
- package/dist/verification-gate.js.map +1 -0
- package/dist/version.js +16 -0
- package/dist/version.js.map +1 -0
- package/hooks/README.md +54 -0
- package/hooks/md-policy.py +497 -0
- package/marketplace.json +13 -0
- package/package.json +66 -0
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { supabase } from "../supabase.js";
|
|
2
|
+
import { currentProjectId } from "../project.js";
|
|
3
|
+
import { getSleepLearnerStatus } from "../sleep/daemon.js";
|
|
4
|
+
import { getCurriculumStatus } from "../curriculum/daemon.js";
|
|
5
|
+
import { getCompactorStatus } from "../trajectory/daemon.js";
|
|
6
|
+
import { getTelemetryPrunerStatus } from "../telemetry/pruner.js";
|
|
7
|
+
function rollupFor(rows, sinceMs) {
|
|
8
|
+
const filtered = rows.filter((r) => Date.parse(r.created_at) >= sinceMs);
|
|
9
|
+
let runs = 0;
|
|
10
|
+
let errors = 0;
|
|
11
|
+
let itemsProcessed = 0;
|
|
12
|
+
const outcomes = { verified: 0, rejected: 0, auto_promoted: 0 };
|
|
13
|
+
for (const r of filtered) {
|
|
14
|
+
const p = r.payload ?? {};
|
|
15
|
+
if (r.event_type === "run_ended") {
|
|
16
|
+
runs++;
|
|
17
|
+
const compacted = typeof p.compacted === "number" ? p.compacted : 0;
|
|
18
|
+
const mined = typeof p.mined === "number" ? p.mined : 0;
|
|
19
|
+
const queued = typeof p.queued === "number" ? p.queued : 0;
|
|
20
|
+
const deleted = typeof p.deleted === "number" ? p.deleted : 0;
|
|
21
|
+
itemsProcessed += compacted + mined + queued + deleted;
|
|
22
|
+
}
|
|
23
|
+
else if (r.event_type === "run_errored") {
|
|
24
|
+
errors++;
|
|
25
|
+
}
|
|
26
|
+
else if (r.event_type === "task_outcome") {
|
|
27
|
+
if (typeof p.verified === "number")
|
|
28
|
+
outcomes.verified += p.verified;
|
|
29
|
+
if (typeof p.rejected === "number")
|
|
30
|
+
outcomes.rejected += p.rejected;
|
|
31
|
+
if (typeof p.auto_promoted === "number")
|
|
32
|
+
outcomes.auto_promoted += p.auto_promoted;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return { runs, errors, items_processed: itemsProcessed, outcomes };
|
|
36
|
+
}
|
|
37
|
+
export async function systemDashboardHandler(input) {
|
|
38
|
+
const windowHours = input.window_hours ?? 24;
|
|
39
|
+
const sinceIso = new Date(Date.now() - windowHours * 3600_000).toISOString();
|
|
40
|
+
let q = supabase
|
|
41
|
+
.from("daemon_telemetry")
|
|
42
|
+
.select("daemon, event_type, payload, created_at")
|
|
43
|
+
.eq("project_id", currentProjectId)
|
|
44
|
+
.gte("created_at", sinceIso)
|
|
45
|
+
.order("created_at", { ascending: false })
|
|
46
|
+
.limit(2000);
|
|
47
|
+
if (input.daemon)
|
|
48
|
+
q = q.eq("daemon", input.daemon);
|
|
49
|
+
const { data, error } = await q;
|
|
50
|
+
if (error)
|
|
51
|
+
throw new Error(`system_dashboard query failed: ${error.message}`);
|
|
52
|
+
const rows = (data ?? []);
|
|
53
|
+
const live = {
|
|
54
|
+
sleep_learner: getSleepLearnerStatus(),
|
|
55
|
+
curriculum_scanner: getCurriculumStatus(),
|
|
56
|
+
trajectory_compactor: getCompactorStatus(),
|
|
57
|
+
telemetry_pruner: getTelemetryPrunerStatus(),
|
|
58
|
+
};
|
|
59
|
+
const now = Date.now();
|
|
60
|
+
const oneHourAgo = now - 3600_000;
|
|
61
|
+
const windowStart = now - windowHours * 3600_000;
|
|
62
|
+
const daemons = {};
|
|
63
|
+
for (const d of ["sleep_learner", "curriculum_scanner", "trajectory_compactor", "telemetry_pruner"]) {
|
|
64
|
+
if (input.daemon && input.daemon !== d)
|
|
65
|
+
continue;
|
|
66
|
+
const daemonRows = rows.filter((r) => r.daemon === d);
|
|
67
|
+
const r1h = rollupFor(daemonRows, oneHourAgo);
|
|
68
|
+
const r24h = rollupFor(daemonRows, windowStart);
|
|
69
|
+
const lastError = daemonRows.find((r) => r.event_type === "run_errored");
|
|
70
|
+
const errDenominator = r24h.runs + r24h.errors;
|
|
71
|
+
daemons[d] = {
|
|
72
|
+
live: live[d],
|
|
73
|
+
rollup_1h: r1h,
|
|
74
|
+
rollup_24h: r24h,
|
|
75
|
+
error_rate_24h: errDenominator === 0 ? 0 : r24h.errors / errDenominator,
|
|
76
|
+
last_error_at: lastError?.created_at ?? null,
|
|
77
|
+
last_error_message: lastError?.payload?.error_message ?? null,
|
|
78
|
+
recent_runs: daemonRows.slice(0, 20).map((r) => ({
|
|
79
|
+
event_type: r.event_type,
|
|
80
|
+
created_at: r.created_at,
|
|
81
|
+
payload: r.payload,
|
|
82
|
+
})),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
project_id: currentProjectId,
|
|
87
|
+
window_hours: windowHours,
|
|
88
|
+
generated_at: new Date().toISOString(),
|
|
89
|
+
daemons,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function relTime(iso, now) {
|
|
93
|
+
const ms = now - Date.parse(iso);
|
|
94
|
+
if (!Number.isFinite(ms))
|
|
95
|
+
return "?";
|
|
96
|
+
const sec = Math.max(0, Math.round(ms / 1000));
|
|
97
|
+
if (sec < 60)
|
|
98
|
+
return `T-${sec}s`;
|
|
99
|
+
const min = Math.round(sec / 60);
|
|
100
|
+
if (min < 60)
|
|
101
|
+
return `T-${min}m`;
|
|
102
|
+
const hr = Math.round(min / 60);
|
|
103
|
+
if (hr < 24)
|
|
104
|
+
return `T-${hr}h`;
|
|
105
|
+
return `T-${Math.round(hr / 24)}d`;
|
|
106
|
+
}
|
|
107
|
+
function compactLive(snap) {
|
|
108
|
+
const pick = [
|
|
109
|
+
"enabled", "running", "interval_ms", "retention_days", "last_run_at",
|
|
110
|
+
"candidates_mined_total", "queued_total",
|
|
111
|
+
"verified_total", "rejected_total", "auto_promotions_total",
|
|
112
|
+
"last_run_deleted",
|
|
113
|
+
];
|
|
114
|
+
const parts = [];
|
|
115
|
+
for (const k of pick) {
|
|
116
|
+
if (!(k in snap))
|
|
117
|
+
continue;
|
|
118
|
+
const v = snap[k];
|
|
119
|
+
const short = typeof v === "boolean" ? (v ? "t" : "f")
|
|
120
|
+
: v === null ? "null"
|
|
121
|
+
: typeof v === "number" ? String(v)
|
|
122
|
+
: typeof v === "string" ? v
|
|
123
|
+
: JSON.stringify(v);
|
|
124
|
+
parts.push(`${k}=${short}`);
|
|
125
|
+
}
|
|
126
|
+
return parts.join(" ");
|
|
127
|
+
}
|
|
128
|
+
export function renderDashboardMarkdown(result) {
|
|
129
|
+
const now = Date.now();
|
|
130
|
+
const order = ["sleep_learner", "curriculum_scanner", "trajectory_compactor", "telemetry_pruner"];
|
|
131
|
+
const D = result.daemons;
|
|
132
|
+
const lines = [];
|
|
133
|
+
lines.push(`# Dashboard \`${result.project_id}\` · ${result.window_hours}h · ${result.generated_at}`);
|
|
134
|
+
lines.push("");
|
|
135
|
+
lines.push("| Daemon | runs 1h/24h | err 1h/24h | items 24h | v/r/ap 24h | err_rate | last_err |");
|
|
136
|
+
lines.push("|---|---|---|---|---|---|---|");
|
|
137
|
+
for (const d of order) {
|
|
138
|
+
const b = D[d];
|
|
139
|
+
if (!b) {
|
|
140
|
+
lines.push(`| ${d} | — | — | — | — | — | — |`);
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
const o = b.rollup_24h.outcomes;
|
|
144
|
+
const lastErr = b.last_error_at
|
|
145
|
+
? `${relTime(b.last_error_at, now)} ${b.last_error_message ?? ""}`.trim()
|
|
146
|
+
: "—";
|
|
147
|
+
lines.push(`| ${d} | ${b.rollup_1h.runs}/${b.rollup_24h.runs} | ${b.rollup_1h.errors}/${b.rollup_24h.errors} | ${b.rollup_24h.items_processed} | ${o.verified}/${o.rejected}/${o.auto_promoted} | ${b.error_rate_24h.toFixed(3)} | ${lastErr} |`);
|
|
148
|
+
}
|
|
149
|
+
lines.push("");
|
|
150
|
+
lines.push("## Live");
|
|
151
|
+
for (const d of order) {
|
|
152
|
+
const b = D[d];
|
|
153
|
+
if (!b)
|
|
154
|
+
continue;
|
|
155
|
+
lines.push(`- ${d}: ${compactLive(b.live ?? {})}`);
|
|
156
|
+
}
|
|
157
|
+
lines.push("");
|
|
158
|
+
lines.push("## Recent (max 5 per daemon)");
|
|
159
|
+
for (const d of order) {
|
|
160
|
+
const b = D[d];
|
|
161
|
+
if (!b)
|
|
162
|
+
continue;
|
|
163
|
+
const recent = b.recent_runs.slice(0, 5);
|
|
164
|
+
if (recent.length === 0) {
|
|
165
|
+
lines.push(`- ${d}: (no activity)`);
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
const parts = recent.map((r) => {
|
|
169
|
+
const p = r.payload ?? {};
|
|
170
|
+
if (r.event_type === "task_outcome") {
|
|
171
|
+
const keys = ["verified", "rejected", "auto_promoted"].filter((k) => k in p);
|
|
172
|
+
const inner = keys.map((k) => `${k[0]}:${p[k]}`).join(",");
|
|
173
|
+
return `task_outcome{${inner}}@${relTime(r.created_at, now)}`;
|
|
174
|
+
}
|
|
175
|
+
return `${r.event_type}@${relTime(r.created_at, now)}`;
|
|
176
|
+
});
|
|
177
|
+
lines.push(`- ${d}: ${parts.join(", ")}`);
|
|
178
|
+
}
|
|
179
|
+
return lines.join("\n");
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=system_dashboard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"system_dashboard.js","sourceRoot":"","sources":["../../src/tools/system_dashboard.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { embed } from "../ollama.js";
|
|
2
|
+
import { upsertRule } from "../supabase.js";
|
|
3
|
+
import { currentProjectId } from "../project.js";
|
|
4
|
+
export async function updateRule(args) {
|
|
5
|
+
const projectId = args.project_id ?? currentProjectId;
|
|
6
|
+
const [vec] = await embed([args.content]);
|
|
7
|
+
const id = await upsertRule(projectId, args.file_origin, args.chunk_index, args.content, vec, args.metadata ?? {});
|
|
8
|
+
return {
|
|
9
|
+
id,
|
|
10
|
+
project_id: projectId,
|
|
11
|
+
file_origin: args.file_origin,
|
|
12
|
+
chunk_index: args.chunk_index,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=update-rule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update-rule.js","sourceRoot":"","sources":["../../src/tools/update-rule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjD,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAMhC;IACC,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,IAAI,gBAAgB,CAAC;IACtD,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,KAAK,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IAC1C,MAAM,EAAE,GAAG,MAAM,UAAU,CACzB,SAAS,EACT,IAAI,CAAC,WAAW,EAChB,IAAI,CAAC,WAAW,EAChB,IAAI,CAAC,OAAO,EACZ,GAAG,EACH,IAAI,CAAC,QAAQ,IAAI,EAAE,CACpB,CAAC;IACF,OAAO;QACL,EAAE;QACF,UAAU,EAAE,SAAS;QACrB,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,WAAW,EAAE,IAAI,CAAC,WAAW;KAC9B,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
import { resolve, dirname, join, basename, relative } from "node:path";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
import { readFile } from "node:fs/promises";
|
|
4
|
+
import { homedir } from "node:os";
|
|
5
|
+
import { glob } from "glob";
|
|
6
|
+
import { classifyLegacyBackup } from "./setup.js";
|
|
7
|
+
import { setPending, clearPending, getPending, FLAG_PATH, } from "../verification-gate.js";
|
|
8
|
+
import { addFrozenPattern, writeFrozenPatternsCache } from "../supabase.js";
|
|
9
|
+
import { currentProjectId } from "../project.js";
|
|
10
|
+
// TODO(v1.2.0): drop the legacy CLAUDE_MEMORY_GATE_DIR fallback after the Smart Claude Memory rebrand has settled.
|
|
11
|
+
// The on-disk dir `~/.claude-memory` is intentionally preserved to keep existing backups discoverable.
|
|
12
|
+
const GATE_DIR = process.env.SMART_CLAUDE_MEMORY_GATE_DIR ??
|
|
13
|
+
process.env.CLAUDE_MEMORY_GATE_DIR ??
|
|
14
|
+
join(homedir(), ".claude-memory");
|
|
15
|
+
const BACKUP_INDEX_PATH = join(GATE_DIR, "backup-index.json");
|
|
16
|
+
async function getLatestBackup(filePath) {
|
|
17
|
+
try {
|
|
18
|
+
const raw = await readFile(BACKUP_INDEX_PATH, "utf8");
|
|
19
|
+
const data = JSON.parse(raw);
|
|
20
|
+
const abs = resolve(filePath);
|
|
21
|
+
return (data.entries?.[abs] ??
|
|
22
|
+
data.entries?.[filePath] ??
|
|
23
|
+
data.entries?.[abs.replace(/\\/g, "/")] ??
|
|
24
|
+
null);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* When the hook-managed backup-index has no entry for a broken file (e.g.,
|
|
32
|
+
* the break predates this plugin, or the backup was done manually by a
|
|
33
|
+
* previous workflow), scan the project for legacy backups whose filenames
|
|
34
|
+
* match the broken file's stem. Recognizes patterns like:
|
|
35
|
+
* logic_backup.ts, old_backup_auth.js, auth.ts.bak, payments.backup.ts
|
|
36
|
+
*/
|
|
37
|
+
async function findLegacyBackups(brokenFile) {
|
|
38
|
+
const abs = resolve(brokenFile);
|
|
39
|
+
const name = basename(abs);
|
|
40
|
+
const stem = name.replace(/\.[^.]+$/, "").toLowerCase();
|
|
41
|
+
// Determine workspace root — walk up until we find a package.json or git dir.
|
|
42
|
+
// If that fails, fall back to the broken file's directory.
|
|
43
|
+
let workspace = dirname(abs);
|
|
44
|
+
for (let i = 0; i < 8; i++) {
|
|
45
|
+
try {
|
|
46
|
+
await readFile(join(workspace, "package.json"));
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
const parent = dirname(workspace);
|
|
51
|
+
if (parent === workspace)
|
|
52
|
+
break;
|
|
53
|
+
workspace = parent;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
let hits = [];
|
|
57
|
+
try {
|
|
58
|
+
hits = await glob("**/*", {
|
|
59
|
+
cwd: workspace,
|
|
60
|
+
absolute: true,
|
|
61
|
+
nodir: true,
|
|
62
|
+
ignore: [
|
|
63
|
+
"**/node_modules/**",
|
|
64
|
+
"**/.git/**",
|
|
65
|
+
"**/dist/**",
|
|
66
|
+
"**/build/**",
|
|
67
|
+
],
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return [];
|
|
72
|
+
}
|
|
73
|
+
const out = [];
|
|
74
|
+
for (const p of hits) {
|
|
75
|
+
if (resolve(p) === abs)
|
|
76
|
+
continue;
|
|
77
|
+
const cls = classifyLegacyBackup(p);
|
|
78
|
+
if (!cls)
|
|
79
|
+
continue;
|
|
80
|
+
// Require the filename to mention the stem — otherwise we'd surface
|
|
81
|
+
// every backup file in the project when only the ones matching the
|
|
82
|
+
// broken file are relevant.
|
|
83
|
+
const candidateBase = basename(p).toLowerCase();
|
|
84
|
+
if (!candidateBase.includes(stem))
|
|
85
|
+
continue;
|
|
86
|
+
out.push({
|
|
87
|
+
path: p,
|
|
88
|
+
confidence: cls.confidence,
|
|
89
|
+
reason: `${cls.reason}; filename references '${stem}'`,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
// Sort HIGH first, then by relative path for stable ordering.
|
|
93
|
+
const order = { high: 0, medium: 1, low: 2 };
|
|
94
|
+
out.sort((a, b) => {
|
|
95
|
+
if (a.confidence !== b.confidence)
|
|
96
|
+
return order[a.confidence] - order[b.confidence];
|
|
97
|
+
return relative(workspace, a.path).localeCompare(relative(workspace, b.path));
|
|
98
|
+
});
|
|
99
|
+
return out.slice(0, 20);
|
|
100
|
+
}
|
|
101
|
+
// Resolve the package root so auto-freeze can skip files inside this plugin —
|
|
102
|
+
// we don't want verification-success on our own source to start blocking our
|
|
103
|
+
// own Write calls.
|
|
104
|
+
const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..", "..");
|
|
105
|
+
function isSmartClaudeMemorySource(filePath) {
|
|
106
|
+
try {
|
|
107
|
+
const abs = resolve(filePath);
|
|
108
|
+
// Normalize drive-letter casing on Windows so the startsWith check holds.
|
|
109
|
+
return abs.toLowerCase().startsWith(packageRoot.toLowerCase());
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
export async function confirmVerification(args) {
|
|
116
|
+
const existing = await getPending();
|
|
117
|
+
if (args.success) {
|
|
118
|
+
const cleared = await clearPending();
|
|
119
|
+
// Auto-freeze: if the gate was raised for a file, that file is now
|
|
120
|
+
// verified — add a frozen_features row so subsequent Writes to the same
|
|
121
|
+
// path are blocked by the hook. Edits remain allowed.
|
|
122
|
+
let autoFreeze = null;
|
|
123
|
+
if (existing?.file) {
|
|
124
|
+
if (isSmartClaudeMemorySource(existing.file)) {
|
|
125
|
+
autoFreeze = {
|
|
126
|
+
added: false,
|
|
127
|
+
skipped_reason: "System filter: file is inside the Smart Claude Memory package — not auto-freezing its own engine source.",
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
const projectId = existing.project_id ?? currentProjectId;
|
|
132
|
+
const reason = `Auto-frozen after successful manual verification. ${existing.reason ?? ""}`.trim();
|
|
133
|
+
try {
|
|
134
|
+
await addFrozenPattern(projectId, existing.file, reason);
|
|
135
|
+
const cache = await writeFrozenPatternsCache();
|
|
136
|
+
autoFreeze = {
|
|
137
|
+
added: true,
|
|
138
|
+
pattern: existing.file,
|
|
139
|
+
project_id: projectId,
|
|
140
|
+
reason,
|
|
141
|
+
cache_path: cache.path,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
catch (e) {
|
|
145
|
+
autoFreeze = {
|
|
146
|
+
added: false,
|
|
147
|
+
skipped_reason: `addFrozenPattern failed: ${e.message}`,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
const latestBackup = existing?.file ? await getLatestBackup(existing.file) : null;
|
|
153
|
+
const legacyBackups = existing?.file && !latestBackup
|
|
154
|
+
? await findLegacyBackups(existing.file)
|
|
155
|
+
: [];
|
|
156
|
+
return {
|
|
157
|
+
action: "confirm_verification",
|
|
158
|
+
success: true,
|
|
159
|
+
previously_pending: existing,
|
|
160
|
+
cleared,
|
|
161
|
+
auto_freeze: autoFreeze,
|
|
162
|
+
latest_backup: latestBackup,
|
|
163
|
+
legacy_backups: legacyBackups,
|
|
164
|
+
flag_path: FLAG_PATH,
|
|
165
|
+
message: cleared
|
|
166
|
+
? "Gate cleared. You may proceed with further tool calls."
|
|
167
|
+
: "No pending verification was active. Nothing to clear.",
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
// success:false → keep the gate closed, annotate with notes, and surface
|
|
171
|
+
// both the hook-managed backup AND any legacy "*backup*" files that
|
|
172
|
+
// reference the broken file's stem — so the AI has every restore option
|
|
173
|
+
// in one response.
|
|
174
|
+
if (existing) {
|
|
175
|
+
await setPending({ ...existing, reason: args.notes ?? "Verification failed" });
|
|
176
|
+
}
|
|
177
|
+
const latestBackup = existing?.file ? await getLatestBackup(existing.file) : null;
|
|
178
|
+
const legacyBackups = existing?.file ? await findLegacyBackups(existing.file) : [];
|
|
179
|
+
const parts = [];
|
|
180
|
+
parts.push(`Verification FAILED${existing?.file ? ` for ${existing.file}` : ""}.`);
|
|
181
|
+
if (latestBackup) {
|
|
182
|
+
parts.push(`PRIMARY RECOVERY: pre-edit snapshot at ${latestBackup.backup} ` +
|
|
183
|
+
`(created by ${latestBackup.tool} at ${latestBackup.timestamp}).`);
|
|
184
|
+
}
|
|
185
|
+
if (legacyBackups.length > 0) {
|
|
186
|
+
const top = legacyBackups.slice(0, 3);
|
|
187
|
+
parts.push(`LEGACY CANDIDATES: ${top.length} file${top.length === 1 ? "" : "s"} in the project whose name references '${basename(existing?.file ?? "").replace(/\.[^.]+$/, "")}' — e.g., ${top
|
|
188
|
+
.map((b) => b.path)
|
|
189
|
+
.join("; ")}. Treat these as additional restoration sources (they predate the plugin or came from prior workflows).`);
|
|
190
|
+
}
|
|
191
|
+
if (!latestBackup && legacyBackups.length === 0) {
|
|
192
|
+
parts.push("No backup was recorded and no legacy backup files match this file's stem. Restore from git or ask the user for the prior implementation.");
|
|
193
|
+
}
|
|
194
|
+
parts.push("Once fixed, call confirm_verification again with success:true.");
|
|
195
|
+
return {
|
|
196
|
+
action: "confirm_verification",
|
|
197
|
+
success: false,
|
|
198
|
+
still_pending: existing,
|
|
199
|
+
latest_backup: latestBackup,
|
|
200
|
+
legacy_backups: legacyBackups,
|
|
201
|
+
flag_path: FLAG_PATH,
|
|
202
|
+
message: parts.join(" "),
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
export async function raisePendingVerification(payload) {
|
|
206
|
+
await setPending(payload);
|
|
207
|
+
}
|
|
208
|
+
// ─── Regression tracer ────────────────────────────────────────────────────
|
|
209
|
+
async function listBackupsForFile(file) {
|
|
210
|
+
try {
|
|
211
|
+
const raw = await readFile(BACKUP_INDEX_PATH, "utf8");
|
|
212
|
+
const data = JSON.parse(raw);
|
|
213
|
+
const abs = resolve(file);
|
|
214
|
+
const found = data.entries?.[abs] ??
|
|
215
|
+
data.entries?.[file] ??
|
|
216
|
+
data.entries?.[abs.replace(/\\/g, "/")] ??
|
|
217
|
+
null;
|
|
218
|
+
// The index keeps only the LATEST per file. For history, rely on the
|
|
219
|
+
// timestamped subdirs produced by the hook under ~/.claude-memory/backups/.
|
|
220
|
+
const historical = [];
|
|
221
|
+
if (found)
|
|
222
|
+
historical.push(found);
|
|
223
|
+
// Walk backup root and collect anything matching the file's basename,
|
|
224
|
+
// newest first.
|
|
225
|
+
const { readdir } = await import("node:fs/promises");
|
|
226
|
+
const rootBase = join(GATE_DIR, "backups");
|
|
227
|
+
try {
|
|
228
|
+
const projects = await readdir(rootBase, { withFileTypes: true });
|
|
229
|
+
const bn = basename(abs).toLowerCase();
|
|
230
|
+
for (const p of projects) {
|
|
231
|
+
if (!p.isDirectory())
|
|
232
|
+
continue;
|
|
233
|
+
const projDir = join(rootBase, p.name);
|
|
234
|
+
const stamps = await readdir(projDir, { withFileTypes: true });
|
|
235
|
+
for (const ts of stamps) {
|
|
236
|
+
if (!ts.isDirectory())
|
|
237
|
+
continue;
|
|
238
|
+
const walk = async (d) => {
|
|
239
|
+
const entries = await readdir(d, { withFileTypes: true });
|
|
240
|
+
for (const e of entries) {
|
|
241
|
+
const full = join(d, e.name);
|
|
242
|
+
if (e.isDirectory())
|
|
243
|
+
await walk(full);
|
|
244
|
+
else if (e.name.toLowerCase() === bn) {
|
|
245
|
+
historical.push({ backup: full, tool: "history", timestamp: ts.name });
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
await walk(join(projDir, ts.name));
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
catch {
|
|
254
|
+
// No history root yet.
|
|
255
|
+
}
|
|
256
|
+
// Dedupe by backup path; sort by timestamp desc (lexical works with ISO).
|
|
257
|
+
const seen = new Set();
|
|
258
|
+
const unique = historical.filter((r) => !seen.has(r.backup) && seen.add(r.backup));
|
|
259
|
+
unique.sort((a, b) => b.timestamp.localeCompare(a.timestamp));
|
|
260
|
+
return unique;
|
|
261
|
+
}
|
|
262
|
+
catch {
|
|
263
|
+
return [];
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
function diffSummary(currentLines, priorLines) {
|
|
267
|
+
const curSet = new Set(currentLines);
|
|
268
|
+
const priorSet = new Set(priorLines);
|
|
269
|
+
const added = currentLines.filter((l) => !priorSet.has(l));
|
|
270
|
+
const removed = priorLines.filter((l) => !curSet.has(l));
|
|
271
|
+
const sample = [];
|
|
272
|
+
for (const l of added.slice(0, 3))
|
|
273
|
+
sample.push(`+ ${l.slice(0, 120)}`);
|
|
274
|
+
for (const l of removed.slice(0, 3))
|
|
275
|
+
sample.push(`- ${l.slice(0, 120)}`);
|
|
276
|
+
return { added: added.length, removed: removed.length, sample_changes: sample };
|
|
277
|
+
}
|
|
278
|
+
export async function analyzeRegression(args) {
|
|
279
|
+
const abs = resolve(args.file);
|
|
280
|
+
const n = Math.max(1, Math.min(args.backups_to_compare ?? 3, 10));
|
|
281
|
+
let currentText;
|
|
282
|
+
try {
|
|
283
|
+
currentText = await readFile(abs, "utf8");
|
|
284
|
+
}
|
|
285
|
+
catch (e) {
|
|
286
|
+
return {
|
|
287
|
+
action: "analyze_regression",
|
|
288
|
+
file: abs,
|
|
289
|
+
error: `Cannot read current file: ${e.message}`,
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
const currentLines = currentText.split(/\r?\n/);
|
|
293
|
+
const history = (await listBackupsForFile(abs)).slice(0, n);
|
|
294
|
+
if (history.length === 0) {
|
|
295
|
+
return {
|
|
296
|
+
action: "analyze_regression",
|
|
297
|
+
file: abs,
|
|
298
|
+
current_lines: currentLines.length,
|
|
299
|
+
comparisons: [],
|
|
300
|
+
note: "No backups found for this file. Check ~/.claude-memory/backups/ or fall back to git.",
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
const comparisons = [];
|
|
304
|
+
for (const rec of history) {
|
|
305
|
+
let priorText;
|
|
306
|
+
try {
|
|
307
|
+
priorText = await readFile(rec.backup, "utf8");
|
|
308
|
+
}
|
|
309
|
+
catch {
|
|
310
|
+
continue;
|
|
311
|
+
}
|
|
312
|
+
const priorLines = priorText.split(/\r?\n/);
|
|
313
|
+
comparisons.push({
|
|
314
|
+
backup: rec.backup,
|
|
315
|
+
tool: rec.tool,
|
|
316
|
+
timestamp: rec.timestamp,
|
|
317
|
+
prior_lines: priorLines.length,
|
|
318
|
+
diff: diffSummary(currentLines, priorLines),
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
const likelyStablePrior = comparisons.reduce((best, c) => (!best || c.diff.added + c.diff.removed < best.diff.added + best.diff.removed ? c : best), null);
|
|
322
|
+
return {
|
|
323
|
+
action: "analyze_regression",
|
|
324
|
+
file: abs,
|
|
325
|
+
current_lines: currentLines.length,
|
|
326
|
+
comparisons,
|
|
327
|
+
closest_prior: likelyStablePrior?.backup ?? null,
|
|
328
|
+
note: comparisons.length === 0
|
|
329
|
+
? "Backup files referenced in the index are missing on disk."
|
|
330
|
+
: `Compared current file against ${comparisons.length} prior snapshot(s). 'closest_prior' is the snapshot with the smallest edit distance — often the best restore candidate.`,
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
//# sourceMappingURL=verification.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verification.js","sourceRoot":"","sources":["../../src/tools/verification.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,EACL,UAAU,EACV,YAAY,EACZ,UAAU,EACV,SAAS,GAEV,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAC5E,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjD,mHAAmH;AACnH,uGAAuG;AACvG,MAAM,QAAQ,GACZ,OAAO,CAAC,GAAG,CAAC,4BAA4B;IACxC,OAAO,CAAC,GAAG,CAAC,sBAAsB;IAClC,IAAI,CAAC,OAAO,EAAE,EAAE,gBAAgB,CAAC,CAAC;AACpC,MAAM,iBAAiB,GAAG,IAAI,CAAC,QAAQ,EAAE,mBAAmB,CAAC,CAAC;AAI9D,KAAK,UAAU,eAAe,CAAC,QAAgB;IAC7C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC;QACtD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAA+C,CAAC;QAC3E,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC9B,OAAO,CACL,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC;YACnB,IAAI,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC;YACxB,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YACvC,IAAI,CACL,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,KAAK,UAAU,iBAAiB,CAAC,UAAkB;IAGjD,MAAM,GAAG,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAChC,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC3B,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IAExD,8EAA8E;IAC9E,2DAA2D;IAC3D,IAAI,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAC7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,IAAI,CAAC;YACH,MAAM,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC,CAAC;YAChD,MAAM;QACR,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;YAClC,IAAI,MAAM,KAAK,SAAS;gBAAE,MAAM;YAChC,SAAS,GAAG,MAAM,CAAC;QACrB,CAAC;IACH,CAAC;IAED,IAAI,IAAI,GAAa,EAAE,CAAC;IACxB,IAAI,CAAC;QACH,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE;YACxB,GAAG,EAAE,SAAS;YACd,QAAQ,EAAE,IAAI;YACd,KAAK,EAAE,IAAI;YACX,MAAM,EAAE;gBACN,oBAAoB;gBACpB,YAAY;gBACZ,YAAY;gBACZ,aAAa;aACd;SACF,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,GAAG,GAAmF,EAAE,CAAC;IAC/F,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QACrB,IAAI,OAAO,CAAC,CAAC,CAAC,KAAK,GAAG;YAAE,SAAS;QACjC,MAAM,GAAG,GAAG,oBAAoB,CAAC,CAAC,CAAC,CAAC;QACpC,IAAI,CAAC,GAAG;YAAE,SAAS;QACnB,oEAAoE;QACpE,mEAAmE;QACnE,4BAA4B;QAC5B,MAAM,aAAa,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QAChD,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,SAAS;QAC5C,GAAG,CAAC,IAAI,CAAC;YACP,IAAI,EAAE,CAAC;YACP,UAAU,EAAE,GAAG,CAAC,UAAU;YAC1B,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,0BAA0B,IAAI,GAAG;SACvD,CAAC,CAAC;IACL,CAAC;IACD,8DAA8D;IAC9D,MAAM,KAAK,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;IAC7C,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QAChB,IAAI,CAAC,CAAC,UAAU,KAAK,CAAC,CAAC,UAAU;YAAE,OAAO,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;QACpF,OAAO,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAChF,CAAC,CAAC,CAAC;IACH,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAC1B,CAAC;AAED,8EAA8E;AAC9E,6EAA6E;AAC7E,mBAAmB;AACnB,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AAEjF,SAAS,yBAAyB,CAAC,QAAgB;IACjD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC9B,0EAA0E;QAC1E,OAAO,GAAG,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC,CAAC;IACjE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,IAA0C;IAClF,MAAM,QAAQ,GAAG,MAAM,UAAU,EAAE,CAAC;IAEpC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,MAAM,OAAO,GAAG,MAAM,YAAY,EAAE,CAAC;QAErC,mEAAmE;QACnE,wEAAwE;QACxE,sDAAsD;QACtD,IAAI,UAAU,GAGH,IAAI,CAAC;QAEhB,IAAI,QAAQ,EAAE,IAAI,EAAE,CAAC;YACnB,IAAI,yBAAyB,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC7C,UAAU,GAAG;oBACX,KAAK,EAAE,KAAK;oBACZ,cAAc,EACZ,0GAA0G;iBAC7G,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,MAAM,SAAS,GAAG,QAAQ,CAAC,UAAU,IAAI,gBAAgB,CAAC;gBAC1D,MAAM,MAAM,GAAG,qDAAqD,QAAQ,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC;gBACnG,IAAI,CAAC;oBACH,MAAM,gBAAgB,CAAC,SAAS,EAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;oBACzD,MAAM,KAAK,GAAG,MAAM,wBAAwB,EAAE,CAAC;oBAC/C,UAAU,GAAG;wBACX,KAAK,EAAE,IAAI;wBACX,OAAO,EAAE,QAAQ,CAAC,IAAI;wBACtB,UAAU,EAAE,SAAS;wBACrB,MAAM;wBACN,UAAU,EAAE,KAAK,CAAC,IAAI;qBACvB,CAAC;gBACJ,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC;oBACX,UAAU,GAAG;wBACX,KAAK,EAAE,KAAK;wBACZ,cAAc,EAAE,4BAA6B,CAAW,CAAC,OAAO,EAAE;qBACnE,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;QAED,MAAM,YAAY,GAAG,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAClF,MAAM,aAAa,GAAG,QAAQ,EAAE,IAAI,IAAI,CAAC,YAAY;YACnD,CAAC,CAAC,MAAM,iBAAiB,CAAC,QAAQ,CAAC,IAAI,CAAC;YACxC,CAAC,CAAC,EAAE,CAAC;QAEP,OAAO;YACL,MAAM,EAAE,sBAAsB;YAC9B,OAAO,EAAE,IAAI;YACb,kBAAkB,EAAE,QAAQ;YAC5B,OAAO;YACP,WAAW,EAAE,UAAU;YACvB,aAAa,EAAE,YAAY;YAC3B,cAAc,EAAE,aAAa;YAC7B,SAAS,EAAE,SAAS;YACpB,OAAO,EAAE,OAAO;gBACd,CAAC,CAAC,wDAAwD;gBAC1D,CAAC,CAAC,uDAAuD;SAC5D,CAAC;IACJ,CAAC;IAED,yEAAyE;IACzE,oEAAoE;IACpE,wEAAwE;IACxE,mBAAmB;IACnB,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,UAAU,CAAC,EAAE,GAAG,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,IAAI,qBAAqB,EAAE,CAAC,CAAC;IACjF,CAAC;IACD,MAAM,YAAY,GAAG,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAClF,MAAM,aAAa,GAAG,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,iBAAiB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAEnF,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,CAAC,IAAI,CAAC,sBAAsB,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,QAAQ,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACnF,IAAI,YAAY,EAAE,CAAC;QACjB,KAAK,CAAC,IAAI,CACR,0CAA0C,YAAY,CAAC,MAAM,GAAG;YAC9D,eAAe,YAAY,CAAC,IAAI,OAAO,YAAY,CAAC,SAAS,IAAI,CACpE,CAAC;IACJ,CAAC;IACD,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACtC,KAAK,CAAC,IAAI,CACR,sBAAsB,GAAG,CAAC,MAAM,QAAQ,GAAG,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,0CAA0C,QAAQ,CAAC,QAAQ,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,aAAa,GAAG;aAChL,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;aAClB,IAAI,CAAC,IAAI,CAAC,yGAAyG,CACvH,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,YAAY,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChD,KAAK,CAAC,IAAI,CAAC,0IAA0I,CAAC,CAAC;IACzJ,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,gEAAgE,CAAC,CAAC;IAE7E,OAAO;QACL,MAAM,EAAE,sBAAsB;QAC9B,OAAO,EAAE,KAAK;QACd,aAAa,EAAE,QAAQ;QACvB,aAAa,EAAE,YAAY;QAC3B,cAAc,EAAE,aAAa;QAC7B,SAAS,EAAE,SAAS;QACpB,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC;KACzB,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAAC,OAAoB;IACjE,MAAM,UAAU,CAAC,OAAO,CAAC,CAAC;AAC5B,CAAC;AAED,6EAA6E;AAE7E,KAAK,UAAU,kBAAkB,CAAC,IAAY;IAC5C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC;QACtD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAA+C,CAAC;QAC3E,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAC1B,MAAM,KAAK,GACT,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC;YACnB,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC;YACpB,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YACvC,IAAI,CAAC;QACP,qEAAqE;QACrE,4EAA4E;QAC5E,MAAM,UAAU,GAAmB,EAAE,CAAC;QACtC,IAAI,KAAK;YAAE,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClC,sEAAsE;QACtE,gBAAgB;QAChB,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;QACrD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QAC3C,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,QAAQ,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;YAClE,MAAM,EAAE,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;YACvC,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;gBACzB,IAAI,CAAC,CAAC,CAAC,WAAW,EAAE;oBAAE,SAAS;gBAC/B,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;gBACvC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC/D,KAAK,MAAM,EAAE,IAAI,MAAM,EAAE,CAAC;oBACxB,IAAI,CAAC,EAAE,CAAC,WAAW,EAAE;wBAAE,SAAS;oBAChC,MAAM,IAAI,GAAG,KAAK,EAAE,CAAS,EAAE,EAAE;wBAC/B,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,CAAC,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;wBAC1D,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;4BACxB,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;4BAC7B,IAAI,CAAC,CAAC,WAAW,EAAE;gCAAE,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC;iCACjC,IAAI,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,EAAE,EAAE,CAAC;gCACrC,UAAU,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;4BACzE,CAAC;wBACH,CAAC;oBACH,CAAC,CAAC;oBACF,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;gBACrC,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,uBAAuB;QACzB,CAAC;QACD,0EAA0E;QAC1E,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;QAC/B,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;QACnF,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;QAC9D,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAClB,YAAsB,EACtB,UAAoB;IAEpB,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC;IACrC,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC;IACrC,MAAM,KAAK,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3D,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACzD,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IACvE,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IACzE,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC;AAClF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,IAAmD;IACzF,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,kBAAkB,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IAElE,IAAI,WAAmB,CAAC;IACxB,IAAI,CAAC;QACH,WAAW,GAAG,MAAM,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAC5C,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO;YACL,MAAM,EAAE,oBAAoB;YAC5B,IAAI,EAAE,GAAG;YACT,KAAK,EAAE,6BAA8B,CAAW,CAAC,OAAO,EAAE;SAC3D,CAAC;IACJ,CAAC;IACD,MAAM,YAAY,GAAG,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAEhD,MAAM,OAAO,GAAG,CAAC,MAAM,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5D,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO;YACL,MAAM,EAAE,oBAAoB;YAC5B,IAAI,EAAE,GAAG;YACT,aAAa,EAAE,YAAY,CAAC,MAAM;YAClC,WAAW,EAAE,EAAE;YACf,IAAI,EAAE,sFAAsF;SAC7F,CAAC;IACJ,CAAC;IAED,MAAM,WAAW,GAMZ,EAAE,CAAC;IACR,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC1B,IAAI,SAAiB,CAAC;QACtB,IAAI,CAAC;YACH,SAAS,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACjD,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QACD,MAAM,UAAU,GAAG,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC5C,WAAW,CAAC,IAAI,CAAC;YACf,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,WAAW,EAAE,UAAU,CAAC,MAAM;YAC9B,IAAI,EAAE,WAAW,CAAC,YAAY,EAAE,UAAU,CAAC;SAC5C,CAAC,CAAC;IACL,CAAC;IAED,MAAM,iBAAiB,GAAG,WAAW,CAAC,MAAM,CAC1C,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EACtG,IAAI,CACL,CAAC;IAEF,OAAO;QACL,MAAM,EAAE,oBAAoB;QAC5B,IAAI,EAAE,GAAG;QACT,aAAa,EAAE,YAAY,CAAC,MAAM;QAClC,WAAW;QACX,aAAa,EAAE,iBAAiB,EAAE,MAAM,IAAI,IAAI;QAChD,IAAI,EACF,WAAW,CAAC,MAAM,KAAK,CAAC;YACtB,CAAC,CAAC,2DAA2D;YAC7D,CAAC,CAAC,iCAAiC,WAAW,CAAC,MAAM,yHAAyH;KACnL,CAAC;AACJ,CAAC"}
|