@mmnto/cli 1.50.0 → 1.52.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.
Files changed (34) hide show
  1. package/dist/commands/eject.d.ts.map +1 -1
  2. package/dist/commands/eject.js +12 -4
  3. package/dist/commands/eject.js.map +1 -1
  4. package/dist/commands/gate-install.d.ts +59 -0
  5. package/dist/commands/gate-install.d.ts.map +1 -0
  6. package/dist/commands/gate-install.js +111 -0
  7. package/dist/commands/gate-install.js.map +1 -0
  8. package/dist/commands/gate-install.test.d.ts +2 -0
  9. package/dist/commands/gate-install.test.d.ts.map +1 -0
  10. package/dist/commands/gate-install.test.js +472 -0
  11. package/dist/commands/gate-install.test.js.map +1 -0
  12. package/dist/commands/gate.d.ts +47 -0
  13. package/dist/commands/gate.d.ts.map +1 -0
  14. package/dist/commands/gate.js +102 -0
  15. package/dist/commands/gate.js.map +1 -0
  16. package/dist/commands/gate.test.d.ts +2 -0
  17. package/dist/commands/gate.test.d.ts.map +1 -0
  18. package/dist/commands/gate.test.js +104 -0
  19. package/dist/commands/gate.test.js.map +1 -0
  20. package/dist/commands/host-hooks.d.ts +745 -0
  21. package/dist/commands/host-hooks.d.ts.map +1 -0
  22. package/dist/commands/host-hooks.js +229 -0
  23. package/dist/commands/host-hooks.js.map +1 -0
  24. package/dist/commands/init-templates.d.ts +8 -0
  25. package/dist/commands/init-templates.d.ts.map +1 -1
  26. package/dist/commands/init-templates.js +240 -0
  27. package/dist/commands/init-templates.js.map +1 -1
  28. package/dist/commands/init.d.ts +6 -4
  29. package/dist/commands/init.d.ts.map +1 -1
  30. package/dist/commands/init.js +81 -94
  31. package/dist/commands/init.js.map +1 -1
  32. package/dist/index.js +39 -0
  33. package/dist/index.js.map +1 -1
  34. package/package.json +2 -2
