@zigrivers/mmr 1.0.0 → 1.1.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/README.md ADDED
@@ -0,0 +1,77 @@
1
+ # @zigrivers/mmr — Multi-Model Review CLI
2
+
3
+ Automated multi-model code review with dispatch, reconciliation, and severity gating.
4
+
5
+ Dispatches reviews to Claude CLI, Codex CLI, and Gemini CLI. Reconciles findings with consensus scoring. Gates on configurable severity thresholds.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install -g @zigrivers/mmr
11
+ ```
12
+
13
+ ## Quick Start
14
+
15
+ ```bash
16
+ # One-command review (recommended for agents and CI)
17
+ mmr review --pr 47 --sync
18
+
19
+ # Or step-by-step
20
+ mmr review --pr 47 # Dispatch to all channels
21
+ mmr status mmr-a1b2c3 # Check progress
22
+ mmr results mmr-a1b2c3 # Reconcile and output findings
23
+
24
+ # Inject external review findings
25
+ mmr reconcile <job-id> --channel superpowers --input findings.json
26
+ ```
27
+
28
+ ## Commands
29
+
30
+ | Command | Purpose |
31
+ |---------|---------|
32
+ | `mmr review` | Dispatch review to configured channels |
33
+ | `mmr review --sync` | Full pipeline: dispatch, parse, reconcile, output verdict |
34
+ | `mmr status <job-id>` | Check job progress |
35
+ | `mmr results <job-id>` | Collect and reconcile findings |
36
+ | `mmr config init` | Auto-detect CLIs and generate `.mmr.yaml` |
37
+ | `mmr config test` | Verify channel installation and auth |
38
+ | `mmr jobs list` | List recent review jobs |
39
+ | `mmr jobs prune` | Remove old jobs |
40
+ | `mmr reconcile <job-id>` | Inject external findings and re-reconcile |
41
+
42
+ ## Verdict System
43
+
44
+ | Verdict | Meaning | Exit Code |
45
+ |---------|---------|-----------|
46
+ | `pass` | All channels completed, no findings above threshold | 0 |
47
+ | `degraded-pass` | Some channels unavailable, compensating passes ran, gate passed | 0 |
48
+ | `blocked` | Findings at or above severity threshold | 2 |
49
+ | `needs-user-decision` | No channels completed | 3 |
50
+
51
+ ## Configuration
52
+
53
+ Run `mmr config init` to generate `.mmr.yaml`, or create manually:
54
+
55
+ ```yaml
56
+ version: 1
57
+ defaults:
58
+ fix_threshold: P2
59
+ timeout: 300
60
+ channels:
61
+ claude:
62
+ enabled: true
63
+ codex:
64
+ enabled: true
65
+ gemini:
66
+ enabled: true
67
+ ```
68
+
69
+ ## Features
70
+
71
+ - **--sync mode** — single-command entry point for agents and CI
72
+ - **Compensating passes** — Claude-based review for unavailable channels
73
+ - **Consensus scoring** — multi-source findings get high confidence
74
+ - **Atomic job store** — per-channel status files, no write races
75
+ - **POSIX-portable** — `command -v` for install checks, works everywhere
76
+
77
+ Full documentation: [scaffold README](https://github.com/zigrivers/scaffold#mmr--multi-model-review-cli)
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAOA,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAa1D"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAQA,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAc1D"}
package/dist/cli.js CHANGED
@@ -4,6 +4,7 @@ import { statusCommand } from './commands/status.js';
4
4
  import { resultsCommand } from './commands/results.js';
5
5
  import { configCommand } from './commands/config.js';
6
6
  import { jobsCommand } from './commands/jobs.js';
7
+ import { reconcileCommand } from './commands/reconcile.js';
7
8
  export async function runCli(argv) {
8
9
  await yargs(argv)
9
10
  .scriptName('mmr')
@@ -13,6 +14,7 @@ export async function runCli(argv) {
13
14
  .command(resultsCommand)
14
15
  .command(configCommand)
15
16
  .command(jobsCommand)
17
+ .command(reconcileCommand)
16
18
  .demandCommand(1, 'Run mmr --help for usage')
17
19
  .strict()
18
20
  .help()
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAEhD,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,IAAc;IACzC,MAAM,KAAK,CAAC,IAAI,CAAC;SACd,UAAU,CAAC,KAAK,CAAC;SACjB,KAAK,CAAC,wBAAwB,CAAC;SAC/B,OAAO,CAAC,aAAa,CAAC;SACtB,OAAO,CAAC,aAAa,CAAC;SACtB,OAAO,CAAC,cAAc,CAAC;SACvB,OAAO,CAAC,aAAa,CAAC;SACtB,OAAO,CAAC,WAAW,CAAC;SACpB,aAAa,CAAC,CAAC,EAAE,0BAA0B,CAAC;SAC5C,MAAM,EAAE;SACR,IAAI,EAAE;SACN,IAAI,CAAA;AACT,CAAC"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAE1D,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,IAAc;IACzC,MAAM,KAAK,CAAC,IAAI,CAAC;SACd,UAAU,CAAC,KAAK,CAAC;SACjB,KAAK,CAAC,wBAAwB,CAAC;SAC/B,OAAO,CAAC,aAAa,CAAC;SACtB,OAAO,CAAC,aAAa,CAAC;SACtB,OAAO,CAAC,cAAc,CAAC;SACvB,OAAO,CAAC,aAAa,CAAC;SACtB,OAAO,CAAC,WAAW,CAAC;SACpB,OAAO,CAAC,gBAAgB,CAAC;SACzB,aAAa,CAAC,CAAC,EAAE,0BAA0B,CAAC;SAC5C,MAAM,EAAE;SACR,IAAI,EAAE;SACN,IAAI,CAAA;AACT,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { CommandModule } from 'yargs';
2
+ interface ReconcileArgs {
3
+ 'job-id': string;
4
+ channel: string;
5
+ input: string;
6
+ format?: string;
7
+ }
8
+ export declare const reconcileCommand: CommandModule<object, ReconcileArgs>;
9
+ export {};
10
+ //# sourceMappingURL=reconcile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconcile.d.ts","sourceRoot":"","sources":["../../src/commands/reconcile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAsB,MAAM,OAAO,CAAA;AAS9D,UAAU,aAAa;IACrB,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,eAAO,MAAM,gBAAgB,EAAE,aAAa,CAAC,MAAM,EAAE,aAAa,CAsGjE,CAAA"}
@@ -0,0 +1,102 @@
1
+ import path from 'node:path';
2
+ import os from 'node:os';
3
+ import { JobStore } from '../core/job-store.js';
4
+ import { normalizeExternalInput, readInput } from '../core/normalize-input.js';
5
+ import { runResultsPipeline } from '../core/results-pipeline.js';
6
+ import { TERMINAL_STATUSES } from '../types.js';
7
+ export const reconcileCommand = {
8
+ command: 'reconcile <job-id>',
9
+ describe: 'Inject external findings into a job and re-reconcile',
10
+ builder: (yargs) => yargs
11
+ .positional('job-id', {
12
+ type: 'string',
13
+ demandOption: true,
14
+ describe: 'Job ID (e.g. mmr-abc123)',
15
+ })
16
+ .option('channel', {
17
+ type: 'string',
18
+ demandOption: true,
19
+ describe: 'Name for the external channel (e.g. superpowers). Stored in lowercase.',
20
+ })
21
+ .option('input', {
22
+ type: 'string',
23
+ demandOption: true,
24
+ describe: 'Findings: file path, - for stdin, or inline JSON',
25
+ })
26
+ .option('format', {
27
+ type: 'string',
28
+ describe: 'Output format',
29
+ choices: ['json', 'text', 'markdown'],
30
+ }),
31
+ handler: (args) => {
32
+ const jobsDir = path.join(os.homedir(), '.mmr', 'jobs');
33
+ const store = new JobStore(jobsDir);
34
+ // 1. Load job
35
+ let job;
36
+ try {
37
+ job = store.loadJob(args['job-id']);
38
+ }
39
+ catch {
40
+ console.error(`Job not found: ${args['job-id']}`);
41
+ process.exit(5);
42
+ }
43
+ // 2. Verify all channels in terminal state
44
+ const incompleteChannels = Object.entries(job.channels)
45
+ .filter(([, entry]) => !TERMINAL_STATUSES.has(entry.status))
46
+ .map(([name]) => name);
47
+ if (incompleteChannels.length > 0) {
48
+ console.error(`Channels still running: ${incompleteChannels.join(', ')}`);
49
+ console.error('Wait for completion or use `mmr status` to check progress.');
50
+ process.exit(1);
51
+ }
52
+ // 3. Validate raw channel name, then lowercase for case-insensitive safety
53
+ const rawChannel = args.channel;
54
+ if (!/^[a-zA-Z0-9._-]+$/.test(rawChannel)) {
55
+ console.error(`Invalid channel name: "${rawChannel}"`);
56
+ process.exit(5);
57
+ }
58
+ const channelName = rawChannel.toLowerCase();
59
+ const existingLower = Object.keys(job.channels).map(k => k.toLowerCase());
60
+ if (existingLower.includes(channelName)) {
61
+ console.error(`Channel '${channelName}' already exists in job ${job.job_id}`);
62
+ process.exit(5);
63
+ }
64
+ // 4. Read input
65
+ let rawInput;
66
+ try {
67
+ rawInput = readInput(args.input);
68
+ }
69
+ catch (err) {
70
+ console.error(err instanceof Error ? err.message : String(err));
71
+ process.exit(5);
72
+ }
73
+ // 5. Normalize and validate (fully in memory before any writes)
74
+ let normalized;
75
+ try {
76
+ normalized = normalizeExternalInput(rawInput);
77
+ }
78
+ catch (err) {
79
+ console.error(`Invalid input: ${err instanceof Error ? err.message : String(err)}`);
80
+ process.exit(5);
81
+ }
82
+ // 6. Commit sequence (only after validation)
83
+ // Synthetic timestamps — injected channel has no actual runtime
84
+ const now = new Date().toISOString();
85
+ store.registerChannel(job.job_id, channelName, { output_parser: 'default' });
86
+ store.saveChannelOutput(job.job_id, channelName, normalized);
87
+ store.updateChannel(job.job_id, channelName, {
88
+ status: 'completed',
89
+ started_at: now,
90
+ completed_at: now,
91
+ });
92
+ // 7. Re-run pipeline
93
+ const updatedJob = store.loadJob(job.job_id);
94
+ const outputFormat = (args.format ?? job.format ?? 'json');
95
+ const { results, formatted, exitCode } = runResultsPipeline(store, updatedJob, outputFormat);
96
+ // 8. Save and output
97
+ store.saveResults(job.job_id, results);
98
+ console.log(formatted);
99
+ process.exit(exitCode);
100
+ },
101
+ };
102
+ //# sourceMappingURL=reconcile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconcile.js","sourceRoot":"","sources":["../../src/commands/reconcile.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { ParsedOutput } from './parser.js';
2
+ /**
3
+ * Normalize external findings input into a ParsedOutput.
4
+ * Accepts wrapper format ({ approved, findings, summary }) or bare array ([finding, ...]).
5
+ * Strips markdown fences and surrounding text. Uses strict validation (throws on invalid).
6
+ */
7
+ export declare function normalizeExternalInput(raw: string): ParsedOutput;
8
+ /**
9
+ * Read input from the detected source.
10
+ * Detection order: stdin (-), inline JSON ({/[), file path, error.
11
+ */
12
+ export declare function readInput(input: string): string;
13
+ //# sourceMappingURL=normalize-input.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize-input.d.ts","sourceRoot":"","sources":["../../src/core/normalize-input.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE/C;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAkFhE;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAoB/C"}
@@ -0,0 +1,139 @@
1
+ import fs from 'node:fs';
2
+ import { stripMarkdownFences, extractJson, fixTrailingCommas, validateParsedOutputStrict, validateFindingStrict } from './parser.js';
3
+ /**
4
+ * Normalize external findings input into a ParsedOutput.
5
+ * Accepts wrapper format ({ approved, findings, summary }) or bare array ([finding, ...]).
6
+ * Strips markdown fences and surrounding text. Uses strict validation (throws on invalid).
7
+ */
8
+ export function normalizeExternalInput(raw) {
9
+ let text = stripMarkdownFences(raw);
10
+ text = text.trim();
11
+ let parsed;
12
+ if (text.startsWith('[')) {
13
+ // Bare array — use balanced bracket extraction to handle trailing text
14
+ let depth = 0;
15
+ let inStr = false;
16
+ for (let i = 0; i < text.length; i++) {
17
+ const c = text[i];
18
+ if (inStr) {
19
+ if (c === '\\')
20
+ i++;
21
+ else if (c === '"')
22
+ inStr = false;
23
+ continue;
24
+ }
25
+ if (c === '"')
26
+ inStr = true;
27
+ else if (c === '[')
28
+ depth++;
29
+ else if (c === ']') {
30
+ depth--;
31
+ if (depth === 0) {
32
+ const arrayText = fixTrailingCommas(text.slice(0, i + 1));
33
+ parsed = JSON.parse(arrayText);
34
+ break;
35
+ }
36
+ }
37
+ }
38
+ if (parsed === undefined)
39
+ throw new Error('Unbalanced brackets in array input');
40
+ }
41
+ else if (text.startsWith('{')) {
42
+ // Object at start — use extractJson for robustness
43
+ text = extractJson(text);
44
+ text = fixTrailingCommas(text);
45
+ parsed = JSON.parse(text);
46
+ }
47
+ else {
48
+ // Surrounded text — try extractJson for wrapper objects first
49
+ let extractedWrapper = false;
50
+ try {
51
+ const extracted = extractJson(text);
52
+ const candidate = JSON.parse(fixTrailingCommas(extracted));
53
+ // Only accept as wrapper if it has findings array AND does not look like a bare finding
54
+ if (typeof candidate === 'object' && candidate !== null && Array.isArray(candidate.findings) && typeof candidate.severity !== 'string') {
55
+ parsed = candidate;
56
+ extractedWrapper = true;
57
+ }
58
+ }
59
+ catch {
60
+ // extractJson failed — will try array scanning below
61
+ }
62
+ if (!extractedWrapper) {
63
+ // Look for bare array in the stripped text
64
+ const stripped = stripMarkdownFences(raw).trim();
65
+ const arrayStart = stripped.indexOf('[');
66
+ if (arrayStart === -1)
67
+ throw new Error('No JSON object or array found in input');
68
+ // Find matching ] by tracking bracket depth (mirrors extractJson for arrays)
69
+ let depth = 0;
70
+ let inStr = false;
71
+ for (let i = arrayStart; i < stripped.length; i++) {
72
+ const c = stripped[i];
73
+ if (inStr) {
74
+ if (c === '\\')
75
+ i++;
76
+ else if (c === '"')
77
+ inStr = false;
78
+ continue;
79
+ }
80
+ if (c === '"')
81
+ inStr = true;
82
+ else if (c === '[')
83
+ depth++;
84
+ else if (c === ']') {
85
+ depth--;
86
+ if (depth === 0) {
87
+ const arrayText = fixTrailingCommas(stripped.slice(arrayStart, i + 1));
88
+ parsed = JSON.parse(arrayText);
89
+ break;
90
+ }
91
+ }
92
+ }
93
+ if (parsed === undefined)
94
+ throw new Error('Unbalanced brackets in array input');
95
+ }
96
+ }
97
+ // Normalize based on shape
98
+ if (Array.isArray(parsed)) {
99
+ const findings = parsed.map(validateFindingStrict);
100
+ const hasBlockingFindings = findings.some(f => f.severity === 'P0' || f.severity === 'P1');
101
+ return {
102
+ approved: !hasBlockingFindings,
103
+ findings,
104
+ summary: 'Injected external findings',
105
+ };
106
+ }
107
+ if (typeof parsed === 'object' && parsed !== null) {
108
+ const record = parsed;
109
+ if (Array.isArray(record.findings)) {
110
+ return validateParsedOutputStrict(parsed);
111
+ }
112
+ }
113
+ throw new Error('Invalid input format: expected JSON object with findings array or bare array of findings');
114
+ }
115
+ /**
116
+ * Read input from the detected source.
117
+ * Detection order: stdin (-), inline JSON ({/[), file path, error.
118
+ */
119
+ export function readInput(input) {
120
+ if (input === '-') {
121
+ return fs.readFileSync(0, 'utf-8');
122
+ }
123
+ const trimmed = input.trimStart();
124
+ if (trimmed.startsWith('{') || trimmed.startsWith('[')) {
125
+ return input;
126
+ }
127
+ // Try to read as file path
128
+ try {
129
+ return fs.readFileSync(input, 'utf-8');
130
+ }
131
+ catch (err) {
132
+ const code = err.code;
133
+ if (code === 'ENOENT' || code === 'ENAMETOOLONG') {
134
+ throw new Error(`Input not found: "${input}" is not a file, stdin (-), or valid JSON`);
135
+ }
136
+ throw err; // permission error, etc. — surface it
137
+ }
138
+ }
139
+ //# sourceMappingURL=normalize-input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize-input.js","sourceRoot":"","sources":["../../src/core/normalize-input.ts"],"names":[],"mappings":"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"}
@@ -5,6 +5,27 @@ export interface ParsedOutput {
5
5
  summary: string;
6
6
  }
7
7
  export type Parser = (raw: string) => ParsedOutput;
8
+ /**
9
+ * Remove ```json and ``` markdown fence markers from text.
10
+ */
11
+ export declare function stripMarkdownFences(text: string): string;
12
+ /**
13
+ * Remove trailing commas before `}` and `]`.
14
+ */
15
+ export declare function fixTrailingCommas(text: string): string;
16
+ /**
17
+ * Find first `{`, count brace depth, extract to matching `}`.
18
+ * Tracks in-string state to ignore braces inside JSON string values.
19
+ */
20
+ export declare function extractJson(text: string): string;
21
+ /**
22
+ * Default parser: strips markdown fences, extracts JSON from surrounding text,
23
+ * fixes trailing commas, then JSON.parse.
24
+ */
25
+ export declare function validateParsedOutput(obj: unknown): ParsedOutput;
26
+ export declare function validateFinding(f: unknown): Finding;
27
+ export declare function validateFindingStrict(f: unknown): Finding;
28
+ export declare function validateParsedOutputStrict(obj: unknown): ParsedOutput;
8
29
  /**
9
30
  * Returns a parser function by name. Falls back to default if name is unknown.
10
31
  */
@@ -1 +1 @@
1
- {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/core/parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAE1C,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,OAAO,CAAA;IACjB,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,MAAM,MAAM,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,YAAY,CAAA;AA0HlD;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,YAAY,CAmBhF"}
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/core/parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAE1C,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,OAAO,CAAA;IACjB,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,MAAM,MAAM,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,YAAY,CAAA;AAElD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAExD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAgChD;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,OAAO,GAAG,YAAY,CAU/D;AAED,wBAAgB,eAAe,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAcnD;AAED,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAsBzD;AAED,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,OAAO,GAAG,YAAY,CAarE;AAsCD;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,YAAY,CAmBhF"}
@@ -1,20 +1,20 @@
1
1
  /**
2
2
  * Remove ```json and ``` markdown fence markers from text.
3
3
  */
4
- function stripMarkdownFences(text) {
4
+ export function stripMarkdownFences(text) {
5
5
  return text.replace(/^```(?:json)?\s*\n?/gm, '').replace(/\n?```\s*$/gm, '');
6
6
  }
7
7
  /**
8
8
  * Remove trailing commas before `}` and `]`.
9
9
  */
10
- function fixTrailingCommas(text) {
10
+ export function fixTrailingCommas(text) {
11
11
  return text.replace(/,\s*([}\]])/g, '$1');
12
12
  }
13
13
  /**
14
14
  * Find first `{`, count brace depth, extract to matching `}`.
15
15
  * Tracks in-string state to ignore braces inside JSON string values.
16
16
  */
17
- function extractJson(text) {
17
+ export function extractJson(text) {
18
18
  const start = text.indexOf('{');
19
19
  if (start === -1)
20
20
  throw new Error('No JSON object found in output');
@@ -50,7 +50,7 @@ function extractJson(text) {
50
50
  * Default parser: strips markdown fences, extracts JSON from surrounding text,
51
51
  * fixes trailing commas, then JSON.parse.
52
52
  */
53
- function validateParsedOutput(obj) {
53
+ export function validateParsedOutput(obj) {
54
54
  if (typeof obj !== 'object' || obj === null) {
55
55
  throw new Error('Parsed output is not an object');
56
56
  }
@@ -61,7 +61,7 @@ function validateParsedOutput(obj) {
61
61
  summary: typeof record.summary === 'string' ? record.summary : '',
62
62
  };
63
63
  }
64
- function validateFinding(f) {
64
+ export function validateFinding(f) {
65
65
  if (typeof f !== 'object' || f === null) {
66
66
  return { severity: 'P2', location: 'unknown', description: 'Malformed finding', suggestion: '' };
67
67
  }
@@ -76,6 +76,43 @@ function validateFinding(f) {
76
76
  ...(typeof record.category === 'string' ? { category: record.category } : {}),
77
77
  };
78
78
  }
79
+ export function validateFindingStrict(f) {
80
+ if (typeof f !== 'object' || f === null) {
81
+ throw new Error('Finding must be an object');
82
+ }
83
+ const record = f;
84
+ if (!['P0', 'P1', 'P2', 'P3'].includes(record.severity)) {
85
+ throw new Error('Finding missing or invalid severity (must be P0-P3)');
86
+ }
87
+ if (typeof record.location !== 'string' || !record.location) {
88
+ throw new Error('Finding missing location');
89
+ }
90
+ if (typeof record.description !== 'string' || !record.description) {
91
+ throw new Error('Finding missing description');
92
+ }
93
+ return {
94
+ severity: record.severity,
95
+ location: record.location,
96
+ description: record.description,
97
+ suggestion: typeof record.suggestion === 'string' ? record.suggestion : '',
98
+ ...(typeof record.id === 'string' ? { id: record.id } : {}),
99
+ ...(typeof record.category === 'string' ? { category: record.category } : {}),
100
+ };
101
+ }
102
+ export function validateParsedOutputStrict(obj) {
103
+ if (typeof obj !== 'object' || obj === null) {
104
+ throw new Error('Input must be an object');
105
+ }
106
+ const record = obj;
107
+ if (!Array.isArray(record.findings)) {
108
+ throw new Error('Input findings must be an array');
109
+ }
110
+ return {
111
+ approved: typeof record.approved === 'boolean' ? record.approved : false,
112
+ findings: record.findings.map(validateFindingStrict),
113
+ summary: typeof record.summary === 'string' ? record.summary : '',
114
+ };
115
+ }
79
116
  function defaultParser(raw) {
80
117
  let text = stripMarkdownFences(raw);
81
118
  text = extractJson(text);
@@ -1 +1 @@
1
- {"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/core/parser.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/core/parser.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zigrivers/mmr",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Multi-model code review CLI — async dispatch, reconciliation, and severity gating",
5
5
  "type": "module",
6
6
  "license": "MIT",