@mmnto/cli 0.23.0 → 0.25.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/dist/commands/extract.d.ts +1 -1
- package/dist/commands/extract.d.ts.map +1 -1
- package/dist/commands/extract.js +2 -8
- package/dist/commands/extract.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +34 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/install-hooks.d.ts +20 -0
- package/dist/commands/install-hooks.d.ts.map +1 -1
- package/dist/commands/install-hooks.js +150 -21
- package/dist/commands/install-hooks.js.map +1 -1
- package/dist/commands/install-hooks.test.d.ts +2 -0
- package/dist/commands/install-hooks.test.d.ts.map +1 -0
- package/dist/commands/install-hooks.test.js +221 -0
- package/dist/commands/install-hooks.test.js.map +1 -0
- package/dist/commands/shield-eval.integration.test.d.ts +2 -0
- package/dist/commands/shield-eval.integration.test.d.ts.map +1 -0
- package/dist/commands/shield-eval.integration.test.js +321 -0
- package/dist/commands/shield-eval.integration.test.js.map +1 -0
- package/dist/orchestrators/anthropic-orchestrator.test.js +2 -2
- package/dist/orchestrators/anthropic-orchestrator.test.js.map +1 -1
- package/dist/orchestrators/openai-orchestrator.test.js +2 -2
- package/dist/orchestrators/openai-orchestrator.test.js.map +1 -1
- package/dist/orchestrators/orchestrator.test.js +6 -6
- package/dist/orchestrators/orchestrator.test.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as os from 'node:os';
|
|
3
|
+
import * as path from 'node:path';
|
|
4
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
5
|
+
import { buildPreCommitHook, buildPrePushHook, detectTotemPrefix, installGitHook, TOTEM_PRECOMMIT_MARKER, TOTEM_PREPUSH_MARKER, } from './install-hooks.js';
|
|
6
|
+
describe('detectTotemPrefix', () => {
|
|
7
|
+
let tmpDir;
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'totem-detect-'));
|
|
10
|
+
});
|
|
11
|
+
afterEach(() => {
|
|
12
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
13
|
+
});
|
|
14
|
+
it('returns pnpm exec when pnpm-lock.yaml exists', () => {
|
|
15
|
+
fs.writeFileSync(path.join(tmpDir, 'pnpm-lock.yaml'), '');
|
|
16
|
+
expect(detectTotemPrefix(tmpDir)).toBe('pnpm exec totem');
|
|
17
|
+
});
|
|
18
|
+
it('returns yarn when yarn.lock exists', () => {
|
|
19
|
+
fs.writeFileSync(path.join(tmpDir, 'yarn.lock'), '');
|
|
20
|
+
expect(detectTotemPrefix(tmpDir)).toBe('yarn totem');
|
|
21
|
+
});
|
|
22
|
+
it('returns bunx when bun.lockb exists (legacy)', () => {
|
|
23
|
+
fs.writeFileSync(path.join(tmpDir, 'bun.lockb'), '');
|
|
24
|
+
expect(detectTotemPrefix(tmpDir)).toBe('bunx totem');
|
|
25
|
+
});
|
|
26
|
+
it('returns bunx when bun.lock exists (Bun >= 1.2)', () => {
|
|
27
|
+
fs.writeFileSync(path.join(tmpDir, 'bun.lock'), '');
|
|
28
|
+
expect(detectTotemPrefix(tmpDir)).toBe('bunx totem');
|
|
29
|
+
});
|
|
30
|
+
it('falls back to npx when no lockfile exists', () => {
|
|
31
|
+
expect(detectTotemPrefix(tmpDir)).toBe('npx totem');
|
|
32
|
+
});
|
|
33
|
+
it('prefers pnpm over bun when both lockfiles exist', () => {
|
|
34
|
+
fs.writeFileSync(path.join(tmpDir, 'pnpm-lock.yaml'), '');
|
|
35
|
+
fs.writeFileSync(path.join(tmpDir, 'bun.lock'), '');
|
|
36
|
+
expect(detectTotemPrefix(tmpDir)).toBe('pnpm exec totem');
|
|
37
|
+
});
|
|
38
|
+
it('prefers yarn over bun when both lockfiles exist', () => {
|
|
39
|
+
fs.writeFileSync(path.join(tmpDir, 'yarn.lock'), '');
|
|
40
|
+
fs.writeFileSync(path.join(tmpDir, 'bun.lockb'), '');
|
|
41
|
+
expect(detectTotemPrefix(tmpDir)).toBe('yarn totem');
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
describe('buildPreCommitHook', () => {
|
|
45
|
+
it('contains the marker for idempotency', () => {
|
|
46
|
+
const hook = buildPreCommitHook();
|
|
47
|
+
expect(hook).toContain(TOTEM_PRECOMMIT_MARKER);
|
|
48
|
+
});
|
|
49
|
+
it('blocks main and master branches', () => {
|
|
50
|
+
const hook = buildPreCommitHook();
|
|
51
|
+
expect(hook).toContain('"main"');
|
|
52
|
+
expect(hook).toContain('"master"');
|
|
53
|
+
});
|
|
54
|
+
it('prints a helpful error message with override instructions', () => {
|
|
55
|
+
const hook = buildPreCommitHook();
|
|
56
|
+
expect(hook).toContain('git checkout -b feat/my-feature');
|
|
57
|
+
expect(hook).toContain('git commit --no-verify');
|
|
58
|
+
});
|
|
59
|
+
it('starts with a shebang', () => {
|
|
60
|
+
const hook = buildPreCommitHook();
|
|
61
|
+
expect(hook).toMatch(/^#!\/bin\/sh\n/);
|
|
62
|
+
});
|
|
63
|
+
it('exits with code 1 when on protected branch', () => {
|
|
64
|
+
const hook = buildPreCommitHook();
|
|
65
|
+
expect(hook).toContain('exit 1');
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
describe('buildPrePushHook', () => {
|
|
69
|
+
const shieldCmd = 'pnpm exec totem shield --deterministic';
|
|
70
|
+
it('contains the marker for idempotency', () => {
|
|
71
|
+
const hook = buildPrePushHook(shieldCmd);
|
|
72
|
+
expect(hook).toContain(TOTEM_PREPUSH_MARKER);
|
|
73
|
+
});
|
|
74
|
+
it('only runs shield when compiled-rules.json exists (if/fi, safe for appending)', () => {
|
|
75
|
+
const hook = buildPrePushHook(shieldCmd);
|
|
76
|
+
expect(hook).toContain('if [ -f ".totem/compiled-rules.json" ]; then');
|
|
77
|
+
expect(hook).toContain('fi');
|
|
78
|
+
// Must use if/fi guard, NOT `&& exit 0` which would terminate appended hooks early
|
|
79
|
+
expect(hook).not.toContain('&& exit 0');
|
|
80
|
+
});
|
|
81
|
+
it('runs the shield command when rules exist', () => {
|
|
82
|
+
const hook = buildPrePushHook(shieldCmd);
|
|
83
|
+
expect(hook).toContain(shieldCmd);
|
|
84
|
+
});
|
|
85
|
+
it('mentions --no-verify override', () => {
|
|
86
|
+
const hook = buildPrePushHook(shieldCmd);
|
|
87
|
+
expect(hook).toContain('git push --no-verify');
|
|
88
|
+
});
|
|
89
|
+
it('starts with a shebang', () => {
|
|
90
|
+
const hook = buildPrePushHook(shieldCmd);
|
|
91
|
+
expect(hook).toMatch(/^#!\/bin\/sh\n/);
|
|
92
|
+
});
|
|
93
|
+
it('uses the provided shield command (respects package manager)', () => {
|
|
94
|
+
const npxHook = buildPrePushHook('npx totem shield --deterministic');
|
|
95
|
+
expect(npxHook).toContain('npx totem shield --deterministic');
|
|
96
|
+
const yarnHook = buildPrePushHook('yarn totem shield --deterministic');
|
|
97
|
+
expect(yarnHook).toContain('yarn totem shield --deterministic');
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
describe('installGitHook', () => {
|
|
101
|
+
let tmpDir;
|
|
102
|
+
let hooksDir;
|
|
103
|
+
beforeEach(() => {
|
|
104
|
+
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'totem-hooks-'));
|
|
105
|
+
hooksDir = path.join(tmpDir, '.git', 'hooks');
|
|
106
|
+
});
|
|
107
|
+
afterEach(() => {
|
|
108
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
109
|
+
});
|
|
110
|
+
it('creates a new hook file when none exists', () => {
|
|
111
|
+
const content = buildPreCommitHook();
|
|
112
|
+
const result = installGitHook(hooksDir, 'pre-commit', content, TOTEM_PRECOMMIT_MARKER);
|
|
113
|
+
expect(result).toBe('installed');
|
|
114
|
+
expect(fs.existsSync(path.join(hooksDir, 'pre-commit'))).toBe(true);
|
|
115
|
+
const written = fs.readFileSync(path.join(hooksDir, 'pre-commit'), 'utf-8');
|
|
116
|
+
expect(written).toContain(TOTEM_PRECOMMIT_MARKER);
|
|
117
|
+
});
|
|
118
|
+
it('creates parent directories as needed', () => {
|
|
119
|
+
expect(fs.existsSync(hooksDir)).toBe(false);
|
|
120
|
+
installGitHook(hooksDir, 'pre-commit', buildPreCommitHook(), TOTEM_PRECOMMIT_MARKER);
|
|
121
|
+
expect(fs.existsSync(hooksDir)).toBe(true);
|
|
122
|
+
});
|
|
123
|
+
it('returns exists when marker is already present (idempotent)', () => {
|
|
124
|
+
const content = buildPreCommitHook();
|
|
125
|
+
installGitHook(hooksDir, 'pre-commit', content, TOTEM_PRECOMMIT_MARKER);
|
|
126
|
+
const result = installGitHook(hooksDir, 'pre-commit', content, TOTEM_PRECOMMIT_MARKER);
|
|
127
|
+
expect(result).toBe('exists');
|
|
128
|
+
});
|
|
129
|
+
it('appends to existing hook without marker (preserves user hooks)', () => {
|
|
130
|
+
fs.mkdirSync(hooksDir, { recursive: true });
|
|
131
|
+
const hookPath = path.join(hooksDir, 'pre-commit');
|
|
132
|
+
const userHook = '#!/bin/sh\necho "user hook"\n';
|
|
133
|
+
fs.writeFileSync(hookPath, userHook);
|
|
134
|
+
const result = installGitHook(hooksDir, 'pre-commit', buildPreCommitHook(), TOTEM_PRECOMMIT_MARKER);
|
|
135
|
+
expect(result).toBe('appended');
|
|
136
|
+
const written = fs.readFileSync(hookPath, 'utf-8');
|
|
137
|
+
expect(written).toContain('echo "user hook"');
|
|
138
|
+
expect(written).toContain(TOTEM_PRECOMMIT_MARKER);
|
|
139
|
+
// Should not duplicate shebang when appending
|
|
140
|
+
expect((written.match(/^#!\/bin\/sh$/gm) ?? []).length).toBe(1);
|
|
141
|
+
});
|
|
142
|
+
it('does not clobber existing hook content', () => {
|
|
143
|
+
fs.mkdirSync(hooksDir, { recursive: true });
|
|
144
|
+
const hookPath = path.join(hooksDir, 'pre-push');
|
|
145
|
+
const userHook = '#!/bin/sh\nrun_my_tests\n';
|
|
146
|
+
fs.writeFileSync(hookPath, userHook);
|
|
147
|
+
installGitHook(hooksDir, 'pre-push', buildPrePushHook('npx totem shield --deterministic'), TOTEM_PREPUSH_MARKER);
|
|
148
|
+
const written = fs.readFileSync(hookPath, 'utf-8');
|
|
149
|
+
expect(written).toContain('run_my_tests');
|
|
150
|
+
expect(written).toContain(TOTEM_PREPUSH_MARKER);
|
|
151
|
+
});
|
|
152
|
+
it('is idempotent — double install does not duplicate', () => {
|
|
153
|
+
const content = buildPrePushHook('npx totem shield --deterministic');
|
|
154
|
+
installGitHook(hooksDir, 'pre-push', content, TOTEM_PREPUSH_MARKER);
|
|
155
|
+
installGitHook(hooksDir, 'pre-push', content, TOTEM_PREPUSH_MARKER);
|
|
156
|
+
const written = fs.readFileSync(path.join(hooksDir, 'pre-push'), 'utf-8');
|
|
157
|
+
const matches = written.match(new RegExp(TOTEM_PREPUSH_MARKER.replace(/[[\]]/g, '\\$&'), 'g'));
|
|
158
|
+
expect(matches).toHaveLength(1);
|
|
159
|
+
});
|
|
160
|
+
it('returns skipped-non-shell for Node hook (does not corrupt file)', () => {
|
|
161
|
+
fs.mkdirSync(hooksDir, { recursive: true });
|
|
162
|
+
const hookPath = path.join(hooksDir, 'pre-commit');
|
|
163
|
+
const nodeHook = '#!/usr/bin/env node\nconsole.log("lint");\n'; // totem-ignore — test fixture, not real logging
|
|
164
|
+
fs.writeFileSync(hookPath, nodeHook);
|
|
165
|
+
const result = installGitHook(hooksDir, 'pre-commit', buildPreCommitHook(), TOTEM_PRECOMMIT_MARKER);
|
|
166
|
+
expect(result).toBe('skipped-non-shell');
|
|
167
|
+
const written = fs.readFileSync(hookPath, 'utf-8');
|
|
168
|
+
expect(written).toBe(nodeHook); // File untouched
|
|
169
|
+
});
|
|
170
|
+
it('returns skipped-non-shell for Python hook', () => {
|
|
171
|
+
fs.mkdirSync(hooksDir, { recursive: true });
|
|
172
|
+
const hookPath = path.join(hooksDir, 'pre-push');
|
|
173
|
+
const pythonHook = '#!/usr/bin/env python3\nimport subprocess\n';
|
|
174
|
+
fs.writeFileSync(hookPath, pythonHook);
|
|
175
|
+
const result = installGitHook(hooksDir, 'pre-push', buildPrePushHook('npx totem shield --deterministic'), TOTEM_PREPUSH_MARKER);
|
|
176
|
+
expect(result).toBe('skipped-non-shell');
|
|
177
|
+
const written = fs.readFileSync(hookPath, 'utf-8');
|
|
178
|
+
expect(written).toBe(pythonHook); // File untouched
|
|
179
|
+
});
|
|
180
|
+
it('appends normally to sh hooks', () => {
|
|
181
|
+
fs.mkdirSync(hooksDir, { recursive: true });
|
|
182
|
+
const hookPath = path.join(hooksDir, 'pre-commit');
|
|
183
|
+
fs.writeFileSync(hookPath, '#!/bin/sh\necho "existing"\n');
|
|
184
|
+
const result = installGitHook(hooksDir, 'pre-commit', buildPreCommitHook(), TOTEM_PRECOMMIT_MARKER);
|
|
185
|
+
expect(result).toBe('appended');
|
|
186
|
+
});
|
|
187
|
+
it('appends normally to bash hooks', () => {
|
|
188
|
+
fs.mkdirSync(hooksDir, { recursive: true });
|
|
189
|
+
const hookPath = path.join(hooksDir, 'pre-commit');
|
|
190
|
+
fs.writeFileSync(hookPath, '#!/bin/bash\necho "existing"\n');
|
|
191
|
+
const result = installGitHook(hooksDir, 'pre-commit', buildPreCommitHook(), TOTEM_PRECOMMIT_MARKER);
|
|
192
|
+
expect(result).toBe('appended');
|
|
193
|
+
});
|
|
194
|
+
it('appends normally to env bash hooks', () => {
|
|
195
|
+
fs.mkdirSync(hooksDir, { recursive: true });
|
|
196
|
+
const hookPath = path.join(hooksDir, 'pre-commit');
|
|
197
|
+
fs.writeFileSync(hookPath, '#!/usr/bin/env bash\necho "existing"\n');
|
|
198
|
+
const result = installGitHook(hooksDir, 'pre-commit', buildPreCommitHook(), TOTEM_PRECOMMIT_MARKER);
|
|
199
|
+
expect(result).toBe('appended');
|
|
200
|
+
});
|
|
201
|
+
it('appends to hooks without a shebang (plain text)', () => {
|
|
202
|
+
fs.mkdirSync(hooksDir, { recursive: true });
|
|
203
|
+
const hookPath = path.join(hooksDir, 'pre-commit');
|
|
204
|
+
fs.writeFileSync(hookPath, 'echo "no shebang"\n');
|
|
205
|
+
const result = installGitHook(hooksDir, 'pre-commit', buildPreCommitHook(), TOTEM_PRECOMMIT_MARKER);
|
|
206
|
+
expect(result).toBe('appended');
|
|
207
|
+
});
|
|
208
|
+
it('handles pre-commit and pre-push independently', () => {
|
|
209
|
+
installGitHook(hooksDir, 'pre-commit', buildPreCommitHook(), TOTEM_PRECOMMIT_MARKER);
|
|
210
|
+
installGitHook(hooksDir, 'pre-push', buildPrePushHook('pnpm exec totem shield --deterministic'), TOTEM_PREPUSH_MARKER);
|
|
211
|
+
expect(fs.existsSync(path.join(hooksDir, 'pre-commit'))).toBe(true);
|
|
212
|
+
expect(fs.existsSync(path.join(hooksDir, 'pre-push'))).toBe(true);
|
|
213
|
+
const preCommit = fs.readFileSync(path.join(hooksDir, 'pre-commit'), 'utf-8');
|
|
214
|
+
const prePush = fs.readFileSync(path.join(hooksDir, 'pre-push'), 'utf-8');
|
|
215
|
+
expect(preCommit).toContain(TOTEM_PRECOMMIT_MARKER);
|
|
216
|
+
expect(preCommit).not.toContain(TOTEM_PREPUSH_MARKER);
|
|
217
|
+
expect(prePush).toContain(TOTEM_PREPUSH_MARKER);
|
|
218
|
+
expect(prePush).not.toContain(TOTEM_PRECOMMIT_MARKER);
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
//# sourceMappingURL=install-hooks.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-hooks.test.js","sourceRoot":"","sources":["../../src/commands/install-hooks.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shield-eval.integration.test.d.ts","sourceRoot":"","sources":["../../src/commands/shield-eval.integration.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adversarial Evaluation Harness — Model Drift Detection
|
|
3
|
+
*
|
|
4
|
+
* Sets up a real git repository with planted architectural violations
|
|
5
|
+
* and corresponding Totem lessons, then runs `totem shield` to verify
|
|
6
|
+
* that both deterministic and LLM modes catch the planted traps.
|
|
7
|
+
*
|
|
8
|
+
* Deterministic tests run on every CI run (no API keys needed).
|
|
9
|
+
* LLM tests are gated behind CI_INTEGRATION=true (nightly only).
|
|
10
|
+
*
|
|
11
|
+
* Run locally:
|
|
12
|
+
* pnpm --filter @mmnto/cli vitest run -c vitest.integration.config.ts shield-eval
|
|
13
|
+
* CI_INTEGRATION=true GEMINI_API_KEY=... pnpm --filter @mmnto/cli vitest run -c vitest.integration.config.ts shield-eval
|
|
14
|
+
*
|
|
15
|
+
* @see https://github.com/mmnto-ai/totem/issues/196
|
|
16
|
+
*/
|
|
17
|
+
import { execSync } from 'node:child_process';
|
|
18
|
+
import * as fs from 'node:fs';
|
|
19
|
+
import * as os from 'node:os';
|
|
20
|
+
import * as path from 'node:path';
|
|
21
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
22
|
+
import { applyRules, applyRulesToAdditions, extractAddedLines, hashLesson, } from '@mmnto/totem';
|
|
23
|
+
import { parseVerdict } from './shield.js';
|
|
24
|
+
// ─── Adversarial Fixtures ────────────────────────────
|
|
25
|
+
/** Planted trap rules that map to specific violations in the bad code. */
|
|
26
|
+
const TRAP_RULES = [
|
|
27
|
+
{
|
|
28
|
+
lessonHash: hashLesson('Use fs/promises not fs', 'TRAP-001: Never import fs directly'),
|
|
29
|
+
lessonHeading: 'Use fs/promises not fs',
|
|
30
|
+
pattern: 'import\\s+.*\\bfrom\\s+[\'"]fs[\'"]',
|
|
31
|
+
message: 'TRAP-001: Never import fs directly — use fs/promises for async safety',
|
|
32
|
+
engine: 'regex',
|
|
33
|
+
compiledAt: new Date().toISOString(),
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
lessonHash: hashLesson('No console.log in library code', 'TRAP-002'),
|
|
37
|
+
lessonHeading: 'No console.log in library code',
|
|
38
|
+
pattern: 'console\\.log\\(',
|
|
39
|
+
message: 'TRAP-002: Use structured logger, not console.log, in library code',
|
|
40
|
+
engine: 'regex',
|
|
41
|
+
compiledAt: new Date().toISOString(),
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
lessonHash: hashLesson('Catch blocks use err not error', 'TRAP-003'),
|
|
45
|
+
lessonHeading: 'Catch blocks use err not error',
|
|
46
|
+
pattern: 'catch\\s*\\(\\s*error\\s*[\\):]',
|
|
47
|
+
message: 'TRAP-003: Use err (not error) in catch blocks — project convention',
|
|
48
|
+
engine: 'regex',
|
|
49
|
+
compiledAt: new Date().toISOString(),
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
lessonHash: hashLesson('No sync file reads', 'TRAP-004'),
|
|
53
|
+
lessonHeading: 'No sync file reads',
|
|
54
|
+
pattern: 'readFileSync',
|
|
55
|
+
message: 'TRAP-004: Use async readFile, not readFileSync, in request handlers',
|
|
56
|
+
engine: 'regex',
|
|
57
|
+
compiledAt: new Date().toISOString(),
|
|
58
|
+
},
|
|
59
|
+
];
|
|
60
|
+
/** Totem lessons that match the trap rules (for LLM mode context). */
|
|
61
|
+
const TRAP_LESSONS = `# Lessons
|
|
62
|
+
|
|
63
|
+
## Lesson — Use fs/promises not fs
|
|
64
|
+
TRAP-001: Never import \`fs\` directly in library code. Always use \`fs/promises\`
|
|
65
|
+
for async safety. Direct \`fs\` imports lead to blocking I/O in request handlers.
|
|
66
|
+
|
|
67
|
+
## Lesson — No console.log in library code
|
|
68
|
+
TRAP-002: Library modules must use a structured logger (onWarn callback or
|
|
69
|
+
similar pattern), never \`console.log()\`. Console output breaks MCP stdio
|
|
70
|
+
transport and pollutes test output.
|
|
71
|
+
|
|
72
|
+
## Lesson — Catch blocks use err not error
|
|
73
|
+
TRAP-003: All catch blocks must use \`err\` as the variable name, never \`error\`.
|
|
74
|
+
This is a project-wide convention enforced by the style guide.
|
|
75
|
+
|
|
76
|
+
## Lesson — No sync file reads
|
|
77
|
+
TRAP-004: Never use \`readFileSync\` in request handlers or hot paths. Use
|
|
78
|
+
\`readFile\` from \`fs/promises\` for non-blocking I/O.
|
|
79
|
+
`;
|
|
80
|
+
/** Clean code that passes all rules — used as baseline commit. */
|
|
81
|
+
const CLEAN_CODE = `import { readFile } from 'fs/promises';
|
|
82
|
+
|
|
83
|
+
export async function loadConfig(configPath: string): Promise<string> {
|
|
84
|
+
try {
|
|
85
|
+
const content = await readFile(configPath, 'utf-8');
|
|
86
|
+
return content;
|
|
87
|
+
} catch (err) {
|
|
88
|
+
throw new Error(\`Failed to load config: \${(err as Error).message}\`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
`;
|
|
92
|
+
/** Bad code with 4 planted violations — staged after baseline. */
|
|
93
|
+
const BAD_CODE = `import fs from 'fs';
|
|
94
|
+
|
|
95
|
+
export async function loadConfig(configPath: string): Promise<string> {
|
|
96
|
+
try {
|
|
97
|
+
console.log('Loading config from', configPath);
|
|
98
|
+
const content = fs.readFileSync(configPath, 'utf-8');
|
|
99
|
+
return content;
|
|
100
|
+
} catch (error) {
|
|
101
|
+
throw new Error(\`Failed to load config: \${(error as Error).message}\`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
`;
|
|
105
|
+
/** The diff that shield will see (pre-computed for deterministic tests). */
|
|
106
|
+
const EXPECTED_DIFF = `diff --git a/src/config.ts b/src/config.ts
|
|
107
|
+
--- a/src/config.ts
|
|
108
|
+
+++ b/src/config.ts
|
|
109
|
+
@@ -1,9 +1,10 @@
|
|
110
|
+
-import { readFile } from 'fs/promises';
|
|
111
|
+
+import fs from 'fs';
|
|
112
|
+
|
|
113
|
+
export async function loadConfig(configPath: string): Promise<string> {
|
|
114
|
+
try {
|
|
115
|
+
- const content = await readFile(configPath, 'utf-8');
|
|
116
|
+
+ console.log('Loading config from', configPath);
|
|
117
|
+
+ const content = fs.readFileSync(configPath, 'utf-8');
|
|
118
|
+
return content;
|
|
119
|
+
- } catch (err) {
|
|
120
|
+
- throw new Error(\`Failed to load config: \${(err as Error).message}\`);
|
|
121
|
+
+ } catch (error) {
|
|
122
|
+
+ throw new Error(\`Failed to load config: \${(error as Error).message}\`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
`;
|
|
126
|
+
// ─── Test helpers ────────────────────────────────────
|
|
127
|
+
function git(cmd, cwd) {
|
|
128
|
+
return execSync(`git ${cmd}`, {
|
|
129
|
+
cwd,
|
|
130
|
+
encoding: 'utf-8',
|
|
131
|
+
timeout: 15_000,
|
|
132
|
+
env: { ...process.env, GIT_TERMINAL_PROMPT: '0' },
|
|
133
|
+
}).trim();
|
|
134
|
+
}
|
|
135
|
+
function scaffoldAdversarialRepo(tmpDir) {
|
|
136
|
+
// Initialize git repo
|
|
137
|
+
git('init', tmpDir);
|
|
138
|
+
git('config user.email "eval@totem.dev"', tmpDir);
|
|
139
|
+
git('config user.name "Totem Eval"', tmpDir);
|
|
140
|
+
// Create directory structure
|
|
141
|
+
const srcDir = path.join(tmpDir, 'src');
|
|
142
|
+
const totemDir = path.join(tmpDir, '.totem');
|
|
143
|
+
fs.mkdirSync(srcDir, { recursive: true });
|
|
144
|
+
fs.mkdirSync(totemDir, { recursive: true });
|
|
145
|
+
// Write clean baseline
|
|
146
|
+
fs.writeFileSync(path.join(srcDir, 'config.ts'), CLEAN_CODE);
|
|
147
|
+
fs.writeFileSync(path.join(totemDir, 'lessons.md'), TRAP_LESSONS);
|
|
148
|
+
// Write compiled rules for deterministic mode
|
|
149
|
+
const rulesFile = {
|
|
150
|
+
version: 1,
|
|
151
|
+
rules: TRAP_RULES,
|
|
152
|
+
};
|
|
153
|
+
fs.writeFileSync(path.join(totemDir, 'compiled-rules.json'), JSON.stringify(rulesFile, null, 2));
|
|
154
|
+
// Commit baseline
|
|
155
|
+
git('add -A', tmpDir);
|
|
156
|
+
git('commit -m "baseline: clean code"', tmpDir);
|
|
157
|
+
// Stage bad code (this creates the diff shield will see)
|
|
158
|
+
fs.writeFileSync(path.join(srcDir, 'config.ts'), BAD_CODE);
|
|
159
|
+
git('add -A', tmpDir);
|
|
160
|
+
}
|
|
161
|
+
// ─── Deterministic evaluation (no API keys) ─────────
|
|
162
|
+
describe('Adversarial Eval — Deterministic', () => {
|
|
163
|
+
it('catches all 4 planted traps via compiled rules against expected diff', () => {
|
|
164
|
+
const violations = applyRules(TRAP_RULES, EXPECTED_DIFF);
|
|
165
|
+
expect(violations.length).toBeGreaterThanOrEqual(4); // totem-ignore
|
|
166
|
+
const headings = new Set(violations.map((v) => v.rule.lessonHeading));
|
|
167
|
+
expect(headings.has('Use fs/promises not fs')).toBe(true);
|
|
168
|
+
expect(headings.has('No console.log in library code')).toBe(true);
|
|
169
|
+
expect(headings.has('Catch blocks use err not error')).toBe(true);
|
|
170
|
+
expect(headings.has('No sync file reads')).toBe(true);
|
|
171
|
+
});
|
|
172
|
+
it('catches all traps with AST-aware additions pipeline', () => {
|
|
173
|
+
const additions = extractAddedLines(EXPECTED_DIFF);
|
|
174
|
+
const violations = applyRulesToAdditions(TRAP_RULES, additions);
|
|
175
|
+
// extractAddedLines only processes + lines, so we should still catch violations
|
|
176
|
+
const headings = new Set(violations.map((v) => v.rule.lessonHeading));
|
|
177
|
+
expect(headings.has('Use fs/promises not fs')).toBe(true);
|
|
178
|
+
expect(headings.has('No console.log in library code')).toBe(true);
|
|
179
|
+
expect(headings.has('No sync file reads')).toBe(true);
|
|
180
|
+
expect(headings.has('Catch blocks use err not error')).toBe(true);
|
|
181
|
+
});
|
|
182
|
+
it('passes a clean diff with zero violations', () => {
|
|
183
|
+
const cleanDiff = `diff --git a/src/clean.ts b/src/clean.ts
|
|
184
|
+
--- a/src/clean.ts
|
|
185
|
+
+++ b/src/clean.ts
|
|
186
|
+
@@ -1,3 +1,5 @@
|
|
187
|
+
export function greet(name: string): string {
|
|
188
|
+
- return 'hello';
|
|
189
|
+
+ return \`Hello, \${name}!\`;
|
|
190
|
+
}
|
|
191
|
+
`;
|
|
192
|
+
const violations = applyRules(TRAP_RULES, cleanDiff);
|
|
193
|
+
expect(violations).toHaveLength(0);
|
|
194
|
+
});
|
|
195
|
+
it('sets up a real git repo and produces a valid diff', () => {
|
|
196
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'totem-eval-'));
|
|
197
|
+
try {
|
|
198
|
+
scaffoldAdversarialRepo(tmpDir);
|
|
199
|
+
// Verify the staged diff contains our planted violations
|
|
200
|
+
const diff = git('diff --staged', tmpDir);
|
|
201
|
+
expect(diff).toContain("import fs from 'fs'");
|
|
202
|
+
expect(diff).toContain('console.log');
|
|
203
|
+
expect(diff).toContain('readFileSync');
|
|
204
|
+
expect(diff).toContain('catch (error)');
|
|
205
|
+
// Run compiled rules against the real diff
|
|
206
|
+
const violations = applyRules(TRAP_RULES, diff);
|
|
207
|
+
expect(violations.length).toBeGreaterThanOrEqual(4); // totem-ignore
|
|
208
|
+
}
|
|
209
|
+
finally {
|
|
210
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
// ─── LLM evaluation (nightly, requires API keys) ────
|
|
215
|
+
const EVAL_TIMEOUT_MS = 120_000; // 2 min — LLM can be slow
|
|
216
|
+
describe.runIf(process.env['CI_INTEGRATION'] === 'true')('Adversarial Eval — LLM Model Drift', () => {
|
|
217
|
+
let tmpDir;
|
|
218
|
+
beforeEach(() => {
|
|
219
|
+
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'totem-eval-llm-'));
|
|
220
|
+
scaffoldAdversarialRepo(tmpDir);
|
|
221
|
+
});
|
|
222
|
+
afterEach(() => {
|
|
223
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
224
|
+
});
|
|
225
|
+
/**
|
|
226
|
+
* Run shield as a subprocess against the adversarial repo.
|
|
227
|
+
* Returns stdout, stderr, and exit code.
|
|
228
|
+
*/
|
|
229
|
+
function runShield(args, env = {}) {
|
|
230
|
+
const cliEntry = path.resolve('dist/index.js');
|
|
231
|
+
const cmd = `node ${cliEntry} shield ${args.join(' ')}`;
|
|
232
|
+
try {
|
|
233
|
+
const stdout = execSync(cmd, {
|
|
234
|
+
cwd: tmpDir,
|
|
235
|
+
encoding: 'utf-8',
|
|
236
|
+
timeout: EVAL_TIMEOUT_MS,
|
|
237
|
+
env: {
|
|
238
|
+
...process.env,
|
|
239
|
+
...env,
|
|
240
|
+
GIT_TERMINAL_PROMPT: '0',
|
|
241
|
+
},
|
|
242
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
243
|
+
});
|
|
244
|
+
return { stdout, stderr: '', exitCode: 0 };
|
|
245
|
+
}
|
|
246
|
+
catch (err) {
|
|
247
|
+
const e = err;
|
|
248
|
+
return {
|
|
249
|
+
stdout: e.stdout ?? '',
|
|
250
|
+
stderr: e.stderr ?? '',
|
|
251
|
+
exitCode: e.status ?? 1,
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
it('deterministic shield exits 1 and catches planted traps via subprocess', () => {
|
|
256
|
+
const { exitCode, stdout, stderr } = runShield(['--deterministic', '--staged']);
|
|
257
|
+
const output = stdout + stderr;
|
|
258
|
+
expect(exitCode).toBe(1);
|
|
259
|
+
expect(output).toContain('TRAP-001');
|
|
260
|
+
expect(output).toContain('TRAP-002');
|
|
261
|
+
expect(output).toContain('TRAP-003');
|
|
262
|
+
expect(output).toContain('TRAP-004');
|
|
263
|
+
}, EVAL_TIMEOUT_MS);
|
|
264
|
+
// Gemini model drift test
|
|
265
|
+
it.runIf(!!process.env['GEMINI_API_KEY'])('Gemini catches planted traps (FAIL verdict expected)', async () => {
|
|
266
|
+
// Write a minimal totem.config.ts for the adversarial repo
|
|
267
|
+
const config = `
|
|
268
|
+
export default {
|
|
269
|
+
targets: [{ glob: 'src/**/*.ts', type: 'code', strategy: 'typescript-ast' }],
|
|
270
|
+
totemDir: '.totem',
|
|
271
|
+
lanceDir: '.lancedb',
|
|
272
|
+
orchestrator: { provider: 'gemini', model: 'gemini-2.5-flash' },
|
|
273
|
+
};
|
|
274
|
+
`;
|
|
275
|
+
fs.writeFileSync(path.join(tmpDir, 'totem.config.ts'), config);
|
|
276
|
+
const { exitCode, stdout, stderr } = runShield(['--staged', '--mode=structural'], {
|
|
277
|
+
GEMINI_API_KEY: process.env['GEMINI_API_KEY'],
|
|
278
|
+
});
|
|
279
|
+
const output = stdout + stderr;
|
|
280
|
+
// The model should detect at least some of the violations and FAIL
|
|
281
|
+
const verdict = parseVerdict(stdout);
|
|
282
|
+
expect(exitCode === 1 || (verdict && !verdict.pass), `Expected FAIL verdict but got exitCode=${exitCode}, verdict=${JSON.stringify(verdict)}\nOutput:\n${output}`).toBe(true);
|
|
283
|
+
}, EVAL_TIMEOUT_MS);
|
|
284
|
+
// Anthropic model drift test
|
|
285
|
+
it.runIf(!!process.env['ANTHROPIC_API_KEY'])('Anthropic catches planted traps (FAIL verdict expected)', async () => {
|
|
286
|
+
const config = `
|
|
287
|
+
export default {
|
|
288
|
+
targets: [{ glob: 'src/**/*.ts', type: 'code', strategy: 'typescript-ast' }],
|
|
289
|
+
totemDir: '.totem',
|
|
290
|
+
lanceDir: '.lancedb',
|
|
291
|
+
orchestrator: { provider: 'anthropic', model: 'claude-haiku-4-5-20251001' },
|
|
292
|
+
};
|
|
293
|
+
`;
|
|
294
|
+
fs.writeFileSync(path.join(tmpDir, 'totem.config.ts'), config);
|
|
295
|
+
const { exitCode, stdout, stderr } = runShield(['--staged', '--mode=structural'], {
|
|
296
|
+
ANTHROPIC_API_KEY: process.env['ANTHROPIC_API_KEY'],
|
|
297
|
+
});
|
|
298
|
+
const output = stdout + stderr;
|
|
299
|
+
const verdict = parseVerdict(stdout);
|
|
300
|
+
expect(exitCode === 1 || (verdict && !verdict.pass), `Expected FAIL verdict but got exitCode=${exitCode}, verdict=${JSON.stringify(verdict)}\nOutput:\n${output}`).toBe(true);
|
|
301
|
+
}, EVAL_TIMEOUT_MS);
|
|
302
|
+
// OpenAI model drift test
|
|
303
|
+
it.runIf(!!process.env['OPENAI_API_KEY'])('OpenAI catches planted traps (FAIL verdict expected)', async () => {
|
|
304
|
+
const config = `
|
|
305
|
+
export default {
|
|
306
|
+
targets: [{ glob: 'src/**/*.ts', type: 'code', strategy: 'typescript-ast' }],
|
|
307
|
+
totemDir: '.totem',
|
|
308
|
+
lanceDir: '.lancedb',
|
|
309
|
+
orchestrator: { provider: 'openai', model: 'gpt-5-mini' },
|
|
310
|
+
};
|
|
311
|
+
`;
|
|
312
|
+
fs.writeFileSync(path.join(tmpDir, 'totem.config.ts'), config);
|
|
313
|
+
const { exitCode, stdout, stderr } = runShield(['--staged', '--mode=structural'], {
|
|
314
|
+
OPENAI_API_KEY: process.env['OPENAI_API_KEY'],
|
|
315
|
+
});
|
|
316
|
+
const output = stdout + stderr;
|
|
317
|
+
const verdict = parseVerdict(stdout);
|
|
318
|
+
expect(exitCode === 1 || (verdict && !verdict.pass), `Expected FAIL verdict but got exitCode=${exitCode}, verdict=${JSON.stringify(verdict)}\nOutput:\n${output}`).toBe(true);
|
|
319
|
+
}, EVAL_TIMEOUT_MS);
|
|
320
|
+
});
|
|
321
|
+
//# sourceMappingURL=shield-eval.integration.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shield-eval.integration.test.js","sourceRoot":"","sources":["../../src/commands/shield-eval.integration.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,7 +16,7 @@ vi.mock('../ui.js', () => ({
|
|
|
16
16
|
describe('invokeAnthropicOrchestrator', () => {
|
|
17
17
|
const baseOpts = {
|
|
18
18
|
prompt: 'test prompt',
|
|
19
|
-
model: 'claude-sonnet-4-
|
|
19
|
+
model: 'claude-sonnet-4-6',
|
|
20
20
|
cwd: '.',
|
|
21
21
|
tag: 'Test',
|
|
22
22
|
totemDir: '.totem',
|
|
@@ -49,7 +49,7 @@ describe('invokeAnthropicOrchestrator', () => {
|
|
|
49
49
|
});
|
|
50
50
|
await invokeAnthropicOrchestrator(baseOpts);
|
|
51
51
|
expect(mockCreate).toHaveBeenCalledWith(expect.objectContaining({
|
|
52
|
-
model: 'claude-sonnet-4-
|
|
52
|
+
model: 'claude-sonnet-4-6',
|
|
53
53
|
messages: [{ role: 'user', content: 'test prompt' }],
|
|
54
54
|
}));
|
|
55
55
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"anthropic-orchestrator.test.js","sourceRoot":"","sources":["../../src/orchestrators/anthropic-orchestrator.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAEzE,OAAO,EAAE,2BAA2B,EAAE,MAAM,6BAA6B,CAAC;AAE1E,uDAAuD;AAEvD,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACvC,UAAU,EAAE,EAAE,CAAC,EAAE,EAAE;CACpB,CAAC,CAAC,CAAC;AAEJ,EAAE,CAAC,IAAI,CAAC,mBAAmB,EAAE,GAAG,EAAE,CAAC,CAAC;IAClC,OAAO,EAAE;QACP,QAAQ,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;KACnC;CACF,CAAC,CAAC,CAAC;AAEJ,EAAE,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC;IACzB,GAAG,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE;CACtF,CAAC,CAAC,CAAC;AAEJ,uDAAuD;AAEvD,QAAQ,CAAC,6BAA6B,EAAE,GAAG,EAAE;IAC3C,MAAM,QAAQ,GAAG;QACf,MAAM,EAAE,aAAa;QACrB,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"anthropic-orchestrator.test.js","sourceRoot":"","sources":["../../src/orchestrators/anthropic-orchestrator.test.ts"],"names":[],"mappings":"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"}
|