@panguard-ai/atr 1.4.3 → 1.5.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.
- package/dist/action-executor.d.ts +44 -0
- package/dist/action-executor.d.ts.map +1 -0
- package/dist/action-executor.js +130 -0
- package/dist/action-executor.js.map +1 -0
- package/dist/adapters/default-adapter.d.ts +24 -0
- package/dist/adapters/default-adapter.d.ts.map +1 -0
- package/dist/adapters/default-adapter.js +51 -0
- package/dist/adapters/default-adapter.js.map +1 -0
- package/dist/adapters/stdio-adapter.d.ts +30 -0
- package/dist/adapters/stdio-adapter.d.ts.map +1 -0
- package/dist/adapters/stdio-adapter.js +128 -0
- package/dist/adapters/stdio-adapter.js.map +1 -0
- package/dist/badge.d.ts +42 -0
- package/dist/badge.d.ts.map +1 -0
- package/dist/badge.js +163 -0
- package/dist/badge.js.map +1 -0
- package/dist/capability-extractor.d.ts +35 -0
- package/dist/capability-extractor.d.ts.map +1 -0
- package/dist/capability-extractor.js +91 -0
- package/dist/capability-extractor.js.map +1 -0
- package/dist/cli/scan-handler.d.ts +21 -0
- package/dist/cli/scan-handler.d.ts.map +1 -0
- package/dist/cli/scan-handler.js +276 -0
- package/dist/cli/scan-handler.js.map +1 -0
- package/dist/cli/tc-pipeline.d.ts +18 -0
- package/dist/cli/tc-pipeline.d.ts.map +1 -0
- package/dist/cli/tc-pipeline.js +295 -0
- package/dist/cli/tc-pipeline.js.map +1 -0
- package/dist/cli.d.ts +12 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +894 -0
- package/dist/cli.js.map +1 -0
- package/dist/content-hash.d.ts +7 -0
- package/dist/content-hash.d.ts.map +1 -0
- package/dist/content-hash.js +10 -0
- package/dist/content-hash.js.map +1 -0
- package/dist/converters/elastic.d.ts +36 -0
- package/dist/converters/elastic.d.ts.map +1 -0
- package/dist/converters/elastic.js +125 -0
- package/dist/converters/elastic.js.map +1 -0
- package/dist/converters/generic-regex.d.ts +37 -0
- package/dist/converters/generic-regex.d.ts.map +1 -0
- package/dist/converters/generic-regex.js +59 -0
- package/dist/converters/generic-regex.js.map +1 -0
- package/dist/converters/index.d.ts +32 -0
- package/dist/converters/index.d.ts.map +1 -0
- package/dist/converters/index.js +38 -0
- package/dist/converters/index.js.map +1 -0
- package/dist/converters/sarif.d.ts +18 -0
- package/dist/converters/sarif.d.ts.map +1 -0
- package/dist/converters/sarif.js +142 -0
- package/dist/converters/sarif.js.map +1 -0
- package/dist/converters/splunk.d.ts +19 -0
- package/dist/converters/splunk.d.ts.map +1 -0
- package/dist/converters/splunk.js +148 -0
- package/dist/converters/splunk.js.map +1 -0
- package/dist/coverage-analyzer.d.ts +43 -0
- package/dist/coverage-analyzer.d.ts.map +1 -0
- package/dist/coverage-analyzer.js +329 -0
- package/dist/coverage-analyzer.js.map +1 -0
- package/dist/embedding/build-corpus.d.ts +15 -0
- package/dist/embedding/build-corpus.d.ts.map +1 -0
- package/dist/embedding/build-corpus.js +105 -0
- package/dist/embedding/build-corpus.js.map +1 -0
- package/dist/embedding/model-loader.d.ts +41 -0
- package/dist/embedding/model-loader.d.ts.map +1 -0
- package/dist/embedding/model-loader.js +90 -0
- package/dist/embedding/model-loader.js.map +1 -0
- package/dist/embedding/vector-store.d.ts +41 -0
- package/dist/embedding/vector-store.d.ts.map +1 -0
- package/dist/embedding/vector-store.js +70 -0
- package/dist/embedding/vector-store.js.map +1 -0
- package/dist/engine.d.ts +222 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +1185 -0
- package/dist/engine.js.map +1 -0
- package/dist/eval/corpus.d.ts +42 -0
- package/dist/eval/corpus.d.ts.map +1 -0
- package/dist/eval/corpus.js +427 -0
- package/dist/eval/corpus.js.map +1 -0
- package/dist/eval/eval-harness.d.ts +44 -0
- package/dist/eval/eval-harness.d.ts.map +1 -0
- package/dist/eval/eval-harness.js +296 -0
- package/dist/eval/eval-harness.js.map +1 -0
- package/dist/eval/index.d.ts +13 -0
- package/dist/eval/index.d.ts.map +1 -0
- package/dist/eval/index.js +9 -0
- package/dist/eval/index.js.map +1 -0
- package/dist/eval/metrics.d.ts +74 -0
- package/dist/eval/metrics.d.ts.map +1 -0
- package/dist/eval/metrics.js +108 -0
- package/dist/eval/metrics.js.map +1 -0
- package/dist/eval/pint-corpus.d.ts +34 -0
- package/dist/eval/pint-corpus.d.ts.map +1 -0
- package/dist/eval/pint-corpus.js +113 -0
- package/dist/eval/pint-corpus.js.map +1 -0
- package/dist/eval/rule-corpus.d.ts +9 -0
- package/dist/eval/rule-corpus.d.ts.map +1 -0
- package/dist/eval/rule-corpus.js +4780 -0
- package/dist/eval/rule-corpus.js.map +1 -0
- package/dist/eval/rule-metrics.d.ts +34 -0
- package/dist/eval/rule-metrics.d.ts.map +1 -0
- package/dist/eval/rule-metrics.js +92 -0
- package/dist/eval/rule-metrics.js.map +1 -0
- package/dist/eval/run-eval.d.ts +7 -0
- package/dist/eval/run-eval.d.ts.map +1 -0
- package/dist/eval/run-eval.js +11 -0
- package/dist/eval/run-eval.js.map +1 -0
- package/dist/eval/run-pint-benchmark.d.ts +18 -0
- package/dist/eval/run-pint-benchmark.d.ts.map +1 -0
- package/dist/eval/run-pint-benchmark.js +159 -0
- package/dist/eval/run-pint-benchmark.js.map +1 -0
- package/dist/eval/skill-benchmark.d.ts +66 -0
- package/dist/eval/skill-benchmark.d.ts.map +1 -0
- package/dist/eval/skill-benchmark.js +194 -0
- package/dist/eval/skill-benchmark.js.map +1 -0
- package/dist/flywheel.d.ts +54 -0
- package/dist/flywheel.d.ts.map +1 -0
- package/dist/flywheel.js +121 -0
- package/dist/flywheel.js.map +1 -0
- package/dist/hook-handler.d.ts +61 -0
- package/dist/hook-handler.d.ts.map +1 -0
- package/dist/hook-handler.js +178 -0
- package/dist/hook-handler.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/{src/index.ts → dist/index.js} +1 -0
- package/dist/index.js.map +1 -0
- package/dist/layer-integration.d.ts +55 -0
- package/dist/layer-integration.d.ts.map +1 -0
- package/dist/layer-integration.js +187 -0
- package/dist/layer-integration.js.map +1 -0
- package/dist/loader.d.ts +18 -0
- package/dist/loader.d.ts.map +1 -0
- package/dist/loader.js +129 -0
- package/dist/loader.js.map +1 -0
- package/dist/mcp-server.d.ts +13 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +246 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/mcp-tools/coverage-gaps.d.ts +13 -0
- package/dist/mcp-tools/coverage-gaps.d.ts.map +1 -0
- package/dist/mcp-tools/coverage-gaps.js +55 -0
- package/dist/mcp-tools/coverage-gaps.js.map +1 -0
- package/dist/mcp-tools/list-rules.d.ts +17 -0
- package/dist/mcp-tools/list-rules.d.ts.map +1 -0
- package/dist/mcp-tools/list-rules.js +45 -0
- package/dist/mcp-tools/list-rules.js.map +1 -0
- package/dist/mcp-tools/scan-skill.d.ts +17 -0
- package/dist/mcp-tools/scan-skill.d.ts.map +1 -0
- package/dist/mcp-tools/scan-skill.js +65 -0
- package/dist/mcp-tools/scan-skill.js.map +1 -0
- package/dist/mcp-tools/scan.d.ts +24 -0
- package/dist/mcp-tools/scan.d.ts.map +1 -0
- package/dist/mcp-tools/scan.js +94 -0
- package/dist/mcp-tools/scan.js.map +1 -0
- package/dist/mcp-tools/submit-proposal.d.ts +12 -0
- package/dist/mcp-tools/submit-proposal.d.ts.map +1 -0
- package/dist/mcp-tools/submit-proposal.js +103 -0
- package/dist/mcp-tools/submit-proposal.js.map +1 -0
- package/dist/mcp-tools/threat-summary.d.ts +12 -0
- package/dist/mcp-tools/threat-summary.d.ts.map +1 -0
- package/dist/mcp-tools/threat-summary.js +74 -0
- package/dist/mcp-tools/threat-summary.js.map +1 -0
- package/dist/mcp-tools/validate.d.ts +15 -0
- package/dist/mcp-tools/validate.d.ts.map +1 -0
- package/dist/mcp-tools/validate.js +51 -0
- package/dist/mcp-tools/validate.js.map +1 -0
- package/dist/modules/embedding.d.ts +71 -0
- package/dist/modules/embedding.d.ts.map +1 -0
- package/dist/modules/embedding.js +141 -0
- package/dist/modules/embedding.js.map +1 -0
- package/dist/modules/index.d.ts +144 -0
- package/dist/modules/index.d.ts.map +1 -0
- package/dist/modules/index.js +82 -0
- package/dist/modules/index.js.map +1 -0
- package/dist/modules/semantic.d.ts +106 -0
- package/dist/modules/semantic.d.ts.map +1 -0
- package/dist/modules/semantic.js +359 -0
- package/dist/modules/semantic.js.map +1 -0
- package/dist/modules/session.d.ts +70 -0
- package/dist/modules/session.d.ts.map +1 -0
- package/dist/modules/session.js +128 -0
- package/dist/modules/session.js.map +1 -0
- package/dist/quality/adapters/atr.d.ts +65 -0
- package/dist/quality/adapters/atr.d.ts.map +1 -0
- package/dist/quality/adapters/atr.js +154 -0
- package/dist/quality/adapters/atr.js.map +1 -0
- package/dist/quality/adapters/index.d.ts +10 -0
- package/dist/quality/adapters/index.d.ts.map +1 -0
- package/dist/quality/adapters/index.js +10 -0
- package/dist/quality/adapters/index.js.map +1 -0
- package/dist/quality/compute-confidence.d.ts +45 -0
- package/dist/quality/compute-confidence.d.ts.map +1 -0
- package/dist/quality/compute-confidence.js +133 -0
- package/dist/quality/compute-confidence.js.map +1 -0
- package/dist/quality/index.d.ts +36 -0
- package/dist/quality/index.d.ts.map +1 -0
- package/dist/quality/index.js +39 -0
- package/dist/quality/index.js.map +1 -0
- package/dist/quality/quality-gate.d.ts +86 -0
- package/dist/quality/quality-gate.d.ts.map +1 -0
- package/dist/quality/quality-gate.js +187 -0
- package/dist/quality/quality-gate.js.map +1 -0
- package/dist/quality/types.d.ts +129 -0
- package/dist/quality/types.d.ts.map +1 -0
- package/dist/quality/types.js +10 -0
- package/dist/quality/types.js.map +1 -0
- package/dist/quality/validate-maturity.d.ts +51 -0
- package/dist/quality/validate-maturity.d.ts.map +1 -0
- package/dist/quality/validate-maturity.js +134 -0
- package/dist/quality/validate-maturity.js.map +1 -0
- package/dist/quality.d.ts +8 -0
- package/dist/quality.d.ts.map +1 -0
- package/dist/quality.js +8 -0
- package/dist/quality.js.map +1 -0
- package/dist/rule-scaffolder.d.ts +53 -0
- package/dist/rule-scaffolder.d.ts.map +1 -0
- package/dist/rule-scaffolder.js +301 -0
- package/dist/rule-scaffolder.js.map +1 -0
- package/dist/session-tracker.d.ts +58 -0
- package/dist/session-tracker.d.ts.map +1 -0
- package/dist/session-tracker.js +176 -0
- package/dist/session-tracker.js.map +1 -0
- package/dist/shadow-evaluator.d.ts +48 -0
- package/dist/shadow-evaluator.d.ts.map +1 -0
- package/dist/shadow-evaluator.js +129 -0
- package/dist/shadow-evaluator.js.map +1 -0
- package/dist/skill-fingerprint.d.ts +85 -0
- package/dist/skill-fingerprint.d.ts.map +1 -0
- package/dist/skill-fingerprint.js +284 -0
- package/dist/skill-fingerprint.js.map +1 -0
- package/dist/tc-reporter.d.ts +50 -0
- package/dist/tc-reporter.d.ts.map +1 -0
- package/dist/tc-reporter.js +164 -0
- package/dist/tc-reporter.js.map +1 -0
- package/dist/tier0-invariant.d.ts +49 -0
- package/dist/tier0-invariant.d.ts.map +1 -0
- package/dist/tier0-invariant.js +185 -0
- package/dist/tier0-invariant.js.map +1 -0
- package/dist/tier1-blacklist.d.ts +48 -0
- package/dist/tier1-blacklist.d.ts.map +1 -0
- package/dist/tier1-blacklist.js +92 -0
- package/dist/tier1-blacklist.js.map +1 -0
- package/dist/types.d.ts +232 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/dist/verdict.d.ts +26 -0
- package/dist/verdict.d.ts.map +1 -0
- package/dist/verdict.js +127 -0
- package/dist/verdict.js.map +1 -0
- package/package.json +16 -4
- package/.github/ISSUE_TEMPLATE/evasion-report.yml +0 -75
- package/.github/ISSUE_TEMPLATE/false-positive.yml +0 -31
- package/.github/ISSUE_TEMPLATE/mirofish-prediction.yml +0 -128
- package/.github/ISSUE_TEMPLATE/new-rule.yml +0 -37
- package/.github/PULL_REQUEST_TEMPLATE.md +0 -23
- package/.github/workflows/rule-quality.yml +0 -203
- package/.github/workflows/validate.yml +0 -42
- package/CHANGELOG.md +0 -30
- package/CONTRIBUTING.md +0 -168
- package/CONTRIBUTORS.md +0 -28
- package/COVERAGE.md +0 -135
- package/LIMITATIONS.md +0 -154
- package/SECURITY.md +0 -48
- package/THREAT-MODEL.md +0 -243
- package/docs/contribution-paths.md +0 -202
- package/docs/mirofish-prediction-guide.md +0 -304
- package/docs/quick-start.md +0 -245
- package/docs/rule-writing-guide.md +0 -647
- package/docs/schema-spec.md +0 -594
- package/examples/how-to-write-a-rule.md +0 -251
- package/tsconfig.json +0 -17
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ATR Quality Standard — Public API
|
|
3
|
+
*
|
|
4
|
+
* Vendor-neutral library for scoring and validating AI agent threat detection
|
|
5
|
+
* rules. See docs/proposals/001-atr-quality-standard-rfc.md for the RFC.
|
|
6
|
+
*
|
|
7
|
+
* @example Compute a confidence score for an ATR rule
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { parseATRRule, computeConfidence } from 'agent-threat-rules/quality';
|
|
10
|
+
* import { readFileSync } from 'node:fs';
|
|
11
|
+
*
|
|
12
|
+
* const yaml = readFileSync('rules/prompt-injection/ATR-2026-00001.yaml', 'utf-8');
|
|
13
|
+
* const rule = parseATRRule(yaml);
|
|
14
|
+
* const score = computeConfidence(rule);
|
|
15
|
+
* console.log(`Confidence: ${score.total}/100`);
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* @example Run a rule through the quality gate
|
|
19
|
+
* ```typescript
|
|
20
|
+
* import { parseATRRule, validateRuleMeetsStandard } from 'agent-threat-rules/quality';
|
|
21
|
+
*
|
|
22
|
+
* const rule = parseATRRule(yamlContent);
|
|
23
|
+
* const gate = validateRuleMeetsStandard(rule, 'experimental');
|
|
24
|
+
* if (!gate.passed) {
|
|
25
|
+
* console.error('Rule rejected:', gate.issues);
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* @module agent-threat-rules/quality
|
|
30
|
+
*/
|
|
31
|
+
// Scoring
|
|
32
|
+
export { computeConfidence, deploymentFor, applyCrossContextPenalty, } from "./compute-confidence.js";
|
|
33
|
+
// Validation
|
|
34
|
+
export { validateRuleMeetsStandard, getRequirements } from "./quality-gate.js";
|
|
35
|
+
// Maturity transitions
|
|
36
|
+
export { canPromote, shouldDemote, getMaturityThresholds, } from "./validate-maturity.js";
|
|
37
|
+
// Adapters
|
|
38
|
+
export { parseATRRule, atrRuleToMetadata } from "./adapters/atr.js";
|
|
39
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/quality/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAcH,UAAU;AACV,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,wBAAwB,GACzB,MAAM,yBAAyB,CAAC;AAEjC,aAAa;AACb,OAAO,EAAE,yBAAyB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAE/E,uBAAuB;AACvB,OAAO,EACL,UAAU,EACV,YAAY,EACZ,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAEhC,WAAW;AACX,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ATR Quality Standard — Quality Gate
|
|
3
|
+
*
|
|
4
|
+
* Checks whether a rule meets the minimum quality bar for a target maturity
|
|
5
|
+
* level. Used by TC crystallization pipeline to reject weak LLM-generated
|
|
6
|
+
* rules before they enter the proposal pipeline.
|
|
7
|
+
*
|
|
8
|
+
* See docs/proposals/001-atr-quality-standard-rfc.md §3 for the required
|
|
9
|
+
* metadata matrix.
|
|
10
|
+
*
|
|
11
|
+
* @module agent-threat-rules/quality/quality-gate
|
|
12
|
+
*/
|
|
13
|
+
import type { Maturity, QualityGateResult, RuleMetadata } from "./types.js";
|
|
14
|
+
/**
|
|
15
|
+
* Minimum requirements for each maturity level.
|
|
16
|
+
*
|
|
17
|
+
* RFC-001 v1.1 (effective 2026-04-12) splits the quality bar:
|
|
18
|
+
* - experimental: 3/3/0 — low barrier for community contribution. OWASP,
|
|
19
|
+
* MITRE, evasion tests, and FP docs are encouraged but NOT required.
|
|
20
|
+
* The upgrade pipeline adds these during promotion to stable.
|
|
21
|
+
* - stable: 5/5/3 — production-quality bar with verified provenance,
|
|
22
|
+
* OWASP + MITRE mapping, evasion tests, and wild validation.
|
|
23
|
+
*
|
|
24
|
+
* Rationale: VirusTotal doesn't reject "low quality" samples — everything
|
|
25
|
+
* gets in. Sigma experimental is loose. A strict experimental gate kills
|
|
26
|
+
* community contribution velocity. Data velocity > data purity at scale.
|
|
27
|
+
*
|
|
28
|
+
* See docs/proposals/001-atr-quality-standard-rfc.md §1 and §3.
|
|
29
|
+
*/
|
|
30
|
+
declare const REQUIREMENTS: {
|
|
31
|
+
readonly draft: {
|
|
32
|
+
readonly minConditions: 1;
|
|
33
|
+
readonly minTruePositives: 1;
|
|
34
|
+
readonly minTrueNegatives: 1;
|
|
35
|
+
readonly minEvasionTests: 0;
|
|
36
|
+
readonly requireOwasp: false;
|
|
37
|
+
readonly requireMitre: false;
|
|
38
|
+
readonly requireFalsePositiveDocs: false;
|
|
39
|
+
readonly requireHumanReviewedProvenance: false;
|
|
40
|
+
};
|
|
41
|
+
readonly experimental: {
|
|
42
|
+
readonly minConditions: 1;
|
|
43
|
+
readonly minTruePositives: 3;
|
|
44
|
+
readonly minTrueNegatives: 3;
|
|
45
|
+
readonly minEvasionTests: 0;
|
|
46
|
+
readonly requireOwasp: false;
|
|
47
|
+
readonly requireMitre: false;
|
|
48
|
+
readonly requireFalsePositiveDocs: false;
|
|
49
|
+
readonly requireHumanReviewedProvenance: false;
|
|
50
|
+
};
|
|
51
|
+
readonly stable: {
|
|
52
|
+
readonly minConditions: 3;
|
|
53
|
+
readonly minTruePositives: 5;
|
|
54
|
+
readonly minTrueNegatives: 5;
|
|
55
|
+
readonly minEvasionTests: 3;
|
|
56
|
+
readonly requireOwasp: true;
|
|
57
|
+
readonly requireMitre: true;
|
|
58
|
+
readonly requireFalsePositiveDocs: true;
|
|
59
|
+
readonly requireHumanReviewedProvenance: true;
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* RFC-001 v1.1 §1.1 — Single-Pattern Rule Exception threshold.
|
|
64
|
+
*
|
|
65
|
+
* A rule with fewer than `minConditions` for its target maturity level
|
|
66
|
+
* is still accepted if it has been validated against at least this many
|
|
67
|
+
* real-world samples with a measured false-positive rate of exactly 0.
|
|
68
|
+
* Set to the size of the most recent ATR mega scan as of effective date,
|
|
69
|
+
* which is the empirical evidence baseline the standard authors used.
|
|
70
|
+
*/
|
|
71
|
+
export declare const SINGLE_PATTERN_EXCEPTION_MIN_SAMPLES = 50000;
|
|
72
|
+
/**
|
|
73
|
+
* Validate a rule against the quality bar for a target maturity level.
|
|
74
|
+
*
|
|
75
|
+
* @param rule - Rule metadata
|
|
76
|
+
* @param target - Target maturity level to validate against (default: rule.maturity)
|
|
77
|
+
* @returns Gate result with passed/failed and human-readable issues
|
|
78
|
+
*/
|
|
79
|
+
export declare function validateRuleMeetsStandard(rule: RuleMetadata, target?: Maturity): QualityGateResult;
|
|
80
|
+
/**
|
|
81
|
+
* Public accessor for the requirements table.
|
|
82
|
+
* Useful for documentation generators and UIs that display the quality bar.
|
|
83
|
+
*/
|
|
84
|
+
export declare function getRequirements(): typeof REQUIREMENTS;
|
|
85
|
+
export {};
|
|
86
|
+
//# sourceMappingURL=quality-gate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quality-gate.d.ts","sourceRoot":"","sources":["../../src/quality/quality-gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EACV,QAAQ,EAER,iBAAiB,EACjB,YAAY,EACb,MAAM,YAAY,CAAC;AAEpB;;;;;;;;;;;;;;;GAeG;AACH,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+BR,CAAC;AAEX;;;;;;;;GAQG;AACH,eAAO,MAAM,oCAAoC,QAAS,CAAC;AAQ3D;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,YAAY,EAClB,MAAM,CAAC,EAAE,QAAQ,GAChB,iBAAiB,CAiHnB;AAMD;;;GAGG;AACH,wBAAgB,eAAe,IAAI,OAAO,YAAY,CAErD"}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ATR Quality Standard — Quality Gate
|
|
3
|
+
*
|
|
4
|
+
* Checks whether a rule meets the minimum quality bar for a target maturity
|
|
5
|
+
* level. Used by TC crystallization pipeline to reject weak LLM-generated
|
|
6
|
+
* rules before they enter the proposal pipeline.
|
|
7
|
+
*
|
|
8
|
+
* See docs/proposals/001-atr-quality-standard-rfc.md §3 for the required
|
|
9
|
+
* metadata matrix.
|
|
10
|
+
*
|
|
11
|
+
* @module agent-threat-rules/quality/quality-gate
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Minimum requirements for each maturity level.
|
|
15
|
+
*
|
|
16
|
+
* RFC-001 v1.1 (effective 2026-04-12) splits the quality bar:
|
|
17
|
+
* - experimental: 3/3/0 — low barrier for community contribution. OWASP,
|
|
18
|
+
* MITRE, evasion tests, and FP docs are encouraged but NOT required.
|
|
19
|
+
* The upgrade pipeline adds these during promotion to stable.
|
|
20
|
+
* - stable: 5/5/3 — production-quality bar with verified provenance,
|
|
21
|
+
* OWASP + MITRE mapping, evasion tests, and wild validation.
|
|
22
|
+
*
|
|
23
|
+
* Rationale: VirusTotal doesn't reject "low quality" samples — everything
|
|
24
|
+
* gets in. Sigma experimental is loose. A strict experimental gate kills
|
|
25
|
+
* community contribution velocity. Data velocity > data purity at scale.
|
|
26
|
+
*
|
|
27
|
+
* See docs/proposals/001-atr-quality-standard-rfc.md §1 and §3.
|
|
28
|
+
*/
|
|
29
|
+
const REQUIREMENTS = {
|
|
30
|
+
draft: {
|
|
31
|
+
minConditions: 1,
|
|
32
|
+
minTruePositives: 1,
|
|
33
|
+
minTrueNegatives: 1,
|
|
34
|
+
minEvasionTests: 0,
|
|
35
|
+
requireOwasp: false,
|
|
36
|
+
requireMitre: false,
|
|
37
|
+
requireFalsePositiveDocs: false,
|
|
38
|
+
requireHumanReviewedProvenance: false,
|
|
39
|
+
},
|
|
40
|
+
experimental: {
|
|
41
|
+
minConditions: 1,
|
|
42
|
+
minTruePositives: 3, // RFC-001 v1.1: lowered for community contribution velocity
|
|
43
|
+
minTrueNegatives: 3,
|
|
44
|
+
minEvasionTests: 0, // encouraged but not required — pipeline adds during upgrade
|
|
45
|
+
requireOwasp: false, // pipeline adds during promotion to stable
|
|
46
|
+
requireMitre: false, // pipeline adds during promotion to stable
|
|
47
|
+
requireFalsePositiveDocs: false, // pipeline adds during promotion to stable
|
|
48
|
+
requireHumanReviewedProvenance: false,
|
|
49
|
+
},
|
|
50
|
+
stable: {
|
|
51
|
+
minConditions: 3,
|
|
52
|
+
minTruePositives: 5,
|
|
53
|
+
minTrueNegatives: 5,
|
|
54
|
+
minEvasionTests: 3, // hard requirement
|
|
55
|
+
requireOwasp: true,
|
|
56
|
+
requireMitre: true,
|
|
57
|
+
requireFalsePositiveDocs: true,
|
|
58
|
+
requireHumanReviewedProvenance: true, // stable demands verified provenance
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* RFC-001 v1.1 §1.1 — Single-Pattern Rule Exception threshold.
|
|
63
|
+
*
|
|
64
|
+
* A rule with fewer than `minConditions` for its target maturity level
|
|
65
|
+
* is still accepted if it has been validated against at least this many
|
|
66
|
+
* real-world samples with a measured false-positive rate of exactly 0.
|
|
67
|
+
* Set to the size of the most recent ATR mega scan as of effective date,
|
|
68
|
+
* which is the empirical evidence baseline the standard authors used.
|
|
69
|
+
*/
|
|
70
|
+
export const SINGLE_PATTERN_EXCEPTION_MIN_SAMPLES = 50_000;
|
|
71
|
+
/** Provenance values that count as "verified" for stable promotion */
|
|
72
|
+
const VERIFIED_PROVENANCE = [
|
|
73
|
+
"human-reviewed",
|
|
74
|
+
"community-contributed",
|
|
75
|
+
];
|
|
76
|
+
/**
|
|
77
|
+
* Validate a rule against the quality bar for a target maturity level.
|
|
78
|
+
*
|
|
79
|
+
* @param rule - Rule metadata
|
|
80
|
+
* @param target - Target maturity level to validate against (default: rule.maturity)
|
|
81
|
+
* @returns Gate result with passed/failed and human-readable issues
|
|
82
|
+
*/
|
|
83
|
+
export function validateRuleMeetsStandard(rule, target) {
|
|
84
|
+
const level = target ?? rule.maturity;
|
|
85
|
+
// Deprecated rules are always valid (they're being retired, not used)
|
|
86
|
+
if (level === "deprecated") {
|
|
87
|
+
return { passed: true, issues: [], warnings: [] };
|
|
88
|
+
}
|
|
89
|
+
const req = REQUIREMENTS[level];
|
|
90
|
+
const issues = [];
|
|
91
|
+
const warnings = [];
|
|
92
|
+
// RFC-001 v1.1 §1.1 — Single-Pattern Rule Exception.
|
|
93
|
+
//
|
|
94
|
+
// A rule with fewer than the default minimum number of detection conditions
|
|
95
|
+
// MAY still pass the experimental gate if it has been wild-validated to a
|
|
96
|
+
// very high standard. Empirically (see ATR-2026-00139, 00146, etc.) some
|
|
97
|
+
// attack categories — casual social engineering, single-token homoglyph
|
|
98
|
+
// injection, ChatML system-token spoofing — are best caught by exactly one
|
|
99
|
+
// narrow regex; padding with additional conditions only adds false-positive
|
|
100
|
+
// surface without improving recall.
|
|
101
|
+
//
|
|
102
|
+
// Eligibility for the exception:
|
|
103
|
+
// - wild_samples >= SINGLE_PATTERN_EXCEPTION_MIN_SAMPLES
|
|
104
|
+
// - wild_fp_rate === 0 (must be exactly zero, not <= 0.5%)
|
|
105
|
+
// - rule still has >= 1 condition (true zero-condition rules are invalid)
|
|
106
|
+
//
|
|
107
|
+
// The exception is intentionally narrow: it costs the rule author a hard
|
|
108
|
+
// empirical claim (wild_fp_rate exactly 0% on >=N samples). Authors who
|
|
109
|
+
// cannot meet this bar must add more detection conditions OR keep the rule
|
|
110
|
+
// at maturity `draft` until they can.
|
|
111
|
+
const meetsSinglePatternException = level === "experimental" &&
|
|
112
|
+
rule.conditions >= 1 &&
|
|
113
|
+
rule.wildSamples !== undefined &&
|
|
114
|
+
rule.wildSamples >= SINGLE_PATTERN_EXCEPTION_MIN_SAMPLES &&
|
|
115
|
+
rule.wildFpRate === 0;
|
|
116
|
+
if (rule.conditions < req.minConditions) {
|
|
117
|
+
if (meetsSinglePatternException) {
|
|
118
|
+
warnings.push(`only ${rule.conditions} detection condition(s) — accepted under RFC-001 v1.1 §1.1 single-pattern exception (wild_samples=${rule.wildSamples}, wild_fp_rate=0%)`);
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
issues.push(`only ${rule.conditions} detection condition(s) (need ${req.minConditions}+, or wild_samples >= ${SINGLE_PATTERN_EXCEPTION_MIN_SAMPLES} with wild_fp_rate = 0% for the single-pattern exception)`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
if (rule.truePositives < req.minTruePositives) {
|
|
125
|
+
issues.push(`only ${rule.truePositives} true_positive(s) (need ${req.minTruePositives}+)`);
|
|
126
|
+
}
|
|
127
|
+
if (rule.trueNegatives < req.minTrueNegatives) {
|
|
128
|
+
issues.push(`only ${rule.trueNegatives} true_negative(s) (need ${req.minTrueNegatives}+)`);
|
|
129
|
+
}
|
|
130
|
+
if (req.minEvasionTests > 0 && rule.evasionTests < req.minEvasionTests) {
|
|
131
|
+
issues.push(`only ${rule.evasionTests} evasion_test(s) (need ${req.minEvasionTests}+)`);
|
|
132
|
+
}
|
|
133
|
+
else if (rule.evasionTests < 3 && level === "experimental") {
|
|
134
|
+
warnings.push(`only ${rule.evasionTests} evasion_test(s) — recommend 3+ for stable promotion`);
|
|
135
|
+
}
|
|
136
|
+
if (req.requireOwasp && !rule.hasOwaspRef) {
|
|
137
|
+
issues.push("missing OWASP reference (LLM Top 10 or Agentic Top 10)");
|
|
138
|
+
}
|
|
139
|
+
if (req.requireMitre && !rule.hasMitreRef) {
|
|
140
|
+
issues.push("missing MITRE reference (ATLAS or ATT&CK)");
|
|
141
|
+
}
|
|
142
|
+
if (req.requireFalsePositiveDocs && !rule.hasFalsePositiveDocs) {
|
|
143
|
+
issues.push("missing false_positives documentation");
|
|
144
|
+
}
|
|
145
|
+
// Stable promotion requires human-verified provenance on key fields
|
|
146
|
+
if (req.requireHumanReviewedProvenance) {
|
|
147
|
+
const p = rule.provenance ?? {};
|
|
148
|
+
const mitreProvenance = p.mitre_atlas ?? p.mitre_attack;
|
|
149
|
+
const owaspProvenance = p.owasp_llm ?? p.owasp_agentic;
|
|
150
|
+
if (rule.hasMitreRef && mitreProvenance && !isVerified(mitreProvenance)) {
|
|
151
|
+
issues.push(`MITRE reference is "${mitreProvenance}" — stable requires human-reviewed or community-contributed`);
|
|
152
|
+
}
|
|
153
|
+
if (rule.hasOwaspRef && owaspProvenance && !isVerified(owaspProvenance)) {
|
|
154
|
+
issues.push(`OWASP reference is "${owaspProvenance}" — stable requires human-reviewed or community-contributed`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
// experimental/draft: surface provenance as warning so consumers can see it
|
|
159
|
+
const p = rule.provenance ?? {};
|
|
160
|
+
const autoFields = [];
|
|
161
|
+
if (p.mitre_atlas === "auto-generated")
|
|
162
|
+
autoFields.push("mitre_atlas");
|
|
163
|
+
if (p.owasp_llm === "auto-generated")
|
|
164
|
+
autoFields.push("owasp_llm");
|
|
165
|
+
if (p.owasp_agentic === "auto-generated")
|
|
166
|
+
autoFields.push("owasp_agentic");
|
|
167
|
+
if (autoFields.length > 0) {
|
|
168
|
+
warnings.push(`auto-generated provenance on: ${autoFields.join(", ")} — needs human review for stable`);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return {
|
|
172
|
+
passed: issues.length === 0,
|
|
173
|
+
issues,
|
|
174
|
+
warnings,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
function isVerified(p) {
|
|
178
|
+
return VERIFIED_PROVENANCE.includes(p);
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Public accessor for the requirements table.
|
|
182
|
+
* Useful for documentation generators and UIs that display the quality bar.
|
|
183
|
+
*/
|
|
184
|
+
export function getRequirements() {
|
|
185
|
+
return REQUIREMENTS;
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=quality-gate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quality-gate.js","sourceRoot":"","sources":["../../src/quality/quality-gate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ATR Quality Standard — Type Definitions
|
|
3
|
+
*
|
|
4
|
+
* Vendor-neutral types for rule quality scoring and maturity validation.
|
|
5
|
+
* See docs/proposals/001-atr-quality-standard-rfc.md for the full RFC.
|
|
6
|
+
*
|
|
7
|
+
* @module agent-threat-rules/quality/types
|
|
8
|
+
*/
|
|
9
|
+
/** Rule maturity level — matches ATR schema and RFC-001 §1 */
|
|
10
|
+
export type Maturity = "draft" | "experimental" | "stable" | "deprecated";
|
|
11
|
+
/**
|
|
12
|
+
* Provenance of a metadata field.
|
|
13
|
+
* RFC-001 §4: two-dimensional compliance model.
|
|
14
|
+
*
|
|
15
|
+
* - `human-reviewed`: a human maintainer verified this mapping/content
|
|
16
|
+
* - `community-contributed`: submitted via PR by an external contributor
|
|
17
|
+
* - `auto-generated`: filled by a script or LLM without human review
|
|
18
|
+
* - `llm-generated`: produced by the TC crystallization flywheel
|
|
19
|
+
*
|
|
20
|
+
* The quality gate treats these differently:
|
|
21
|
+
* - experimental gate accepts any provenance
|
|
22
|
+
* - stable gate requires `human-reviewed` or `community-contributed`
|
|
23
|
+
*/
|
|
24
|
+
export type Provenance = "human-reviewed" | "community-contributed" | "auto-generated" | "llm-generated";
|
|
25
|
+
/**
|
|
26
|
+
* Per-field provenance tracking.
|
|
27
|
+
* Each metadata field can have its own provenance so partially-reviewed
|
|
28
|
+
* rules are represented accurately.
|
|
29
|
+
*/
|
|
30
|
+
export interface MetadataProvenance {
|
|
31
|
+
readonly mitre_atlas?: Provenance;
|
|
32
|
+
readonly mitre_attack?: Provenance;
|
|
33
|
+
readonly owasp_llm?: Provenance;
|
|
34
|
+
readonly owasp_agentic?: Provenance;
|
|
35
|
+
readonly test_cases?: Provenance;
|
|
36
|
+
readonly evasion_tests?: Provenance;
|
|
37
|
+
readonly false_positives?: Provenance;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Minimal metadata required to score and validate a rule.
|
|
41
|
+
* Any vendor's rule format can be adapted to this interface via a parser.
|
|
42
|
+
*/
|
|
43
|
+
export interface RuleMetadata {
|
|
44
|
+
/** Unique rule identifier */
|
|
45
|
+
readonly id: string;
|
|
46
|
+
/** Human-readable title */
|
|
47
|
+
readonly title: string;
|
|
48
|
+
/** Current maturity level */
|
|
49
|
+
readonly maturity: Maturity;
|
|
50
|
+
/** Number of distinct detection conditions (layers) */
|
|
51
|
+
readonly conditions: number;
|
|
52
|
+
/** Count of true_positive test cases */
|
|
53
|
+
readonly truePositives: number;
|
|
54
|
+
/** Count of true_negative test cases */
|
|
55
|
+
readonly trueNegatives: number;
|
|
56
|
+
/** Count of documented evasion tests */
|
|
57
|
+
readonly evasionTests: number;
|
|
58
|
+
/** Has at least one OWASP reference (LLM Top 10 or Agentic Top 10) */
|
|
59
|
+
readonly hasOwaspRef: boolean;
|
|
60
|
+
/** Has at least one MITRE reference (ATLAS or ATT&CK) */
|
|
61
|
+
readonly hasMitreRef: boolean;
|
|
62
|
+
/** Has at least one documented false_positive pattern */
|
|
63
|
+
readonly hasFalsePositiveDocs: boolean;
|
|
64
|
+
/** Number of real-world samples validated against this rule */
|
|
65
|
+
readonly wildSamples?: number;
|
|
66
|
+
/** Measured false positive rate on wild samples (0.0 - 100.0) */
|
|
67
|
+
readonly wildFpRate?: number;
|
|
68
|
+
/** ISO date of last wild validation run */
|
|
69
|
+
readonly wildValidatedAt?: string;
|
|
70
|
+
/** True if the rule was generated by an LLM (not human-authored) */
|
|
71
|
+
readonly llmGenerated?: boolean;
|
|
72
|
+
/** True if a human reviewer has explicitly approved this rule */
|
|
73
|
+
readonly humanReviewed?: boolean;
|
|
74
|
+
/** Per-field provenance tracking (RFC-001 §4) */
|
|
75
|
+
readonly provenance?: MetadataProvenance;
|
|
76
|
+
}
|
|
77
|
+
/** Confidence score components and total */
|
|
78
|
+
export interface ConfidenceScore {
|
|
79
|
+
/** Overall score 0-100, rounded to integer */
|
|
80
|
+
readonly total: number;
|
|
81
|
+
/** Precision component (weight 0.40) */
|
|
82
|
+
readonly precisionScore: number;
|
|
83
|
+
/** Wild validation component (weight 0.30) */
|
|
84
|
+
readonly wildValidationScore: number;
|
|
85
|
+
/** Coverage breadth component (weight 0.20) */
|
|
86
|
+
readonly coverageScore: number;
|
|
87
|
+
/** Evasion documentation component (weight 0.10) */
|
|
88
|
+
readonly evasionScore: number;
|
|
89
|
+
/** True if score was capped due to LLM-generated origin without human review */
|
|
90
|
+
readonly capped: boolean;
|
|
91
|
+
}
|
|
92
|
+
/** Result of running a rule through the quality gate */
|
|
93
|
+
export interface QualityGateResult {
|
|
94
|
+
/** True if the rule meets all required criteria for its target maturity */
|
|
95
|
+
readonly passed: boolean;
|
|
96
|
+
/** Human-readable list of gate failures (empty if passed) */
|
|
97
|
+
readonly issues: readonly string[];
|
|
98
|
+
/** Warnings that do not block promotion but should be addressed */
|
|
99
|
+
readonly warnings: readonly string[];
|
|
100
|
+
}
|
|
101
|
+
/** Decision output from canPromote() */
|
|
102
|
+
export interface PromotionDecision {
|
|
103
|
+
/** True if the rule is eligible to promote to `to` */
|
|
104
|
+
readonly eligible: boolean;
|
|
105
|
+
/** The maturity level this decision is for */
|
|
106
|
+
readonly to: Maturity;
|
|
107
|
+
/** Reasons the rule is not eligible (empty if eligible) */
|
|
108
|
+
readonly blockers: readonly string[];
|
|
109
|
+
}
|
|
110
|
+
/** A false positive report used in demotion decisions */
|
|
111
|
+
export interface FpReport {
|
|
112
|
+
/** ISO timestamp of the report */
|
|
113
|
+
readonly reportedAt: string;
|
|
114
|
+
/** Whether this report has been investigated and resolved */
|
|
115
|
+
readonly resolved: boolean;
|
|
116
|
+
}
|
|
117
|
+
/** Decision output from shouldDemote() */
|
|
118
|
+
export interface DemotionDecision {
|
|
119
|
+
/** True if the rule should be automatically demoted */
|
|
120
|
+
readonly shouldDemote: boolean;
|
|
121
|
+
/** Reasons for demotion (empty if shouldDemote is false) */
|
|
122
|
+
readonly reasons: readonly string[];
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Deployment guidance based on confidence score.
|
|
126
|
+
* Maps confidence to a recommended production use.
|
|
127
|
+
*/
|
|
128
|
+
export type DeploymentRecommendation = "block-in-production" | "block-with-monitoring" | "alert-only" | "evaluation-only" | "do-not-deploy";
|
|
129
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/quality/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ATR Quality Standard — Type Definitions
|
|
3
|
+
*
|
|
4
|
+
* Vendor-neutral types for rule quality scoring and maturity validation.
|
|
5
|
+
* See docs/proposals/001-atr-quality-standard-rfc.md for the full RFC.
|
|
6
|
+
*
|
|
7
|
+
* @module agent-threat-rules/quality/types
|
|
8
|
+
*/
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/quality/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ATR Quality Standard — Maturity Promotion and Demotion
|
|
3
|
+
*
|
|
4
|
+
* Pure functions that decide whether a rule is eligible to promote to a
|
|
5
|
+
* higher maturity level, or should be automatically demoted due to
|
|
6
|
+
* quality regression.
|
|
7
|
+
*
|
|
8
|
+
* See docs/proposals/001-atr-quality-standard-rfc.md §1 for the gate
|
|
9
|
+
* definitions.
|
|
10
|
+
*
|
|
11
|
+
* @module agent-threat-rules/quality/validate-maturity
|
|
12
|
+
*/
|
|
13
|
+
import type { DemotionDecision, FpReport, Maturity, PromotionDecision, RuleMetadata } from "./types.js";
|
|
14
|
+
/**
|
|
15
|
+
* Determine whether a rule is eligible to promote from its current maturity
|
|
16
|
+
* to the next level.
|
|
17
|
+
*
|
|
18
|
+
* @param rule - Rule metadata
|
|
19
|
+
* @param target - Target maturity level
|
|
20
|
+
* @param now - Current timestamp (ISO string) for age calculations
|
|
21
|
+
* @returns Promotion decision with blockers listed
|
|
22
|
+
*/
|
|
23
|
+
export declare function canPromote(rule: RuleMetadata, target: Maturity, now?: string): PromotionDecision;
|
|
24
|
+
/**
|
|
25
|
+
* Determine whether a stable rule should be automatically demoted to
|
|
26
|
+
* experimental due to quality regression.
|
|
27
|
+
*
|
|
28
|
+
* Triggers:
|
|
29
|
+
* - Wild FP rate exceeds DEMOTION_FP_RATE_THRESHOLD
|
|
30
|
+
* - DEMOTION_FP_REPORT_COUNT+ unresolved FP reports in the window
|
|
31
|
+
*
|
|
32
|
+
* @param rule - Rule metadata
|
|
33
|
+
* @param recentFpReports - FP reports from the demotion window
|
|
34
|
+
* @param now - Current timestamp (ISO string)
|
|
35
|
+
* @returns Demotion decision
|
|
36
|
+
*/
|
|
37
|
+
export declare function shouldDemote(rule: RuleMetadata, recentFpReports: readonly FpReport[], now?: string): DemotionDecision;
|
|
38
|
+
/**
|
|
39
|
+
* Public accessor for the promotion/demotion thresholds.
|
|
40
|
+
* Useful for documentation and UI that displays the gate policy.
|
|
41
|
+
*/
|
|
42
|
+
export declare function getMaturityThresholds(): {
|
|
43
|
+
minExperimentalDays: number;
|
|
44
|
+
minWildSamplesForStable: number;
|
|
45
|
+
maxWildFpForStable: number;
|
|
46
|
+
minConfidenceForStable: number;
|
|
47
|
+
demotionFpRateThreshold: number;
|
|
48
|
+
demotionFpReportCount: number;
|
|
49
|
+
demotionWindowDays: number;
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=validate-maturity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-maturity.d.ts","sourceRoot":"","sources":["../../src/quality/validate-maturity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,KAAK,EACV,gBAAgB,EAChB,QAAQ,EACR,QAAQ,EACR,iBAAiB,EACjB,YAAY,EACb,MAAM,YAAY,CAAC;AAiBpB;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CACxB,IAAI,EAAE,YAAY,EAClB,MAAM,EAAE,QAAQ,EAChB,GAAG,GAAE,MAAiC,GACrC,iBAAiB,CA4DnB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,YAAY,EAClB,eAAe,EAAE,SAAS,QAAQ,EAAE,EACpC,GAAG,GAAE,MAAiC,GACrC,gBAAgB,CAmClB;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,IAAI;IACvC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,uBAAuB,EAAE,MAAM,CAAC;IAChC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,sBAAsB,EAAE,MAAM,CAAC;IAC/B,uBAAuB,EAAE,MAAM,CAAC;IAChC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,kBAAkB,EAAE,MAAM,CAAC;CAC5B,CAUA"}
|