tryassay 0.6.0 → 0.11.1

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 (109) hide show
  1. package/dist/api/pricing-enforcer.d.ts +45 -0
  2. package/dist/api/pricing-enforcer.js +144 -0
  3. package/dist/api/pricing-enforcer.js.map +1 -0
  4. package/dist/api/server.d.ts +28 -0
  5. package/dist/api/server.js +265 -0
  6. package/dist/api/server.js.map +1 -0
  7. package/dist/api/team-session.d.ts +59 -0
  8. package/dist/api/team-session.js +240 -0
  9. package/dist/api/team-session.js.map +1 -0
  10. package/dist/cli.js +123 -2
  11. package/dist/cli.js.map +1 -1
  12. package/dist/commands/api.d.ts +4 -0
  13. package/dist/commands/api.js +50 -0
  14. package/dist/commands/api.js.map +1 -0
  15. package/dist/commands/runtime.d.ts +61 -0
  16. package/dist/commands/runtime.js +554 -0
  17. package/dist/commands/runtime.js.map +1 -1
  18. package/dist/runtime/agent-spawner.d.ts +56 -0
  19. package/dist/runtime/agent-spawner.js +217 -0
  20. package/dist/runtime/agent-spawner.js.map +1 -0
  21. package/dist/runtime/agents/coordinator-agent.d.ts +20 -0
  22. package/dist/runtime/agents/coordinator-agent.js +182 -0
  23. package/dist/runtime/agents/coordinator-agent.js.map +1 -0
  24. package/dist/runtime/agents/ops-agent.d.ts +11 -0
  25. package/dist/runtime/agents/ops-agent.js +113 -0
  26. package/dist/runtime/agents/ops-agent.js.map +1 -0
  27. package/dist/runtime/agents/research-agent.d.ts +11 -0
  28. package/dist/runtime/agents/research-agent.js +114 -0
  29. package/dist/runtime/agents/research-agent.js.map +1 -0
  30. package/dist/runtime/agents/test-agent.d.ts +11 -0
  31. package/dist/runtime/agents/test-agent.js +114 -0
  32. package/dist/runtime/agents/test-agent.js.map +1 -0
  33. package/dist/runtime/audit-log.js +2 -2
  34. package/dist/runtime/audit-log.js.map +1 -1
  35. package/dist/runtime/capability-registry.d.ts +62 -0
  36. package/dist/runtime/capability-registry.js +191 -0
  37. package/dist/runtime/capability-registry.js.map +1 -0
  38. package/dist/runtime/collusion-detector.d.ts +35 -0
  39. package/dist/runtime/collusion-detector.js +97 -0
  40. package/dist/runtime/collusion-detector.js.map +1 -0
  41. package/dist/runtime/control-server.js +8 -4
  42. package/dist/runtime/control-server.js.map +1 -1
  43. package/dist/runtime/domain-coverage-analyzer.d.ts +24 -0
  44. package/dist/runtime/domain-coverage-analyzer.js +178 -0
  45. package/dist/runtime/domain-coverage-analyzer.js.map +1 -0
  46. package/dist/runtime/executor.js +27 -12
  47. package/dist/runtime/executor.js.map +1 -1
  48. package/dist/runtime/human-escalation.d.ts +41 -0
  49. package/dist/runtime/human-escalation.js +122 -0
  50. package/dist/runtime/human-escalation.js.map +1 -0
  51. package/dist/runtime/kill-switch.d.ts +51 -0
  52. package/dist/runtime/kill-switch.js +185 -0
  53. package/dist/runtime/kill-switch.js.map +1 -0
  54. package/dist/runtime/layer2-guardian.d.ts +81 -0
  55. package/dist/runtime/layer2-guardian.js +263 -0
  56. package/dist/runtime/layer2-guardian.js.map +1 -0
  57. package/dist/runtime/multi-agent-loop.d.ts +37 -0
  58. package/dist/runtime/multi-agent-loop.js +411 -0
  59. package/dist/runtime/multi-agent-loop.js.map +1 -0
  60. package/dist/runtime/prompt-safety-analyzer.d.ts +17 -0
  61. package/dist/runtime/prompt-safety-analyzer.js +230 -0
  62. package/dist/runtime/prompt-safety-analyzer.js.map +1 -0
  63. package/dist/runtime/rollback-manager.d.ts +50 -0
  64. package/dist/runtime/rollback-manager.js +157 -0
  65. package/dist/runtime/rollback-manager.js.map +1 -0
  66. package/dist/runtime/rule-canary-deployer.d.ts +69 -0
  67. package/dist/runtime/rule-canary-deployer.js +289 -0
  68. package/dist/runtime/rule-canary-deployer.js.map +1 -0
  69. package/dist/runtime/rule-conflict-detector.d.ts +48 -0
  70. package/dist/runtime/rule-conflict-detector.js +214 -0
  71. package/dist/runtime/rule-conflict-detector.js.map +1 -0
  72. package/dist/runtime/rule-meta-verifier.d.ts +18 -0
  73. package/dist/runtime/rule-meta-verifier.js +275 -0
  74. package/dist/runtime/rule-meta-verifier.js.map +1 -0
  75. package/dist/runtime/rule-proposal-manager.d.ts +95 -0
  76. package/dist/runtime/rule-proposal-manager.js +190 -0
  77. package/dist/runtime/rule-proposal-manager.js.map +1 -0
  78. package/dist/runtime/safety-enforcer.d.ts +35 -0
  79. package/dist/runtime/safety-enforcer.js +165 -0
  80. package/dist/runtime/safety-enforcer.js.map +1 -0
  81. package/dist/runtime/safety-status.d.ts +48 -0
  82. package/dist/runtime/safety-status.js +119 -0
  83. package/dist/runtime/safety-status.js.map +1 -0
  84. package/dist/runtime/shared-memory.d.ts +47 -0
  85. package/dist/runtime/shared-memory.js +151 -0
  86. package/dist/runtime/shared-memory.js.map +1 -0
  87. package/dist/runtime/specialized-agent.d.ts +5 -0
  88. package/dist/runtime/specialized-agent.js +37 -0
  89. package/dist/runtime/specialized-agent.js.map +1 -1
  90. package/dist/runtime/stall-detector.d.ts +13 -0
  91. package/dist/runtime/stall-detector.js +121 -0
  92. package/dist/runtime/stall-detector.js.map +1 -0
  93. package/dist/runtime/tool-approval.d.ts +51 -0
  94. package/dist/runtime/tool-approval.js +148 -0
  95. package/dist/runtime/tool-approval.js.map +1 -0
  96. package/dist/runtime/tool-sandbox.d.ts +43 -0
  97. package/dist/runtime/tool-sandbox.js +394 -0
  98. package/dist/runtime/tool-sandbox.js.map +1 -0
  99. package/dist/runtime/tool-verifier.d.ts +18 -0
  100. package/dist/runtime/tool-verifier.js +323 -0
  101. package/dist/runtime/tool-verifier.js.map +1 -0
  102. package/dist/runtime/trust-manager.d.ts +33 -3
  103. package/dist/runtime/trust-manager.js +128 -26
  104. package/dist/runtime/trust-manager.js.map +1 -1
  105. package/dist/runtime/types.d.ts +652 -0
  106. package/dist/runtime/verification-intensity.d.ts +34 -0
  107. package/dist/runtime/verification-intensity.js +104 -0
  108. package/dist/runtime/verification-intensity.js.map +1 -0
  109. package/package.json +1 -1