@@ -0,0 +1,102 @@
1
+ import * as path from 'node:path';
2
+ import { isGlobalConfigPath, loadConfig, resolveConfigPath } from '../utils.js';
3
+ import { installGates } from './gate-install.js';
4
+ /**
5
+ * Command-specific log tag for non-error output (log.success / log.dim).
6
+ * `log.error` keeps the mandatory fixed literal `'Totem Error'` tag per the
7
+ * repo styleguide (command-specific tags for info/success/dim, the unified
8
+ * error tag for log.error).
9
+ */
10
+ const TAG = 'Gate';
11
+ /** Derive the install-time tier from the CLI options (default strict). */
12
+ function resolveTier(opts) {
13
+ return opts.pilot ? 'pilot' : 'strict';
14
+ }
15
+ /**
16
+ * Resolve + validate the gate events to install from the CLI options. The
17
+ * `knownGateEvents()` registry is the single source of truth: `--all`
18
+ * enumerates it, and a named gate must be a member or we throw (mirror the
19
+ * engine's no-default-allow — never silently install nothing).
20
+ */
21
+ export async function resolveGateEvents(opts) {
22
+ const { knownGateEvents, TotemError } = await import('@mmnto/totem');
23
+ const known = knownGateEvents();
24
+ if (opts.all) {
25
+ return known;
26
+ }
27
+ const name = opts.name?.trim();
28
+ if (!name) {
29
+ throw new TotemError('GATE_INVALID', 'No gate selected: pass --all or --<name>.', `Use --all or one of: ${known.join(', ')}.`);
30
+ }
31
+ if (!known.includes(name)) {
32
+ throw new TotemError('GATE_INVALID', `Unknown gate "${name}". Known gates: ${known.join(', ')}.`, 'Use --all or one of the known gate names.');
33
+ }
34
+ return [name];
35
+ }
36
+ /**
37
+ * `totem gate install [--all | --<name>]`
38
+ *
39
+ * Idempotently merges one PreToolUse entry per selected gate into committed
40
+ * `.claude/settings.json` and scaffolds the shared parameterized wrapper to
41
+ * `.claude/hooks/gate-wrapper.cjs`. Thin caller of the shared `installGates`
42
+ * merger (the same path `init --gates=` routes through) — no second copy of
43
+ * the merge logic. Fails loud on an unknown `--<name>` (no default-install).
44
+ */
45
+ export async function gateInstallCommand(opts) {
46
+ const events = await resolveGateEvents(opts);
47
+ const { log } = await import('../ui.js');
48
+ const cwd = process.cwd();
49
+ const tier = resolveTier(opts);
50
+ const results = installGates(cwd, events, tier);
51
+ for (const result of results) {
52
+ if (result.err) {
53
+ log.error('Totem Error', `Gate install failed for ${result.file}: ${result.err}`);
54
+ continue;
55
+ }
56
+ const label = result.event ? `${result.file} (${result.event})` : result.file;
57
+ if (result.action === 'created') {
58
+ log.success(TAG, `Scaffolded ${label}`);
59
+ }
60
+ else if (result.action === 'merged') {
61
+ log.success(TAG, `Installed gate entry into ${label}`);
62
+ }
63
+ else if (result.action === 'updated') {
64
+ // Tier switch: the one existing entry's command was rewritten in place.
65
+ log.success(TAG, `Updated ${result.event ?? result.file} tier to ${tier}`);
66
+ }
67
+ else {
68
+ // Genuine same-tier no-op — the ONLY case that prints "no change".
69
+ log.dim(TAG, `${label} already present — no change`);
70
+ }
71
+ }
72
+ }
73
+ /**
74
+ * `totem gate check --event <type> --payload <json>`
75
+ *
76
+ * Evaluates a gate against deterministic state and writes the raw `GateVerdict`
77
+ * JSON to stdout. The command is host-agnostic: it does NOT map the disposition
78
+ * onto an exit code — the calling PreToolUse wrapper does that. Exit is 0 on a
79
+ * successful evaluation (any disposition); a non-zero exit means the evaluation
80
+ * itself failed (unknown event, bad payload, unparseable source) — never a
81
+ * silent default-allow.
82
+ */
83
+ export async function gateCheckCommand(opts) {
84
+ // Lazy-load @mmnto/totem inside the handler (ADR-072 §3) so the heavy core
85
+ // module never loads on unrelated CLI invocations (e.g. `totem --help`).
86
+ const { evaluateGate, TotemError } = await import('@mmnto/totem');
87
+ let payload;
88
+ try {
89
+ payload = JSON.parse(opts.payload);
90
+ }
91
+ catch (err) {
92
+ throw new TotemError('GATE_INVALID', 'Invalid --payload JSON', 'Pass valid JSON, e.g. --payload \'{"subsystem":"rule-compilation"}\'.', err);
93
+ }
94
+ const cwd = process.cwd();
95
+ const configPath = resolveConfigPath(cwd);
96
+ const config = await loadConfig(configPath);
97
+ const configRoot = isGlobalConfigPath(configPath) ? cwd : path.dirname(configPath);
98
+ const totemDir = path.join(configRoot, config.totemDir);
99
+ const verdict = evaluateGate(opts.event, payload, totemDir);
100
+ process.stdout.write(JSON.stringify(verdict) + '\n');
101
+ }
102
+ //# sourceMappingURL=gate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gate.js","sourceRoot":"","sources":["../../src/commands/gate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=gate.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gate.test.d.ts","sourceRoot":"","sources":["../../src/commands/gate.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,104 @@
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, vi } from 'vitest';
5
+ import { TotemError } from '@mmnto/totem';
6
+ import { gateCheckCommand } from './gate.js';
7
+ /**
8
+ * CLI-boundary tests for `totem gate check`.
9
+ *
10
+ * The engine itself (allow/deny/no-file/fail-closed/side-effect-free) is
11
+ * covered by `@mmnto/totem`'s gate-engine.test.ts. This file covers the
12
+ * command seam the engine tests can't reach:
13
+ * - `--payload` JSON parsing (a command-layer concern, before the engine runs)
14
+ * - the unknown-event throw propagating through the command (never silent-allow)
15
+ * - the LOCKED host-agnostic contract: the command emits a raw `GateVerdict`
16
+ * to stdout and does NOT map the disposition onto an exit code (a `deny`
17
+ * leaves `process.exitCode` untouched — the PreToolUse wrapper owns 0/2).
18
+ *
19
+ * The non-zero exit on a thrown error is delegated to the shared `handleError`
20
+ * entrypoint in index.ts (exercised by every command); these tests assert the
21
+ * command's own contract — throw on failure, never default-allow.
22
+ */
23
+ function makeTmpDir() {
24
+ // `.native` expands Windows 8.3 short names so process.cwd()/realpath agree.
25
+ return fs.realpathSync.native(fs.mkdtempSync(path.join(os.tmpdir(), 'totem-gate-cli-')));
26
+ }
27
+ const MINIMAL_CONFIG = [
28
+ 'targets:',
29
+ ' - glob: "**/*.ts"',
30
+ ' type: code',
31
+ ' strategy: typescript-ast',
32
+ '',
33
+ ].join('\n');
34
+ const FROZEN = JSON.stringify({
35
+ _note: 'test fixture',
36
+ frozen: [
37
+ { subsystem: 'rule-compilation', since: '2026-05-17', reason: 'paused', tracking: '#1' },
38
+ ],
39
+ });
40
+ describe('gateCheckCommand', () => {
41
+ let tmpDir;
42
+ let originalCwd;
43
+ beforeEach(() => {
44
+ tmpDir = makeTmpDir();
45
+ originalCwd = process.cwd();
46
+ // The command resolves config + totemDir from process.cwd().
47
+ fs.writeFileSync(path.join(tmpDir, 'totem.yaml'), MINIMAL_CONFIG);
48
+ fs.mkdirSync(path.join(tmpDir, '.totem'), { recursive: true });
49
+ process.chdir(tmpDir);
50
+ });
51
+ afterEach(() => {
52
+ process.chdir(originalCwd);
53
+ vi.restoreAllMocks();
54
+ process.exitCode = undefined;
55
+ // maxRetries/retryDelay rides out transient Windows ENOTEMPTY/EBUSY without
56
+ // an empty catch swallowing real teardown failures (repo test-cleanup idiom).
57
+ fs.rmSync(tmpDir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
58
+ });
59
+ it('throws GATE_INVALID on malformed --payload JSON — never silent-allow', async () => {
60
+ // Payload parsing fails before the engine (or even config) runs.
61
+ try {
62
+ await gateCheckCommand({ event: 'freeze-check', payload: '{ not valid json' });
63
+ expect.unreachable('expected gateCheckCommand to throw on malformed payload');
64
+ }
65
+ catch (err) {
66
+ expect(err).toBeInstanceOf(TotemError);
67
+ expect(err.code).toBe('GATE_INVALID');
68
+ expect(err.message).toMatch(/invalid --payload json/i);
69
+ }
70
+ });
71
+ it('throws on an unknown --event — never default-allow', async () => {
72
+ await expect(gateCheckCommand({ event: 'made-up-gate', payload: '{}' })).rejects.toThrow(/unknown gate event/i);
73
+ });
74
+ it('emits a raw GateVerdict to stdout and does NOT map disposition to an exit code', async () => {
75
+ fs.writeFileSync(path.join(tmpDir, '.totem', 'freeze.json'), FROZEN);
76
+ const spy = vi.spyOn(process.stdout, 'write').mockImplementation(() => true);
77
+ await gateCheckCommand({ event: 'freeze-check', payload: '{"subsystem":"rule-compilation"}' });
78
+ // Exactly one JSON line written.
79
+ expect(spy.mock.calls).toHaveLength(1);
80
+ const output = spy.mock.calls[0][0];
81
+ expect(output.endsWith('\n')).toBe(true);
82
+ const verdict = JSON.parse(output);
83
+ // Host-agnostic GateVerdict shape (the output-contract-stability invariant).
84
+ expect(verdict.disposition).toBe('deny');
85
+ expect(verdict).toHaveProperty('reason');
86
+ expect(verdict.provenance.source).toBe('.totem/freeze.json');
87
+ expect(verdict.provenance.matched).toBe('rule-compilation');
88
+ expect(verdict.provenance.checkedAt).toMatch(/^\d{4}-\d{2}-\d{2}T/);
89
+ // LOCKED: a `deny` is a successful evaluation — the command must not couple
90
+ // itself to Claude's 0/2 contract. Exit-code mapping is the wrapper's job.
91
+ expect(process.exitCode).toBeFalsy();
92
+ });
93
+ it('emits an allow verdict (exit code untouched) when nothing matches', async () => {
94
+ fs.writeFileSync(path.join(tmpDir, '.totem', 'freeze.json'), FROZEN);
95
+ const spy = vi.spyOn(process.stdout, 'write').mockImplementation(() => true);
96
+ await gateCheckCommand({ event: 'freeze-check', payload: '{"subsystem":"something-else"}' });
97
+ const output = spy.mock.calls[0][0];
98
+ const verdict = JSON.parse(output);
99
+ expect(verdict.disposition).toBe('allow');
100
+ expect(verdict.provenance.matched).toBeNull();
101
+ expect(process.exitCode).toBeFalsy();
102
+ });
103
+ });
104
+ //# sourceMappingURL=gate.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gate.test.js","sourceRoot":"","sources":["../../src/commands/gate.test.ts"],"names":[],"mappings":"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"}