@zigrivers/mmr 0.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.
Files changed (82) hide show
  1. package/dist/cli.d.ts +2 -0
  2. package/dist/cli.d.ts.map +1 -0
  3. package/dist/cli.js +21 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/commands/config.d.ts +7 -0
  6. package/dist/commands/config.d.ts.map +1 -0
  7. package/dist/commands/config.js +98 -0
  8. package/dist/commands/config.js.map +1 -0
  9. package/dist/commands/jobs.d.ts +7 -0
  10. package/dist/commands/jobs.d.ts.map +1 -0
  11. package/dist/commands/jobs.js +48 -0
  12. package/dist/commands/jobs.js.map +1 -0
  13. package/dist/commands/results.d.ts +9 -0
  14. package/dist/commands/results.d.ts.map +1 -0
  15. package/dist/commands/results.js +145 -0
  16. package/dist/commands/results.js.map +1 -0
  17. package/dist/commands/review.d.ts +18 -0
  18. package/dist/commands/review.d.ts.map +1 -0
  19. package/dist/commands/review.js +203 -0
  20. package/dist/commands/review.js.map +1 -0
  21. package/dist/commands/status.d.ts +7 -0
  22. package/dist/commands/status.d.ts.map +1 -0
  23. package/dist/commands/status.js +56 -0
  24. package/dist/commands/status.js.map +1 -0
  25. package/dist/config/defaults.d.ts +12 -0
  26. package/dist/config/defaults.d.ts.map +1 -0
  27. package/dist/config/defaults.js +69 -0
  28. package/dist/config/defaults.js.map +1 -0
  29. package/dist/config/loader.d.ts +23 -0
  30. package/dist/config/loader.d.ts.map +1 -0
  31. package/dist/config/loader.js +100 -0
  32. package/dist/config/loader.js.map +1 -0
  33. package/dist/config/schema.d.ts +207 -0
  34. package/dist/config/schema.d.ts.map +1 -0
  35. package/dist/config/schema.js +38 -0
  36. package/dist/config/schema.js.map +1 -0
  37. package/dist/core/auth.d.ts +17 -0
  38. package/dist/core/auth.d.ts.map +1 -0
  39. package/dist/core/auth.js +60 -0
  40. package/dist/core/auth.js.map +1 -0
  41. package/dist/core/dispatcher.d.ts +15 -0
  42. package/dist/core/dispatcher.d.ts.map +1 -0
  43. package/dist/core/dispatcher.js +107 -0
  44. package/dist/core/dispatcher.js.map +1 -0
  45. package/dist/core/job-store.d.ts +46 -0
  46. package/dist/core/job-store.d.ts.map +1 -0
  47. package/dist/core/job-store.js +141 -0
  48. package/dist/core/job-store.js.map +1 -0
  49. package/dist/core/parser.d.ts +16 -0
  50. package/dist/core/parser.d.ts.map +1 -0
  51. package/dist/core/parser.js +123 -0
  52. package/dist/core/parser.js.map +1 -0
  53. package/dist/core/prompt.d.ts +26 -0
  54. package/dist/core/prompt.d.ts.map +1 -0
  55. package/dist/core/prompt.js +53 -0
  56. package/dist/core/prompt.js.map +1 -0
  57. package/dist/core/reconciler.d.ts +17 -0
  58. package/dist/core/reconciler.d.ts.map +1 -0
  59. package/dist/core/reconciler.js +84 -0
  60. package/dist/core/reconciler.js.map +1 -0
  61. package/dist/formatters/json.d.ts +3 -0
  62. package/dist/formatters/json.d.ts.map +1 -0
  63. package/dist/formatters/json.js +4 -0
  64. package/dist/formatters/json.js.map +1 -0
  65. package/dist/formatters/markdown.d.ts +3 -0
  66. package/dist/formatters/markdown.d.ts.map +1 -0
  67. package/dist/formatters/markdown.js +36 -0
  68. package/dist/formatters/markdown.js.map +1 -0
  69. package/dist/formatters/text.d.ts +3 -0
  70. package/dist/formatters/text.d.ts.map +1 -0
  71. package/dist/formatters/text.js +31 -0
  72. package/dist/formatters/text.js.map +1 -0
  73. package/dist/index.d.ts +3 -0
  74. package/dist/index.d.ts.map +1 -0
  75. package/dist/index.js +7 -0
  76. package/dist/index.js.map +1 -0
  77. package/dist/types.d.ts +59 -0
  78. package/dist/types.d.ts.map +1 -0
  79. package/dist/types.js +7 -0
  80. package/dist/types.js.map +1 -0
  81. package/package.json +45 -0
  82. package/templates/core-prompt.md +33 -0