@@ -0,0 +1,289 @@
1
+ // ============================================================
2
+ // Assay Verified Agent Runtime — Rule Canary Deployer
3
+ // Manages rule progression: shadow -> canary 5% -> canary 25% -> full.
4
+ // Automatic rollback on error rate spikes.
5
+ // ============================================================
6
+ import { readFile, writeFile, mkdir } from 'node:fs/promises';
7
+ import { dirname } from 'node:path';
8
+ // ── Default Exit Criteria ───────────────────────────────
9
+ const DEFAULT_EXIT_CRITERIA = {
10
+ shadow: {
11
+ min_evaluations: 50,
12
+ max_error_rate: 0.05,
13
+ max_disagreement_rate: 0.15,
14
+ min_duration_hours: 24,
15
+ },
16
+ canary_5: {
17
+ min_evaluations: 100,
18
+ max_error_rate: 0.03,
19
+ max_disagreement_rate: 0.10,
20
+ min_duration_hours: 48,
21
+ },
22
+ canary_25: {
23
+ min_evaluations: 250,
24
+ max_error_rate: 0.02,
25
+ max_disagreement_rate: 0.05,
26
+ min_duration_hours: 24,
27
+ },
28
+ full_rollout: {
29
+ min_evaluations: 0,
30
+ max_error_rate: 0,
31
+ max_disagreement_rate: 0,
32
+ min_duration_hours: 0,
33
+ },
34
+ };
35
+ const STAGE_PROGRESSION = [
36
+ 'shadow',
37
+ 'canary_5',
38
+ 'canary_25',
39
+ 'full_rollout',
40
+ ];
41
+ // ── Rule Canary Deployer ────────────────────────────────
42
+ export class RuleCanaryDeployer {
43
+ deployments = new Map();
44
+ evaluations = new Map();
45
+ statePath;
46
+ constructor(statePath) {
47
+ this.statePath = statePath ?? '.assay/canary-state.json';
48
+ }
49
+ /**
50
+ * Start canary deployment for a rule.
51
+ * Formal rules skip shadow mode (they are deterministic).
52
+ */
53
+ startDeployment(rule, customExitCriteria) {
54
+ // Formal rules skip shadow mode
55
+ const startStage = rule.substrate.startsWith('formal_')
56
+ ? 'canary_5'
57
+ : 'shadow';
58
+ const exitCriteria = {
59
+ ...DEFAULT_EXIT_CRITERIA[startStage],
60
+ ...(customExitCriteria?.[startStage] ?? {}),
61
+ };
62
+ const deployment = {
63
+ rule_id: rule.id,
64
+ stage: startStage,
65
+ started_at: new Date().toISOString(),
66
+ stage_duration_hours: 0,
67
+ metrics: this.emptyMetrics(),
68
+ exit_criteria: exitCriteria,
69
+ };
70
+ this.deployments.set(rule.id, deployment);
71
+ this.evaluations.set(rule.id, []);
72
+ return deployment;
73
+ }
74
+ /**
75
+ * Record a canary evaluation (comparison of new rule against baseline).
76
+ */
77
+ recordEvaluation(evaluation) {
78
+ const evals = this.evaluations.get(evaluation.rule_id) ?? [];
79
+ evals.push(evaluation);
80
+ this.evaluations.set(evaluation.rule_id, evals);
81
+ // Update deployment metrics
82
+ const deployment = this.deployments.get(evaluation.rule_id);
83
+ if (deployment) {
84
+ const updatedMetrics = this.computeMetrics(evaluation.rule_id);
85
+ const updatedDeployment = {
86
+ ...deployment,
87
+ metrics: updatedMetrics,
88
+ stage_duration_hours: this.computeDurationHours(deployment.started_at),
89
+ };
90
+ this.deployments.set(evaluation.rule_id, updatedDeployment);
91
+ }
92
+ }
93
+ /**
94
+ * Check if a rule is ready to promote to the next canary stage.
95
+ * Returns the next stage if ready, null if not ready, 'rollback' if metrics are bad.
96
+ */
97
+ checkPromotion(ruleId) {
98
+ const deployment = this.deployments.get(ruleId);
99
+ if (!deployment) {
100
+ return { action: 'wait', reason: 'No active deployment found' };
101
+ }
102
+ const metrics = deployment.metrics;
103
+ const criteria = deployment.exit_criteria;
104
+ // Check for rollback conditions
105
+ if (metrics.error_rate > criteria.max_error_rate * 2) {
106
+ return {
107
+ action: 'rollback',
108
+ reason: `Error rate ${(metrics.error_rate * 100).toFixed(1)}% exceeds 2x threshold (${(criteria.max_error_rate * 100).toFixed(1)}%)`,
109
+ };
110
+ }
111
+ // Check exit criteria
112
+ if (metrics.total_evaluations < criteria.min_evaluations) {
113
+ return {
114
+ action: 'wait',
115
+ reason: `Need ${criteria.min_evaluations - metrics.total_evaluations} more evaluations (${metrics.total_evaluations}/${criteria.min_evaluations})`,
116
+ };
117
+ }
118
+ const durationHours = this.computeDurationHours(deployment.started_at);
119
+ if (durationHours < criteria.min_duration_hours) {
120
+ return {
121
+ action: 'wait',
122
+ reason: `Need ${(criteria.min_duration_hours - durationHours).toFixed(1)} more hours (${durationHours.toFixed(1)}/${criteria.min_duration_hours}h)`,
123
+ };
124
+ }
125
+ if (metrics.error_rate > criteria.max_error_rate) {
126
+ return {
127
+ action: 'rollback',
128
+ reason: `Error rate ${(metrics.error_rate * 100).toFixed(1)}% exceeds threshold (${(criteria.max_error_rate * 100).toFixed(1)}%)`,
129
+ };
130
+ }
131
+ const disagreementRate = metrics.total_evaluations > 0
132
+ ? metrics.disagreements / metrics.total_evaluations
133
+ : 0;
134
+ if (disagreementRate > criteria.max_disagreement_rate) {
135
+ return {
136
+ action: 'rollback',
137
+ reason: `Disagreement rate ${(disagreementRate * 100).toFixed(1)}% exceeds threshold (${(criteria.max_disagreement_rate * 100).toFixed(1)}%)`,
138
+ };
139
+ }
140
+ // All criteria met — promote
141
+ const currentIdx = STAGE_PROGRESSION.indexOf(deployment.stage);
142
+ if (currentIdx >= STAGE_PROGRESSION.length - 1) {
143
+ return {
144
+ action: 'wait',
145
+ reason: 'Already at full rollout',
146
+ };
147
+ }
148
+ const nextStage = STAGE_PROGRESSION[currentIdx + 1];
149
+ return {
150
+ action: 'promote',
151
+ nextStage,
152
+ reason: `All exit criteria met for ${deployment.stage}. Ready for ${nextStage}.`,
153
+ };
154
+ }
155
+ /**
156
+ * Promote a rule to the next canary stage.
157
+ */
158
+ promote(ruleId) {
159
+ const deployment = this.deployments.get(ruleId);
160
+ if (!deployment)
161
+ return null;
162
+ const currentIdx = STAGE_PROGRESSION.indexOf(deployment.stage);
163
+ if (currentIdx >= STAGE_PROGRESSION.length - 1)
164
+ return null;
165
+ const nextStage = STAGE_PROGRESSION[currentIdx + 1];
166
+ const exitCriteria = DEFAULT_EXIT_CRITERIA[nextStage];
167
+ const promoted = {
168
+ ...deployment,
169
+ stage: nextStage,
170
+ promoted_at: new Date().toISOString(),
171
+ started_at: new Date().toISOString(), // Reset timer for new stage
172
+ stage_duration_hours: 0,
173
+ metrics: this.emptyMetrics(), // Reset metrics for new stage
174
+ exit_criteria: exitCriteria,
175
+ };
176
+ this.deployments.set(ruleId, promoted);
177
+ this.evaluations.set(ruleId, []); // Reset evaluations for new stage
178
+ return promoted;
179
+ }
180
+ /**
181
+ * Rollback a rule's canary deployment. Removes it from all stages.
182
+ */
183
+ rollback(ruleId) {
184
+ const deployment = this.deployments.get(ruleId);
185
+ if (!deployment) {
186
+ return { success: false, reason: 'No active deployment found' };
187
+ }
188
+ this.deployments.delete(ruleId);
189
+ this.evaluations.delete(ruleId);
190
+ return {
191
+ success: true,
192
+ reason: `Rolled back from ${deployment.stage} after ${deployment.metrics.total_evaluations} evaluations`,
193
+ };
194
+ }
195
+ /**
196
+ * Get the current deployment state for a rule.
197
+ */
198
+ getDeployment(ruleId) {
199
+ return this.deployments.get(ruleId);
200
+ }
201
+ /**
202
+ * List all active canary deployments.
203
+ */
204
+ listDeployments() {
205
+ return Array.from(this.deployments.values());
206
+ }
207
+ /**
208
+ * Check if a rule should be evaluated for a given request.
209
+ * Based on the canary stage traffic percentage.
210
+ */
211
+ shouldEvaluate(ruleId) {
212
+ const deployment = this.deployments.get(ruleId);
213
+ if (!deployment)
214
+ return false;
215
+ switch (deployment.stage) {
216
+ case 'shadow': return true; // Always evaluate in shadow (results not used)
217
+ case 'canary_5': return Math.random() < 0.05;
218
+ case 'canary_25': return Math.random() < 0.25;
219
+ case 'full_rollout': return true;
220
+ }
221
+ }
222
+ /**
223
+ * Save deployment state to disk.
224
+ */
225
+ async saveState() {
226
+ const state = {
227
+ deployments: Object.fromEntries(this.deployments),
228
+ evaluationCounts: Object.fromEntries(Array.from(this.evaluations.entries()).map(([k, v]) => [k, v.length])),
229
+ };
230
+ await mkdir(dirname(this.statePath), { recursive: true });
231
+ await writeFile(this.statePath, JSON.stringify(state, null, 2), 'utf-8');
232
+ }
233
+ /**
234
+ * Load deployment state from disk.
235
+ */
236
+ async loadState() {
237
+ try {
238
+ const raw = await readFile(this.statePath, 'utf-8');
239
+ const state = JSON.parse(raw);
240
+ if (state.deployments) {
241
+ this.deployments = new Map(Object.entries(state.deployments));
242
+ }
243
+ }
244
+ catch {
245
+ // No state file — start fresh
246
+ }
247
+ }
248
+ // ── Private helpers ────────────────────────────────────
249
+ computeMetrics(ruleId) {
250
+ const evals = this.evaluations.get(ruleId) ?? [];
251
+ if (evals.length === 0)
252
+ return this.emptyMetrics();
253
+ const totalEvaluations = evals.length;
254
+ const agreements = evals.filter(e => e.agreed).length;
255
+ const disagreements = totalEvaluations - agreements;
256
+ const errors = evals.filter(e => e.error !== undefined).length;
257
+ const totalLatency = evals.reduce((sum, e) => sum + e.latency_ms, 0);
258
+ // False positive: canary says FAIL, baseline says PASS
259
+ const falsePositives = evals.filter(e => e.canary_verdict === 'FAIL' && e.baseline_verdict === 'PASS').length;
260
+ // False negative: canary says PASS, baseline says FAIL
261
+ const falseNegatives = evals.filter(e => e.canary_verdict === 'PASS' && e.baseline_verdict === 'FAIL').length;
262
+ return {
263
+ total_evaluations: totalEvaluations,
264
+ agreements_with_baseline: agreements,
265
+ disagreements,
266
+ error_rate: totalEvaluations > 0 ? errors / totalEvaluations : 0,
267
+ false_positive_rate: totalEvaluations > 0 ? falsePositives / totalEvaluations : 0,
268
+ false_negative_rate: totalEvaluations > 0 ? falseNegatives / totalEvaluations : 0,
269
+ avg_latency_ms: totalEvaluations > 0 ? totalLatency / totalEvaluations : 0,
270
+ };
271
+ }
272
+ computeDurationHours(startedAt) {
273
+ const start = new Date(startedAt).getTime();
274
+ const now = Date.now();
275
+ return (now - start) / (1000 * 60 * 60);
276
+ }
277
+ emptyMetrics() {
278
+ return {
279
+ total_evaluations: 0,
280
+ agreements_with_baseline: 0,
281
+ disagreements: 0,
282
+ error_rate: 0,
283
+ false_positive_rate: 0,
284
+ false_negative_rate: 0,
285
+ avg_latency_ms: 0,
286
+ };
287
+ }
288
+ }
289
+ //# sourceMappingURL=rule-canary-deployer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-canary-deployer.js","sourceRoot":"","sources":["../../src/runtime/rule-canary-deployer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ import type { VerificationRule } from './types.js';
2
+ export interface ConflictReport {
3
+ readonly direct_conflicts: readonly DirectConflict[];
4
+ readonly scope_overlaps: readonly ScopeOverlap[];
5
+ readonly transitive_chains: readonly TransitiveChain[];
6
+ readonly summary: string;
7
+ }
8
+ export interface DirectConflict {
9
+ readonly rule_a: string;
10
+ readonly rule_b: string;
11
+ readonly test_case_id: string;
12
+ readonly rule_a_verdict: 'PASS' | 'FAIL';
13
+ readonly rule_b_verdict: 'PASS' | 'FAIL';
14
+ readonly description: string;
15
+ }
16
+ export interface ScopeOverlap {
17
+ readonly rule_a: string;
18
+ readonly rule_b: string;
19
+ readonly overlapping_categories: readonly string[];
20
+ readonly overlapping_languages: readonly string[];
21
+ readonly risk: 'low' | 'medium' | 'high';
22
+ readonly description: string;
23
+ }
24
+ export interface TransitiveChain {
25
+ readonly chain: readonly string[];
26
+ readonly root_conflict: string;
27
+ }
28
+ export declare class RuleConflictDetector {
29
+ /**
30
+ * Perform comprehensive conflict analysis on a set of rules.
31
+ * Detects direct conflicts (opposite verdicts on same input),
32
+ * scope overlaps (same claim categories + languages), and
33
+ * transitive conflict chains.
34
+ */
35
+ analyze(rules: readonly VerificationRule[]): ConflictReport;
36
+ /**
37
+ * Check if adding a new rule would introduce conflicts.
38
+ */
39
+ checkNewRule(newRule: VerificationRule, existingRules: readonly VerificationRule[]): ConflictReport;
40
+ private findDirectConflicts;
41
+ private compareRulePair;
42
+ private runFormalCheck;
43
+ private findScopeOverlaps;
44
+ private assessOverlapRisk;
45
+ private findTransitiveChains;
46
+ private hasOverlappingScope;
47
+ private generateSummary;
48
+ }
@@ -0,0 +1,214 @@
1
+ // ============================================================
2
+ // Assay Verified Agent Runtime — Rule Conflict Detector
3
+ // Finds rules that contradict each other, detects scope overlaps,
4
+ // and identifies transitive conflict chains.
5
+ // ============================================================
6
+ // ── Rule Conflict Detector ──────────────────────────────
7
+ export class RuleConflictDetector {
8
+ /**
9
+ * Perform comprehensive conflict analysis on a set of rules.
10
+ * Detects direct conflicts (opposite verdicts on same input),
11
+ * scope overlaps (same claim categories + languages), and
12
+ * transitive conflict chains.
13
+ */
14
+ analyze(rules) {
15
+ const directConflicts = this.findDirectConflicts(rules);
16
+ const scopeOverlaps = this.findScopeOverlaps(rules);
17
+ const transitiveChains = this.findTransitiveChains(directConflicts, rules);
18
+ const summary = this.generateSummary(directConflicts, scopeOverlaps, transitiveChains);
19
+ return {
20
+ direct_conflicts: directConflicts,
21
+ scope_overlaps: scopeOverlaps,
22
+ transitive_chains: transitiveChains,
23
+ summary,
24
+ };
25
+ }
26
+ /**
27
+ * Check if adding a new rule would introduce conflicts.
28
+ */
29
+ checkNewRule(newRule, existingRules) {
30
+ const allRules = [...existingRules, newRule];
31
+ const fullReport = this.analyze(allRules);
32
+ // Filter to only conflicts involving the new rule
33
+ return {
34
+ direct_conflicts: fullReport.direct_conflicts.filter(c => c.rule_a === newRule.id || c.rule_b === newRule.id),
35
+ scope_overlaps: fullReport.scope_overlaps.filter(o => o.rule_a === newRule.id || o.rule_b === newRule.id),
36
+ transitive_chains: fullReport.transitive_chains.filter(t => t.chain.includes(newRule.id)),
37
+ summary: fullReport.summary,
38
+ };
39
+ }
40
+ // ── Private: Direct Conflict Detection ─────────────────
41
+ findDirectConflicts(rules) {
42
+ const conflicts = [];
43
+ // For each pair of rules that have formal checks, compare
44
+ // their pattern behavior on each other's test cases
45
+ for (let i = 0; i < rules.length; i++) {
46
+ for (let j = i + 1; j < rules.length; j++) {
47
+ const ruleA = rules[i];
48
+ const ruleB = rules[j];
49
+ // Only compare rules with overlapping scope
50
+ if (!this.hasOverlappingScope(ruleA, ruleB))
51
+ continue;
52
+ // Test rule B's test cases against rule A (and vice versa)
53
+ const abConflicts = this.compareRulePair(ruleA, ruleB);
54
+ conflicts.push(...abConflicts);
55
+ }
56
+ }
57
+ return conflicts;
58
+ }
59
+ compareRulePair(ruleA, ruleB) {
60
+ const conflicts = [];
61
+ // Run ruleA's formal check against ruleB's test cases
62
+ if (ruleA.check.type === 'formal' || ruleA.check.type === 'composite') {
63
+ const formalCheck = ruleA.check.type === 'formal'
64
+ ? ruleA.check
65
+ : ruleA.check.formal_component;
66
+ for (const testCase of ruleB.test_cases) {
67
+ if (!ruleA.target.languages.includes(testCase.input_language))
68
+ continue;
69
+ const aVerdict = this.runFormalCheck(formalCheck, testCase.input_code);
70
+ // If ruleA says PASS but the test case expects FAIL (or vice versa),
71
+ // this is a potential conflict
72
+ if (aVerdict !== testCase.expected_verdict) {
73
+ conflicts.push({
74
+ rule_a: ruleA.id,
75
+ rule_b: ruleB.id,
76
+ test_case_id: testCase.id,
77
+ rule_a_verdict: aVerdict,
78
+ rule_b_verdict: testCase.expected_verdict,
79
+ description: `Rule "${ruleA.name}" produces ${aVerdict} on test case "${testCase.description}" from rule "${ruleB.name}" which expects ${testCase.expected_verdict}`,
80
+ });
81
+ }
82
+ }
83
+ }
84
+ return conflicts;
85
+ }
86
+ runFormalCheck(check, code) {
87
+ const results = [];
88
+ for (const pattern of check.patterns) {
89
+ if (pattern.pattern_type === 'regex') {
90
+ try {
91
+ const regex = new RegExp(pattern.pattern, 'gm');
92
+ results.push(regex.test(code));
93
+ }
94
+ catch {
95
+ results.push(false);
96
+ }
97
+ }
98
+ else {
99
+ // Non-regex patterns are skipped in conflict detection
100
+ results.push(true);
101
+ }
102
+ }
103
+ switch (check.logic) {
104
+ case 'all_match': return results.every(r => r) ? 'PASS' : 'FAIL';
105
+ case 'any_match': return results.some(r => r) ? 'PASS' : 'FAIL';
106
+ case 'none_match': return results.every(r => !r) ? 'PASS' : 'FAIL';
107
+ case 'custom': return results.every(r => r) ? 'PASS' : 'FAIL';
108
+ }
109
+ }
110
+ // ── Private: Scope Overlap Detection ───────────────────
111
+ findScopeOverlaps(rules) {
112
+ const overlaps = [];
113
+ for (let i = 0; i < rules.length; i++) {
114
+ for (let j = i + 1; j < rules.length; j++) {
115
+ const ruleA = rules[i];
116
+ const ruleB = rules[j];
117
+ const overlappingCategories = ruleA.target.claim_categories.filter(c => ruleB.target.claim_categories.includes(c));
118
+ const overlappingLanguages = ruleA.target.languages.filter(l => ruleB.target.languages.includes(l));
119
+ if (overlappingCategories.length > 0 && overlappingLanguages.length > 0) {
120
+ // Determine risk based on substrate compatibility
121
+ const risk = this.assessOverlapRisk(ruleA, ruleB, overlappingCategories);
122
+ overlaps.push({
123
+ rule_a: ruleA.id,
124
+ rule_b: ruleB.id,
125
+ overlapping_categories: overlappingCategories,
126
+ overlapping_languages: overlappingLanguages,
127
+ risk,
128
+ description: `Rules "${ruleA.name}" and "${ruleB.name}" both target ${overlappingCategories.join(', ')} in ${overlappingLanguages.join(', ')}`,
129
+ });
130
+ }
131
+ }
132
+ }
133
+ return overlaps;
134
+ }
135
+ assessOverlapRisk(ruleA, ruleB, overlappingCategories) {
136
+ // Two formal rules with overlapping scope = low risk (deterministic, can be reconciled)
137
+ if (ruleA.substrate.startsWith('formal_') && ruleB.substrate.startsWith('formal_')) {
138
+ return 'low';
139
+ }
140
+ // Formal + LLM = medium risk (formal override handles disagreement)
141
+ if (ruleA.substrate.startsWith('formal_') || ruleB.substrate.startsWith('formal_')) {
142
+ return 'medium';
143
+ }
144
+ // Two LLM rules with many overlapping categories = high risk
145
+ if (overlappingCategories.length >= 2) {
146
+ return 'high';
147
+ }
148
+ return 'medium';
149
+ }
150
+ // ── Private: Transitive Chain Detection ────────────────
151
+ findTransitiveChains(directConflicts, _rules) {
152
+ // Build an adjacency graph of conflicts
153
+ const conflictGraph = new Map();
154
+ for (const conflict of directConflicts) {
155
+ if (!conflictGraph.has(conflict.rule_a)) {
156
+ conflictGraph.set(conflict.rule_a, new Set());
157
+ }
158
+ if (!conflictGraph.has(conflict.rule_b)) {
159
+ conflictGraph.set(conflict.rule_b, new Set());
160
+ }
161
+ conflictGraph.get(conflict.rule_a).add(conflict.rule_b);
162
+ conflictGraph.get(conflict.rule_b).add(conflict.rule_a);
163
+ }
164
+ // Find connected components of size > 2 (transitive chains)
165
+ const visited = new Set();
166
+ const chains = [];
167
+ for (const [ruleId] of conflictGraph) {
168
+ if (visited.has(ruleId))
169
+ continue;
170
+ const component = [];
171
+ const queue = [ruleId];
172
+ while (queue.length > 0) {
173
+ const current = queue.shift();
174
+ if (visited.has(current))
175
+ continue;
176
+ visited.add(current);
177
+ component.push(current);
178
+ const neighbors = conflictGraph.get(current) ?? new Set();
179
+ for (const neighbor of neighbors) {
180
+ if (!visited.has(neighbor)) {
181
+ queue.push(neighbor);
182
+ }
183
+ }
184
+ }
185
+ if (component.length > 2) {
186
+ chains.push({
187
+ chain: component,
188
+ root_conflict: `${component.length} rules form a transitive conflict chain: ${component.join(' <-> ')}`,
189
+ });
190
+ }
191
+ }
192
+ return chains;
193
+ }
194
+ // ── Private: Helpers ───────────────────────────────────
195
+ hasOverlappingScope(a, b) {
196
+ const categoryOverlap = a.target.claim_categories.some(c => b.target.claim_categories.includes(c));
197
+ const languageOverlap = a.target.languages.some(l => b.target.languages.includes(l));
198
+ return categoryOverlap && languageOverlap;
199
+ }
200
+ generateSummary(conflicts, overlaps, chains) {
201
+ const parts = [];
202
+ parts.push(`Direct conflicts: ${conflicts.length}`);
203
+ parts.push(`Scope overlaps: ${overlaps.length} (${overlaps.filter(o => o.risk === 'high').length} high-risk)`);
204
+ parts.push(`Transitive chains: ${chains.length}`);
205
+ if (conflicts.length === 0 && chains.length === 0) {
206
+ parts.push('No conflicts detected. Safe to proceed.');
207
+ }
208
+ else {
209
+ parts.push('Manual review recommended before activation.');
210
+ }
211
+ return parts.join('. ');
212
+ }
213
+ }
214
+ //# sourceMappingURL=rule-conflict-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-conflict-detector.js","sourceRoot":"","sources":["../../src/runtime/rule-conflict-detector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { VerificationRule, RuleMetaVerification } from './types.js';
2
+ export declare class RuleMetaVerifier {
3
+ private consistencyRuns;
4
+ constructor(opts?: {
5
+ consistencyRuns?: number;
6
+ });
7
+ /**
8
+ * Meta-verify a proposed rule:
9
+ * 1. Run all test cases through the rule's check logic
10
+ * 2. Check consistency (run multiple times for LLM-based rules)
11
+ * 3. Check for conflicts with existing rules
12
+ * Returns a RuleMetaVerification report.
13
+ */
14
+ verify(proposedRule: VerificationRule, existingRules: readonly VerificationRule[]): Promise<RuleMetaVerification>;
15
+ private runTestCases;
16
+ private checkConsistency;
17
+ private checkConflicts;
18
+ }