olympus-ai 3.2.2 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/dist/__tests__/ascent-checkpoint.test.d.ts +2 -0
- package/dist/__tests__/ascent-checkpoint.test.d.ts.map +1 -0
- package/dist/__tests__/ascent-checkpoint.test.js +261 -0
- package/dist/__tests__/ascent-checkpoint.test.js.map +1 -0
- package/dist/__tests__/config-ascent.test.d.ts +2 -0
- package/dist/__tests__/config-ascent.test.d.ts.map +1 -0
- package/dist/__tests__/config-ascent.test.js +134 -0
- package/dist/__tests__/config-ascent.test.js.map +1 -0
- package/dist/__tests__/hook-blocking.test.d.ts +8 -0
- package/dist/__tests__/hook-blocking.test.d.ts.map +1 -0
- package/dist/__tests__/hook-blocking.test.js +277 -0
- package/dist/__tests__/hook-blocking.test.js.map +1 -0
- package/dist/__tests__/installer.test.js +1 -1
- package/dist/__tests__/metrics-cli.test.d.ts +5 -0
- package/dist/__tests__/metrics-cli.test.d.ts.map +1 -0
- package/dist/__tests__/metrics-cli.test.js +24 -0
- package/dist/__tests__/metrics-cli.test.js.map +1 -0
- package/dist/__tests__/skill-auto-detection.test.d.ts +2 -0
- package/dist/__tests__/skill-auto-detection.test.d.ts.map +1 -0
- package/dist/__tests__/skill-auto-detection.test.js +255 -0
- package/dist/__tests__/skill-auto-detection.test.js.map +1 -0
- package/dist/__tests__/token-estimator.test.d.ts +5 -0
- package/dist/__tests__/token-estimator.test.d.ts.map +1 -0
- package/dist/__tests__/token-estimator.test.js +192 -0
- package/dist/__tests__/token-estimator.test.js.map +1 -0
- package/dist/agents/definitions.d.ts.map +1 -1
- package/dist/agents/definitions.js +83 -1
- package/dist/agents/definitions.js.map +1 -1
- package/dist/agents/document-writer.d.ts.map +1 -1
- package/dist/agents/document-writer.js +38 -0
- package/dist/agents/document-writer.js.map +1 -1
- package/dist/agents/frontend-engineer.d.ts.map +1 -1
- package/dist/agents/frontend-engineer.js +16 -0
- package/dist/agents/frontend-engineer.js.map +1 -1
- package/dist/agents/olympian.d.ts.map +1 -1
- package/dist/agents/olympian.js +15 -0
- package/dist/agents/olympian.js.map +1 -1
- package/dist/cli/commands/metrics.d.ts +31 -0
- package/dist/cli/commands/metrics.d.ts.map +1 -0
- package/dist/cli/commands/metrics.js +266 -0
- package/dist/cli/commands/metrics.js.map +1 -0
- package/dist/cli/index.js +39 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/loader.js +16 -0
- package/dist/config/loader.js.map +1 -1
- package/dist/features/ascent-checkpoint/index.d.ts +48 -0
- package/dist/features/ascent-checkpoint/index.d.ts.map +1 -0
- package/dist/features/ascent-checkpoint/index.js +144 -0
- package/dist/features/ascent-checkpoint/index.js.map +1 -0
- package/dist/features/hook-logging/index.d.ts +37 -0
- package/dist/features/hook-logging/index.d.ts.map +1 -0
- package/dist/features/hook-logging/index.js +120 -0
- package/dist/features/hook-logging/index.js.map +1 -0
- package/dist/features/hook-logging/index.test.d.ts +5 -0
- package/dist/features/hook-logging/index.test.d.ts.map +1 -0
- package/dist/features/hook-logging/index.test.js +268 -0
- package/dist/features/hook-logging/index.test.js.map +1 -0
- package/dist/features/index.d.ts +3 -0
- package/dist/features/index.d.ts.map +1 -1
- package/dist/features/index.js +8 -0
- package/dist/features/index.js.map +1 -1
- package/dist/features/magic-keywords.d.ts +51 -0
- package/dist/features/magic-keywords.d.ts.map +1 -1
- package/dist/features/magic-keywords.js +172 -0
- package/dist/features/magic-keywords.js.map +1 -1
- package/dist/features/session-state/index.d.ts +50 -0
- package/dist/features/session-state/index.d.ts.map +1 -0
- package/dist/features/session-state/index.js +64 -0
- package/dist/features/session-state/index.js.map +1 -0
- package/dist/features/session-state/index.test.d.ts +5 -0
- package/dist/features/session-state/index.test.d.ts.map +1 -0
- package/dist/features/session-state/index.test.js +221 -0
- package/dist/features/session-state/index.test.js.map +1 -0
- package/dist/features/token-metrics/index.d.ts +6 -0
- package/dist/features/token-metrics/index.d.ts.map +1 -0
- package/dist/features/token-metrics/index.js +5 -0
- package/dist/features/token-metrics/index.js.map +1 -0
- package/dist/features/token-metrics/storage.d.ts +16 -0
- package/dist/features/token-metrics/storage.d.ts.map +1 -0
- package/dist/features/token-metrics/storage.js +144 -0
- package/dist/features/token-metrics/storage.js.map +1 -0
- package/dist/features/token-metrics/token-estimator.d.ts +66 -0
- package/dist/features/token-metrics/token-estimator.d.ts.map +1 -0
- package/dist/features/token-metrics/token-estimator.js +230 -0
- package/dist/features/token-metrics/token-estimator.js.map +1 -0
- package/dist/features/token-metrics/types.d.ts +63 -0
- package/dist/features/token-metrics/types.d.ts.map +1 -0
- package/dist/features/token-metrics/types.js +5 -0
- package/dist/features/token-metrics/types.js.map +1 -0
- package/dist/hooks/olympus-orchestrator/constants.d.ts +2 -0
- package/dist/hooks/olympus-orchestrator/constants.d.ts.map +1 -1
- package/dist/hooks/olympus-orchestrator/constants.js +41 -0
- package/dist/hooks/olympus-orchestrator/constants.js.map +1 -1
- package/dist/hooks/olympus-orchestrator/index.d.ts +10 -1
- package/dist/hooks/olympus-orchestrator/index.d.ts.map +1 -1
- package/dist/hooks/olympus-orchestrator/index.js +108 -14
- package/dist/hooks/olympus-orchestrator/index.js.map +1 -1
- package/dist/hooks/registrations/index.d.ts +2 -1
- package/dist/hooks/registrations/index.d.ts.map +1 -1
- package/dist/hooks/registrations/index.js +3 -1
- package/dist/hooks/registrations/index.js.map +1 -1
- package/dist/hooks/registrations/token-metrics.d.ts +11 -0
- package/dist/hooks/registrations/token-metrics.d.ts.map +1 -0
- package/dist/hooks/registrations/token-metrics.js +119 -0
- package/dist/hooks/registrations/token-metrics.js.map +1 -0
- package/dist/installer/index.d.ts +1 -1
- package/dist/installer/index.d.ts.map +1 -1
- package/dist/installer/index.js +334 -9
- package/dist/installer/index.js.map +1 -1
- package/dist/shared/types.d.ts +16 -0
- package/dist/shared/types.d.ts.map +1 -1
- package/package.json +3 -3
- package/scripts/.olympus/token-metrics.jsonl +1 -0
- package/scripts/dist/hooks/olympus-hooks.cjs +127 -128
- package/scripts/esbuild.hooks.mjs +1 -1
- package/.claude/.olympus-version.json +0 -6
- package/.claude/CLAUDE.md +0 -339
- package/.claude/agents/document-writer.md +0 -152
- package/.claude/agents/explore-medium.md +0 -25
- package/.claude/agents/explore.md +0 -86
- package/.claude/agents/frontend-engineer-high.md +0 -17
- package/.claude/agents/frontend-engineer-low.md +0 -17
- package/.claude/agents/frontend-engineer.md +0 -80
- package/.claude/agents/librarian-low.md +0 -22
- package/.claude/agents/librarian.md +0 -70
- package/.claude/agents/metis.md +0 -85
- package/.claude/agents/momus.md +0 -97
- package/.claude/agents/multimodal-looker.md +0 -39
- package/.claude/agents/olympian-high.md +0 -32
- package/.claude/agents/olympian-low.md +0 -22
- package/.claude/agents/olympian.md +0 -78
- package/.claude/agents/oracle-low.md +0 -23
- package/.claude/agents/oracle-medium.md +0 -28
- package/.claude/agents/oracle.md +0 -77
- package/.claude/agents/prometheus.md +0 -125
- package/.claude/agents/qa-tester.md +0 -220
- package/.claude/commands/analyze/skill.md +0 -14
- package/.claude/commands/ascent/skill.md +0 -152
- package/.claude/commands/cancel-ascent.md +0 -9
- package/.claude/commands/complete-plan.md +0 -101
- package/.claude/commands/deepsearch/skill.md +0 -15
- package/.claude/commands/olympus/skill.md +0 -82
- package/.claude/commands/olympus-default.md +0 -26
- package/.claude/commands/plan.md +0 -71
- package/.claude/commands/prometheus/skill.md +0 -38
- package/.claude/commands/review/skill.md +0 -34
- package/.claude/commands/ultrawork/skill.md +0 -90
- package/.claude/commands/update.md +0 -38
- package/scripts/generate-logo-hybrid-v2.mjs +0 -213
- package/scripts/generate-logo-hybrid.mjs +0 -209
- package/scripts/generate-logo-infinity.mjs +0 -239
- package/scripts/generate-logo-mythology.mjs +0 -190
- package/scripts/generate-logo-orchestration.mjs +0 -228
- package/scripts/generate-logo-recraft.mjs +0 -147
- package/scripts/generate-logo-simple.mjs +0 -154
- package/scripts/generate-logo.mjs +0 -117
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ascent Checkpoint System
|
|
3
|
+
*
|
|
4
|
+
* Manages checkpoints for ascent tasks to enable safe resumption after max iterations.
|
|
5
|
+
*/
|
|
6
|
+
import type { AscentCheckpoint } from '../../shared/types.js';
|
|
7
|
+
export type { AscentCheckpoint } from '../../shared/types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Get the checkpoints directory path
|
|
10
|
+
* @param testDir Optional test directory override for testing
|
|
11
|
+
*/
|
|
12
|
+
export declare function getCheckpointsDir(testDir?: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* Generate a hash of plan content for drift detection
|
|
15
|
+
*/
|
|
16
|
+
export declare function hashPlanContent(planContent: string): string;
|
|
17
|
+
/**
|
|
18
|
+
* Get current git SHA
|
|
19
|
+
*/
|
|
20
|
+
export declare function getGitSha(): string;
|
|
21
|
+
/**
|
|
22
|
+
* Save a checkpoint for an ascent task
|
|
23
|
+
* @param planName Name of the plan
|
|
24
|
+
* @param state Checkpoint state
|
|
25
|
+
* @param testDir Optional test directory override for testing
|
|
26
|
+
*/
|
|
27
|
+
export declare function saveCheckpoint(planName: string, state: Omit<AscentCheckpoint, 'planName' | 'timestamp'>, testDir?: string): void;
|
|
28
|
+
/**
|
|
29
|
+
* Load the most recent checkpoint for a plan
|
|
30
|
+
* @param planName Name of the plan
|
|
31
|
+
* @param testDir Optional test directory override for testing
|
|
32
|
+
*/
|
|
33
|
+
export declare function loadCheckpoint(planName: string, testDir?: string): AscentCheckpoint | null;
|
|
34
|
+
/**
|
|
35
|
+
* List all checkpoint files for a plan, sorted by most recent first
|
|
36
|
+
* @param planName Name of the plan
|
|
37
|
+
* @param testDir Optional test directory override for testing
|
|
38
|
+
*/
|
|
39
|
+
export declare function listCheckpoints(planName: string, testDir?: string): string[];
|
|
40
|
+
/**
|
|
41
|
+
* Validate a checkpoint for resumption
|
|
42
|
+
* Returns warnings if git SHA or plan hash has changed
|
|
43
|
+
*/
|
|
44
|
+
export declare function validateCheckpoint(checkpoint: AscentCheckpoint, currentGitSha: string, currentPlanHash: string): {
|
|
45
|
+
valid: boolean;
|
|
46
|
+
warnings: string[];
|
|
47
|
+
};
|
|
48
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/features/ascent-checkpoint/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAG9D,YAAY,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAE9D;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAM1D;AAaD;;GAEG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED;;GAEG;AACH,wBAAgB,SAAS,IAAI,MAAM,CASlC;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,IAAI,CAAC,gBAAgB,EAAE,UAAU,GAAG,WAAW,CAAC,EACvD,OAAO,CAAC,EAAE,MAAM,GACf,IAAI,CAcN;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAwB1F;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAuB5E;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,gBAAgB,EAC5B,aAAa,EAAE,MAAM,EACrB,eAAe,EAAE,MAAM,GACtB;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CAyBxC"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ascent Checkpoint System
|
|
3
|
+
*
|
|
4
|
+
* Manages checkpoints for ascent tasks to enable safe resumption after max iterations.
|
|
5
|
+
*/
|
|
6
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync } from 'fs';
|
|
7
|
+
import { join } from 'path';
|
|
8
|
+
import { createHash } from 'crypto';
|
|
9
|
+
/**
|
|
10
|
+
* Get the checkpoints directory path
|
|
11
|
+
* @param testDir Optional test directory override for testing
|
|
12
|
+
*/
|
|
13
|
+
export function getCheckpointsDir(testDir) {
|
|
14
|
+
if (testDir) {
|
|
15
|
+
return testDir;
|
|
16
|
+
}
|
|
17
|
+
const cwd = process.cwd();
|
|
18
|
+
return join(cwd, '.olympus', 'checkpoints');
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Ensure checkpoints directory exists
|
|
22
|
+
* @param testDir Optional test directory override for testing
|
|
23
|
+
*/
|
|
24
|
+
function ensureCheckpointsDir(testDir) {
|
|
25
|
+
const dir = getCheckpointsDir(testDir);
|
|
26
|
+
if (!existsSync(dir)) {
|
|
27
|
+
mkdirSync(dir, { recursive: true });
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Generate a hash of plan content for drift detection
|
|
32
|
+
*/
|
|
33
|
+
export function hashPlanContent(planContent) {
|
|
34
|
+
return createHash('sha256').update(planContent).digest('hex').substring(0, 16);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Get current git SHA
|
|
38
|
+
*/
|
|
39
|
+
export function getGitSha() {
|
|
40
|
+
try {
|
|
41
|
+
const { execSync } = require('child_process');
|
|
42
|
+
const sha = execSync('git rev-parse HEAD', { encoding: 'utf-8' }).trim();
|
|
43
|
+
return sha;
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
console.warn('Warning: Could not get git SHA:', error);
|
|
47
|
+
return 'unknown';
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Save a checkpoint for an ascent task
|
|
52
|
+
* @param planName Name of the plan
|
|
53
|
+
* @param state Checkpoint state
|
|
54
|
+
* @param testDir Optional test directory override for testing
|
|
55
|
+
*/
|
|
56
|
+
export function saveCheckpoint(planName, state, testDir) {
|
|
57
|
+
ensureCheckpointsDir(testDir);
|
|
58
|
+
const checkpoint = {
|
|
59
|
+
planName,
|
|
60
|
+
timestamp: new Date().toISOString(),
|
|
61
|
+
...state
|
|
62
|
+
};
|
|
63
|
+
const filename = `${planName}-${Date.now()}.json`;
|
|
64
|
+
const filepath = join(getCheckpointsDir(testDir), filename);
|
|
65
|
+
writeFileSync(filepath, JSON.stringify(checkpoint, null, 2), 'utf-8');
|
|
66
|
+
console.log(`Checkpoint saved: ${filepath}`);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Load the most recent checkpoint for a plan
|
|
70
|
+
* @param planName Name of the plan
|
|
71
|
+
* @param testDir Optional test directory override for testing
|
|
72
|
+
*/
|
|
73
|
+
export function loadCheckpoint(planName, testDir) {
|
|
74
|
+
const dir = getCheckpointsDir(testDir);
|
|
75
|
+
if (!existsSync(dir)) {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
const checkpoints = listCheckpoints(planName, testDir);
|
|
79
|
+
if (checkpoints.length === 0) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
// Most recent is first in sorted list
|
|
83
|
+
const latestFile = checkpoints[0];
|
|
84
|
+
const filepath = join(dir, latestFile);
|
|
85
|
+
try {
|
|
86
|
+
const content = readFileSync(filepath, 'utf-8');
|
|
87
|
+
return JSON.parse(content);
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
console.error(`Error loading checkpoint ${latestFile}:`, error);
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* List all checkpoint files for a plan, sorted by most recent first
|
|
96
|
+
* @param planName Name of the plan
|
|
97
|
+
* @param testDir Optional test directory override for testing
|
|
98
|
+
*/
|
|
99
|
+
export function listCheckpoints(planName, testDir) {
|
|
100
|
+
const dir = getCheckpointsDir(testDir);
|
|
101
|
+
if (!existsSync(dir)) {
|
|
102
|
+
return [];
|
|
103
|
+
}
|
|
104
|
+
try {
|
|
105
|
+
const files = readdirSync(dir);
|
|
106
|
+
const checkpointFiles = files
|
|
107
|
+
.filter(f => f.startsWith(`${planName}-`) && f.endsWith('.json'))
|
|
108
|
+
.sort((a, b) => {
|
|
109
|
+
// Extract timestamps from filenames
|
|
110
|
+
const tsA = parseInt(a.split('-').pop()?.replace('.json', '') || '0');
|
|
111
|
+
const tsB = parseInt(b.split('-').pop()?.replace('.json', '') || '0');
|
|
112
|
+
return tsB - tsA; // Most recent first
|
|
113
|
+
});
|
|
114
|
+
return checkpointFiles;
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
console.error('Error listing checkpoints:', error);
|
|
118
|
+
return [];
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Validate a checkpoint for resumption
|
|
123
|
+
* Returns warnings if git SHA or plan hash has changed
|
|
124
|
+
*/
|
|
125
|
+
export function validateCheckpoint(checkpoint, currentGitSha, currentPlanHash) {
|
|
126
|
+
const warnings = [];
|
|
127
|
+
if (checkpoint.gitSha !== currentGitSha && checkpoint.gitSha !== 'unknown') {
|
|
128
|
+
warnings.push(`WARNING: Git SHA has changed since checkpoint.\n` +
|
|
129
|
+
`Checkpoint SHA: ${checkpoint.gitSha}\n` +
|
|
130
|
+
`Current SHA: ${currentGitSha}\n` +
|
|
131
|
+
`Code changes may have occurred.`);
|
|
132
|
+
}
|
|
133
|
+
if (checkpoint.planHash !== currentPlanHash) {
|
|
134
|
+
warnings.push(`WARNING: Plan has been modified since checkpoint.\n` +
|
|
135
|
+
`Checkpoint hash: ${checkpoint.planHash}\n` +
|
|
136
|
+
`Current hash: ${currentPlanHash}\n` +
|
|
137
|
+
`Plan drift detected - review changes before resuming.`);
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
valid: true,
|
|
141
|
+
warnings
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/features/ascent-checkpoint/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook Violation Logging
|
|
3
|
+
*
|
|
4
|
+
* Logs all hook violations (blocked and allowed) for debugging and analysis.
|
|
5
|
+
* Violations are appended to .olympus/logs/hook-violations.jsonl
|
|
6
|
+
*/
|
|
7
|
+
export interface HookViolation {
|
|
8
|
+
timestamp: string;
|
|
9
|
+
filePath: string;
|
|
10
|
+
toolName: string;
|
|
11
|
+
linesChanged?: number;
|
|
12
|
+
wasBlocked: boolean;
|
|
13
|
+
reason: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Log a hook violation to .olympus/logs/hook-violations.jsonl
|
|
17
|
+
*/
|
|
18
|
+
export declare function logViolation(violation: HookViolation, workDir?: string): void;
|
|
19
|
+
/**
|
|
20
|
+
* Get violation statistics from the log
|
|
21
|
+
*/
|
|
22
|
+
export declare function getViolationStats(workDir?: string): {
|
|
23
|
+
total: number;
|
|
24
|
+
byFile: Record<string, number>;
|
|
25
|
+
byTool: Record<string, number>;
|
|
26
|
+
blocked: number;
|
|
27
|
+
allowed: number;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Read all violations from the log
|
|
31
|
+
*/
|
|
32
|
+
export declare function readViolations(workDir?: string): HookViolation[];
|
|
33
|
+
/**
|
|
34
|
+
* Clear the violations log (for testing)
|
|
35
|
+
*/
|
|
36
|
+
export declare function clearViolations(workDir?: string): void;
|
|
37
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/features/hook-logging/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAkB7E;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG;IACnD,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB,CA+CA;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,aAAa,EAAE,CA0BhE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAYtD"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook Violation Logging
|
|
3
|
+
*
|
|
4
|
+
* Logs all hook violations (blocked and allowed) for debugging and analysis.
|
|
5
|
+
* Violations are appended to .olympus/logs/hook-violations.jsonl
|
|
6
|
+
*/
|
|
7
|
+
import { mkdirSync, appendFileSync, readFileSync, existsSync } from 'fs';
|
|
8
|
+
import { join } from 'path';
|
|
9
|
+
/**
|
|
10
|
+
* Log a hook violation to .olympus/logs/hook-violations.jsonl
|
|
11
|
+
*/
|
|
12
|
+
export function logViolation(violation, workDir) {
|
|
13
|
+
const baseDir = workDir || process.cwd();
|
|
14
|
+
const logDir = join(baseDir, '.olympus', 'logs');
|
|
15
|
+
const logPath = join(logDir, 'hook-violations.jsonl');
|
|
16
|
+
try {
|
|
17
|
+
// Create directory if needed
|
|
18
|
+
if (!existsSync(logDir)) {
|
|
19
|
+
mkdirSync(logDir, { recursive: true });
|
|
20
|
+
}
|
|
21
|
+
// Append violation as JSON line
|
|
22
|
+
const line = JSON.stringify(violation) + '\n';
|
|
23
|
+
appendFileSync(logPath, line, 'utf-8');
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
// Silently fail - don't block hook execution due to logging errors
|
|
27
|
+
console.error('[Hook Logging] Failed to log violation:', error);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Get violation statistics from the log
|
|
32
|
+
*/
|
|
33
|
+
export function getViolationStats(workDir) {
|
|
34
|
+
const baseDir = workDir || process.cwd();
|
|
35
|
+
const logPath = join(baseDir, '.olympus', 'logs', 'hook-violations.jsonl');
|
|
36
|
+
const stats = {
|
|
37
|
+
total: 0,
|
|
38
|
+
byFile: {},
|
|
39
|
+
byTool: {},
|
|
40
|
+
blocked: 0,
|
|
41
|
+
allowed: 0,
|
|
42
|
+
};
|
|
43
|
+
try {
|
|
44
|
+
if (!existsSync(logPath)) {
|
|
45
|
+
return stats;
|
|
46
|
+
}
|
|
47
|
+
const content = readFileSync(logPath, 'utf-8');
|
|
48
|
+
const lines = content.trim().split('\n').filter(Boolean);
|
|
49
|
+
for (const line of lines) {
|
|
50
|
+
try {
|
|
51
|
+
const violation = JSON.parse(line);
|
|
52
|
+
stats.total++;
|
|
53
|
+
// Count by file
|
|
54
|
+
stats.byFile[violation.filePath] = (stats.byFile[violation.filePath] || 0) + 1;
|
|
55
|
+
// Count by tool
|
|
56
|
+
stats.byTool[violation.toolName] = (stats.byTool[violation.toolName] || 0) + 1;
|
|
57
|
+
// Count blocked vs allowed
|
|
58
|
+
if (violation.wasBlocked) {
|
|
59
|
+
stats.blocked++;
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
stats.allowed++;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
// Skip malformed lines
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return stats;
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
return stats;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Read all violations from the log
|
|
78
|
+
*/
|
|
79
|
+
export function readViolations(workDir) {
|
|
80
|
+
const baseDir = workDir || process.cwd();
|
|
81
|
+
const logPath = join(baseDir, '.olympus', 'logs', 'hook-violations.jsonl');
|
|
82
|
+
try {
|
|
83
|
+
if (!existsSync(logPath)) {
|
|
84
|
+
return [];
|
|
85
|
+
}
|
|
86
|
+
const content = readFileSync(logPath, 'utf-8');
|
|
87
|
+
const lines = content.trim().split('\n').filter(Boolean);
|
|
88
|
+
const violations = [];
|
|
89
|
+
for (const line of lines) {
|
|
90
|
+
try {
|
|
91
|
+
violations.push(JSON.parse(line));
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
// Skip malformed lines
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return violations;
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return [];
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Clear the violations log (for testing)
|
|
106
|
+
*/
|
|
107
|
+
export function clearViolations(workDir) {
|
|
108
|
+
const baseDir = workDir || process.cwd();
|
|
109
|
+
const logPath = join(baseDir, '.olympus', 'logs', 'hook-violations.jsonl');
|
|
110
|
+
try {
|
|
111
|
+
if (existsSync(logPath)) {
|
|
112
|
+
const { unlinkSync } = require('fs');
|
|
113
|
+
unlinkSync(logPath);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
// Silently fail
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/features/hook-logging/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../../src/features/hook-logging/index.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for Hook Violation Logging
|
|
3
|
+
*/
|
|
4
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
5
|
+
import { mkdirSync, rmSync, existsSync } from 'fs';
|
|
6
|
+
import { join } from 'path';
|
|
7
|
+
import { tmpdir } from 'os';
|
|
8
|
+
import { logViolation, getViolationStats, readViolations, } from './index.js';
|
|
9
|
+
describe('Hook Logging', () => {
|
|
10
|
+
let testDir;
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
// Create unique test directory
|
|
13
|
+
testDir = join(tmpdir(), `olympus-test-${Date.now()}`);
|
|
14
|
+
mkdirSync(testDir, { recursive: true });
|
|
15
|
+
});
|
|
16
|
+
afterEach(() => {
|
|
17
|
+
// Clean up test directory
|
|
18
|
+
if (existsSync(testDir)) {
|
|
19
|
+
rmSync(testDir, { recursive: true, force: true });
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
describe('logViolation', () => {
|
|
23
|
+
it('should create log directory if it does not exist', () => {
|
|
24
|
+
const violation = {
|
|
25
|
+
timestamp: new Date().toISOString(),
|
|
26
|
+
filePath: 'src/index.ts',
|
|
27
|
+
toolName: 'Edit',
|
|
28
|
+
wasBlocked: true,
|
|
29
|
+
reason: 'Test violation',
|
|
30
|
+
};
|
|
31
|
+
logViolation(violation, testDir);
|
|
32
|
+
const logDir = join(testDir, '.olympus', 'logs');
|
|
33
|
+
expect(existsSync(logDir)).toBe(true);
|
|
34
|
+
});
|
|
35
|
+
it('should append violation to log file', () => {
|
|
36
|
+
const violation = {
|
|
37
|
+
timestamp: new Date().toISOString(),
|
|
38
|
+
filePath: 'src/index.ts',
|
|
39
|
+
toolName: 'Edit',
|
|
40
|
+
wasBlocked: true,
|
|
41
|
+
reason: 'Test violation',
|
|
42
|
+
};
|
|
43
|
+
logViolation(violation, testDir);
|
|
44
|
+
const violations = readViolations(testDir);
|
|
45
|
+
expect(violations).toHaveLength(1);
|
|
46
|
+
expect(violations[0]).toEqual(violation);
|
|
47
|
+
});
|
|
48
|
+
it('should append multiple violations', () => {
|
|
49
|
+
const violation1 = {
|
|
50
|
+
timestamp: new Date().toISOString(),
|
|
51
|
+
filePath: 'src/index.ts',
|
|
52
|
+
toolName: 'Edit',
|
|
53
|
+
wasBlocked: true,
|
|
54
|
+
reason: 'Violation 1',
|
|
55
|
+
};
|
|
56
|
+
const violation2 = {
|
|
57
|
+
timestamp: new Date().toISOString(),
|
|
58
|
+
filePath: 'src/utils.ts',
|
|
59
|
+
toolName: 'Write',
|
|
60
|
+
wasBlocked: false,
|
|
61
|
+
reason: 'Violation 2',
|
|
62
|
+
};
|
|
63
|
+
logViolation(violation1, testDir);
|
|
64
|
+
logViolation(violation2, testDir);
|
|
65
|
+
const violations = readViolations(testDir);
|
|
66
|
+
expect(violations).toHaveLength(2);
|
|
67
|
+
expect(violations[0]).toEqual(violation1);
|
|
68
|
+
expect(violations[1]).toEqual(violation2);
|
|
69
|
+
});
|
|
70
|
+
it('should handle violations with linesChanged', () => {
|
|
71
|
+
const violation = {
|
|
72
|
+
timestamp: new Date().toISOString(),
|
|
73
|
+
filePath: 'src/index.ts',
|
|
74
|
+
toolName: 'Edit',
|
|
75
|
+
linesChanged: 25,
|
|
76
|
+
wasBlocked: true,
|
|
77
|
+
reason: 'Large edit',
|
|
78
|
+
};
|
|
79
|
+
logViolation(violation, testDir);
|
|
80
|
+
const violations = readViolations(testDir);
|
|
81
|
+
expect(violations[0].linesChanged).toBe(25);
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
describe('getViolationStats', () => {
|
|
85
|
+
it('should return empty stats when no violations', () => {
|
|
86
|
+
const stats = getViolationStats(testDir);
|
|
87
|
+
expect(stats.total).toBe(0);
|
|
88
|
+
expect(stats.blocked).toBe(0);
|
|
89
|
+
expect(stats.allowed).toBe(0);
|
|
90
|
+
expect(stats.byFile).toEqual({});
|
|
91
|
+
expect(stats.byTool).toEqual({});
|
|
92
|
+
});
|
|
93
|
+
it('should count total violations', () => {
|
|
94
|
+
logViolation({
|
|
95
|
+
timestamp: new Date().toISOString(),
|
|
96
|
+
filePath: 'file1.ts',
|
|
97
|
+
toolName: 'Edit',
|
|
98
|
+
wasBlocked: true,
|
|
99
|
+
reason: 'Test',
|
|
100
|
+
}, testDir);
|
|
101
|
+
logViolation({
|
|
102
|
+
timestamp: new Date().toISOString(),
|
|
103
|
+
filePath: 'file2.ts',
|
|
104
|
+
toolName: 'Write',
|
|
105
|
+
wasBlocked: false,
|
|
106
|
+
reason: 'Test',
|
|
107
|
+
}, testDir);
|
|
108
|
+
const stats = getViolationStats(testDir);
|
|
109
|
+
expect(stats.total).toBe(2);
|
|
110
|
+
});
|
|
111
|
+
it('should count violations by file', () => {
|
|
112
|
+
logViolation({
|
|
113
|
+
timestamp: new Date().toISOString(),
|
|
114
|
+
filePath: 'file1.ts',
|
|
115
|
+
toolName: 'Edit',
|
|
116
|
+
wasBlocked: true,
|
|
117
|
+
reason: 'Test',
|
|
118
|
+
}, testDir);
|
|
119
|
+
logViolation({
|
|
120
|
+
timestamp: new Date().toISOString(),
|
|
121
|
+
filePath: 'file1.ts',
|
|
122
|
+
toolName: 'Edit',
|
|
123
|
+
wasBlocked: true,
|
|
124
|
+
reason: 'Test',
|
|
125
|
+
}, testDir);
|
|
126
|
+
logViolation({
|
|
127
|
+
timestamp: new Date().toISOString(),
|
|
128
|
+
filePath: 'file2.ts',
|
|
129
|
+
toolName: 'Write',
|
|
130
|
+
wasBlocked: false,
|
|
131
|
+
reason: 'Test',
|
|
132
|
+
}, testDir);
|
|
133
|
+
const stats = getViolationStats(testDir);
|
|
134
|
+
expect(stats.byFile['file1.ts']).toBe(2);
|
|
135
|
+
expect(stats.byFile['file2.ts']).toBe(1);
|
|
136
|
+
});
|
|
137
|
+
it('should count violations by tool', () => {
|
|
138
|
+
logViolation({
|
|
139
|
+
timestamp: new Date().toISOString(),
|
|
140
|
+
filePath: 'file1.ts',
|
|
141
|
+
toolName: 'Edit',
|
|
142
|
+
wasBlocked: true,
|
|
143
|
+
reason: 'Test',
|
|
144
|
+
}, testDir);
|
|
145
|
+
logViolation({
|
|
146
|
+
timestamp: new Date().toISOString(),
|
|
147
|
+
filePath: 'file2.ts',
|
|
148
|
+
toolName: 'Edit',
|
|
149
|
+
wasBlocked: true,
|
|
150
|
+
reason: 'Test',
|
|
151
|
+
}, testDir);
|
|
152
|
+
logViolation({
|
|
153
|
+
timestamp: new Date().toISOString(),
|
|
154
|
+
filePath: 'file3.ts',
|
|
155
|
+
toolName: 'Write',
|
|
156
|
+
wasBlocked: false,
|
|
157
|
+
reason: 'Test',
|
|
158
|
+
}, testDir);
|
|
159
|
+
const stats = getViolationStats(testDir);
|
|
160
|
+
expect(stats.byTool['Edit']).toBe(2);
|
|
161
|
+
expect(stats.byTool['Write']).toBe(1);
|
|
162
|
+
});
|
|
163
|
+
it('should count blocked vs allowed violations', () => {
|
|
164
|
+
logViolation({
|
|
165
|
+
timestamp: new Date().toISOString(),
|
|
166
|
+
filePath: 'file1.ts',
|
|
167
|
+
toolName: 'Edit',
|
|
168
|
+
wasBlocked: true,
|
|
169
|
+
reason: 'Blocked',
|
|
170
|
+
}, testDir);
|
|
171
|
+
logViolation({
|
|
172
|
+
timestamp: new Date().toISOString(),
|
|
173
|
+
filePath: 'file2.ts',
|
|
174
|
+
toolName: 'Write',
|
|
175
|
+
wasBlocked: true,
|
|
176
|
+
reason: 'Blocked',
|
|
177
|
+
}, testDir);
|
|
178
|
+
logViolation({
|
|
179
|
+
timestamp: new Date().toISOString(),
|
|
180
|
+
filePath: 'file3.ts',
|
|
181
|
+
toolName: 'Edit',
|
|
182
|
+
wasBlocked: false,
|
|
183
|
+
reason: 'Allowed',
|
|
184
|
+
}, testDir);
|
|
185
|
+
const stats = getViolationStats(testDir);
|
|
186
|
+
expect(stats.blocked).toBe(2);
|
|
187
|
+
expect(stats.allowed).toBe(1);
|
|
188
|
+
});
|
|
189
|
+
it('should handle malformed log lines gracefully', () => {
|
|
190
|
+
const logPath = join(testDir, '.olympus', 'logs', 'hook-violations.jsonl');
|
|
191
|
+
mkdirSync(join(testDir, '.olympus', 'logs'), { recursive: true });
|
|
192
|
+
// Write valid and invalid lines
|
|
193
|
+
const fs = require('fs');
|
|
194
|
+
fs.writeFileSync(logPath, JSON.stringify({
|
|
195
|
+
timestamp: new Date().toISOString(),
|
|
196
|
+
filePath: 'file1.ts',
|
|
197
|
+
toolName: 'Edit',
|
|
198
|
+
wasBlocked: true,
|
|
199
|
+
reason: 'Valid',
|
|
200
|
+
}) +
|
|
201
|
+
'\n' +
|
|
202
|
+
'invalid json line\n' +
|
|
203
|
+
JSON.stringify({
|
|
204
|
+
timestamp: new Date().toISOString(),
|
|
205
|
+
filePath: 'file2.ts',
|
|
206
|
+
toolName: 'Write',
|
|
207
|
+
wasBlocked: false,
|
|
208
|
+
reason: 'Valid',
|
|
209
|
+
}) +
|
|
210
|
+
'\n');
|
|
211
|
+
const stats = getViolationStats(testDir);
|
|
212
|
+
expect(stats.total).toBe(2); // Should skip invalid line
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
describe('readViolations', () => {
|
|
216
|
+
it('should return empty array when no log file exists', () => {
|
|
217
|
+
const violations = readViolations(testDir);
|
|
218
|
+
expect(violations).toEqual([]);
|
|
219
|
+
});
|
|
220
|
+
it('should read all violations from log', () => {
|
|
221
|
+
const violation1 = {
|
|
222
|
+
timestamp: new Date().toISOString(),
|
|
223
|
+
filePath: 'file1.ts',
|
|
224
|
+
toolName: 'Edit',
|
|
225
|
+
wasBlocked: true,
|
|
226
|
+
reason: 'Test 1',
|
|
227
|
+
};
|
|
228
|
+
const violation2 = {
|
|
229
|
+
timestamp: new Date().toISOString(),
|
|
230
|
+
filePath: 'file2.ts',
|
|
231
|
+
toolName: 'Write',
|
|
232
|
+
wasBlocked: false,
|
|
233
|
+
reason: 'Test 2',
|
|
234
|
+
};
|
|
235
|
+
logViolation(violation1, testDir);
|
|
236
|
+
logViolation(violation2, testDir);
|
|
237
|
+
const violations = readViolations(testDir);
|
|
238
|
+
expect(violations).toHaveLength(2);
|
|
239
|
+
expect(violations[0]).toEqual(violation1);
|
|
240
|
+
expect(violations[1]).toEqual(violation2);
|
|
241
|
+
});
|
|
242
|
+
it('should skip malformed lines', () => {
|
|
243
|
+
const logPath = join(testDir, '.olympus', 'logs', 'hook-violations.jsonl');
|
|
244
|
+
mkdirSync(join(testDir, '.olympus', 'logs'), { recursive: true });
|
|
245
|
+
const fs = require('fs');
|
|
246
|
+
fs.writeFileSync(logPath, JSON.stringify({
|
|
247
|
+
timestamp: new Date().toISOString(),
|
|
248
|
+
filePath: 'file1.ts',
|
|
249
|
+
toolName: 'Edit',
|
|
250
|
+
wasBlocked: true,
|
|
251
|
+
reason: 'Valid',
|
|
252
|
+
}) +
|
|
253
|
+
'\n' +
|
|
254
|
+
'invalid\n' +
|
|
255
|
+
JSON.stringify({
|
|
256
|
+
timestamp: new Date().toISOString(),
|
|
257
|
+
filePath: 'file2.ts',
|
|
258
|
+
toolName: 'Write',
|
|
259
|
+
wasBlocked: false,
|
|
260
|
+
reason: 'Valid',
|
|
261
|
+
}) +
|
|
262
|
+
'\n');
|
|
263
|
+
const violations = readViolations(testDir);
|
|
264
|
+
expect(violations).toHaveLength(2);
|
|
265
|
+
});
|
|
266
|
+
});
|
|
267
|
+
});
|
|
268
|
+
//# sourceMappingURL=index.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../../src/features/hook-logging/index.test.ts"],"names":[],"mappings":"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"}
|