@weavelogic/knowledge-graph-agent 0.11.5 → 0.11.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/commands/hooks.d.ts +1 -0
- package/dist/cli/commands/hooks.d.ts.map +1 -1
- package/dist/cli/commands/hooks.js +161 -20
- package/dist/cli/commands/hooks.js.map +1 -1
- package/dist/sops/compliance-checker.d.ts.map +1 -1
- package/dist/sops/compliance-checker.js +151 -23
- package/dist/sops/compliance-checker.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/hooks.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/hooks.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAoLpC;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,CAub5C"}
|
|
@@ -6,6 +6,7 @@ import { join, dirname } from "path";
|
|
|
6
6
|
import { validateProjectRoot } from "../../core/security.js";
|
|
7
7
|
import "../../claude/types.js";
|
|
8
8
|
import { generateHookConfig, processHookEvent, HookCaptureSystem } from "../../claude/hook-capture.js";
|
|
9
|
+
const KG_HOOK_MARKER = "@weavelogic/knowledge-graph-agent";
|
|
9
10
|
function getClaudeSettingsPath(scope) {
|
|
10
11
|
if (scope === "user") {
|
|
11
12
|
const home = process.env.HOME || process.env.USERPROFILE || "";
|
|
@@ -30,25 +31,104 @@ function saveSettings(path, settings) {
|
|
|
30
31
|
}
|
|
31
32
|
writeFileSync(path, JSON.stringify(settings, null, 2));
|
|
32
33
|
}
|
|
34
|
+
function isKgHook(entry) {
|
|
35
|
+
if (entry.command?.includes(KG_HOOK_MARKER)) {
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
if (entry.hooks?.some((h) => h.command?.includes(KG_HOOK_MARKER))) {
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
function removeKgHooksFromArray(entries) {
|
|
44
|
+
return entries.filter((entry) => !isKgHook(entry));
|
|
45
|
+
}
|
|
46
|
+
function mergeHooksConfig(existingHooks, kgHooks) {
|
|
47
|
+
const merged = {
|
|
48
|
+
UserPromptSubmit: [],
|
|
49
|
+
PreToolUse: [],
|
|
50
|
+
PostToolUse: [],
|
|
51
|
+
Stop: [],
|
|
52
|
+
PreCompact: []
|
|
53
|
+
};
|
|
54
|
+
if (existingHooks) {
|
|
55
|
+
for (const [event, entries] of Object.entries(existingHooks)) {
|
|
56
|
+
if (Array.isArray(entries)) {
|
|
57
|
+
merged[event] = removeKgHooksFromArray(entries);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
for (const [event, entries] of Object.entries(kgHooks)) {
|
|
62
|
+
if (Array.isArray(entries)) {
|
|
63
|
+
merged[event] = [
|
|
64
|
+
...merged[event],
|
|
65
|
+
...entries
|
|
66
|
+
];
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
for (const event of Object.keys(merged)) {
|
|
70
|
+
if (merged[event].length === 0) {
|
|
71
|
+
delete merged[event];
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return merged;
|
|
75
|
+
}
|
|
76
|
+
function removeKgHooksOnly(existingHooks) {
|
|
77
|
+
if (!existingHooks) return null;
|
|
78
|
+
const cleaned = {};
|
|
79
|
+
let hasRemainingHooks = false;
|
|
80
|
+
for (const [event, entries] of Object.entries(existingHooks)) {
|
|
81
|
+
if (Array.isArray(entries)) {
|
|
82
|
+
const remaining = removeKgHooksFromArray(entries);
|
|
83
|
+
if (remaining.length > 0) {
|
|
84
|
+
cleaned[event] = remaining;
|
|
85
|
+
hasRemainingHooks = true;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return hasRemainingHooks ? cleaned : null;
|
|
90
|
+
}
|
|
91
|
+
function hasKgHooks(hooks) {
|
|
92
|
+
if (!hooks) return false;
|
|
93
|
+
for (const entries of Object.values(hooks)) {
|
|
94
|
+
if (Array.isArray(entries) && entries.some(isKgHook)) {
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
33
100
|
function createHooksCommand() {
|
|
34
101
|
const command = new Command("hooks");
|
|
35
102
|
command.description("Claude Code hooks for capturing interactions in the knowledge graph");
|
|
36
|
-
command.command("install").description("Install Claude Code hooks to capture all interactions").option("-p, --path <path>", "Project root path", ".").option("-s, --scope <scope>", "Installation scope: project or user", "project").option("-f, --force", "
|
|
103
|
+
command.command("install").description("Install Claude Code hooks to capture all interactions (merges with existing hooks)").option("-p, --path <path>", "Project root path", ".").option("-s, --scope <scope>", "Installation scope: project or user", "project").option("-f, --force", "Reinstall even if KG hooks already present").option("--replace", "Replace all hooks instead of merging (not recommended)").option("--no-markdown", "Disable markdown document generation").option("--no-tool-outputs", "Disable separate tool output storage").action(async (options) => {
|
|
37
104
|
const spinner = ora("Installing Claude Code hooks...").start();
|
|
38
105
|
try {
|
|
39
106
|
const projectRoot = validateProjectRoot(options.path);
|
|
40
107
|
const settingsPath = getClaudeSettingsPath(options.scope);
|
|
41
108
|
const settings = loadSettings(settingsPath);
|
|
42
|
-
|
|
43
|
-
|
|
109
|
+
const existingHooks = settings.hooks;
|
|
110
|
+
if (hasKgHooks(existingHooks) && !options.force) {
|
|
111
|
+
spinner.info("KG capture hooks already installed.");
|
|
44
112
|
console.log();
|
|
45
|
-
console.log(chalk.gray("
|
|
113
|
+
console.log(chalk.gray(" Use --force to reinstall."));
|
|
114
|
+
console.log(chalk.gray(" Settings:"), chalk.white(settingsPath));
|
|
46
115
|
return;
|
|
47
116
|
}
|
|
48
|
-
const
|
|
117
|
+
const kgHookConfig = generateHookConfig(projectRoot);
|
|
118
|
+
const kgHooks = kgHookConfig.hooks;
|
|
119
|
+
let mergedHooks;
|
|
120
|
+
if (options.replace) {
|
|
121
|
+
mergedHooks = kgHooks;
|
|
122
|
+
spinner.text = "Replacing all hooks with KG capture hooks...";
|
|
123
|
+
} else {
|
|
124
|
+
mergedHooks = mergeHooksConfig(existingHooks, kgHooks);
|
|
125
|
+
if (existingHooks && Object.keys(existingHooks).length > 0) {
|
|
126
|
+
spinner.text = "Merging KG capture hooks with existing hooks...";
|
|
127
|
+
}
|
|
128
|
+
}
|
|
49
129
|
const newSettings = {
|
|
50
130
|
...settings,
|
|
51
|
-
|
|
131
|
+
hooks: mergedHooks
|
|
52
132
|
};
|
|
53
133
|
saveSettings(settingsPath, newSettings);
|
|
54
134
|
const storageDir = join(projectRoot, ".kg", "claude");
|
|
@@ -61,7 +141,15 @@ function createHooksCommand() {
|
|
|
61
141
|
console.log(chalk.gray(" Settings file:"), chalk.white(settingsPath));
|
|
62
142
|
console.log(chalk.gray(" Storage dir:"), chalk.white(storageDir));
|
|
63
143
|
console.log();
|
|
64
|
-
|
|
144
|
+
if (!options.replace && existingHooks && Object.keys(existingHooks).length > 0) {
|
|
145
|
+
const preservedCount = Object.values(existingHooks).flat().filter((e) => !isKgHook(e)).length;
|
|
146
|
+
if (preservedCount > 0) {
|
|
147
|
+
console.log(chalk.cyan(" Compatibility:"));
|
|
148
|
+
console.log(chalk.gray(` - Preserved ${preservedCount} existing hook(s) (e.g., claude-flow)`));
|
|
149
|
+
console.log();
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
console.log(chalk.cyan(" KG Hooks Added:"));
|
|
65
153
|
console.log(chalk.gray(" - UserPromptSubmit: Captures all user prompts"));
|
|
66
154
|
console.log(chalk.gray(" - PreToolUse: Captures tool invocations"));
|
|
67
155
|
console.log(chalk.gray(" - PostToolUse: Captures tool results"));
|
|
@@ -75,18 +163,43 @@ function createHooksCommand() {
|
|
|
75
163
|
process.exit(1);
|
|
76
164
|
}
|
|
77
165
|
});
|
|
78
|
-
command.command("uninstall").description("Remove
|
|
79
|
-
const spinner = ora("Removing
|
|
166
|
+
command.command("uninstall").description("Remove KG capture hooks (preserves other hooks like claude-flow)").option("-s, --scope <scope>", "Installation scope: project or user", "project").option("--all", "Remove ALL hooks, not just KG hooks (use with caution)").action(async (options) => {
|
|
167
|
+
const spinner = ora("Removing KG capture hooks...").start();
|
|
80
168
|
try {
|
|
81
169
|
const settingsPath = getClaudeSettingsPath(options.scope);
|
|
82
170
|
const settings = loadSettings(settingsPath);
|
|
83
|
-
|
|
171
|
+
const existingHooks = settings.hooks;
|
|
172
|
+
if (!existingHooks) {
|
|
84
173
|
spinner.info("No hooks configured.");
|
|
85
174
|
return;
|
|
86
175
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
176
|
+
if (options.all) {
|
|
177
|
+
delete settings.hooks;
|
|
178
|
+
saveSettings(settingsPath, settings);
|
|
179
|
+
spinner.succeed("All hooks removed.");
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
if (!hasKgHooks(existingHooks)) {
|
|
183
|
+
spinner.info("No KG capture hooks found.");
|
|
184
|
+
console.log();
|
|
185
|
+
console.log(chalk.gray(" Other hooks are still configured."));
|
|
186
|
+
console.log(chalk.gray(" Use --all to remove all hooks."));
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
const remainingHooks = removeKgHooksOnly(existingHooks);
|
|
190
|
+
if (remainingHooks) {
|
|
191
|
+
settings.hooks = remainingHooks;
|
|
192
|
+
saveSettings(settingsPath, settings);
|
|
193
|
+
const preservedCount = Object.values(remainingHooks).flat().length;
|
|
194
|
+
spinner.succeed("KG capture hooks removed.");
|
|
195
|
+
console.log();
|
|
196
|
+
console.log(chalk.gray(` Preserved ${preservedCount} other hook(s) (e.g., claude-flow).`));
|
|
197
|
+
console.log(chalk.gray(" Use --all to remove all hooks."));
|
|
198
|
+
} else {
|
|
199
|
+
delete settings.hooks;
|
|
200
|
+
saveSettings(settingsPath, settings);
|
|
201
|
+
spinner.succeed("KG capture hooks removed (no other hooks remaining).");
|
|
202
|
+
}
|
|
90
203
|
} catch (error) {
|
|
91
204
|
spinner.fail("Failed to remove hooks");
|
|
92
205
|
console.error(chalk.red(String(error)));
|
|
@@ -107,19 +220,47 @@ function createHooksCommand() {
|
|
|
107
220
|
const projectRoot = validateProjectRoot(options.path);
|
|
108
221
|
const settingsPath = getClaudeSettingsPath(options.scope);
|
|
109
222
|
const settings = loadSettings(settingsPath);
|
|
223
|
+
const existingHooks = settings.hooks;
|
|
110
224
|
console.log();
|
|
111
225
|
console.log(chalk.cyan(" Claude Code Hooks Status"));
|
|
112
226
|
console.log();
|
|
113
|
-
if (
|
|
114
|
-
|
|
227
|
+
if (existingHooks) {
|
|
228
|
+
const kgInstalled = hasKgHooks(existingHooks);
|
|
229
|
+
const totalHooks = Object.values(existingHooks).flat().length;
|
|
230
|
+
const kgHookCount = Object.values(existingHooks).flat().filter((e) => isKgHook(e)).length;
|
|
231
|
+
const otherHookCount = totalHooks - kgHookCount;
|
|
232
|
+
console.log(chalk.green(" ✓ Hooks configured"));
|
|
115
233
|
console.log(chalk.gray(" Settings:"), chalk.white(settingsPath));
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
console.log(chalk.gray(`
|
|
234
|
+
console.log();
|
|
235
|
+
if (kgInstalled) {
|
|
236
|
+
console.log(chalk.green(" ✓ KG capture hooks installed"));
|
|
237
|
+
console.log(chalk.gray(` KG hooks: ${kgHookCount} active`));
|
|
238
|
+
} else {
|
|
239
|
+
console.log(chalk.yellow(" ✗ KG capture hooks not installed"));
|
|
240
|
+
console.log(chalk.gray(" Run:"), chalk.white("kg hooks install"));
|
|
241
|
+
}
|
|
242
|
+
if (otherHookCount > 0) {
|
|
243
|
+
console.log(chalk.green(` ✓ Other hooks present (${otherHookCount})`));
|
|
244
|
+
console.log(chalk.gray(" (e.g., claude-flow, custom hooks)"));
|
|
245
|
+
}
|
|
246
|
+
console.log();
|
|
247
|
+
console.log(chalk.gray(" All configured events:"));
|
|
248
|
+
for (const [event, handlers] of Object.entries(existingHooks)) {
|
|
249
|
+
const arr = handlers;
|
|
250
|
+
const kgCount = arr.filter(isKgHook).length;
|
|
251
|
+
const otherCount = arr.length - kgCount;
|
|
252
|
+
let info = "";
|
|
253
|
+
if (kgCount > 0 && otherCount > 0) {
|
|
254
|
+
info = `(${kgCount} KG, ${otherCount} other)`;
|
|
255
|
+
} else if (kgCount > 0) {
|
|
256
|
+
info = "(KG)";
|
|
257
|
+
} else {
|
|
258
|
+
info = "(other)";
|
|
259
|
+
}
|
|
260
|
+
console.log(chalk.gray(` - ${event}:`), chalk.white(`${arr.length} handler(s) ${info}`));
|
|
120
261
|
}
|
|
121
262
|
} else {
|
|
122
|
-
console.log(chalk.yellow(" ✗
|
|
263
|
+
console.log(chalk.yellow(" ✗ No hooks configured"));
|
|
123
264
|
console.log(chalk.gray(" Run:"), chalk.white("kg hooks install"));
|
|
124
265
|
}
|
|
125
266
|
console.log();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.js","sources":["../../../src/cli/commands/hooks.ts"],"sourcesContent":["/**\n * Hooks Command\n *\n * Manage Claude Code hooks for capturing interactions in the knowledge graph.\n */\n\nimport { Command } from 'commander';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { validateProjectRoot } from '../../core/security.js';\nimport {\n HookCaptureSystem,\n processHookEvent,\n generateHookConfig,\n type HookEventType,\n} from '../../claude/index.js';\n\n/**\n * Path to Claude settings\n */\nfunction getClaudeSettingsPath(scope: 'project' | 'user'): string {\n if (scope === 'user') {\n const home = process.env.HOME || process.env.USERPROFILE || '';\n return join(home, '.claude', 'settings.json');\n }\n return join(process.cwd(), '.claude', 'settings.json');\n}\n\n/**\n * Load existing settings or return empty object\n */\nfunction loadSettings(path: string): Record<string, unknown> {\n if (!existsSync(path)) {\n return {};\n }\n try {\n return JSON.parse(readFileSync(path, 'utf-8'));\n } catch {\n return {};\n }\n}\n\n/**\n * Save settings to file\n */\nfunction saveSettings(path: string, settings: Record<string, unknown>): void {\n const dir = dirname(path);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n writeFileSync(path, JSON.stringify(settings, null, 2));\n}\n\n/**\n * Create hooks command\n */\nexport function createHooksCommand(): Command {\n const command = new Command('hooks');\n\n command.description('Claude Code hooks for capturing interactions in the knowledge graph');\n\n // Install hooks\n command\n .command('install')\n .description('Install Claude Code hooks to capture all interactions')\n .option('-p, --path <path>', 'Project root path', '.')\n .option('-s, --scope <scope>', 'Installation scope: project or user', 'project')\n .option('-f, --force', 'Overwrite existing hooks configuration')\n .option('--no-markdown', 'Disable markdown document generation')\n .option('--no-tool-outputs', 'Disable separate tool output storage')\n .action(async (options) => {\n const spinner = ora('Installing Claude Code hooks...').start();\n\n try {\n const projectRoot = validateProjectRoot(options.path);\n const settingsPath = getClaudeSettingsPath(options.scope);\n\n // Load existing settings\n const settings = loadSettings(settingsPath);\n\n // Check for existing hooks\n if (settings.hooks && !options.force) {\n spinner.warn('Hooks already configured. Use --force to overwrite.');\n console.log();\n console.log(chalk.gray(' Current settings:'), chalk.white(settingsPath));\n return;\n }\n\n // Generate hook configuration\n const hookConfig = generateHookConfig(projectRoot);\n\n // Merge with existing settings\n const newSettings = {\n ...settings,\n ...hookConfig,\n };\n\n // Save settings\n saveSettings(settingsPath, newSettings);\n\n // Ensure storage directory exists\n const storageDir = join(projectRoot, '.kg', 'claude');\n if (!existsSync(storageDir)) {\n mkdirSync(storageDir, { recursive: true });\n }\n\n spinner.succeed('Claude Code hooks installed!');\n\n console.log();\n console.log(chalk.cyan(' Hook Configuration'));\n console.log(chalk.gray(' Settings file:'), chalk.white(settingsPath));\n console.log(chalk.gray(' Storage dir:'), chalk.white(storageDir));\n console.log();\n console.log(chalk.cyan(' Hooks Installed:'));\n console.log(chalk.gray(' - UserPromptSubmit: Captures all user prompts'));\n console.log(chalk.gray(' - PreToolUse: Captures tool invocations'));\n console.log(chalk.gray(' - PostToolUse: Captures tool results'));\n console.log(chalk.gray(' - Stop: Finalizes session on completion'));\n console.log();\n console.log(chalk.green(' All Claude interactions will now be stored in the knowledge graph.'));\n console.log();\n\n } catch (error) {\n spinner.fail('Failed to install hooks');\n console.error(chalk.red(String(error)));\n process.exit(1);\n }\n });\n\n // Uninstall hooks\n command\n .command('uninstall')\n .description('Remove Claude Code hooks')\n .option('-s, --scope <scope>', 'Installation scope: project or user', 'project')\n .action(async (options) => {\n const spinner = ora('Removing Claude Code hooks...').start();\n\n try {\n const settingsPath = getClaudeSettingsPath(options.scope);\n const settings = loadSettings(settingsPath);\n\n if (!settings.hooks) {\n spinner.info('No hooks configured.');\n return;\n }\n\n // Remove hooks configuration\n delete settings.hooks;\n saveSettings(settingsPath, settings);\n\n spinner.succeed('Claude Code hooks removed.');\n\n } catch (error) {\n spinner.fail('Failed to remove hooks');\n console.error(chalk.red(String(error)));\n process.exit(1);\n }\n });\n\n // Capture event (used by hooks)\n command\n .command('capture')\n .description('Capture a hook event (internal use)')\n .option('-e, --event <type>', 'Event type', 'UserPromptSubmit')\n .option('-p, --path <path>', 'Project root path', '.')\n .action(async (options) => {\n try {\n const projectRoot = validateProjectRoot(options.path);\n const eventType = options.event as HookEventType;\n\n await processHookEvent(projectRoot, eventType);\n\n } catch (error) {\n // Silent failure - hooks should not disrupt Claude Code operation\n console.error(`Hook capture error: ${error}`);\n }\n });\n\n // Status command\n command\n .command('status')\n .description('Show hooks status and recent captures')\n .option('-p, --path <path>', 'Project root path', '.')\n .option('-s, --scope <scope>', 'Check scope: project or user', 'project')\n .action(async (options) => {\n try {\n const projectRoot = validateProjectRoot(options.path);\n const settingsPath = getClaudeSettingsPath(options.scope);\n const settings = loadSettings(settingsPath);\n\n console.log();\n console.log(chalk.cyan(' Claude Code Hooks Status'));\n console.log();\n\n // Check installation\n if (settings.hooks) {\n console.log(chalk.green(' ✓ Hooks installed'));\n console.log(chalk.gray(' Settings:'), chalk.white(settingsPath));\n\n const hooks = settings.hooks as Record<string, unknown[]>;\n console.log(chalk.gray(' Configured hooks:'));\n for (const [event, handlers] of Object.entries(hooks)) {\n console.log(chalk.gray(` - ${event}:`), chalk.white(`${(handlers as unknown[]).length} handler(s)`));\n }\n } else {\n console.log(chalk.yellow(' ✗ Hooks not installed'));\n console.log(chalk.gray(' Run:'), chalk.white('kg hooks install'));\n }\n\n console.log();\n\n // Check storage\n const storageDir = join(projectRoot, '.kg', 'claude');\n if (existsSync(storageDir)) {\n console.log(chalk.green(' ✓ Storage directory exists'));\n console.log(chalk.gray(' Path:'), chalk.white(storageDir));\n\n // List sessions\n const capture = new HookCaptureSystem(projectRoot);\n const sessions = capture.listSessions();\n\n if (sessions.length > 0) {\n console.log(chalk.gray(' Sessions:'), chalk.white(`${sessions.length} stored`));\n\n // Show recent sessions\n const recent = sessions.slice(-3);\n for (const sessionId of recent) {\n const session = capture.loadSession(sessionId);\n if (session) {\n console.log(\n chalk.gray(` - ${sessionId}:`),\n chalk.white(session.name),\n chalk.gray(`(${session.status})`)\n );\n }\n }\n } else {\n console.log(chalk.gray(' Sessions:'), chalk.white('None yet'));\n }\n } else {\n console.log(chalk.yellow(' ✗ Storage directory not found'));\n console.log(chalk.gray(' Will be created on first capture'));\n }\n\n console.log();\n\n } catch (error) {\n console.error(chalk.red('Failed to get status:'), String(error));\n process.exit(1);\n }\n });\n\n // List sessions\n command\n .command('sessions')\n .description('List captured sessions')\n .option('-p, --path <path>', 'Project root path', '.')\n .option('-l, --limit <number>', 'Limit number of sessions', '10')\n .option('--json', 'Output as JSON')\n .action(async (options) => {\n try {\n const projectRoot = validateProjectRoot(options.path);\n const limit = parseInt(options.limit, 10);\n\n const capture = new HookCaptureSystem(projectRoot);\n const sessions = capture.listSessions();\n\n if (options.json) {\n const sessionData = sessions.slice(-limit).map(id => capture.loadSession(id));\n console.log(JSON.stringify(sessionData, null, 2));\n return;\n }\n\n console.log();\n console.log(chalk.cyan(' Captured Sessions'));\n console.log();\n\n if (sessions.length === 0) {\n console.log(chalk.gray(' No sessions captured yet.'));\n console.log();\n return;\n }\n\n const recentSessions = sessions.slice(-limit);\n for (const sessionId of recentSessions) {\n const session = capture.loadSession(sessionId);\n if (session) {\n const statusColor = session.status === 'completed' ? chalk.green : chalk.yellow;\n console.log(\n chalk.white(` ${session.id}`),\n chalk.gray('|'),\n chalk.cyan(session.name)\n );\n console.log(\n chalk.gray(' Status:'),\n statusColor(session.status),\n chalk.gray('|'),\n chalk.gray('Conversations:'),\n chalk.white(String(session.conversationIds.length)),\n chalk.gray('|'),\n chalk.gray('Tokens:'),\n chalk.white(String(session.tokenUsage.totalTokens))\n );\n console.log(\n chalk.gray(' Started:'),\n chalk.white(new Date(session.startedAt).toLocaleString())\n );\n console.log();\n }\n }\n\n if (sessions.length > limit) {\n console.log(chalk.gray(` ... and ${sessions.length - limit} more sessions`));\n console.log();\n }\n\n } catch (error) {\n console.error(chalk.red('Failed to list sessions:'), String(error));\n process.exit(1);\n }\n });\n\n // Export sessions\n command\n .command('export')\n .description('Export captured sessions')\n .option('-p, --path <path>', 'Project root path', '.')\n .option('-o, --output <file>', 'Output file path')\n .option('-f, --format <format>', 'Output format: json or markdown', 'json')\n .option('--session <id>', 'Export specific session')\n .action(async (options) => {\n const spinner = ora('Exporting sessions...').start();\n\n try {\n const projectRoot = validateProjectRoot(options.path);\n const capture = new HookCaptureSystem(projectRoot);\n\n let sessionsToExport: string[];\n\n if (options.session) {\n sessionsToExport = [options.session];\n } else {\n sessionsToExport = capture.listSessions();\n }\n\n if (sessionsToExport.length === 0) {\n spinner.info('No sessions to export.');\n return;\n }\n\n const exportData = sessionsToExport\n .map(id => capture.loadSession(id as any))\n .filter(Boolean);\n\n if (options.format === 'json') {\n const output = JSON.stringify(exportData, null, 2);\n\n if (options.output) {\n writeFileSync(options.output, output);\n spinner.succeed(`Exported ${exportData.length} session(s) to ${options.output}`);\n } else {\n spinner.stop();\n console.log(output);\n }\n } else if (options.format === 'markdown') {\n let markdown = '# Claude Interaction Sessions\\n\\n';\n\n for (const session of exportData) {\n if (!session) continue;\n markdown += `## ${session.name}\\n\\n`;\n markdown += `- **ID:** ${session.id}\\n`;\n markdown += `- **Status:** ${session.status}\\n`;\n markdown += `- **Purpose:** ${session.purpose || 'N/A'}\\n`;\n markdown += `- **Started:** ${new Date(session.startedAt).toISOString()}\\n`;\n if (session.endedAt) {\n markdown += `- **Ended:** ${new Date(session.endedAt).toISOString()}\\n`;\n }\n markdown += `- **Conversations:** ${session.conversationIds.length}\\n`;\n markdown += `- **Tokens:** ${session.tokenUsage.totalTokens}\\n\\n`;\n }\n\n if (options.output) {\n writeFileSync(options.output, markdown);\n spinner.succeed(`Exported ${exportData.length} session(s) to ${options.output}`);\n } else {\n spinner.stop();\n console.log(markdown);\n }\n }\n\n } catch (error) {\n spinner.fail('Failed to export sessions');\n console.error(chalk.red(String(error)));\n process.exit(1);\n }\n });\n\n return command;\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"hooks.js","sources":["../../../src/cli/commands/hooks.ts"],"sourcesContent":["/**\n * Hooks Command\n *\n * Manage Claude Code hooks for capturing interactions in the knowledge graph.\n * Supports merging with existing hooks (e.g., claude-flow) for compatibility.\n */\n\nimport { Command } from 'commander';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { validateProjectRoot } from '../../core/security.js';\nimport {\n HookCaptureSystem,\n processHookEvent,\n generateHookConfig,\n type HookEventType,\n} from '../../claude/index.js';\n\n/** KG hook identifier to track which hooks belong to us */\nconst KG_HOOK_MARKER = '@weavelogic/knowledge-graph-agent';\n\n/** Hook event types we support */\ntype HookEventName = 'UserPromptSubmit' | 'PreToolUse' | 'PostToolUse' | 'Stop' | 'PreCompact';\n\n/** Single hook handler configuration */\ninterface HookHandler {\n type: 'command';\n command: string;\n timeout?: number;\n}\n\n/** Hook entry can be nested (with hooks array) or flat (direct command) */\ninterface HookEntry {\n matcher?: string;\n hooks?: HookHandler[];\n // Flat format fields\n type?: 'command';\n command?: string;\n timeout?: number;\n}\n\n/** Full hooks configuration */\ntype HooksConfig = Record<HookEventName, HookEntry[]>;\n\n/**\n * Path to Claude settings\n */\nfunction getClaudeSettingsPath(scope: 'project' | 'user'): string {\n if (scope === 'user') {\n const home = process.env.HOME || process.env.USERPROFILE || '';\n return join(home, '.claude', 'settings.json');\n }\n return join(process.cwd(), '.claude', 'settings.json');\n}\n\n/**\n * Load existing settings or return empty object\n */\nfunction loadSettings(path: string): Record<string, unknown> {\n if (!existsSync(path)) {\n return {};\n }\n try {\n return JSON.parse(readFileSync(path, 'utf-8'));\n } catch {\n return {};\n }\n}\n\n/**\n * Save settings to file\n */\nfunction saveSettings(path: string, settings: Record<string, unknown>): void {\n const dir = dirname(path);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n writeFileSync(path, JSON.stringify(settings, null, 2));\n}\n\n/**\n * Check if a hook entry belongs to KG agent\n * Handles both flat format ({ type, command }) and nested format ({ hooks: [...] })\n */\nfunction isKgHook(entry: HookEntry): boolean {\n // Check flat format (entry has command directly)\n if (entry.command?.includes(KG_HOOK_MARKER)) {\n return true;\n }\n // Check nested format (entry has hooks array)\n if (entry.hooks?.some(h => h.command?.includes(KG_HOOK_MARKER))) {\n return true;\n }\n return false;\n}\n\n/**\n * Remove KG hooks from a hooks array while preserving others\n */\nfunction removeKgHooksFromArray(entries: HookEntry[]): HookEntry[] {\n return entries.filter(entry => !isKgHook(entry));\n}\n\n/**\n * Merge KG hooks with existing hooks configuration\n * Preserves all existing hooks and adds KG hooks alongside them\n */\nfunction mergeHooksConfig(\n existingHooks: Partial<HooksConfig> | undefined,\n kgHooks: Partial<HooksConfig>\n): HooksConfig {\n const merged: HooksConfig = {\n UserPromptSubmit: [],\n PreToolUse: [],\n PostToolUse: [],\n Stop: [],\n PreCompact: [],\n };\n\n // First, copy all existing non-KG hooks\n if (existingHooks) {\n for (const [event, entries] of Object.entries(existingHooks)) {\n if (Array.isArray(entries)) {\n merged[event as HookEventName] = removeKgHooksFromArray(entries);\n }\n }\n }\n\n // Then add KG hooks\n for (const [event, entries] of Object.entries(kgHooks)) {\n if (Array.isArray(entries)) {\n merged[event as HookEventName] = [\n ...merged[event as HookEventName],\n ...entries,\n ];\n }\n }\n\n // Remove empty arrays\n for (const event of Object.keys(merged) as HookEventName[]) {\n if (merged[event].length === 0) {\n delete (merged as Record<string, unknown>)[event];\n }\n }\n\n return merged;\n}\n\n/**\n * Remove only KG hooks from existing configuration\n * Preserves all other hooks (e.g., claude-flow)\n */\nfunction removeKgHooksOnly(existingHooks: Partial<HooksConfig> | undefined): Partial<HooksConfig> | null {\n if (!existingHooks) return null;\n\n const cleaned: Partial<HooksConfig> = {};\n let hasRemainingHooks = false;\n\n for (const [event, entries] of Object.entries(existingHooks)) {\n if (Array.isArray(entries)) {\n const remaining = removeKgHooksFromArray(entries);\n if (remaining.length > 0) {\n cleaned[event as HookEventName] = remaining;\n hasRemainingHooks = true;\n }\n }\n }\n\n return hasRemainingHooks ? cleaned : null;\n}\n\n/**\n * Check if KG hooks are already installed\n */\nfunction hasKgHooks(hooks: Partial<HooksConfig> | undefined): boolean {\n if (!hooks) return false;\n\n for (const entries of Object.values(hooks)) {\n if (Array.isArray(entries) && entries.some(isKgHook)) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Create hooks command\n */\nexport function createHooksCommand(): Command {\n const command = new Command('hooks');\n\n command.description('Claude Code hooks for capturing interactions in the knowledge graph');\n\n // Install hooks\n command\n .command('install')\n .description('Install Claude Code hooks to capture all interactions (merges with existing hooks)')\n .option('-p, --path <path>', 'Project root path', '.')\n .option('-s, --scope <scope>', 'Installation scope: project or user', 'project')\n .option('-f, --force', 'Reinstall even if KG hooks already present')\n .option('--replace', 'Replace all hooks instead of merging (not recommended)')\n .option('--no-markdown', 'Disable markdown document generation')\n .option('--no-tool-outputs', 'Disable separate tool output storage')\n .action(async (options) => {\n const spinner = ora('Installing Claude Code hooks...').start();\n\n try {\n const projectRoot = validateProjectRoot(options.path);\n const settingsPath = getClaudeSettingsPath(options.scope);\n\n // Load existing settings\n const settings = loadSettings(settingsPath);\n const existingHooks = settings.hooks as Partial<HooksConfig> | undefined;\n\n // Check if KG hooks already installed\n if (hasKgHooks(existingHooks) && !options.force) {\n spinner.info('KG capture hooks already installed.');\n console.log();\n console.log(chalk.gray(' Use --force to reinstall.'));\n console.log(chalk.gray(' Settings:'), chalk.white(settingsPath));\n return;\n }\n\n // Generate KG hook configuration\n const kgHookConfig = generateHookConfig(projectRoot);\n const kgHooks = kgHookConfig.hooks as Partial<HooksConfig>;\n\n let mergedHooks: Partial<HooksConfig>;\n\n if (options.replace) {\n // Replace mode: use only KG hooks\n mergedHooks = kgHooks;\n spinner.text = 'Replacing all hooks with KG capture hooks...';\n } else {\n // Merge mode: preserve existing hooks, add KG hooks\n mergedHooks = mergeHooksConfig(existingHooks, kgHooks);\n if (existingHooks && Object.keys(existingHooks).length > 0) {\n spinner.text = 'Merging KG capture hooks with existing hooks...';\n }\n }\n\n // Update settings with merged hooks\n const newSettings = {\n ...settings,\n hooks: mergedHooks,\n };\n\n // Save settings\n saveSettings(settingsPath, newSettings);\n\n // Ensure storage directory exists\n const storageDir = join(projectRoot, '.kg', 'claude');\n if (!existsSync(storageDir)) {\n mkdirSync(storageDir, { recursive: true });\n }\n\n spinner.succeed('Claude Code hooks installed!');\n\n console.log();\n console.log(chalk.cyan(' Hook Configuration'));\n console.log(chalk.gray(' Settings file:'), chalk.white(settingsPath));\n console.log(chalk.gray(' Storage dir:'), chalk.white(storageDir));\n console.log();\n\n // Show what was preserved\n if (!options.replace && existingHooks && Object.keys(existingHooks).length > 0) {\n const preservedCount = Object.values(existingHooks)\n .flat()\n .filter(e => !isKgHook(e as HookEntry)).length;\n if (preservedCount > 0) {\n console.log(chalk.cyan(' Compatibility:'));\n console.log(chalk.gray(` - Preserved ${preservedCount} existing hook(s) (e.g., claude-flow)`));\n console.log();\n }\n }\n\n console.log(chalk.cyan(' KG Hooks Added:'));\n console.log(chalk.gray(' - UserPromptSubmit: Captures all user prompts'));\n console.log(chalk.gray(' - PreToolUse: Captures tool invocations'));\n console.log(chalk.gray(' - PostToolUse: Captures tool results'));\n console.log(chalk.gray(' - Stop: Finalizes session on completion'));\n console.log();\n console.log(chalk.green(' All Claude interactions will now be stored in the knowledge graph.'));\n console.log();\n\n } catch (error) {\n spinner.fail('Failed to install hooks');\n console.error(chalk.red(String(error)));\n process.exit(1);\n }\n });\n\n // Uninstall hooks\n command\n .command('uninstall')\n .description('Remove KG capture hooks (preserves other hooks like claude-flow)')\n .option('-s, --scope <scope>', 'Installation scope: project or user', 'project')\n .option('--all', 'Remove ALL hooks, not just KG hooks (use with caution)')\n .action(async (options) => {\n const spinner = ora('Removing KG capture hooks...').start();\n\n try {\n const settingsPath = getClaudeSettingsPath(options.scope);\n const settings = loadSettings(settingsPath);\n const existingHooks = settings.hooks as Partial<HooksConfig> | undefined;\n\n if (!existingHooks) {\n spinner.info('No hooks configured.');\n return;\n }\n\n if (options.all) {\n // Remove all hooks\n delete settings.hooks;\n saveSettings(settingsPath, settings);\n spinner.succeed('All hooks removed.');\n return;\n }\n\n // Check if KG hooks are present\n if (!hasKgHooks(existingHooks)) {\n spinner.info('No KG capture hooks found.');\n console.log();\n console.log(chalk.gray(' Other hooks are still configured.'));\n console.log(chalk.gray(' Use --all to remove all hooks.'));\n return;\n }\n\n // Remove only KG hooks, preserve others\n const remainingHooks = removeKgHooksOnly(existingHooks);\n\n if (remainingHooks) {\n settings.hooks = remainingHooks;\n saveSettings(settingsPath, settings);\n\n const preservedCount = Object.values(remainingHooks).flat().length;\n spinner.succeed('KG capture hooks removed.');\n console.log();\n console.log(chalk.gray(` Preserved ${preservedCount} other hook(s) (e.g., claude-flow).`));\n console.log(chalk.gray(' Use --all to remove all hooks.'));\n } else {\n delete settings.hooks;\n saveSettings(settingsPath, settings);\n spinner.succeed('KG capture hooks removed (no other hooks remaining).');\n }\n\n } catch (error) {\n spinner.fail('Failed to remove hooks');\n console.error(chalk.red(String(error)));\n process.exit(1);\n }\n });\n\n // Capture event (used by hooks)\n command\n .command('capture')\n .description('Capture a hook event (internal use)')\n .option('-e, --event <type>', 'Event type', 'UserPromptSubmit')\n .option('-p, --path <path>', 'Project root path', '.')\n .action(async (options) => {\n try {\n const projectRoot = validateProjectRoot(options.path);\n const eventType = options.event as HookEventType;\n\n await processHookEvent(projectRoot, eventType);\n\n } catch (error) {\n // Silent failure - hooks should not disrupt Claude Code operation\n console.error(`Hook capture error: ${error}`);\n }\n });\n\n // Status command\n command\n .command('status')\n .description('Show hooks status and recent captures')\n .option('-p, --path <path>', 'Project root path', '.')\n .option('-s, --scope <scope>', 'Check scope: project or user', 'project')\n .action(async (options) => {\n try {\n const projectRoot = validateProjectRoot(options.path);\n const settingsPath = getClaudeSettingsPath(options.scope);\n const settings = loadSettings(settingsPath);\n const existingHooks = settings.hooks as Partial<HooksConfig> | undefined;\n\n console.log();\n console.log(chalk.cyan(' Claude Code Hooks Status'));\n console.log();\n\n // Check installation\n if (existingHooks) {\n const kgInstalled = hasKgHooks(existingHooks);\n const totalHooks = Object.values(existingHooks).flat().length;\n const kgHookCount = Object.values(existingHooks)\n .flat()\n .filter(e => isKgHook(e as HookEntry)).length;\n const otherHookCount = totalHooks - kgHookCount;\n\n console.log(chalk.green(' ✓ Hooks configured'));\n console.log(chalk.gray(' Settings:'), chalk.white(settingsPath));\n console.log();\n\n // KG hooks status\n if (kgInstalled) {\n console.log(chalk.green(' ✓ KG capture hooks installed'));\n console.log(chalk.gray(` KG hooks: ${kgHookCount} active`));\n } else {\n console.log(chalk.yellow(' ✗ KG capture hooks not installed'));\n console.log(chalk.gray(' Run:'), chalk.white('kg hooks install'));\n }\n\n // Other hooks status\n if (otherHookCount > 0) {\n console.log(chalk.green(` ✓ Other hooks present (${otherHookCount})`));\n console.log(chalk.gray(' (e.g., claude-flow, custom hooks)'));\n }\n\n console.log();\n console.log(chalk.gray(' All configured events:'));\n for (const [event, handlers] of Object.entries(existingHooks)) {\n const arr = handlers as HookEntry[];\n const kgCount = arr.filter(isKgHook).length;\n const otherCount = arr.length - kgCount;\n let info = '';\n if (kgCount > 0 && otherCount > 0) {\n info = `(${kgCount} KG, ${otherCount} other)`;\n } else if (kgCount > 0) {\n info = '(KG)';\n } else {\n info = '(other)';\n }\n console.log(chalk.gray(` - ${event}:`), chalk.white(`${arr.length} handler(s) ${info}`));\n }\n } else {\n console.log(chalk.yellow(' ✗ No hooks configured'));\n console.log(chalk.gray(' Run:'), chalk.white('kg hooks install'));\n }\n\n console.log();\n\n // Check storage\n const storageDir = join(projectRoot, '.kg', 'claude');\n if (existsSync(storageDir)) {\n console.log(chalk.green(' ✓ Storage directory exists'));\n console.log(chalk.gray(' Path:'), chalk.white(storageDir));\n\n // List sessions\n const capture = new HookCaptureSystem(projectRoot);\n const sessions = capture.listSessions();\n\n if (sessions.length > 0) {\n console.log(chalk.gray(' Sessions:'), chalk.white(`${sessions.length} stored`));\n\n // Show recent sessions\n const recent = sessions.slice(-3);\n for (const sessionId of recent) {\n const session = capture.loadSession(sessionId);\n if (session) {\n console.log(\n chalk.gray(` - ${sessionId}:`),\n chalk.white(session.name),\n chalk.gray(`(${session.status})`)\n );\n }\n }\n } else {\n console.log(chalk.gray(' Sessions:'), chalk.white('None yet'));\n }\n } else {\n console.log(chalk.yellow(' ✗ Storage directory not found'));\n console.log(chalk.gray(' Will be created on first capture'));\n }\n\n console.log();\n\n } catch (error) {\n console.error(chalk.red('Failed to get status:'), String(error));\n process.exit(1);\n }\n });\n\n // List sessions\n command\n .command('sessions')\n .description('List captured sessions')\n .option('-p, --path <path>', 'Project root path', '.')\n .option('-l, --limit <number>', 'Limit number of sessions', '10')\n .option('--json', 'Output as JSON')\n .action(async (options) => {\n try {\n const projectRoot = validateProjectRoot(options.path);\n const limit = parseInt(options.limit, 10);\n\n const capture = new HookCaptureSystem(projectRoot);\n const sessions = capture.listSessions();\n\n if (options.json) {\n const sessionData = sessions.slice(-limit).map(id => capture.loadSession(id));\n console.log(JSON.stringify(sessionData, null, 2));\n return;\n }\n\n console.log();\n console.log(chalk.cyan(' Captured Sessions'));\n console.log();\n\n if (sessions.length === 0) {\n console.log(chalk.gray(' No sessions captured yet.'));\n console.log();\n return;\n }\n\n const recentSessions = sessions.slice(-limit);\n for (const sessionId of recentSessions) {\n const session = capture.loadSession(sessionId);\n if (session) {\n const statusColor = session.status === 'completed' ? chalk.green : chalk.yellow;\n console.log(\n chalk.white(` ${session.id}`),\n chalk.gray('|'),\n chalk.cyan(session.name)\n );\n console.log(\n chalk.gray(' Status:'),\n statusColor(session.status),\n chalk.gray('|'),\n chalk.gray('Conversations:'),\n chalk.white(String(session.conversationIds.length)),\n chalk.gray('|'),\n chalk.gray('Tokens:'),\n chalk.white(String(session.tokenUsage.totalTokens))\n );\n console.log(\n chalk.gray(' Started:'),\n chalk.white(new Date(session.startedAt).toLocaleString())\n );\n console.log();\n }\n }\n\n if (sessions.length > limit) {\n console.log(chalk.gray(` ... and ${sessions.length - limit} more sessions`));\n console.log();\n }\n\n } catch (error) {\n console.error(chalk.red('Failed to list sessions:'), String(error));\n process.exit(1);\n }\n });\n\n // Export sessions\n command\n .command('export')\n .description('Export captured sessions')\n .option('-p, --path <path>', 'Project root path', '.')\n .option('-o, --output <file>', 'Output file path')\n .option('-f, --format <format>', 'Output format: json or markdown', 'json')\n .option('--session <id>', 'Export specific session')\n .action(async (options) => {\n const spinner = ora('Exporting sessions...').start();\n\n try {\n const projectRoot = validateProjectRoot(options.path);\n const capture = new HookCaptureSystem(projectRoot);\n\n let sessionsToExport: string[];\n\n if (options.session) {\n sessionsToExport = [options.session];\n } else {\n sessionsToExport = capture.listSessions();\n }\n\n if (sessionsToExport.length === 0) {\n spinner.info('No sessions to export.');\n return;\n }\n\n const exportData = sessionsToExport\n .map(id => capture.loadSession(id as any))\n .filter(Boolean);\n\n if (options.format === 'json') {\n const output = JSON.stringify(exportData, null, 2);\n\n if (options.output) {\n writeFileSync(options.output, output);\n spinner.succeed(`Exported ${exportData.length} session(s) to ${options.output}`);\n } else {\n spinner.stop();\n console.log(output);\n }\n } else if (options.format === 'markdown') {\n let markdown = '# Claude Interaction Sessions\\n\\n';\n\n for (const session of exportData) {\n if (!session) continue;\n markdown += `## ${session.name}\\n\\n`;\n markdown += `- **ID:** ${session.id}\\n`;\n markdown += `- **Status:** ${session.status}\\n`;\n markdown += `- **Purpose:** ${session.purpose || 'N/A'}\\n`;\n markdown += `- **Started:** ${new Date(session.startedAt).toISOString()}\\n`;\n if (session.endedAt) {\n markdown += `- **Ended:** ${new Date(session.endedAt).toISOString()}\\n`;\n }\n markdown += `- **Conversations:** ${session.conversationIds.length}\\n`;\n markdown += `- **Tokens:** ${session.tokenUsage.totalTokens}\\n\\n`;\n }\n\n if (options.output) {\n writeFileSync(options.output, markdown);\n spinner.succeed(`Exported ${exportData.length} session(s) to ${options.output}`);\n } else {\n spinner.stop();\n console.log(markdown);\n }\n }\n\n } catch (error) {\n spinner.fail('Failed to export sessions');\n console.error(chalk.red(String(error)));\n process.exit(1);\n }\n });\n\n return command;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compliance-checker.d.ts","sourceRoot":"","sources":["../../src/sops/compliance-checker.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,EAGL,aAAa,EAGb,WAAW,EAEZ,MAAM,YAAY,CAAC;AAMpB;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,6BAA6B;IAC7B,WAAW,EAAE,MAAM,CAAC;IAEpB,kDAAkD;IAClD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,8CAA8C;IAC9C,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAElB,4BAA4B;IAC5B,UAAU,CAAC,EAAE,WAAW,EAAE,CAAC;IAE3B,uCAAuC;IACvC,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB,oBAAoB;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,+BAA+B;IAC/B,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CAC7C;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,4CAA4C;IAC5C,aAAa,EAAE,MAAM,CAAC;IAEtB,yCAAyC;IACzC,QAAQ,EAAE,MAAM,CAAC;IAEjB,uBAAuB;IACvB,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,UAAU,CAAC;IAE3D,kCAAkC;IAClC,WAAW,EAAE,MAAM,CAAC;IAEpB,6BAA6B;IAC7B,UAAU,EAAE,MAAM,CAAC;IAEnB,iCAAiC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,2CAA2C;IAC3C,OAAO,EAAE,OAAO,CAAC;IAEjB,mBAAmB;IACnB,WAAW,EAAE,MAAM,CAAC;IAEpB,sBAAsB;IACtB,SAAS,EAAE,IAAI,CAAC;IAEhB,yBAAyB;IACzB,WAAW,EAAE,aAAa,EAAE,CAAC;IAE7B,qBAAqB;IACrB,QAAQ,EAAE,YAAY,EAAE,CAAC;IAEzB,+BAA+B;IAC/B,YAAY,EAAE,MAAM,CAAC;IAErB,0BAA0B;IAC1B,cAAc,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IAE5C,yBAAyB;IACzB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AA4CD;;GAEG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,qBAAqB,CAAC,CAkFhC;
|
|
1
|
+
{"version":3,"file":"compliance-checker.d.ts","sourceRoot":"","sources":["../../src/sops/compliance-checker.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,EAGL,aAAa,EAGb,WAAW,EAEZ,MAAM,YAAY,CAAC;AAMpB;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,6BAA6B;IAC7B,WAAW,EAAE,MAAM,CAAC;IAEpB,kDAAkD;IAClD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,8CAA8C;IAC9C,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAElB,4BAA4B;IAC5B,UAAU,CAAC,EAAE,WAAW,EAAE,CAAC;IAE3B,uCAAuC;IACvC,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB,oBAAoB;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,+BAA+B;IAC/B,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CAC7C;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,4CAA4C;IAC5C,aAAa,EAAE,MAAM,CAAC;IAEtB,yCAAyC;IACzC,QAAQ,EAAE,MAAM,CAAC;IAEjB,uBAAuB;IACvB,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,UAAU,CAAC;IAE3D,kCAAkC;IAClC,WAAW,EAAE,MAAM,CAAC;IAEpB,6BAA6B;IAC7B,UAAU,EAAE,MAAM,CAAC;IAEnB,iCAAiC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,2CAA2C;IAC3C,OAAO,EAAE,OAAO,CAAC;IAEjB,mBAAmB;IACnB,WAAW,EAAE,MAAM,CAAC;IAEpB,sBAAsB;IACtB,SAAS,EAAE,IAAI,CAAC;IAEhB,yBAAyB;IACzB,WAAW,EAAE,aAAa,EAAE,CAAC;IAE7B,qBAAqB;IACrB,QAAQ,EAAE,YAAY,EAAE,CAAC;IAEzB,+BAA+B;IAC/B,YAAY,EAAE,MAAM,CAAC;IAErB,0BAA0B;IAC1B,cAAc,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IAE5C,yBAAyB;IACzB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AA4CD;;GAEG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,qBAAqB,CAAC,CAkFhC;AAyjBD;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,EACnB,QAAQ,GAAE,MAAe,GACxB,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAQ/B;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAC1C,WAAW,EAAE,MAAM,EACnB,SAAS,GAAE,MAAW,EACtB,UAAU,CAAC,EAAE,WAAW,EAAE,GACzB,OAAO,CAAC;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAe5D"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync, statSync, readFileSync } from "fs";
|
|
1
|
+
import { existsSync, readdirSync, statSync, readFileSync } from "fs";
|
|
2
2
|
import { basename, join, extname } from "path";
|
|
3
3
|
import { ComplianceStatus, IRBStatus, SOPCategory, SOPPriority } from "./types.js";
|
|
4
4
|
import { getSOPById, getSOPsByCategory, getAllSOPs } from "./registry.js";
|
|
@@ -110,8 +110,63 @@ function scanProjectArtifacts(projectRoot, docsPath, patterns) {
|
|
|
110
110
|
artifacts.set(category, found);
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
|
+
const docsDir = join(projectRoot, docsPath);
|
|
114
|
+
if (existsSync(docsDir)) {
|
|
115
|
+
const allDocs = scanDocsRecursively(docsDir);
|
|
116
|
+
categorizeDocsByPath(allDocs, artifacts);
|
|
117
|
+
}
|
|
113
118
|
return artifacts;
|
|
114
119
|
}
|
|
120
|
+
function scanDocsRecursively(dir) {
|
|
121
|
+
const results = [];
|
|
122
|
+
try {
|
|
123
|
+
const entries = readdirSync(dir, { withFileTypes: true });
|
|
124
|
+
for (const entry of entries) {
|
|
125
|
+
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "analysis") {
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
const fullPath = join(dir, entry.name);
|
|
129
|
+
if (entry.isDirectory()) {
|
|
130
|
+
results.push(...scanDocsRecursively(fullPath));
|
|
131
|
+
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
132
|
+
results.push(fullPath);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
} catch {
|
|
136
|
+
}
|
|
137
|
+
return results;
|
|
138
|
+
}
|
|
139
|
+
function categorizeDocsByPath(docs, artifacts) {
|
|
140
|
+
const pathMappings = {
|
|
141
|
+
"requirements": ["requirements", "specs", "specification", "features"],
|
|
142
|
+
"architecture": ["architecture", "design", "system", "components"],
|
|
143
|
+
"testing": ["testing", "test", "tests", "quality", "qa"],
|
|
144
|
+
"security": ["security", "auth", "authentication", "authorization"],
|
|
145
|
+
"ethics": ["ethics", "bias", "fairness", "responsible"],
|
|
146
|
+
"monitoring": ["monitoring", "observability", "metrics", "logging"],
|
|
147
|
+
"api-docs": ["api", "endpoints", "services", "rest", "graphql"],
|
|
148
|
+
"privacy": ["privacy", "data-protection", "gdpr", "compliance"],
|
|
149
|
+
"ci-cd": ["deployment", "ci-cd", "pipeline", "devops"],
|
|
150
|
+
"documentation": ["guides", "tutorials", "docs", "standards", "references"],
|
|
151
|
+
"validation": ["validation", "schema", "contracts"],
|
|
152
|
+
"config-management": ["config", "settings", "environment"],
|
|
153
|
+
"data-management": ["data", "database", "storage", "migrations"]
|
|
154
|
+
};
|
|
155
|
+
for (const docPath of docs) {
|
|
156
|
+
const lowerPath = docPath.toLowerCase();
|
|
157
|
+
for (const [category, keywords] of Object.entries(pathMappings)) {
|
|
158
|
+
if (keywords.some((kw) => lowerPath.includes(kw))) {
|
|
159
|
+
if (!artifacts.has(category)) {
|
|
160
|
+
artifacts.set(category, []);
|
|
161
|
+
}
|
|
162
|
+
const categoryDocs = artifacts.get(category);
|
|
163
|
+
if (!categoryDocs.includes(docPath)) {
|
|
164
|
+
categoryDocs.push(docPath);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
115
170
|
async function assessSOP(sop, projectRoot, docsPath, projectArtifacts, evidenceList, deepAnalysis, assessor) {
|
|
116
171
|
const requirementsMet = [];
|
|
117
172
|
const requirementsGaps = [];
|
|
@@ -214,26 +269,39 @@ function checkRequirement(requirement, projectRoot, docsPath, projectArtifacts,
|
|
|
214
269
|
}
|
|
215
270
|
}
|
|
216
271
|
function checkDocumentEvidence(requirement, projectRoot, docsPath, projectArtifacts, deepAnalysis) {
|
|
217
|
-
const docPatterns = [
|
|
272
|
+
const docPatterns = [
|
|
273
|
+
"readme",
|
|
274
|
+
"requirements",
|
|
275
|
+
"architecture",
|
|
276
|
+
"api-docs",
|
|
277
|
+
"documentation",
|
|
278
|
+
"testing",
|
|
279
|
+
"security",
|
|
280
|
+
"monitoring",
|
|
281
|
+
"validation",
|
|
282
|
+
"config-management",
|
|
283
|
+
"data-management",
|
|
284
|
+
"privacy",
|
|
285
|
+
"ci-cd",
|
|
286
|
+
"ethics"
|
|
287
|
+
];
|
|
218
288
|
for (const pattern of docPatterns) {
|
|
219
289
|
const artifacts = projectArtifacts.get(pattern);
|
|
220
290
|
if (artifacts && artifacts.length > 0) {
|
|
221
291
|
for (const artifact of artifacts) {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
};
|
|
236
|
-
}
|
|
292
|
+
const contentMatch = checkContentForRequirement(artifact, requirement);
|
|
293
|
+
if (contentMatch) {
|
|
294
|
+
return {
|
|
295
|
+
met: true,
|
|
296
|
+
evidenceFound: {
|
|
297
|
+
requirementId: requirement.id,
|
|
298
|
+
filePath: artifact,
|
|
299
|
+
type: "document",
|
|
300
|
+
description: `Found documentation evidence in ${basename(artifact)}`,
|
|
301
|
+
confidence: deepAnalysis ? 0.9 : 0.75,
|
|
302
|
+
excerpt: contentMatch
|
|
303
|
+
}
|
|
304
|
+
};
|
|
237
305
|
}
|
|
238
306
|
}
|
|
239
307
|
}
|
|
@@ -282,29 +350,89 @@ function checkContentForRequirement(filePath, requirement) {
|
|
|
282
350
|
const content = readFileSync(filePath, "utf-8");
|
|
283
351
|
const lowerContent = content.toLowerCase();
|
|
284
352
|
const lowerDesc = requirement.description.toLowerCase();
|
|
285
|
-
const keywords = lowerDesc.split(/\s+/).filter((w) => w.length >
|
|
353
|
+
const keywords = lowerDesc.split(/\s+/).filter((w) => w.length > 3);
|
|
286
354
|
let matchCount = 0;
|
|
287
355
|
let matchedLine = "";
|
|
288
356
|
for (const keyword of keywords) {
|
|
289
357
|
if (lowerContent.includes(keyword)) {
|
|
290
358
|
matchCount++;
|
|
359
|
+
if (!matchedLine) {
|
|
360
|
+
const lines = content.split("\n");
|
|
361
|
+
for (const line of lines) {
|
|
362
|
+
if (line.toLowerCase().includes(keyword) && line.length < 200 && line.trim().length > 10) {
|
|
363
|
+
matchedLine = line.trim();
|
|
364
|
+
break;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
if (matchCount >= keywords.length * 0.2 && matchedLine) {
|
|
371
|
+
return matchedLine;
|
|
372
|
+
}
|
|
373
|
+
const evidenceKeywords = requirement.evidence || [];
|
|
374
|
+
for (const evidenceKey of evidenceKeywords) {
|
|
375
|
+
const evidenceLower = evidenceKey.toLowerCase();
|
|
376
|
+
if (lowerContent.includes(evidenceLower)) {
|
|
291
377
|
const lines = content.split("\n");
|
|
292
378
|
for (const line of lines) {
|
|
293
|
-
if (line.toLowerCase().includes(
|
|
294
|
-
|
|
295
|
-
break;
|
|
379
|
+
if (line.toLowerCase().includes(evidenceLower) && line.length < 200 && line.trim().length > 10) {
|
|
380
|
+
return line.trim();
|
|
296
381
|
}
|
|
297
382
|
}
|
|
298
383
|
}
|
|
299
384
|
}
|
|
300
|
-
|
|
301
|
-
|
|
385
|
+
const complianceTerms = getComplianceTermsForRequirement(requirement);
|
|
386
|
+
for (const term of complianceTerms) {
|
|
387
|
+
if (lowerContent.includes(term.toLowerCase())) {
|
|
388
|
+
const lines = content.split("\n");
|
|
389
|
+
for (const line of lines) {
|
|
390
|
+
if (line.toLowerCase().includes(term.toLowerCase()) && line.length < 200 && line.trim().length > 10) {
|
|
391
|
+
return line.trim();
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}
|
|
302
395
|
}
|
|
303
396
|
return null;
|
|
304
397
|
} catch {
|
|
305
398
|
return null;
|
|
306
399
|
}
|
|
307
400
|
}
|
|
401
|
+
function getComplianceTermsForRequirement(requirement) {
|
|
402
|
+
const reqId = requirement.id.toLowerCase();
|
|
403
|
+
const terms = [];
|
|
404
|
+
if (reqId.includes("req") || reqId.includes("spec")) {
|
|
405
|
+
terms.push("requirement", "specification", "functional", "non-functional", "acceptance criteria");
|
|
406
|
+
}
|
|
407
|
+
if (reqId.includes("test")) {
|
|
408
|
+
terms.push("test", "testing", "coverage", "unit test", "integration", "validation");
|
|
409
|
+
}
|
|
410
|
+
if (reqId.includes("arch") || reqId.includes("design")) {
|
|
411
|
+
terms.push("architecture", "design", "component", "system", "integration");
|
|
412
|
+
}
|
|
413
|
+
if (reqId.includes("sec")) {
|
|
414
|
+
terms.push("security", "authentication", "authorization", "encryption", "vulnerability");
|
|
415
|
+
}
|
|
416
|
+
if (reqId.includes("doc")) {
|
|
417
|
+
terms.push("documentation", "guide", "reference", "manual", "tutorial");
|
|
418
|
+
}
|
|
419
|
+
if (reqId.includes("deploy") || reqId.includes("ci")) {
|
|
420
|
+
terms.push("deployment", "pipeline", "continuous", "automation", "release");
|
|
421
|
+
}
|
|
422
|
+
if (reqId.includes("monitor") || reqId.includes("observe")) {
|
|
423
|
+
terms.push("monitoring", "metrics", "alerting", "logging", "observability");
|
|
424
|
+
}
|
|
425
|
+
if (reqId.includes("data") || reqId.includes("privacy")) {
|
|
426
|
+
terms.push("data", "privacy", "protection", "governance", "retention");
|
|
427
|
+
}
|
|
428
|
+
if (reqId.includes("risk")) {
|
|
429
|
+
terms.push("risk", "mitigation", "assessment", "impact", "likelihood");
|
|
430
|
+
}
|
|
431
|
+
if (reqId.includes("quality") || reqId.includes("qa")) {
|
|
432
|
+
terms.push("quality", "assurance", "standard", "review", "inspection");
|
|
433
|
+
}
|
|
434
|
+
return terms;
|
|
435
|
+
}
|
|
308
436
|
function categorizeArtifact(filePath) {
|
|
309
437
|
const ext = extname(filePath).toLowerCase();
|
|
310
438
|
const name = basename(filePath).toLowerCase();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compliance-checker.js","sources":["../../src/sops/compliance-checker.ts"],"sourcesContent":["/**\n * SOP Compliance Checker\n *\n * Checks project artifacts against AI-SDLC SOP requirements\n * and determines compliance status.\n *\n * @module sops/compliance-checker\n */\n\nimport { existsSync, readdirSync, readFileSync, statSync } from 'fs';\nimport { join, basename, extname } from 'path';\nimport {\n SOPDefinition,\n SOPRequirement,\n SOPAssessment,\n ComplianceStatus,\n IRBStatus,\n SOPCategory,\n SOPPriority,\n} from './types.js';\nimport { getSOPById, getSOPsByCategory, getAllSOPs } from './registry.js';\nimport { createLogger } from '../utils/logger.js';\n\nconst logger = createLogger('compliance-checker');\n\n/**\n * Compliance check options\n */\nexport interface ComplianceCheckOptions {\n /** Project root directory */\n projectRoot: string;\n\n /** Documentation path relative to project root */\n docsPath?: string;\n\n /** SOPs to check (default: all applicable) */\n sopIds?: string[];\n\n /** Categories to include */\n categories?: SOPCategory[];\n\n /** Whether to perform deep analysis */\n deepAnalysis?: boolean;\n\n /** Assessor name */\n assessor?: string;\n\n /** Custom artifact patterns */\n artifactPatterns?: Record<string, string[]>;\n}\n\n/**\n * Evidence item found during checking\n */\nexport interface EvidenceItem {\n /** Requirement ID this evidence supports */\n requirementId: string;\n\n /** File path where evidence was found */\n filePath: string;\n\n /** Type of evidence */\n type: 'document' | 'code' | 'test' | 'config' | 'artifact';\n\n /** Description of the evidence */\n description: string;\n\n /** Confidence score (0-1) */\n confidence: number;\n\n /** Relevant excerpt from file */\n excerpt?: string;\n}\n\n/**\n * Result of a compliance check\n */\nexport interface ComplianceCheckResult {\n /** Whether check completed successfully */\n success: boolean;\n\n /** Project name */\n projectName: string;\n\n /** Check timestamp */\n checkedAt: Date;\n\n /** Assessments by SOP */\n assessments: SOPAssessment[];\n\n /** Evidence found */\n evidence: EvidenceItem[];\n\n /** Overall compliance score */\n overallScore: number;\n\n /** Summary by category */\n categoryScores: Record<SOPCategory, number>;\n\n /** Errors encountered */\n errors: string[];\n}\n\n/**\n * Default artifact patterns for detecting compliance evidence\n */\nconst DEFAULT_ARTIFACT_PATTERNS: Record<string, string[]> = {\n // Documentation artifacts\n 'requirements': ['requirements.md', 'requirements.txt', 'REQUIREMENTS.md', 'specs/', 'requirements/'],\n 'architecture': ['ARCHITECTURE.md', 'architecture/', 'design/', 'ADR-*.md', 'adr/'],\n 'testing': ['tests/', '__tests__/', 'test/', '*.test.ts', '*.spec.ts', 'jest.config.*', 'vitest.config.*'],\n 'security': ['SECURITY.md', 'security/', '.snyk', 'security-policy.md'],\n 'ethics': ['ETHICS.md', 'ethics/', 'AI-ETHICS.md', 'bias-assessment.md'],\n 'changelog': ['CHANGELOG.md', 'HISTORY.md', 'releases/'],\n 'readme': ['README.md', 'README.txt', 'readme.md'],\n 'license': ['LICENSE', 'LICENSE.md', 'LICENSE.txt'],\n 'contributing': ['CONTRIBUTING.md', 'CONTRIBUTORS.md'],\n 'code-of-conduct': ['CODE_OF_CONDUCT.md'],\n 'ci-cd': ['.github/workflows/', '.gitlab-ci.yml', 'Jenkinsfile', '.circleci/'],\n 'docker': ['Dockerfile', 'docker-compose.yml', '.dockerignore'],\n 'monitoring': ['monitoring/', 'observability/', 'metrics/', 'prometheus.yml'],\n 'validation': ['validation/', 'schemas/', '*.schema.json', 'zod/', 'yup/'],\n 'config-management': ['.env.example', 'config/', 'settings/', '*.config.js', '*.config.ts'],\n 'data-management': ['data/', 'datasets/', 'migrations/', 'seeds/'],\n 'model-cards': ['MODEL_CARD.md', 'model-card.md', 'model-cards/'],\n 'api-docs': ['openapi.yaml', 'swagger.json', 'api/', 'API.md'],\n 'privacy': ['PRIVACY.md', 'privacy-policy.md', 'data-protection.md'],\n};\n\n/**\n * Keyword patterns for detecting compliance in content\n */\nconst COMPLIANCE_KEYWORDS: Record<string, string[]> = {\n 'requirements-definition': ['requirement', 'specification', 'user story', 'acceptance criteria', 'functional', 'non-functional'],\n 'risk-assessment': ['risk', 'mitigation', 'threat', 'vulnerability', 'impact', 'likelihood'],\n 'testing': ['test', 'coverage', 'unit test', 'integration test', 'e2e', 'regression'],\n 'security': ['authentication', 'authorization', 'encryption', 'secure', 'vulnerability', 'audit'],\n 'ethics': ['bias', 'fairness', 'ethical', 'responsible', 'transparency', 'accountability'],\n 'monitoring': ['monitor', 'alert', 'metric', 'observability', 'logging', 'tracing'],\n 'documentation': ['document', 'guide', 'manual', 'tutorial', 'reference'],\n 'validation': ['validate', 'verify', 'check', 'assert', 'schema', 'constraint'],\n 'privacy': ['privacy', 'gdpr', 'pii', 'data protection', 'consent', 'anonymization'],\n 'governance': ['governance', 'policy', 'procedure', 'standard', 'compliance', 'audit'],\n};\n\n/**\n * Check compliance for a project against AI-SDLC SOPs\n */\nexport async function checkCompliance(\n options: ComplianceCheckOptions\n): Promise<ComplianceCheckResult> {\n const {\n projectRoot,\n docsPath = 'docs',\n sopIds,\n categories,\n deepAnalysis = false,\n assessor = 'automated',\n artifactPatterns = DEFAULT_ARTIFACT_PATTERNS,\n } = options;\n\n logger.info('Starting compliance check', { projectRoot, docsPath });\n\n const result: ComplianceCheckResult = {\n success: true,\n projectName: basename(projectRoot),\n checkedAt: new Date(),\n assessments: [],\n evidence: [],\n overallScore: 0,\n categoryScores: {} as Record<SOPCategory, number>,\n errors: [],\n };\n\n try {\n // Determine which SOPs to check\n let sopsToCheck: SOPDefinition[] = [];\n\n if (sopIds && sopIds.length > 0) {\n // Check specific SOPs\n for (const id of sopIds) {\n const sop = getSOPById(id);\n if (sop) {\n sopsToCheck.push(sop);\n } else {\n result.errors.push(`SOP not found: ${id}`);\n }\n }\n } else if (categories && categories.length > 0) {\n // Check SOPs in specified categories\n for (const category of categories) {\n sopsToCheck.push(...getSOPsByCategory(category));\n }\n } else {\n // Check all SOPs\n sopsToCheck = getAllSOPs();\n }\n\n // Scan project for artifacts\n const projectArtifacts = scanProjectArtifacts(projectRoot, docsPath, artifactPatterns);\n logger.debug('Found project artifacts', { count: projectArtifacts.size });\n\n // Check each SOP\n for (const sop of sopsToCheck) {\n const assessment = await assessSOP(\n sop,\n projectRoot,\n docsPath,\n projectArtifacts,\n result.evidence,\n deepAnalysis,\n assessor\n );\n result.assessments.push(assessment);\n }\n\n // Calculate scores\n calculateScores(result);\n\n logger.info('Compliance check complete', {\n overallScore: result.overallScore,\n assessments: result.assessments.length,\n evidence: result.evidence.length,\n });\n\n } catch (error) {\n result.success = false;\n result.errors.push(String(error));\n logger.error(`Compliance check failed: ${String(error)}`);\n }\n\n return result;\n}\n\n/**\n * Scan project for artifacts that may indicate compliance\n */\nfunction scanProjectArtifacts(\n projectRoot: string,\n docsPath: string,\n patterns: Record<string, string[]>\n): Map<string, string[]> {\n const artifacts = new Map<string, string[]>();\n\n for (const [category, filePatterns] of Object.entries(patterns)) {\n const found: string[] = [];\n\n for (const pattern of filePatterns) {\n // Check in project root\n const rootPath = join(projectRoot, pattern);\n if (existsSync(rootPath)) {\n found.push(rootPath);\n }\n\n // Check in docs path\n const docsFullPath = join(projectRoot, docsPath, pattern);\n if (existsSync(docsFullPath)) {\n found.push(docsFullPath);\n }\n }\n\n if (found.length > 0) {\n artifacts.set(category, found);\n }\n }\n\n return artifacts;\n}\n\n/**\n * Assess a single SOP against project\n */\nasync function assessSOP(\n sop: SOPDefinition,\n projectRoot: string,\n docsPath: string,\n projectArtifacts: Map<string, string[]>,\n evidenceList: EvidenceItem[],\n deepAnalysis: boolean,\n assessor: string\n): Promise<SOPAssessment> {\n const requirementsMet: string[] = [];\n const requirementsGaps: string[] = [];\n const evidence: Record<string, string> = {};\n\n // Check each requirement\n for (const requirement of sop.requirements) {\n const { met, evidenceFound } = checkRequirement(\n requirement,\n projectRoot,\n docsPath,\n projectArtifacts,\n deepAnalysis\n );\n\n if (met) {\n requirementsMet.push(requirement.id);\n if (evidenceFound) {\n evidence[requirement.id] = evidenceFound.filePath;\n evidenceList.push(evidenceFound);\n }\n } else {\n requirementsGaps.push(requirement.id);\n }\n }\n\n // Calculate score\n const totalRequirements = sop.requirements.length;\n const mandatoryRequirements = sop.requirements.filter(r => r.mandatory);\n const mandatoryMet = mandatoryRequirements.filter(r => requirementsMet.includes(r.id));\n\n let score = 0;\n if (totalRequirements > 0) {\n // Weight mandatory requirements more heavily\n const mandatoryWeight = 0.7;\n const optionalWeight = 0.3;\n\n const mandatoryScore = mandatoryRequirements.length > 0\n ? (mandatoryMet.length / mandatoryRequirements.length) * 100\n : 100;\n\n const optionalRequirements = sop.requirements.filter(r => !r.mandatory);\n const optionalMet = optionalRequirements.filter(r => requirementsMet.includes(r.id));\n const optionalScore = optionalRequirements.length > 0\n ? (optionalMet.length / optionalRequirements.length) * 100\n : 100;\n\n score = Math.round(mandatoryScore * mandatoryWeight + optionalScore * optionalWeight);\n }\n\n // Determine status\n let status: ComplianceStatus;\n if (score >= 90) {\n status = ComplianceStatus.COMPLIANT;\n } else if (score >= 50) {\n status = ComplianceStatus.PARTIAL;\n } else if (score > 0) {\n status = ComplianceStatus.NON_COMPLIANT;\n } else {\n status = ComplianceStatus.PENDING;\n }\n\n // Determine IRB status\n let irbStatus: IRBStatus = IRBStatus.NOT_REQUIRED;\n if (sop.irbTypicallyRequired) {\n irbStatus = IRBStatus.PENDING;\n // Check for IRB approval artifacts\n const irbArtifacts = projectArtifacts.get('ethics') || [];\n if (irbArtifacts.length > 0) {\n irbStatus = IRBStatus.IN_REVIEW;\n }\n }\n\n return {\n sopId: sop.id,\n status,\n score,\n requirementsMet,\n requirementsGaps,\n evidence,\n irbStatus,\n assessedAt: new Date(),\n assessedBy: assessor,\n notes: `Automated assessment: ${requirementsMet.length}/${totalRequirements} requirements met`,\n };\n}\n\n/**\n * Check if a specific requirement is met\n */\nfunction checkRequirement(\n requirement: SOPRequirement,\n projectRoot: string,\n docsPath: string,\n projectArtifacts: Map<string, string[]>,\n deepAnalysis: boolean\n): { met: boolean; evidenceFound?: EvidenceItem } {\n // Check for artifacts that match the requirement\n for (const artifactType of requirement.artifacts || []) {\n const artifacts = projectArtifacts.get(artifactType);\n if (artifacts && artifacts.length > 0) {\n // Found matching artifact\n const evidenceItem: EvidenceItem = {\n requirementId: requirement.id,\n filePath: artifacts[0],\n type: categorizeArtifact(artifacts[0]),\n description: `Found ${artifactType} artifact: ${basename(artifacts[0])}`,\n confidence: 0.8,\n };\n\n // Deep analysis: check content for keywords\n if (deepAnalysis) {\n const contentMatch = checkContentForRequirement(artifacts[0], requirement);\n if (contentMatch) {\n evidenceItem.confidence = 0.95;\n evidenceItem.excerpt = contentMatch;\n }\n }\n\n return { met: true, evidenceFound: evidenceItem };\n }\n }\n\n // Check based on verification method\n switch (requirement.verification) {\n case 'document':\n return checkDocumentEvidence(requirement, projectRoot, docsPath, projectArtifacts, deepAnalysis);\n case 'test':\n return checkTestEvidence(requirement, projectRoot, projectArtifacts);\n case 'automated':\n return checkAutomatedEvidence(requirement, projectRoot, projectArtifacts);\n case 'review':\n case 'audit':\n // These require manual verification\n return { met: false };\n default:\n return { met: false };\n }\n}\n\n/**\n * Check for document-based evidence\n */\nfunction checkDocumentEvidence(\n requirement: SOPRequirement,\n projectRoot: string,\n docsPath: string,\n projectArtifacts: Map<string, string[]>,\n deepAnalysis: boolean\n): { met: boolean; evidenceFound?: EvidenceItem } {\n // Look for documentation files\n const docPatterns = ['readme', 'requirements', 'architecture', 'api-docs'];\n\n for (const pattern of docPatterns) {\n const artifacts = projectArtifacts.get(pattern);\n if (artifacts && artifacts.length > 0) {\n for (const artifact of artifacts) {\n if (deepAnalysis) {\n const contentMatch = checkContentForRequirement(artifact, requirement);\n if (contentMatch) {\n return {\n met: true,\n evidenceFound: {\n requirementId: requirement.id,\n filePath: artifact,\n type: 'document',\n description: `Found documentation evidence in ${basename(artifact)}`,\n confidence: 0.85,\n excerpt: contentMatch,\n },\n };\n }\n }\n }\n }\n }\n\n return { met: false };\n}\n\n/**\n * Check for test-based evidence\n */\nfunction checkTestEvidence(\n requirement: SOPRequirement,\n projectRoot: string,\n projectArtifacts: Map<string, string[]>\n): { met: boolean; evidenceFound?: EvidenceItem } {\n const testArtifacts = projectArtifacts.get('testing');\n\n if (testArtifacts && testArtifacts.length > 0) {\n return {\n met: true,\n evidenceFound: {\n requirementId: requirement.id,\n filePath: testArtifacts[0],\n type: 'test',\n description: `Test infrastructure found: ${basename(testArtifacts[0])}`,\n confidence: 0.7,\n },\n };\n }\n\n return { met: false };\n}\n\n/**\n * Check for automated/CI evidence\n */\nfunction checkAutomatedEvidence(\n requirement: SOPRequirement,\n projectRoot: string,\n projectArtifacts: Map<string, string[]>\n): { met: boolean; evidenceFound?: EvidenceItem } {\n const ciArtifacts = projectArtifacts.get('ci-cd');\n\n if (ciArtifacts && ciArtifacts.length > 0) {\n return {\n met: true,\n evidenceFound: {\n requirementId: requirement.id,\n filePath: ciArtifacts[0],\n type: 'config',\n description: `CI/CD configuration found: ${basename(ciArtifacts[0])}`,\n confidence: 0.75,\n },\n };\n }\n\n return { met: false };\n}\n\n/**\n * Check file content for requirement keywords\n */\nfunction checkContentForRequirement(\n filePath: string,\n requirement: SOPRequirement\n): string | null {\n try {\n const stat = statSync(filePath);\n if (stat.isDirectory()) return null;\n\n // Only check text files\n const ext = extname(filePath).toLowerCase();\n const textExtensions = ['.md', '.txt', '.ts', '.js', '.json', '.yaml', '.yml', '.html', '.rst'];\n if (!textExtensions.includes(ext)) return null;\n\n const content = readFileSync(filePath, 'utf-8');\n const lowerContent = content.toLowerCase();\n const lowerDesc = requirement.description.toLowerCase();\n\n // Check for keywords from requirement description\n const keywords = lowerDesc.split(/\\s+/).filter(w => w.length > 4);\n let matchCount = 0;\n let matchedLine = '';\n\n for (const keyword of keywords) {\n if (lowerContent.includes(keyword)) {\n matchCount++;\n // Find the line containing this keyword\n const lines = content.split('\\n');\n for (const line of lines) {\n if (line.toLowerCase().includes(keyword) && line.length < 200) {\n matchedLine = line.trim();\n break;\n }\n }\n }\n }\n\n // If at least 30% of keywords match, consider it evidence\n if (matchCount >= keywords.length * 0.3 && matchedLine) {\n return matchedLine;\n }\n\n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * Categorize an artifact by its type\n */\nfunction categorizeArtifact(filePath: string): 'document' | 'code' | 'test' | 'config' | 'artifact' {\n const ext = extname(filePath).toLowerCase();\n const name = basename(filePath).toLowerCase();\n\n if (['.md', '.txt', '.rst', '.html'].includes(ext)) {\n return 'document';\n }\n if (['.ts', '.js', '.py', '.java', '.go', '.rs'].includes(ext)) {\n if (name.includes('test') || name.includes('spec')) {\n return 'test';\n }\n return 'code';\n }\n if (['.json', '.yaml', '.yml', '.toml', '.ini'].includes(ext)) {\n return 'config';\n }\n return 'artifact';\n}\n\n/**\n * Calculate overall scores from assessments\n */\nfunction calculateScores(result: ComplianceCheckResult): void {\n if (result.assessments.length === 0) {\n result.overallScore = 0;\n return;\n }\n\n // Calculate category scores\n const categoryTotals: Record<SOPCategory, { sum: number; count: number }> = {\n [SOPCategory.PROGRAM_MANAGEMENT]: { sum: 0, count: 0 },\n [SOPCategory.OPERATIONS]: { sum: 0, count: 0 },\n [SOPCategory.DEVELOPMENT]: { sum: 0, count: 0 },\n [SOPCategory.GOVERNANCE]: { sum: 0, count: 0 },\n [SOPCategory.QUALITY]: { sum: 0, count: 0 },\n };\n\n for (const assessment of result.assessments) {\n const sop = getSOPById(assessment.sopId);\n if (sop) {\n categoryTotals[sop.category].sum += assessment.score;\n categoryTotals[sop.category].count += 1;\n }\n }\n\n // Calculate category averages\n for (const category of Object.values(SOPCategory)) {\n const totals = categoryTotals[category];\n result.categoryScores[category] = totals.count > 0\n ? Math.round(totals.sum / totals.count)\n : 0;\n }\n\n // Calculate overall score (weighted by priority)\n let weightedSum = 0;\n let totalWeight = 0;\n\n for (const assessment of result.assessments) {\n const sop = getSOPById(assessment.sopId);\n if (sop) {\n const weight = getPriorityWeight(sop.priority);\n weightedSum += assessment.score * weight;\n totalWeight += weight;\n }\n }\n\n result.overallScore = totalWeight > 0\n ? Math.round(weightedSum / totalWeight)\n : 0;\n}\n\n/**\n * Get weight for priority level\n */\nfunction getPriorityWeight(priority: SOPPriority): number {\n switch (priority) {\n case SOPPriority.CRITICAL:\n return 4;\n case SOPPriority.HIGH:\n return 3;\n case SOPPriority.MEDIUM:\n return 2;\n case SOPPriority.LOW:\n return 1;\n default:\n return 1;\n }\n}\n\n/**\n * Quick check for a specific SOP\n */\nexport async function checkSOPCompliance(\n sopId: string,\n projectRoot: string,\n docsPath: string = 'docs'\n): Promise<SOPAssessment | null> {\n const result = await checkCompliance({\n projectRoot,\n docsPath,\n sopIds: [sopId],\n });\n\n return result.assessments[0] || null;\n}\n\n/**\n * Check if project meets minimum compliance threshold\n */\nexport async function meetsMinimumCompliance(\n projectRoot: string,\n threshold: number = 50,\n categories?: SOPCategory[]\n): Promise<{ meets: boolean; score: number; gaps: string[] }> {\n const result = await checkCompliance({\n projectRoot,\n categories,\n });\n\n const gaps = result.assessments\n .filter(a => a.score < threshold)\n .map(a => a.sopId);\n\n return {\n meets: result.overallScore >= threshold,\n score: result.overallScore,\n gaps,\n };\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"compliance-checker.js","sources":["../../src/sops/compliance-checker.ts"],"sourcesContent":["/**\n * SOP Compliance Checker\n *\n * Checks project artifacts against AI-SDLC SOP requirements\n * and determines compliance status.\n *\n * @module sops/compliance-checker\n */\n\nimport { existsSync, readdirSync, readFileSync, statSync } from 'fs';\nimport { join, basename, extname } from 'path';\nimport {\n SOPDefinition,\n SOPRequirement,\n SOPAssessment,\n ComplianceStatus,\n IRBStatus,\n SOPCategory,\n SOPPriority,\n} from './types.js';\nimport { getSOPById, getSOPsByCategory, getAllSOPs } from './registry.js';\nimport { createLogger } from '../utils/logger.js';\n\nconst logger = createLogger('compliance-checker');\n\n/**\n * Compliance check options\n */\nexport interface ComplianceCheckOptions {\n /** Project root directory */\n projectRoot: string;\n\n /** Documentation path relative to project root */\n docsPath?: string;\n\n /** SOPs to check (default: all applicable) */\n sopIds?: string[];\n\n /** Categories to include */\n categories?: SOPCategory[];\n\n /** Whether to perform deep analysis */\n deepAnalysis?: boolean;\n\n /** Assessor name */\n assessor?: string;\n\n /** Custom artifact patterns */\n artifactPatterns?: Record<string, string[]>;\n}\n\n/**\n * Evidence item found during checking\n */\nexport interface EvidenceItem {\n /** Requirement ID this evidence supports */\n requirementId: string;\n\n /** File path where evidence was found */\n filePath: string;\n\n /** Type of evidence */\n type: 'document' | 'code' | 'test' | 'config' | 'artifact';\n\n /** Description of the evidence */\n description: string;\n\n /** Confidence score (0-1) */\n confidence: number;\n\n /** Relevant excerpt from file */\n excerpt?: string;\n}\n\n/**\n * Result of a compliance check\n */\nexport interface ComplianceCheckResult {\n /** Whether check completed successfully */\n success: boolean;\n\n /** Project name */\n projectName: string;\n\n /** Check timestamp */\n checkedAt: Date;\n\n /** Assessments by SOP */\n assessments: SOPAssessment[];\n\n /** Evidence found */\n evidence: EvidenceItem[];\n\n /** Overall compliance score */\n overallScore: number;\n\n /** Summary by category */\n categoryScores: Record<SOPCategory, number>;\n\n /** Errors encountered */\n errors: string[];\n}\n\n/**\n * Default artifact patterns for detecting compliance evidence\n */\nconst DEFAULT_ARTIFACT_PATTERNS: Record<string, string[]> = {\n // Documentation artifacts\n 'requirements': ['requirements.md', 'requirements.txt', 'REQUIREMENTS.md', 'specs/', 'requirements/'],\n 'architecture': ['ARCHITECTURE.md', 'architecture/', 'design/', 'ADR-*.md', 'adr/'],\n 'testing': ['tests/', '__tests__/', 'test/', '*.test.ts', '*.spec.ts', 'jest.config.*', 'vitest.config.*'],\n 'security': ['SECURITY.md', 'security/', '.snyk', 'security-policy.md'],\n 'ethics': ['ETHICS.md', 'ethics/', 'AI-ETHICS.md', 'bias-assessment.md'],\n 'changelog': ['CHANGELOG.md', 'HISTORY.md', 'releases/'],\n 'readme': ['README.md', 'README.txt', 'readme.md'],\n 'license': ['LICENSE', 'LICENSE.md', 'LICENSE.txt'],\n 'contributing': ['CONTRIBUTING.md', 'CONTRIBUTORS.md'],\n 'code-of-conduct': ['CODE_OF_CONDUCT.md'],\n 'ci-cd': ['.github/workflows/', '.gitlab-ci.yml', 'Jenkinsfile', '.circleci/'],\n 'docker': ['Dockerfile', 'docker-compose.yml', '.dockerignore'],\n 'monitoring': ['monitoring/', 'observability/', 'metrics/', 'prometheus.yml'],\n 'validation': ['validation/', 'schemas/', '*.schema.json', 'zod/', 'yup/'],\n 'config-management': ['.env.example', 'config/', 'settings/', '*.config.js', '*.config.ts'],\n 'data-management': ['data/', 'datasets/', 'migrations/', 'seeds/'],\n 'model-cards': ['MODEL_CARD.md', 'model-card.md', 'model-cards/'],\n 'api-docs': ['openapi.yaml', 'swagger.json', 'api/', 'API.md'],\n 'privacy': ['PRIVACY.md', 'privacy-policy.md', 'data-protection.md'],\n};\n\n/**\n * Keyword patterns for detecting compliance in content\n */\nconst COMPLIANCE_KEYWORDS: Record<string, string[]> = {\n 'requirements-definition': ['requirement', 'specification', 'user story', 'acceptance criteria', 'functional', 'non-functional'],\n 'risk-assessment': ['risk', 'mitigation', 'threat', 'vulnerability', 'impact', 'likelihood'],\n 'testing': ['test', 'coverage', 'unit test', 'integration test', 'e2e', 'regression'],\n 'security': ['authentication', 'authorization', 'encryption', 'secure', 'vulnerability', 'audit'],\n 'ethics': ['bias', 'fairness', 'ethical', 'responsible', 'transparency', 'accountability'],\n 'monitoring': ['monitor', 'alert', 'metric', 'observability', 'logging', 'tracing'],\n 'documentation': ['document', 'guide', 'manual', 'tutorial', 'reference'],\n 'validation': ['validate', 'verify', 'check', 'assert', 'schema', 'constraint'],\n 'privacy': ['privacy', 'gdpr', 'pii', 'data protection', 'consent', 'anonymization'],\n 'governance': ['governance', 'policy', 'procedure', 'standard', 'compliance', 'audit'],\n};\n\n/**\n * Check compliance for a project against AI-SDLC SOPs\n */\nexport async function checkCompliance(\n options: ComplianceCheckOptions\n): Promise<ComplianceCheckResult> {\n const {\n projectRoot,\n docsPath = 'docs',\n sopIds,\n categories,\n deepAnalysis = false,\n assessor = 'automated',\n artifactPatterns = DEFAULT_ARTIFACT_PATTERNS,\n } = options;\n\n logger.info('Starting compliance check', { projectRoot, docsPath });\n\n const result: ComplianceCheckResult = {\n success: true,\n projectName: basename(projectRoot),\n checkedAt: new Date(),\n assessments: [],\n evidence: [],\n overallScore: 0,\n categoryScores: {} as Record<SOPCategory, number>,\n errors: [],\n };\n\n try {\n // Determine which SOPs to check\n let sopsToCheck: SOPDefinition[] = [];\n\n if (sopIds && sopIds.length > 0) {\n // Check specific SOPs\n for (const id of sopIds) {\n const sop = getSOPById(id);\n if (sop) {\n sopsToCheck.push(sop);\n } else {\n result.errors.push(`SOP not found: ${id}`);\n }\n }\n } else if (categories && categories.length > 0) {\n // Check SOPs in specified categories\n for (const category of categories) {\n sopsToCheck.push(...getSOPsByCategory(category));\n }\n } else {\n // Check all SOPs\n sopsToCheck = getAllSOPs();\n }\n\n // Scan project for artifacts\n const projectArtifacts = scanProjectArtifacts(projectRoot, docsPath, artifactPatterns);\n logger.debug('Found project artifacts', { count: projectArtifacts.size });\n\n // Check each SOP\n for (const sop of sopsToCheck) {\n const assessment = await assessSOP(\n sop,\n projectRoot,\n docsPath,\n projectArtifacts,\n result.evidence,\n deepAnalysis,\n assessor\n );\n result.assessments.push(assessment);\n }\n\n // Calculate scores\n calculateScores(result);\n\n logger.info('Compliance check complete', {\n overallScore: result.overallScore,\n assessments: result.assessments.length,\n evidence: result.evidence.length,\n });\n\n } catch (error) {\n result.success = false;\n result.errors.push(String(error));\n logger.error(`Compliance check failed: ${String(error)}`);\n }\n\n return result;\n}\n\n/**\n * Scan project for artifacts that may indicate compliance\n */\nfunction scanProjectArtifacts(\n projectRoot: string,\n docsPath: string,\n patterns: Record<string, string[]>\n): Map<string, string[]> {\n const artifacts = new Map<string, string[]>();\n\n for (const [category, filePatterns] of Object.entries(patterns)) {\n const found: string[] = [];\n\n for (const pattern of filePatterns) {\n // Check in project root\n const rootPath = join(projectRoot, pattern);\n if (existsSync(rootPath)) {\n found.push(rootPath);\n }\n\n // Check in docs path\n const docsFullPath = join(projectRoot, docsPath, pattern);\n if (existsSync(docsFullPath)) {\n found.push(docsFullPath);\n }\n }\n\n if (found.length > 0) {\n artifacts.set(category, found);\n }\n }\n\n // Additionally, scan all markdown files in docs recursively\n // and categorize them based on path and content\n const docsDir = join(projectRoot, docsPath);\n if (existsSync(docsDir)) {\n const allDocs = scanDocsRecursively(docsDir);\n categorizeDocsByPath(allDocs, artifacts);\n }\n\n return artifacts;\n}\n\n/**\n * Recursively scan all markdown files in a directory\n */\nfunction scanDocsRecursively(dir: string): string[] {\n const results: string[] = [];\n\n try {\n const entries = readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.name.startsWith('.') || entry.name === 'node_modules' || entry.name === 'analysis') {\n continue;\n }\n\n const fullPath = join(dir, entry.name);\n if (entry.isDirectory()) {\n results.push(...scanDocsRecursively(fullPath));\n } else if (entry.isFile() && entry.name.endsWith('.md')) {\n results.push(fullPath);\n }\n }\n } catch {\n // Ignore errors\n }\n\n return results;\n}\n\n/**\n * Categorize documents by their path structure\n */\nfunction categorizeDocsByPath(docs: string[], artifacts: Map<string, string[]>): void {\n const pathMappings: Record<string, string[]> = {\n 'requirements': ['requirements', 'specs', 'specification', 'features'],\n 'architecture': ['architecture', 'design', 'system', 'components'],\n 'testing': ['testing', 'test', 'tests', 'quality', 'qa'],\n 'security': ['security', 'auth', 'authentication', 'authorization'],\n 'ethics': ['ethics', 'bias', 'fairness', 'responsible'],\n 'monitoring': ['monitoring', 'observability', 'metrics', 'logging'],\n 'api-docs': ['api', 'endpoints', 'services', 'rest', 'graphql'],\n 'privacy': ['privacy', 'data-protection', 'gdpr', 'compliance'],\n 'ci-cd': ['deployment', 'ci-cd', 'pipeline', 'devops'],\n 'documentation': ['guides', 'tutorials', 'docs', 'standards', 'references'],\n 'validation': ['validation', 'schema', 'contracts'],\n 'config-management': ['config', 'settings', 'environment'],\n 'data-management': ['data', 'database', 'storage', 'migrations'],\n };\n\n for (const docPath of docs) {\n const lowerPath = docPath.toLowerCase();\n\n for (const [category, keywords] of Object.entries(pathMappings)) {\n if (keywords.some(kw => lowerPath.includes(kw))) {\n if (!artifacts.has(category)) {\n artifacts.set(category, []);\n }\n const categoryDocs = artifacts.get(category)!;\n if (!categoryDocs.includes(docPath)) {\n categoryDocs.push(docPath);\n }\n }\n }\n }\n}\n\n/**\n * Assess a single SOP against project\n */\nasync function assessSOP(\n sop: SOPDefinition,\n projectRoot: string,\n docsPath: string,\n projectArtifacts: Map<string, string[]>,\n evidenceList: EvidenceItem[],\n deepAnalysis: boolean,\n assessor: string\n): Promise<SOPAssessment> {\n const requirementsMet: string[] = [];\n const requirementsGaps: string[] = [];\n const evidence: Record<string, string> = {};\n\n // Check each requirement\n for (const requirement of sop.requirements) {\n const { met, evidenceFound } = checkRequirement(\n requirement,\n projectRoot,\n docsPath,\n projectArtifacts,\n deepAnalysis\n );\n\n if (met) {\n requirementsMet.push(requirement.id);\n if (evidenceFound) {\n evidence[requirement.id] = evidenceFound.filePath;\n evidenceList.push(evidenceFound);\n }\n } else {\n requirementsGaps.push(requirement.id);\n }\n }\n\n // Calculate score\n const totalRequirements = sop.requirements.length;\n const mandatoryRequirements = sop.requirements.filter(r => r.mandatory);\n const mandatoryMet = mandatoryRequirements.filter(r => requirementsMet.includes(r.id));\n\n let score = 0;\n if (totalRequirements > 0) {\n // Weight mandatory requirements more heavily\n const mandatoryWeight = 0.7;\n const optionalWeight = 0.3;\n\n const mandatoryScore = mandatoryRequirements.length > 0\n ? (mandatoryMet.length / mandatoryRequirements.length) * 100\n : 100;\n\n const optionalRequirements = sop.requirements.filter(r => !r.mandatory);\n const optionalMet = optionalRequirements.filter(r => requirementsMet.includes(r.id));\n const optionalScore = optionalRequirements.length > 0\n ? (optionalMet.length / optionalRequirements.length) * 100\n : 100;\n\n score = Math.round(mandatoryScore * mandatoryWeight + optionalScore * optionalWeight);\n }\n\n // Determine status\n let status: ComplianceStatus;\n if (score >= 90) {\n status = ComplianceStatus.COMPLIANT;\n } else if (score >= 50) {\n status = ComplianceStatus.PARTIAL;\n } else if (score > 0) {\n status = ComplianceStatus.NON_COMPLIANT;\n } else {\n status = ComplianceStatus.PENDING;\n }\n\n // Determine IRB status\n let irbStatus: IRBStatus = IRBStatus.NOT_REQUIRED;\n if (sop.irbTypicallyRequired) {\n irbStatus = IRBStatus.PENDING;\n // Check for IRB approval artifacts\n const irbArtifacts = projectArtifacts.get('ethics') || [];\n if (irbArtifacts.length > 0) {\n irbStatus = IRBStatus.IN_REVIEW;\n }\n }\n\n return {\n sopId: sop.id,\n status,\n score,\n requirementsMet,\n requirementsGaps,\n evidence,\n irbStatus,\n assessedAt: new Date(),\n assessedBy: assessor,\n notes: `Automated assessment: ${requirementsMet.length}/${totalRequirements} requirements met`,\n };\n}\n\n/**\n * Check if a specific requirement is met\n */\nfunction checkRequirement(\n requirement: SOPRequirement,\n projectRoot: string,\n docsPath: string,\n projectArtifacts: Map<string, string[]>,\n deepAnalysis: boolean\n): { met: boolean; evidenceFound?: EvidenceItem } {\n // Check for artifacts that match the requirement\n for (const artifactType of requirement.artifacts || []) {\n const artifacts = projectArtifacts.get(artifactType);\n if (artifacts && artifacts.length > 0) {\n // Found matching artifact\n const evidenceItem: EvidenceItem = {\n requirementId: requirement.id,\n filePath: artifacts[0],\n type: categorizeArtifact(artifacts[0]),\n description: `Found ${artifactType} artifact: ${basename(artifacts[0])}`,\n confidence: 0.8,\n };\n\n // Deep analysis: check content for keywords\n if (deepAnalysis) {\n const contentMatch = checkContentForRequirement(artifacts[0], requirement);\n if (contentMatch) {\n evidenceItem.confidence = 0.95;\n evidenceItem.excerpt = contentMatch;\n }\n }\n\n return { met: true, evidenceFound: evidenceItem };\n }\n }\n\n // Check based on verification method\n switch (requirement.verification) {\n case 'document':\n return checkDocumentEvidence(requirement, projectRoot, docsPath, projectArtifacts, deepAnalysis);\n case 'test':\n return checkTestEvidence(requirement, projectRoot, projectArtifacts);\n case 'automated':\n return checkAutomatedEvidence(requirement, projectRoot, projectArtifacts);\n case 'review':\n case 'audit':\n // These require manual verification\n return { met: false };\n default:\n return { met: false };\n }\n}\n\n/**\n * Check for document-based evidence\n */\nfunction checkDocumentEvidence(\n requirement: SOPRequirement,\n projectRoot: string,\n docsPath: string,\n projectArtifacts: Map<string, string[]>,\n deepAnalysis: boolean\n): { met: boolean; evidenceFound?: EvidenceItem } {\n // Look for documentation files in all relevant categories\n const docPatterns = [\n 'readme', 'requirements', 'architecture', 'api-docs',\n 'documentation', 'testing', 'security', 'monitoring',\n 'validation', 'config-management', 'data-management',\n 'privacy', 'ci-cd', 'ethics'\n ];\n\n for (const pattern of docPatterns) {\n const artifacts = projectArtifacts.get(pattern);\n if (artifacts && artifacts.length > 0) {\n for (const artifact of artifacts) {\n // Always check content for matches (not just with deepAnalysis)\n const contentMatch = checkContentForRequirement(artifact, requirement);\n if (contentMatch) {\n return {\n met: true,\n evidenceFound: {\n requirementId: requirement.id,\n filePath: artifact,\n type: 'document',\n description: `Found documentation evidence in ${basename(artifact)}`,\n confidence: deepAnalysis ? 0.90 : 0.75,\n excerpt: contentMatch,\n },\n };\n }\n }\n }\n }\n\n return { met: false };\n}\n\n/**\n * Check for test-based evidence\n */\nfunction checkTestEvidence(\n requirement: SOPRequirement,\n projectRoot: string,\n projectArtifacts: Map<string, string[]>\n): { met: boolean; evidenceFound?: EvidenceItem } {\n const testArtifacts = projectArtifacts.get('testing');\n\n if (testArtifacts && testArtifacts.length > 0) {\n return {\n met: true,\n evidenceFound: {\n requirementId: requirement.id,\n filePath: testArtifacts[0],\n type: 'test',\n description: `Test infrastructure found: ${basename(testArtifacts[0])}`,\n confidence: 0.7,\n },\n };\n }\n\n return { met: false };\n}\n\n/**\n * Check for automated/CI evidence\n */\nfunction checkAutomatedEvidence(\n requirement: SOPRequirement,\n projectRoot: string,\n projectArtifacts: Map<string, string[]>\n): { met: boolean; evidenceFound?: EvidenceItem } {\n const ciArtifacts = projectArtifacts.get('ci-cd');\n\n if (ciArtifacts && ciArtifacts.length > 0) {\n return {\n met: true,\n evidenceFound: {\n requirementId: requirement.id,\n filePath: ciArtifacts[0],\n type: 'config',\n description: `CI/CD configuration found: ${basename(ciArtifacts[0])}`,\n confidence: 0.75,\n },\n };\n }\n\n return { met: false };\n}\n\n/**\n * Check file content for requirement keywords\n */\nfunction checkContentForRequirement(\n filePath: string,\n requirement: SOPRequirement\n): string | null {\n try {\n const stat = statSync(filePath);\n if (stat.isDirectory()) return null;\n\n // Only check text files\n const ext = extname(filePath).toLowerCase();\n const textExtensions = ['.md', '.txt', '.ts', '.js', '.json', '.yaml', '.yml', '.html', '.rst'];\n if (!textExtensions.includes(ext)) return null;\n\n const content = readFileSync(filePath, 'utf-8');\n const lowerContent = content.toLowerCase();\n const lowerDesc = requirement.description.toLowerCase();\n\n // Check for keywords from requirement description\n const keywords = lowerDesc.split(/\\s+/).filter(w => w.length > 3);\n let matchCount = 0;\n let matchedLine = '';\n\n for (const keyword of keywords) {\n if (lowerContent.includes(keyword)) {\n matchCount++;\n // Find the line containing this keyword\n if (!matchedLine) {\n const lines = content.split('\\n');\n for (const line of lines) {\n if (line.toLowerCase().includes(keyword) && line.length < 200 && line.trim().length > 10) {\n matchedLine = line.trim();\n break;\n }\n }\n }\n }\n }\n\n // If at least 20% of keywords match, consider it evidence (lowered threshold)\n if (matchCount >= keywords.length * 0.2 && matchedLine) {\n return matchedLine;\n }\n\n // Also check for SOP-related keywords based on the requirement's evidence list\n const evidenceKeywords = requirement.evidence || [];\n for (const evidenceKey of evidenceKeywords) {\n const evidenceLower = evidenceKey.toLowerCase();\n if (lowerContent.includes(evidenceLower)) {\n const lines = content.split('\\n');\n for (const line of lines) {\n if (line.toLowerCase().includes(evidenceLower) && line.length < 200 && line.trim().length > 10) {\n return line.trim();\n }\n }\n }\n }\n\n // Check for compliance-related keywords in general\n const complianceTerms = getComplianceTermsForRequirement(requirement);\n for (const term of complianceTerms) {\n if (lowerContent.includes(term.toLowerCase())) {\n const lines = content.split('\\n');\n for (const line of lines) {\n if (line.toLowerCase().includes(term.toLowerCase()) && line.length < 200 && line.trim().length > 10) {\n return line.trim();\n }\n }\n }\n }\n\n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * Get compliance-related terms for a requirement based on its ID\n */\nfunction getComplianceTermsForRequirement(requirement: SOPRequirement): string[] {\n const reqId = requirement.id.toLowerCase();\n const terms: string[] = [];\n\n // Map requirement IDs to relevant terms\n if (reqId.includes('req') || reqId.includes('spec')) {\n terms.push('requirement', 'specification', 'functional', 'non-functional', 'acceptance criteria');\n }\n if (reqId.includes('test')) {\n terms.push('test', 'testing', 'coverage', 'unit test', 'integration', 'validation');\n }\n if (reqId.includes('arch') || reqId.includes('design')) {\n terms.push('architecture', 'design', 'component', 'system', 'integration');\n }\n if (reqId.includes('sec')) {\n terms.push('security', 'authentication', 'authorization', 'encryption', 'vulnerability');\n }\n if (reqId.includes('doc')) {\n terms.push('documentation', 'guide', 'reference', 'manual', 'tutorial');\n }\n if (reqId.includes('deploy') || reqId.includes('ci')) {\n terms.push('deployment', 'pipeline', 'continuous', 'automation', 'release');\n }\n if (reqId.includes('monitor') || reqId.includes('observe')) {\n terms.push('monitoring', 'metrics', 'alerting', 'logging', 'observability');\n }\n if (reqId.includes('data') || reqId.includes('privacy')) {\n terms.push('data', 'privacy', 'protection', 'governance', 'retention');\n }\n if (reqId.includes('risk')) {\n terms.push('risk', 'mitigation', 'assessment', 'impact', 'likelihood');\n }\n if (reqId.includes('quality') || reqId.includes('qa')) {\n terms.push('quality', 'assurance', 'standard', 'review', 'inspection');\n }\n\n return terms;\n}\n\n/**\n * Categorize an artifact by its type\n */\nfunction categorizeArtifact(filePath: string): 'document' | 'code' | 'test' | 'config' | 'artifact' {\n const ext = extname(filePath).toLowerCase();\n const name = basename(filePath).toLowerCase();\n\n if (['.md', '.txt', '.rst', '.html'].includes(ext)) {\n return 'document';\n }\n if (['.ts', '.js', '.py', '.java', '.go', '.rs'].includes(ext)) {\n if (name.includes('test') || name.includes('spec')) {\n return 'test';\n }\n return 'code';\n }\n if (['.json', '.yaml', '.yml', '.toml', '.ini'].includes(ext)) {\n return 'config';\n }\n return 'artifact';\n}\n\n/**\n * Calculate overall scores from assessments\n */\nfunction calculateScores(result: ComplianceCheckResult): void {\n if (result.assessments.length === 0) {\n result.overallScore = 0;\n return;\n }\n\n // Calculate category scores\n const categoryTotals: Record<SOPCategory, { sum: number; count: number }> = {\n [SOPCategory.PROGRAM_MANAGEMENT]: { sum: 0, count: 0 },\n [SOPCategory.OPERATIONS]: { sum: 0, count: 0 },\n [SOPCategory.DEVELOPMENT]: { sum: 0, count: 0 },\n [SOPCategory.GOVERNANCE]: { sum: 0, count: 0 },\n [SOPCategory.QUALITY]: { sum: 0, count: 0 },\n };\n\n for (const assessment of result.assessments) {\n const sop = getSOPById(assessment.sopId);\n if (sop) {\n categoryTotals[sop.category].sum += assessment.score;\n categoryTotals[sop.category].count += 1;\n }\n }\n\n // Calculate category averages\n for (const category of Object.values(SOPCategory)) {\n const totals = categoryTotals[category];\n result.categoryScores[category] = totals.count > 0\n ? Math.round(totals.sum / totals.count)\n : 0;\n }\n\n // Calculate overall score (weighted by priority)\n let weightedSum = 0;\n let totalWeight = 0;\n\n for (const assessment of result.assessments) {\n const sop = getSOPById(assessment.sopId);\n if (sop) {\n const weight = getPriorityWeight(sop.priority);\n weightedSum += assessment.score * weight;\n totalWeight += weight;\n }\n }\n\n result.overallScore = totalWeight > 0\n ? Math.round(weightedSum / totalWeight)\n : 0;\n}\n\n/**\n * Get weight for priority level\n */\nfunction getPriorityWeight(priority: SOPPriority): number {\n switch (priority) {\n case SOPPriority.CRITICAL:\n return 4;\n case SOPPriority.HIGH:\n return 3;\n case SOPPriority.MEDIUM:\n return 2;\n case SOPPriority.LOW:\n return 1;\n default:\n return 1;\n }\n}\n\n/**\n * Quick check for a specific SOP\n */\nexport async function checkSOPCompliance(\n sopId: string,\n projectRoot: string,\n docsPath: string = 'docs'\n): Promise<SOPAssessment | null> {\n const result = await checkCompliance({\n projectRoot,\n docsPath,\n sopIds: [sopId],\n });\n\n return result.assessments[0] || null;\n}\n\n/**\n * Check if project meets minimum compliance threshold\n */\nexport async function meetsMinimumCompliance(\n projectRoot: string,\n threshold: number = 50,\n categories?: SOPCategory[]\n): Promise<{ meets: boolean; score: number; gaps: string[] }> {\n const result = await checkCompliance({\n projectRoot,\n categories,\n });\n\n const gaps = result.assessments\n .filter(a => a.score < threshold)\n .map(a => a.sopId);\n\n return {\n meets: result.overallScore >= threshold,\n score: result.overallScore,\n gaps,\n };\n}\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@weavelogic/knowledge-graph-agent",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.7",
|
|
4
4
|
"description": "Knowledge graph agent for Claude Code - generates knowledge graphs, initializes docs, and integrates with claude-flow",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|