@@ -0,0 +1,84 @@
1
+ import { SEVERITY_ORDER } from '../types.js';
2
+ function normalizeLocation(location) {
3
+ return location.toLowerCase().trim();
4
+ }
5
+ function higherSeverity(a, b) {
6
+ return SEVERITY_ORDER[a] <= SEVERITY_ORDER[b] ? a : b;
7
+ }
8
+ /**
9
+ * Reconcile findings from multiple channels into a unified list with
10
+ * consensus scoring.
11
+ *
12
+ * 1. Flatten all findings with source attribution
13
+ * 2. Group by normalized location
14
+ * 3. For each group, determine agreement, confidence, and effective severity
15
+ * 4. Sort by severity (P0 first)
16
+ */
17
+ export function reconcile(channelFindings) {
18
+ // Step 1: Flatten with source attribution
19
+ const attributed = [];
20
+ for (const [source, findings] of Object.entries(channelFindings)) {
21
+ for (const finding of findings) {
22
+ attributed.push({ ...finding, source });
23
+ }
24
+ }
25
+ if (attributed.length === 0)
26
+ return [];
27
+ // Step 2: Group by normalized location
28
+ const groups = new Map();
29
+ for (const finding of attributed) {
30
+ const key = normalizeLocation(finding.location);
31
+ const group = groups.get(key) ?? [];
32
+ group.push(finding);
33
+ groups.set(key, group);
34
+ }
35
+ // Step 3: Reconcile each group
36
+ const results = [];
37
+ for (const group of groups.values()) {
38
+ const sources = [...new Set(group.map((f) => f.source))];
39
+ const severities = [...new Set(group.map((f) => f.severity))];
40
+ const effectiveSeverity = severities.reduce(higherSeverity);
41
+ let agreement;
42
+ let confidence;
43
+ if (sources.length >= 2) {
44
+ if (severities.length === 1) {
45
+ // 2+ sources, same severity -> consensus, high
46
+ agreement = 'consensus';
47
+ confidence = 'high';
48
+ }
49
+ else {
50
+ // 2+ sources, different severity -> majority, medium
51
+ agreement = 'majority';
52
+ confidence = 'medium';
53
+ }
54
+ }
55
+ else {
56
+ // Single source -> unique
57
+ agreement = 'unique';
58
+ confidence = effectiveSeverity === 'P0' ? 'high' : 'medium';
59
+ }
60
+ // Use first finding's description/suggestion as representative
61
+ const representative = group[0];
62
+ results.push({
63
+ severity: effectiveSeverity,
64
+ location: representative.location,
65
+ description: representative.description,
66
+ suggestion: representative.suggestion,
67
+ confidence,
68
+ sources,
69
+ agreement,
70
+ });
71
+ }
72
+ // Step 4: Sort by severity (P0 first)
73
+ results.sort((a, b) => SEVERITY_ORDER[a.severity] - SEVERITY_ORDER[b.severity]);
74
+ return results;
75
+ }
76
+ /**
77
+ * Evaluate the quality gate: passes if no finding has severity at or above
78
+ * the threshold (i.e., no finding with SEVERITY_ORDER <= threshold order).
79
+ */
80
+ export function evaluateGate(findings, threshold) {
81
+ const thresholdOrder = SEVERITY_ORDER[threshold];
82
+ return findings.every((f) => SEVERITY_ORDER[f.severity] > thresholdOrder);
83
+ }
84
+ //# sourceMappingURL=reconciler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconciler.js","sourceRoot":"","sources":["../../src/core/reconciler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { ReconciledResults } from '../types.js';
2
+ export declare function formatJson(results: ReconciledResults): string;
3
+ //# sourceMappingURL=json.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../../src/formatters/json.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAEpD,wBAAgB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,CAE7D"}
@@ -0,0 +1,4 @@
1
+ export function formatJson(results) {
2
+ return JSON.stringify(results, null, 2);
3
+ }
4
+ //# sourceMappingURL=json.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.js","sourceRoot":"","sources":["../../src/formatters/json.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,UAAU,CAAC,OAA0B;IACnD,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;AACzC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { ReconciledResults } from '../types.js';
2
+ export declare function formatMarkdown(results: ReconciledResults): string;
3
+ //# sourceMappingURL=markdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/formatters/markdown.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAEpD,wBAAgB,cAAc,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,CAuCjE"}
@@ -0,0 +1,36 @@
1
+ export function formatMarkdown(results) {
2
+ const lines = [];
3
+ const gate = results.gate_passed ? 'PASSED' : 'FAILED';
4
+ lines.push(`## Multi-Model Review — ${gate}`);
5
+ lines.push('');
6
+ lines.push(`**Job:** ${results.job_id} | **Threshold:** ${results.fix_threshold}` +
7
+ ` | **Elapsed:** ${results.metadata.total_elapsed}`);
8
+ lines.push('');
9
+ if (results.reconciled_findings.length > 0) {
10
+ lines.push('### Findings');
11
+ lines.push('');
12
+ lines.push('| Severity | Location | Description | Suggestion | Sources | Agreement |');
13
+ lines.push('|----------|----------|-------------|------------|---------|-----------|');
14
+ for (const f of results.reconciled_findings) {
15
+ const src = f.sources.join(', ');
16
+ const esc = (s) => s.replace(/\|/g, '\\|');
17
+ const row = [
18
+ f.severity, f.location, esc(f.description),
19
+ esc(f.suggestion), src, f.agreement,
20
+ ].map((c) => ` ${c} `).join('|');
21
+ lines.push(`|${row}|`);
22
+ }
23
+ lines.push('');
24
+ }
25
+ else {
26
+ lines.push('No findings.');
27
+ lines.push('');
28
+ }
29
+ lines.push('### Channels');
30
+ lines.push('');
31
+ for (const [name, ch] of Object.entries(results.per_channel)) {
32
+ lines.push(`- **${name}:** ${ch.status} (${ch.elapsed})`);
33
+ }
34
+ return lines.join('\n');
35
+ }
36
+ //# sourceMappingURL=markdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/formatters/markdown.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,cAAc,CAAC,OAA0B;IACvD,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,MAAM,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAA;IAEtD,KAAK,CAAC,IAAI,CAAC,2BAA2B,IAAI,EAAE,CAAC,CAAA;IAC7C,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACd,KAAK,CAAC,IAAI,CACR,YAAY,OAAO,CAAC,MAAM,qBAAqB,OAAO,CAAC,aAAa,EAAE;QACtE,mBAAmB,OAAO,CAAC,QAAQ,CAAC,aAAa,EAAE,CACpD,CAAA;IACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAEd,IAAI,OAAO,CAAC,mBAAmB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3C,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAA;QAC1B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QACd,KAAK,CAAC,IAAI,CAAC,0EAA0E,CAAC,CAAA;QACtF,KAAK,CAAC,IAAI,CAAC,0EAA0E,CAAC,CAAA;QACtF,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,mBAAmB,EAAE,CAAC;YAC5C,MAAM,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YAChC,MAAM,GAAG,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;YAClD,MAAM,GAAG,GAAG;gBACV,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC;gBAC1C,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,SAAS;aACpC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YAChC,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC,CAAA;QACxB,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAChB,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAA;QAC1B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAChB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAA;IAC1B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACd,KAAK,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;QAC7D,KAAK,CAAC,IAAI,CAAC,OAAO,IAAI,OAAO,EAAE,CAAC,MAAM,KAAK,EAAE,CAAC,OAAO,GAAG,CAAC,CAAA;IAC3D,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACzB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { ReconciledResults } from '../types.js';
2
+ export declare function formatText(results: ReconciledResults): string;
3
+ //# sourceMappingURL=text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../src/formatters/text.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAEpD,wBAAgB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,CAkC7D"}
@@ -0,0 +1,31 @@
1
+ export function formatText(results) {
2
+ const lines = [];
3
+ const gate = results.gate_passed ? 'PASSED' : 'FAILED';
4
+ lines.push(`MMR ${gate} — ${results.job_id}`);
5
+ const chCount = `${results.metadata.channels_completed}/${results.metadata.channels_dispatched}`;
6
+ lines.push(`Threshold: ${results.fix_threshold} | Channels: ${chCount}` +
7
+ ` | Elapsed: ${results.metadata.total_elapsed}`);
8
+ lines.push('');
9
+ if (results.reconciled_findings.length > 0) {
10
+ lines.push(`Findings (${results.reconciled_findings.length}):`);
11
+ lines.push('');
12
+ for (const f of results.reconciled_findings) {
13
+ lines.push(` [${f.severity}] ${f.location}`);
14
+ lines.push(` ${f.description}`);
15
+ if (f.suggestion) {
16
+ lines.push(` Suggestion: ${f.suggestion}`);
17
+ }
18
+ lines.push(` Sources: ${f.sources.join(', ')} (${f.agreement})`);
19
+ lines.push('');
20
+ }
21
+ }
22
+ else {
23
+ lines.push('No findings.');
24
+ }
25
+ lines.push('Channels:');
26
+ for (const [name, ch] of Object.entries(results.per_channel)) {
27
+ lines.push(` ${name}: ${ch.status} (${ch.elapsed})`);
28
+ }
29
+ return lines.join('\n');
30
+ }
31
+ //# sourceMappingURL=text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text.js","sourceRoot":"","sources":["../../src/formatters/text.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,UAAU,CAAC,OAA0B;IACnD,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,MAAM,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAA;IAEtD,KAAK,CAAC,IAAI,CAAC,OAAO,IAAI,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;IAC7C,MAAM,OAAO,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,kBAAkB,IAAI,OAAO,CAAC,QAAQ,CAAC,mBAAmB,EAAE,CAAA;IAChG,KAAK,CAAC,IAAI,CACR,cAAc,OAAO,CAAC,aAAa,gBAAgB,OAAO,EAAE;QAC5D,eAAe,OAAO,CAAC,QAAQ,CAAC,aAAa,EAAE,CAChD,CAAA;IACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAEd,IAAI,OAAO,CAAC,mBAAmB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3C,KAAK,CAAC,IAAI,CAAC,aAAa,OAAO,CAAC,mBAAmB,CAAC,MAAM,IAAI,CAAC,CAAA;QAC/D,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QACd,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,mBAAmB,EAAE,CAAC;YAC5C,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAA;YAC7C,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC,CAAA;YAClC,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC;gBACjB,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,UAAU,EAAE,CAAC,CAAA;YAC/C,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,SAAS,GAAG,CAAC,CAAA;YACnE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QAChB,CAAC;IACH,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAA;IAC5B,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;IACvB,KAAK,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;QAC7D,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,KAAK,EAAE,CAAC,MAAM,KAAK,EAAE,CAAC,OAAO,GAAG,CAAC,CAAA;IACvD,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACzB,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ import { runCli } from './cli.js';
3
+ runCli(process.argv.slice(2)).catch((err) => {
4
+ console.error(err);
5
+ process.exit(1);
6
+ });
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAEjC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IAC1C,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAClB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACjB,CAAC,CAAC,CAAA"}
@@ -0,0 +1,59 @@
1
+ export type Severity = 'P0' | 'P1' | 'P2' | 'P3';
2
+ export declare const SEVERITY_ORDER: Record<Severity, number>;
3
+ export type ChannelStatus = 'dispatched' | 'running' | 'completed' | 'timeout' | 'failed' | 'auth_failed' | 'skipped';
4
+ export type JobStatus = 'dispatched' | 'running' | 'completed';
5
+ export type Agreement = 'consensus' | 'majority' | 'unique' | 'divergent';
6
+ export type Confidence = 'high' | 'medium' | 'low';
7
+ export type OutputFormat = 'json' | 'text' | 'markdown' | 'sarif';
8
+ export interface Finding {
9
+ severity: Severity;
10
+ location: string;
11
+ description: string;
12
+ suggestion: string;
13
+ }
14
+ export interface ReconciledFinding extends Finding {
15
+ confidence: Confidence;
16
+ sources: string[];
17
+ agreement: Agreement;
18
+ }
19
+ export interface ChannelResult {
20
+ status: ChannelStatus;
21
+ elapsed: string;
22
+ findings: Finding[];
23
+ raw_output?: string;
24
+ error?: string;
25
+ }
26
+ export interface JobMetadata {
27
+ job_id: string;
28
+ status: JobStatus;
29
+ fix_threshold: Severity;
30
+ format: OutputFormat;
31
+ created_at: string;
32
+ channels: Record<string, ChannelJobEntry>;
33
+ }
34
+ export interface ChannelJobEntry {
35
+ status: ChannelStatus;
36
+ auth: 'ok' | 'failed' | 'skipped';
37
+ recovery?: string;
38
+ pid?: number;
39
+ started_at?: string;
40
+ completed_at?: string;
41
+ elapsed?: string;
42
+ findings_count?: number;
43
+ output_parser?: string;
44
+ }
45
+ export interface ReconciledResults {
46
+ job_id: string;
47
+ gate_passed: boolean;
48
+ fix_threshold: Severity;
49
+ reconciled_findings: ReconciledFinding[];
50
+ per_channel: Record<string, ChannelResult>;
51
+ metadata: {
52
+ channels_dispatched: number;
53
+ channels_completed: number;
54
+ channels_partial: number;
55
+ total_elapsed: string;
56
+ };
57
+ }
58
+ export type { MmrConfigParsed as MmrConfig, ChannelConfigParsed as ChannelConfig } from './config/schema.js';
59
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;AAEhD,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAKnD,CAAA;AAED,MAAM,MAAM,aAAa,GACrB,YAAY,GACZ,SAAS,GACT,WAAW,GACX,SAAS,GACT,QAAQ,GACR,aAAa,GACb,SAAS,CAAA;AAEb,MAAM,MAAM,SAAS,GAAG,YAAY,GAAG,SAAS,GAAG,WAAW,CAAA;AAE9D,MAAM,MAAM,SAAS,GAAG,WAAW,GAAG,UAAU,GAAG,QAAQ,GAAG,WAAW,CAAA;AAEzE,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAA;AAElD,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,GAAG,OAAO,CAAA;AAEjE,MAAM,WAAW,OAAO;IACtB,QAAQ,EAAE,QAAQ,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,iBAAkB,SAAQ,OAAO;IAChD,UAAU,EAAE,UAAU,CAAA;IACtB,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,SAAS,EAAE,SAAS,CAAA;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,aAAa,CAAA;IACrB,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,SAAS,CAAA;IACjB,aAAa,EAAE,QAAQ,CAAA;IACvB,MAAM,EAAE,YAAY,CAAA;IACpB,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;CAC1C;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,aAAa,CAAA;IACrB,IAAI,EAAE,IAAI,GAAG,QAAQ,GAAG,SAAS,CAAA;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,OAAO,CAAA;IACpB,aAAa,EAAE,QAAQ,CAAA;IACvB,mBAAmB,EAAE,iBAAiB,EAAE,CAAA;IACxC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;IAC1C,QAAQ,EAAE;QACR,mBAAmB,EAAE,MAAM,CAAA;QAC3B,kBAAkB,EAAE,MAAM,CAAA;QAC1B,gBAAgB,EAAE,MAAM,CAAA;QACxB,aAAa,EAAE,MAAM,CAAA;KACtB,CAAA;CACF;AAID,YAAY,EAAE,eAAe,IAAI,SAAS,EAAE,mBAAmB,IAAI,aAAa,EAAE,MAAM,oBAAoB,CAAA"}
package/dist/types.js ADDED
@@ -0,0 +1,7 @@
1
+ export const SEVERITY_ORDER = {
2
+ P0: 0,
3
+ P1: 1,
4
+ P2: 2,
5
+ P3: 3,
6
+ };
7
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,cAAc,GAA6B;IACtD,EAAE,EAAE,CAAC;IACL,EAAE,EAAE,CAAC;IACL,EAAE,EAAE,CAAC;IACL,EAAE,EAAE,CAAC;CACN,CAAA"}
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "@zigrivers/mmr",
3
+ "version": "0.1.0",
4
+ "description": "Multi-model code review CLI — async dispatch, reconciliation, and severity gating",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/zigrivers/scaffold.git",
10
+ "directory": "packages/mmr"
11
+ },
12
+ "publishConfig": {
13
+ "access": "public",
14
+ "registry": "https://registry.npmjs.org"
15
+ },
16
+ "files": ["dist/", "templates/", "README.md", "LICENSE"],
17
+ "engines": { "node": ">=18" },
18
+ "main": "./dist/index.js",
19
+ "types": "./dist/index.d.ts",
20
+ "bin": { "mmr": "dist/index.js" },
21
+ "scripts": {
22
+ "build": "tsc -p tsconfig.build.json",
23
+ "test": "vitest run",
24
+ "test:coverage": "vitest run --coverage",
25
+ "lint": "eslint src/",
26
+ "type-check": "tsc --noEmit",
27
+ "check": "npm run lint && npm run type-check && npm test"
28
+ },
29
+ "dependencies": {
30
+ "js-yaml": "^4.1.0",
31
+ "yargs": "^17.7.2",
32
+ "zod": "^3.24.0"
33
+ },
34
+ "devDependencies": {
35
+ "@eslint/js": "^9.21.0",
36
+ "@types/js-yaml": "^4.0.9",
37
+ "@types/node": "^22.13.0",
38
+ "@types/yargs": "^17.0.33",
39
+ "@vitest/coverage-v8": "^3.0.7",
40
+ "eslint": "^9.21.0",
41
+ "typescript": "^5.8.2",
42
+ "typescript-eslint": "^8.26.0",
43
+ "vitest": "^3.0.7"
44
+ }
45
+ }
@@ -0,0 +1,33 @@
1
+ You are reviewing code changes. Return ONLY a JSON object with your findings.
2
+
3
+ ## Severity Definitions
4
+ - P0 (Critical): Will cause failure, data loss, security vulnerability, or fundamental architectural flaw
5
+ - P1 (High): Will cause bugs in normal usage, inconsistency, or blocks downstream work
6
+ - P2 (Medium): Improvement opportunity — style, naming, documentation, minor optimization
7
+ - P3 (Trivial): Personal preference, trivial nits — only report if nothing else found
8
+
9
+ ## Review Criteria
10
+ - Correctness: Does the logic do what it claims?
11
+ - Regressions: Does this break existing behavior?
12
+ - Edge cases: What inputs/states are unhandled?
13
+ - Test coverage: Are changes tested? Are tests meaningful?
14
+ - Security: Injection, auth bypass, data exposure?
15
+
16
+ ## Output Format
17
+ Return valid JSON matching this schema exactly:
18
+ {
19
+ "approved": true | false,
20
+ "findings": [
21
+ {
22
+ "severity": "P0 | P1 | P2 | P3",
23
+ "location": "file:line",
24
+ "description": "what is wrong",
25
+ "suggestion": "specific fix"
26
+ }
27
+ ],
28
+ "summary": "one-line assessment"
29
+ }
30
+
31
+ If no issues found, return: {"approved": true, "findings": [], "summary": "No issues found."}
32
+
33
+ Do NOT include markdown fences, preamble, or commentary outside the JSON object.