@hyperlynq/synaptic 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +19 -0
- package/README.md +427 -0
- package/build/scripts/rebuild-index.d.ts +5 -0
- package/build/scripts/rebuild-index.js +33 -0
- package/build/src/cli/init.d.ts +13 -0
- package/build/src/cli/init.js +222 -0
- package/build/src/cli/init.js.map +1 -0
- package/build/src/cli/pre-commit.d.ts +6 -0
- package/build/src/cli/pre-commit.js +159 -0
- package/build/src/cli/pre-commit.js.map +1 -0
- package/build/src/cli.d.ts +2 -0
- package/build/src/cli.js +36 -0
- package/build/src/cli.js.map +1 -0
- package/build/src/hooks/pre-compact.d.ts +6 -0
- package/build/src/hooks/pre-compact.js +64 -0
- package/build/src/hooks/pre-compact.js.map +1 -0
- package/build/src/hooks/session-start.d.ts +13 -0
- package/build/src/hooks/session-start.js +277 -0
- package/build/src/hooks/session-start.js.map +1 -0
- package/build/src/hooks/stop.d.ts +7 -0
- package/build/src/hooks/stop.js +248 -0
- package/build/src/hooks/stop.js.map +1 -0
- package/build/src/index.d.ts +1 -0
- package/build/src/index.js +8 -0
- package/build/src/index.js.map +1 -0
- package/build/src/server.d.ts +6 -0
- package/build/src/server.js +133 -0
- package/build/src/server.js.map +1 -0
- package/build/src/storage/embedder.d.ts +27 -0
- package/build/src/storage/embedder.js +126 -0
- package/build/src/storage/embedder.js.map +1 -0
- package/build/src/storage/git.d.ts +20 -0
- package/build/src/storage/git.js +98 -0
- package/build/src/storage/git.js.map +1 -0
- package/build/src/storage/maintenance.d.ts +9 -0
- package/build/src/storage/maintenance.js +46 -0
- package/build/src/storage/maintenance.js.map +1 -0
- package/build/src/storage/markdown.d.ts +21 -0
- package/build/src/storage/markdown.js +79 -0
- package/build/src/storage/markdown.js.map +1 -0
- package/build/src/storage/paths.d.ts +6 -0
- package/build/src/storage/paths.js +17 -0
- package/build/src/storage/paths.js.map +1 -0
- package/build/src/storage/project.d.ts +2 -0
- package/build/src/storage/project.js +35 -0
- package/build/src/storage/project.js.map +1 -0
- package/build/src/storage/session.d.ts +1 -0
- package/build/src/storage/session.js +17 -0
- package/build/src/storage/session.js.map +1 -0
- package/build/src/storage/sqlite.d.ts +102 -0
- package/build/src/storage/sqlite.js +830 -0
- package/build/src/storage/sqlite.js.map +1 -0
- package/build/src/storage/watcher.d.ts +22 -0
- package/build/src/storage/watcher.js +126 -0
- package/build/src/storage/watcher.js.map +1 -0
- package/build/src/tools/context-archive.d.ts +11 -0
- package/build/src/tools/context-archive.js +13 -0
- package/build/src/tools/context-archive.js.map +1 -0
- package/build/src/tools/context-chain.d.ts +12 -0
- package/build/src/tools/context-chain.js +26 -0
- package/build/src/tools/context-chain.js.map +1 -0
- package/build/src/tools/context-cochanges.d.ts +20 -0
- package/build/src/tools/context-cochanges.js +25 -0
- package/build/src/tools/context-cochanges.js.map +1 -0
- package/build/src/tools/context-delete-rule.d.ts +11 -0
- package/build/src/tools/context-delete-rule.js +12 -0
- package/build/src/tools/context-delete-rule.js.map +1 -0
- package/build/src/tools/context-dna.d.ts +18 -0
- package/build/src/tools/context-dna.js +197 -0
- package/build/src/tools/context-dna.js.map +1 -0
- package/build/src/tools/context-git-index.d.ts +17 -0
- package/build/src/tools/context-git-index.js +59 -0
- package/build/src/tools/context-git-index.js.map +1 -0
- package/build/src/tools/context-list-rules.d.ts +8 -0
- package/build/src/tools/context-list-rules.js +11 -0
- package/build/src/tools/context-list-rules.js.map +1 -0
- package/build/src/tools/context-list.d.ts +26 -0
- package/build/src/tools/context-list.js +42 -0
- package/build/src/tools/context-list.js.map +1 -0
- package/build/src/tools/context-resolve-pattern.d.ts +11 -0
- package/build/src/tools/context-resolve-pattern.js +9 -0
- package/build/src/tools/context-resolve-pattern.js.map +1 -0
- package/build/src/tools/context-save-rule.d.ts +14 -0
- package/build/src/tools/context-save-rule.js +15 -0
- package/build/src/tools/context-save-rule.js.map +1 -0
- package/build/src/tools/context-save.d.ts +26 -0
- package/build/src/tools/context-save.js +68 -0
- package/build/src/tools/context-save.js.map +1 -0
- package/build/src/tools/context-search.d.ts +31 -0
- package/build/src/tools/context-search.js +99 -0
- package/build/src/tools/context-search.js.map +1 -0
- package/build/src/tools/context-session.d.ts +13 -0
- package/build/src/tools/context-session.js +29 -0
- package/build/src/tools/context-session.js.map +1 -0
- package/build/src/tools/context-status.d.ts +13 -0
- package/build/src/tools/context-status.js +15 -0
- package/build/src/tools/context-status.js.map +1 -0
- package/package.json +57 -0
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Init command: Detects environment, configures MCP server, hooks, git hook,
|
|
3
|
+
* and project directory for synaptic.
|
|
4
|
+
*/
|
|
5
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync, chmodSync } from "node:fs";
|
|
6
|
+
import { join, resolve } from "node:path";
|
|
7
|
+
import { homedir } from "node:os";
|
|
8
|
+
import { execSync } from "node:child_process";
|
|
9
|
+
// ── Environment Detection ──────────────────────────────────────────────
|
|
10
|
+
export function detectEnvironment() {
|
|
11
|
+
const isWSL = detectWSL();
|
|
12
|
+
// buildDir: from build/src/cli/ go up two levels to build/
|
|
13
|
+
const buildDir = resolve(join(import.meta.dirname, "..", ".."));
|
|
14
|
+
if (isWSL) {
|
|
15
|
+
const winProfile = getWindowsUserProfile();
|
|
16
|
+
const winProfileWSL = windowsPathToWSL(winProfile);
|
|
17
|
+
return {
|
|
18
|
+
isWSL: true,
|
|
19
|
+
settingsPath: join(winProfileWSL, ".claude", "settings.json"),
|
|
20
|
+
buildDir,
|
|
21
|
+
nodeCommand: String.raw `C:\WINDOWS\system32\wsl.exe`,
|
|
22
|
+
nodeArgs: ["node", "--no-warnings"],
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
isWSL: false,
|
|
27
|
+
settingsPath: join(homedir(), ".claude", "settings.json"),
|
|
28
|
+
buildDir,
|
|
29
|
+
nodeCommand: "node",
|
|
30
|
+
nodeArgs: ["--no-warnings"],
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
// ── Init Command ───────────────────────────────────────────────────────
|
|
34
|
+
export async function initCommand(args) {
|
|
35
|
+
const isGlobal = args.includes("--global");
|
|
36
|
+
console.log("Detecting environment...\n");
|
|
37
|
+
const env = detectEnvironment();
|
|
38
|
+
console.log(` WSL: ${env.isWSL}`);
|
|
39
|
+
console.log(` Settings: ${env.settingsPath}`);
|
|
40
|
+
console.log(` Build dir: ${env.buildDir}`);
|
|
41
|
+
console.log(` Node command: ${env.nodeCommand}`);
|
|
42
|
+
console.log(` Node args: ${env.nodeArgs.join(" ")}`);
|
|
43
|
+
console.log("");
|
|
44
|
+
setupMcpServer(env);
|
|
45
|
+
setupHooks(env);
|
|
46
|
+
if (!isGlobal) {
|
|
47
|
+
setupGitHook(env);
|
|
48
|
+
setupProjectDir();
|
|
49
|
+
}
|
|
50
|
+
console.log("\nDone.");
|
|
51
|
+
}
|
|
52
|
+
// ── Helpers (private) ──────────────────────────────────────────────────
|
|
53
|
+
function detectWSL() {
|
|
54
|
+
try {
|
|
55
|
+
if (!existsSync("/proc/version"))
|
|
56
|
+
return false;
|
|
57
|
+
const version = readFileSync("/proc/version", "utf-8");
|
|
58
|
+
return /microsoft/i.test(version);
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function getWindowsUserProfile() {
|
|
65
|
+
try {
|
|
66
|
+
const raw = execSync("cmd.exe /C echo %USERPROFILE%", {
|
|
67
|
+
encoding: "utf-8",
|
|
68
|
+
timeout: 5000,
|
|
69
|
+
}).trim();
|
|
70
|
+
return raw;
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
throw new Error(`Failed to detect Windows user profile: ${err}`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function windowsPathToWSL(winPath) {
|
|
77
|
+
// C:\Users\foo → /mnt/c/Users/foo
|
|
78
|
+
const normalized = winPath.replace(/\r?\n$/, "");
|
|
79
|
+
const match = normalized.match(/^([A-Za-z]):\\(.*)/);
|
|
80
|
+
if (!match) {
|
|
81
|
+
throw new Error(`Cannot convert Windows path to WSL: ${winPath}`);
|
|
82
|
+
}
|
|
83
|
+
const drive = match[1].toLowerCase();
|
|
84
|
+
const rest = match[2].replace(/\\/g, "/");
|
|
85
|
+
return `/mnt/${drive}/${rest}`;
|
|
86
|
+
}
|
|
87
|
+
function readJsonFile(filePath) {
|
|
88
|
+
try {
|
|
89
|
+
if (!existsSync(filePath))
|
|
90
|
+
return {};
|
|
91
|
+
const raw = readFileSync(filePath, "utf-8");
|
|
92
|
+
return JSON.parse(raw);
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
return {};
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
function writeJsonFile(filePath, data) {
|
|
99
|
+
const dir = resolve(filePath, "..");
|
|
100
|
+
mkdirSync(dir, { recursive: true });
|
|
101
|
+
writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n", "utf-8");
|
|
102
|
+
}
|
|
103
|
+
function setupMcpServer(env) {
|
|
104
|
+
const settings = readJsonFile(env.settingsPath);
|
|
105
|
+
if (!settings.mcpServers || typeof settings.mcpServers !== "object") {
|
|
106
|
+
settings.mcpServers = {};
|
|
107
|
+
}
|
|
108
|
+
const mcpServers = settings.mcpServers;
|
|
109
|
+
if (mcpServers.synaptic) {
|
|
110
|
+
console.log(" [skip] MCP server 'synaptic' already configured.");
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const indexPath = join(env.buildDir, "src", "index.js");
|
|
114
|
+
mcpServers.synaptic = {
|
|
115
|
+
command: env.nodeCommand,
|
|
116
|
+
args: [...env.nodeArgs, indexPath],
|
|
117
|
+
type: "stdio",
|
|
118
|
+
};
|
|
119
|
+
writeJsonFile(env.settingsPath, settings);
|
|
120
|
+
console.log(" [done] MCP server 'synaptic' added to settings.");
|
|
121
|
+
}
|
|
122
|
+
function setupHooks(env) {
|
|
123
|
+
const settings = readJsonFile(env.settingsPath);
|
|
124
|
+
if (!settings.hooks || typeof settings.hooks !== "object") {
|
|
125
|
+
settings.hooks = {};
|
|
126
|
+
}
|
|
127
|
+
const hooks = settings.hooks;
|
|
128
|
+
let changed = false;
|
|
129
|
+
// Helper to build the hook command
|
|
130
|
+
const hookCommand = (scriptPath) => {
|
|
131
|
+
if (env.isWSL) {
|
|
132
|
+
return `wsl node --no-warnings ${scriptPath}`;
|
|
133
|
+
}
|
|
134
|
+
return `node --no-warnings ${scriptPath}`;
|
|
135
|
+
};
|
|
136
|
+
// SessionStart hook
|
|
137
|
+
if (!hooks.SessionStart) {
|
|
138
|
+
const scriptPath = join(env.buildDir, "src", "hooks", "session-start.js");
|
|
139
|
+
hooks.SessionStart = {
|
|
140
|
+
command: hookCommand(scriptPath),
|
|
141
|
+
matcher: "startup|resume|compact",
|
|
142
|
+
timeout: 10000,
|
|
143
|
+
};
|
|
144
|
+
changed = true;
|
|
145
|
+
console.log(" [done] SessionStart hook added.");
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
console.log(" [skip] SessionStart hook already present.");
|
|
149
|
+
}
|
|
150
|
+
// PreCompact hook
|
|
151
|
+
if (!hooks.PreCompact) {
|
|
152
|
+
const scriptPath = join(env.buildDir, "src", "hooks", "pre-compact.js");
|
|
153
|
+
hooks.PreCompact = {
|
|
154
|
+
command: hookCommand(scriptPath),
|
|
155
|
+
timeout: 30000,
|
|
156
|
+
};
|
|
157
|
+
changed = true;
|
|
158
|
+
console.log(" [done] PreCompact hook added.");
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
console.log(" [skip] PreCompact hook already present.");
|
|
162
|
+
}
|
|
163
|
+
// Stop hook
|
|
164
|
+
if (!hooks.Stop) {
|
|
165
|
+
const scriptPath = join(env.buildDir, "src", "hooks", "stop.js");
|
|
166
|
+
hooks.Stop = {
|
|
167
|
+
command: hookCommand(scriptPath),
|
|
168
|
+
timeout: 10000,
|
|
169
|
+
};
|
|
170
|
+
changed = true;
|
|
171
|
+
console.log(" [done] Stop hook added.");
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
console.log(" [skip] Stop hook already present.");
|
|
175
|
+
}
|
|
176
|
+
if (changed) {
|
|
177
|
+
writeJsonFile(env.settingsPath, settings);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
function setupGitHook(env) {
|
|
181
|
+
const gitDir = join(process.cwd(), ".git");
|
|
182
|
+
if (!existsSync(gitDir)) {
|
|
183
|
+
console.log(" [skip] No .git/ directory found, skipping git hook.");
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
const hooksDir = join(gitDir, "hooks");
|
|
187
|
+
const hookPath = join(hooksDir, "pre-commit");
|
|
188
|
+
// Check if hook already has synaptic
|
|
189
|
+
if (existsSync(hookPath)) {
|
|
190
|
+
const existing = readFileSync(hookPath, "utf-8");
|
|
191
|
+
if (existing.includes("synaptic")) {
|
|
192
|
+
console.log(" [skip] Git pre-commit hook already contains synaptic.");
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
// Don't overwrite existing non-synaptic hooks
|
|
196
|
+
console.log(" [skip] Existing pre-commit hook found (not synaptic), leaving untouched.");
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
const preCommitPath = join(env.buildDir, "src", "cli", "pre-commit.js");
|
|
200
|
+
const script = `#!/bin/sh
|
|
201
|
+
# synaptic pre-commit hook
|
|
202
|
+
node --no-warnings ${preCommitPath}
|
|
203
|
+
`;
|
|
204
|
+
mkdirSync(hooksDir, { recursive: true });
|
|
205
|
+
writeFileSync(hookPath, script, "utf-8");
|
|
206
|
+
chmodSync(hookPath, 0o755);
|
|
207
|
+
console.log(" [done] Git pre-commit hook installed.");
|
|
208
|
+
}
|
|
209
|
+
function setupProjectDir() {
|
|
210
|
+
const dir = join(process.cwd(), ".synaptic");
|
|
211
|
+
const configPath = join(dir, "config.json");
|
|
212
|
+
if (existsSync(configPath)) {
|
|
213
|
+
console.log(" [skip] .synaptic/config.json already exists.");
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
const now = new Date();
|
|
217
|
+
const created = now.toISOString().slice(0, 10); // YYYY-MM-DD
|
|
218
|
+
mkdirSync(dir, { recursive: true });
|
|
219
|
+
writeFileSync(configPath, JSON.stringify({ version: "0.6.0", created }, null, 2) + "\n", "utf-8");
|
|
220
|
+
console.log(" [done] .synaptic/config.json created.");
|
|
221
|
+
}
|
|
222
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Synaptic pre-commit guardian.
|
|
4
|
+
* Called by .git/hooks/pre-commit.
|
|
5
|
+
*/
|
|
6
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
import { execSync } from "node:child_process";
|
|
9
|
+
import { randomBytes } from "node:crypto";
|
|
10
|
+
import { ContextIndex } from "../storage/sqlite.js";
|
|
11
|
+
import { Embedder } from "../storage/embedder.js";
|
|
12
|
+
import { appendEntry } from "../storage/markdown.js";
|
|
13
|
+
import { ensureDirs } from "../storage/paths.js";
|
|
14
|
+
import { detectProject } from "../storage/project.js";
|
|
15
|
+
import { getSessionId } from "../storage/session.js";
|
|
16
|
+
function detectScripts(cwd) {
|
|
17
|
+
const pkgPath = join(cwd, "package.json");
|
|
18
|
+
if (!existsSync(pkgPath))
|
|
19
|
+
return [];
|
|
20
|
+
let scripts;
|
|
21
|
+
try {
|
|
22
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
23
|
+
scripts = pkg.scripts ?? {};
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return [];
|
|
27
|
+
}
|
|
28
|
+
const checks = [];
|
|
29
|
+
if (scripts.lint)
|
|
30
|
+
checks.push({ script: "lint", label: "lint" });
|
|
31
|
+
else if (scripts.eslint)
|
|
32
|
+
checks.push({ script: "eslint", label: "lint" });
|
|
33
|
+
if (scripts.typecheck)
|
|
34
|
+
checks.push({ script: "typecheck", label: "typecheck" });
|
|
35
|
+
else if (scripts.tsc)
|
|
36
|
+
checks.push({ script: "tsc", label: "typecheck" });
|
|
37
|
+
else if (scripts.check)
|
|
38
|
+
checks.push({ script: "check", label: "typecheck" });
|
|
39
|
+
if (scripts.test)
|
|
40
|
+
checks.push({ script: "test", label: "test" });
|
|
41
|
+
return checks;
|
|
42
|
+
}
|
|
43
|
+
function getStagedFiles() {
|
|
44
|
+
try {
|
|
45
|
+
const output = execSync("git diff --cached --name-only", {
|
|
46
|
+
encoding: "utf-8",
|
|
47
|
+
timeout: 5000,
|
|
48
|
+
}).trim();
|
|
49
|
+
return output ? output.split("\n") : [];
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return [];
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function runCheck(script, label, cwd) {
|
|
56
|
+
try {
|
|
57
|
+
const output = execSync(`npm run ${script} 2>&1`, {
|
|
58
|
+
cwd,
|
|
59
|
+
encoding: "utf-8",
|
|
60
|
+
timeout: 120000,
|
|
61
|
+
maxBuffer: 5 * 1024 * 1024,
|
|
62
|
+
});
|
|
63
|
+
return { command: `npm run ${script}`, label, success: true, output: output.slice(-2000) };
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
const error = err;
|
|
67
|
+
const output = (error.stdout ?? "") + (error.stderr ?? "");
|
|
68
|
+
const lines = output.split("\n");
|
|
69
|
+
const tail = lines.slice(-50).join("\n");
|
|
70
|
+
return { command: `npm run ${script}`, label, success: false, output: tail };
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function enrichAndInsert(index, entry) {
|
|
74
|
+
return index.insert({
|
|
75
|
+
...entry,
|
|
76
|
+
project: detectProject() ?? undefined,
|
|
77
|
+
sessionId: getSessionId(),
|
|
78
|
+
agentId: "pre-commit",
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
async function main() {
|
|
82
|
+
const cwd = process.cwd();
|
|
83
|
+
const scripts = detectScripts(cwd);
|
|
84
|
+
if (scripts.length === 0) {
|
|
85
|
+
process.exit(0);
|
|
86
|
+
}
|
|
87
|
+
const stagedFiles = getStagedFiles();
|
|
88
|
+
const fileTags = stagedFiles.slice(0, 10).map(f => `file:${f}`);
|
|
89
|
+
for (const { script, label } of scripts) {
|
|
90
|
+
const result = runCheck(script, label, cwd);
|
|
91
|
+
if (!result.success) {
|
|
92
|
+
ensureDirs();
|
|
93
|
+
const index = new ContextIndex();
|
|
94
|
+
const embedder = new Embedder();
|
|
95
|
+
try {
|
|
96
|
+
const chainId = randomBytes(4).toString("hex");
|
|
97
|
+
const content = [
|
|
98
|
+
`Pre-commit failure: \`${result.command}\` exited with error`,
|
|
99
|
+
`Files: ${stagedFiles.slice(0, 5).join(", ") || "unknown"}`,
|
|
100
|
+
`Error: ${result.output.slice(-500)}`,
|
|
101
|
+
].join("\n");
|
|
102
|
+
const entry = appendEntry(content, "issue", [
|
|
103
|
+
"failure", "pre-commit", `cmd:${label}`, `chain:${chainId}`, ...fileTags,
|
|
104
|
+
]);
|
|
105
|
+
entry.tier = "working";
|
|
106
|
+
const rowid = enrichAndInsert(index, entry);
|
|
107
|
+
const embedding = await embedder.embed(content);
|
|
108
|
+
index.insertVec(rowid, embedding);
|
|
109
|
+
console.error(`\n[Synaptic] Failure captured (chain:${chainId})`);
|
|
110
|
+
}
|
|
111
|
+
finally {
|
|
112
|
+
index.close();
|
|
113
|
+
}
|
|
114
|
+
process.exit(1);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
// All checks passed — look for recent failures to create resolution entries
|
|
118
|
+
if (stagedFiles.length > 0) {
|
|
119
|
+
try {
|
|
120
|
+
ensureDirs();
|
|
121
|
+
const index = new ContextIndex();
|
|
122
|
+
const embedder = new Embedder();
|
|
123
|
+
try {
|
|
124
|
+
const recentEntries = index.list({ days: 7 });
|
|
125
|
+
const recentFailures = recentEntries.filter(e => e.tags.includes("failure") &&
|
|
126
|
+
e.tags.includes("pre-commit") &&
|
|
127
|
+
stagedFiles.some(f => e.tags.includes(`file:${f}`)));
|
|
128
|
+
if (recentFailures.length > 0) {
|
|
129
|
+
const lastFailure = recentFailures[0];
|
|
130
|
+
const chainTag = lastFailure.tags.find(t => t.startsWith("chain:"));
|
|
131
|
+
const resolvedFiles = stagedFiles.filter(f => recentFailures.some(e => e.tags.includes(`file:${f}`))).slice(0, 5);
|
|
132
|
+
const content = `Resolved: ${resolvedFiles.join(", ")} now pass pre-commit checks`;
|
|
133
|
+
const tags = [
|
|
134
|
+
"failure-resolved", "pre-commit",
|
|
135
|
+
...(chainTag ? [chainTag] : []),
|
|
136
|
+
...resolvedFiles.map(f => `file:${f}`),
|
|
137
|
+
];
|
|
138
|
+
const entry = appendEntry(content, "progress", tags);
|
|
139
|
+
entry.tier = "ephemeral";
|
|
140
|
+
const rowid = enrichAndInsert(index, entry);
|
|
141
|
+
const embedding = await embedder.embed(content);
|
|
142
|
+
index.insertVec(rowid, embedding);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
finally {
|
|
146
|
+
index.close();
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
// Don't block commits
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
process.exit(0);
|
|
154
|
+
}
|
|
155
|
+
main().catch((err) => {
|
|
156
|
+
console.error(`[Synaptic] Pre-commit error: ${err.message ?? err}`);
|
|
157
|
+
process.exit(0);
|
|
158
|
+
});
|
|
159
|
+
//# sourceMappingURL=pre-commit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pre-commit.js","sourceRoot":"","sources":["../../../src/cli/pre-commit.ts"],"names":[],"mappings":"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"}
|
package/build/src/cli.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { initCommand } from "./cli/init.js";
|
|
3
|
+
const USAGE = `
|
|
4
|
+
synaptic — persistent local memory for Claude Code
|
|
5
|
+
|
|
6
|
+
Usage:
|
|
7
|
+
synaptic <command> [options]
|
|
8
|
+
|
|
9
|
+
Commands:
|
|
10
|
+
init Initialize synaptic in the current project
|
|
11
|
+
|
|
12
|
+
Options:
|
|
13
|
+
-h, --help Show this help message
|
|
14
|
+
`.trim();
|
|
15
|
+
async function main() {
|
|
16
|
+
const args = process.argv.slice(2);
|
|
17
|
+
const command = args[0];
|
|
18
|
+
if (!command || command === "--help" || command === "-h") {
|
|
19
|
+
console.log(USAGE);
|
|
20
|
+
process.exit(0);
|
|
21
|
+
}
|
|
22
|
+
switch (command) {
|
|
23
|
+
case "init":
|
|
24
|
+
await initCommand(args.slice(1));
|
|
25
|
+
break;
|
|
26
|
+
default:
|
|
27
|
+
console.error(`Unknown command: ${command}`);
|
|
28
|
+
console.error(`Run 'synaptic --help' for usage information.`);
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
main().catch((err) => {
|
|
33
|
+
console.error(err);
|
|
34
|
+
process.exit(1);
|
|
35
|
+
});
|
|
36
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,MAAM,KAAK,GAAG;;;;;;;;;;;CAWb,CAAC,IAAI,EAAE,CAAC;AAET,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IAExB,IAAI,CAAC,OAAO,IAAI,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACzD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,MAAM;YACT,MAAM,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YACjC,MAAM;QACR;YACE,OAAO,CAAC,KAAK,CAAC,oBAAoB,OAAO,EAAE,CAAC,CAAC;YAC7C,OAAO,CAAC,KAAK,CAAC,8CAA8C,CAAC,CAAC;YAC9D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PreCompact hook: Saves a progress snapshot before context compaction.
|
|
3
|
+
*
|
|
4
|
+
* Receives JSON on stdin: { trigger: "manual"|"auto", custom_instructions?: string }
|
|
5
|
+
*/
|
|
6
|
+
import { appendEntry } from "../storage/markdown.js";
|
|
7
|
+
import { ContextIndex } from "../storage/sqlite.js";
|
|
8
|
+
import { Embedder } from "../storage/embedder.js";
|
|
9
|
+
import { ensureDirs } from "../storage/paths.js";
|
|
10
|
+
async function main() {
|
|
11
|
+
ensureDirs();
|
|
12
|
+
let input = { trigger: "auto" };
|
|
13
|
+
try {
|
|
14
|
+
const chunks = [];
|
|
15
|
+
for await (const chunk of process.stdin) {
|
|
16
|
+
chunks.push(chunk);
|
|
17
|
+
}
|
|
18
|
+
const raw = Buffer.concat(chunks).toString("utf-8").trim();
|
|
19
|
+
if (raw) {
|
|
20
|
+
input = JSON.parse(raw);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
// Use defaults
|
|
25
|
+
}
|
|
26
|
+
const index = new ContextIndex();
|
|
27
|
+
const embedder = new Embedder();
|
|
28
|
+
try {
|
|
29
|
+
const content = [
|
|
30
|
+
`Context compaction triggered (${input.trigger}).`,
|
|
31
|
+
`Saving progress snapshot before compaction.`,
|
|
32
|
+
];
|
|
33
|
+
if (input.custom_instructions) {
|
|
34
|
+
content.push(`User instructions: ${input.custom_instructions}`);
|
|
35
|
+
}
|
|
36
|
+
// Get a summary of recent work to preserve
|
|
37
|
+
const recent = index.list({ days: 1 });
|
|
38
|
+
if (recent.length > 0) {
|
|
39
|
+
content.push("");
|
|
40
|
+
content.push(`Active session had ${recent.length} entries today.`);
|
|
41
|
+
const types = new Map();
|
|
42
|
+
for (const entry of recent) {
|
|
43
|
+
types.set(entry.type, (types.get(entry.type) ?? 0) + 1);
|
|
44
|
+
}
|
|
45
|
+
const typeSummary = Array.from(types.entries())
|
|
46
|
+
.map(([t, c]) => `${t}:${c}`)
|
|
47
|
+
.join(", ");
|
|
48
|
+
content.push(`Entry types: ${typeSummary}`);
|
|
49
|
+
}
|
|
50
|
+
const entry = appendEntry(content.join("\n"), "progress", ["compaction-snapshot"]);
|
|
51
|
+
entry.tier = ContextIndex.assignTier(entry.type);
|
|
52
|
+
const rowid = index.insert(entry);
|
|
53
|
+
const embedding = await embedder.embed(entry.content);
|
|
54
|
+
index.insertVec(rowid, embedding);
|
|
55
|
+
}
|
|
56
|
+
finally {
|
|
57
|
+
index.close();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
main().catch((err) => {
|
|
61
|
+
process.stderr.write(`pre-compact hook error: ${err}\n`);
|
|
62
|
+
process.exit(0);
|
|
63
|
+
});
|
|
64
|
+
//# sourceMappingURL=pre-compact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pre-compact.js","sourceRoot":"","sources":["../../../src/hooks/pre-compact.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SessionStart hook: Injects rules + recent context into Claude's conversation.
|
|
3
|
+
* Stdout from this hook is automatically added to Claude's context.
|
|
4
|
+
*
|
|
5
|
+
* Injection priority (token budget ~4000 chars):
|
|
6
|
+
* 1. Rules (always full, never truncated)
|
|
7
|
+
* 2. Recent context (last 3 days, compact format, same-project boosted)
|
|
8
|
+
* 3. Most recent handoff note (1 only)
|
|
9
|
+
* 4. Recurring patterns
|
|
10
|
+
* 5. Predicted focus (branch + diff + handoff semantic search)
|
|
11
|
+
* 6. Maintenance summary (only if something changed)
|
|
12
|
+
*/
|
|
13
|
+
export {};
|