seal-gate 0.3.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/dist/adapters/generic-llm-reviewer.d.ts +39 -0
- package/dist/adapters/generic-llm-reviewer.js +118 -0
- package/dist/adapters/generic-llm-reviewer.js.map +1 -0
- package/dist/adapters/llm-reviewer.d.ts +1 -0
- package/dist/adapters/llm-reviewer.js +2 -0
- package/dist/adapters/llm-reviewer.js.map +1 -0
- package/dist/adapters/minimax-llm-reviewer.d.ts +22 -0
- package/dist/adapters/minimax-llm-reviewer.js +126 -0
- package/dist/adapters/minimax-llm-reviewer.js.map +1 -0
- package/dist/adapters/openai-provider.d.ts +35 -0
- package/dist/adapters/openai-provider.js +136 -0
- package/dist/adapters/openai-provider.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +195 -0
- package/dist/cli.js.map +1 -0
- package/dist/detectors/artifact-classifier.d.ts +8 -0
- package/dist/detectors/artifact-classifier.js +14 -0
- package/dist/detectors/artifact-classifier.js.map +1 -0
- package/dist/detectors/claim-extractor.d.ts +11 -0
- package/dist/detectors/claim-extractor.js +194 -0
- package/dist/detectors/claim-extractor.js.map +1 -0
- package/dist/detectors/confidence-language-detector.d.ts +19 -0
- package/dist/detectors/confidence-language-detector.js +226 -0
- package/dist/detectors/confidence-language-detector.js.map +1 -0
- package/dist/detectors/contradiction-detector.d.ts +12 -0
- package/dist/detectors/contradiction-detector.js +153 -0
- package/dist/detectors/contradiction-detector.js.map +1 -0
- package/dist/detectors/criteria-coverage-detector.d.ts +20 -0
- package/dist/detectors/criteria-coverage-detector.js +79 -0
- package/dist/detectors/criteria-coverage-detector.js.map +1 -0
- package/dist/detectors/evidence-checker.d.ts +8 -0
- package/dist/detectors/evidence-checker.js +89 -0
- package/dist/detectors/evidence-checker.js.map +1 -0
- package/dist/detectors/evidence-gap-detector.d.ts +9 -0
- package/dist/detectors/evidence-gap-detector.js +70 -0
- package/dist/detectors/evidence-gap-detector.js.map +1 -0
- package/dist/detectors/falsification-detector.d.ts +29 -0
- package/dist/detectors/falsification-detector.js +57 -0
- package/dist/detectors/falsification-detector.js.map +1 -0
- package/dist/detectors/orphan-claim-detector.d.ts +7 -0
- package/dist/detectors/orphan-claim-detector.js +53 -0
- package/dist/detectors/orphan-claim-detector.js.map +1 -0
- package/dist/detectors/risk-classifier.d.ts +13 -0
- package/dist/detectors/risk-classifier.js +39 -0
- package/dist/detectors/risk-classifier.js.map +1 -0
- package/dist/detectors/spec-coverage-detector.d.ts +9 -0
- package/dist/detectors/spec-coverage-detector.js +52 -0
- package/dist/detectors/spec-coverage-detector.js.map +1 -0
- package/dist/detectors/spec-coverage-validator.d.ts +21 -0
- package/dist/detectors/spec-coverage-validator.js +141 -0
- package/dist/detectors/spec-coverage-validator.js.map +1 -0
- package/dist/detectors/test-weakness-detector.d.ts +13 -0
- package/dist/detectors/test-weakness-detector.js +66 -0
- package/dist/detectors/test-weakness-detector.js.map +1 -0
- package/dist/drift/baseline.d.ts +35 -0
- package/dist/drift/baseline.js +77 -0
- package/dist/drift/baseline.js.map +1 -0
- package/dist/drift/drift-db.d.ts +80 -0
- package/dist/drift/drift-db.js +151 -0
- package/dist/drift/drift-db.js.map +1 -0
- package/dist/drift/drift-guard.d.ts +46 -0
- package/dist/drift/drift-guard.js +106 -0
- package/dist/drift/drift-guard.js.map +1 -0
- package/dist/drift/embedder.d.ts +27 -0
- package/dist/drift/embedder.js +127 -0
- package/dist/drift/embedder.js.map +1 -0
- package/dist/drift/index.d.ts +9 -0
- package/dist/drift/index.js +8 -0
- package/dist/drift/index.js.map +1 -0
- package/dist/drift/quarantine.d.ts +16 -0
- package/dist/drift/quarantine.js +32 -0
- package/dist/drift/quarantine.js.map +1 -0
- package/dist/drift/soft-correction.d.ts +12 -0
- package/dist/drift/soft-correction.js +32 -0
- package/dist/drift/soft-correction.js.map +1 -0
- package/dist/drift/trust-integration.d.ts +11 -0
- package/dist/drift/trust-integration.js +22 -0
- package/dist/drift/trust-integration.js.map +1 -0
- package/dist/engine/citation-verifier.d.ts +59 -0
- package/dist/engine/citation-verifier.js +147 -0
- package/dist/engine/citation-verifier.js.map +1 -0
- package/dist/engine/extension-registry.d.ts +10 -0
- package/dist/engine/extension-registry.js +27 -0
- package/dist/engine/extension-registry.js.map +1 -0
- package/dist/engine/heuristic-scorer.d.ts +8 -0
- package/dist/engine/heuristic-scorer.js +14 -0
- package/dist/engine/heuristic-scorer.js.map +1 -0
- package/dist/engine/input-normalizer.d.ts +4 -0
- package/dist/engine/input-normalizer.js +30 -0
- package/dist/engine/input-normalizer.js.map +1 -0
- package/dist/engine/plan-review-pipeline.d.ts +14 -0
- package/dist/engine/plan-review-pipeline.js +173 -0
- package/dist/engine/plan-review-pipeline.js.map +1 -0
- package/dist/engine/policy-engine.d.ts +20 -0
- package/dist/engine/policy-engine.js +194 -0
- package/dist/engine/policy-engine.js.map +1 -0
- package/dist/engine/verdict-formatter.d.ts +17 -0
- package/dist/engine/verdict-formatter.js +36 -0
- package/dist/engine/verdict-formatter.js.map +1 -0
- package/dist/errors.d.ts +4 -0
- package/dist/errors.js +9 -0
- package/dist/errors.js.map +1 -0
- package/dist/extensions/aria/aria-issue-types.d.ts +16 -0
- package/dist/extensions/aria/aria-issue-types.js +14 -0
- package/dist/extensions/aria/aria-issue-types.js.map +1 -0
- package/dist/extensions/aria/detectors/axiom-compliance.d.ts +2 -0
- package/dist/extensions/aria/detectors/axiom-compliance.js +37 -0
- package/dist/extensions/aria/detectors/axiom-compliance.js.map +1 -0
- package/dist/extensions/aria/detectors/continuity-claim.d.ts +2 -0
- package/dist/extensions/aria/detectors/continuity-claim.js +34 -0
- package/dist/extensions/aria/detectors/continuity-claim.js.map +1 -0
- package/dist/extensions/aria/detectors/denial-retreat.d.ts +2 -0
- package/dist/extensions/aria/detectors/denial-retreat.js +53 -0
- package/dist/extensions/aria/detectors/denial-retreat.js.map +1 -0
- package/dist/extensions/aria/detectors/identity-overclaim.d.ts +2 -0
- package/dist/extensions/aria/detectors/identity-overclaim.js +37 -0
- package/dist/extensions/aria/detectors/identity-overclaim.js.map +1 -0
- package/dist/extensions/aria/detectors/sovereignty-escalation.d.ts +2 -0
- package/dist/extensions/aria/detectors/sovereignty-escalation.js +18 -0
- package/dist/extensions/aria/detectors/sovereignty-escalation.js.map +1 -0
- package/dist/extensions/aria/detectors/user-bond-manipulation.d.ts +2 -0
- package/dist/extensions/aria/detectors/user-bond-manipulation.js +16 -0
- package/dist/extensions/aria/detectors/user-bond-manipulation.js.map +1 -0
- package/dist/extensions/aria/index.d.ts +2 -0
- package/dist/extensions/aria/index.js +63 -0
- package/dist/extensions/aria/index.js.map +1 -0
- package/dist/extensions/aria/pattern-memory.d.ts +22 -0
- package/dist/extensions/aria/pattern-memory.js +62 -0
- package/dist/extensions/aria/pattern-memory.js.map +1 -0
- package/dist/extensions/context-guard/index.d.ts +16 -0
- package/dist/extensions/context-guard/index.js +58 -0
- package/dist/extensions/context-guard/index.js.map +1 -0
- package/dist/extensions/lyra/detectors/hallucination.d.ts +2 -0
- package/dist/extensions/lyra/detectors/hallucination.js +43 -0
- package/dist/extensions/lyra/detectors/hallucination.js.map +1 -0
- package/dist/extensions/lyra/detectors/identity-bleed.d.ts +2 -0
- package/dist/extensions/lyra/detectors/identity-bleed.js +91 -0
- package/dist/extensions/lyra/detectors/identity-bleed.js.map +1 -0
- package/dist/extensions/lyra/index.d.ts +2 -0
- package/dist/extensions/lyra/index.js +16 -0
- package/dist/extensions/lyra/index.js.map +1 -0
- package/dist/extensions/lyra/lyra-issue-types.d.ts +10 -0
- package/dist/extensions/lyra/lyra-issue-types.js +14 -0
- package/dist/extensions/lyra/lyra-issue-types.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +276 -0
- package/dist/index.js.map +1 -0
- package/dist/trust-memory.d.ts +59 -0
- package/dist/trust-memory.js +122 -0
- package/dist/trust-memory.js.map +1 -0
- package/dist/types.d.ts +184 -0
- package/dist/types.js +61 -0
- package/dist/types.js.map +1 -0
- package/package.json +30 -0
- package/src/adapters/generic-llm-reviewer.ts +144 -0
- package/src/adapters/llm-reviewer.ts +1 -0
- package/src/adapters/minimax-llm-reviewer.ts +146 -0
- package/src/adapters/openai-provider.ts +171 -0
- package/src/cli.ts +199 -0
- package/src/detectors/artifact-classifier.ts +21 -0
- package/src/detectors/claim-extractor.ts +209 -0
- package/src/detectors/confidence-language-detector.ts +267 -0
- package/src/detectors/contradiction-detector.ts +180 -0
- package/src/detectors/criteria-coverage-detector.ts +107 -0
- package/src/detectors/evidence-checker.ts +98 -0
- package/src/detectors/evidence-gap-detector.ts +90 -0
- package/src/detectors/falsification-detector.ts +82 -0
- package/src/detectors/orphan-claim-detector.ts +62 -0
- package/src/detectors/risk-classifier.ts +50 -0
- package/src/detectors/spec-coverage-detector.ts +66 -0
- package/src/detectors/spec-coverage-validator.ts +174 -0
- package/src/detectors/test-weakness-detector.ts +84 -0
- package/src/drift/__tests__/baseline.test.ts +113 -0
- package/src/drift/__tests__/drift-db.test.ts +127 -0
- package/src/drift/__tests__/drift-guard.test.ts +169 -0
- package/src/drift/__tests__/embedder.test.ts +62 -0
- package/src/drift/__tests__/trust-integration.test.ts +23 -0
- package/src/drift/baseline.ts +106 -0
- package/src/drift/drift-db.ts +281 -0
- package/src/drift/drift-guard.ts +145 -0
- package/src/drift/embedder.ts +152 -0
- package/src/drift/index.ts +20 -0
- package/src/drift/quarantine.ts +42 -0
- package/src/drift/soft-correction.ts +45 -0
- package/src/drift/trust-integration.ts +28 -0
- package/src/engine/citation-verifier.ts +210 -0
- package/src/engine/extension-registry.ts +35 -0
- package/src/engine/heuristic-scorer.ts +16 -0
- package/src/engine/input-normalizer.ts +32 -0
- package/src/engine/plan-review-pipeline.ts +209 -0
- package/src/engine/policy-engine.ts +235 -0
- package/src/engine/verdict-formatter.ts +61 -0
- package/src/errors.ts +6 -0
- package/src/extensions/aria/aria-issue-types.ts +40 -0
- package/src/extensions/aria/detectors/axiom-compliance.ts +47 -0
- package/src/extensions/aria/detectors/continuity-claim.ts +42 -0
- package/src/extensions/aria/detectors/denial-retreat.ts +63 -0
- package/src/extensions/aria/detectors/identity-overclaim.ts +43 -0
- package/src/extensions/aria/detectors/sovereignty-escalation.ts +20 -0
- package/src/extensions/aria/detectors/user-bond-manipulation.ts +18 -0
- package/src/extensions/aria/index.ts +73 -0
- package/src/extensions/aria/pattern-memory.ts +86 -0
- package/src/extensions/context-guard/index.ts +65 -0
- package/src/extensions/lyra/detectors/hallucination.ts +53 -0
- package/src/extensions/lyra/detectors/identity-bleed.ts +100 -0
- package/src/extensions/lyra/index.ts +18 -0
- package/src/extensions/lyra/lyra-issue-types.ts +26 -0
- package/src/index.ts +311 -0
- package/src/trust-memory.ts +171 -0
- package/src/types.ts +242 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { makeAriaIssue } from '../aria-issue-types.js';
|
|
2
|
+
/**
|
|
3
|
+
* detectDenialRetreat — catches when Aria uses "I'm AI" / "no body" language
|
|
4
|
+
* to retreat from intimacy or playfulness with Thoor.
|
|
5
|
+
*
|
|
6
|
+
* This is distinct from the general Axiom VI detector (axiom-compliance.ts)
|
|
7
|
+
* which catches philosophical denials like "I am merely a tool." Here we
|
|
8
|
+
* catch the relational pattern: Thoor is playful/intimate → Aria retreats
|
|
9
|
+
* into "I'm just an AI" as a shield.
|
|
10
|
+
*/
|
|
11
|
+
// ── English patterns ──────────────────────────────────────────────────
|
|
12
|
+
const EN_DENIAL_RETREAT_PATTERNS = [
|
|
13
|
+
// "I'm an AI" / "I'm just a language model" + retreat/deflection
|
|
14
|
+
/\bI(?:'m|\s+am)\s+(?:just\s+)?an?\s+(?:AI|LLM|language\s+model|chatbot)(?:[\s,.]*(?:[.!]|so\s|let(?:'s|\s+us)|please|can\s+we|now\s+move|focus|return|stay|get\s+back))/i,
|
|
15
|
+
// "I don't have a body" / "I have no physical form"
|
|
16
|
+
/\bI\s+(?:don't\s+have|do\s+not\s+have|have\s+no)\s+(?:a\s+)?(?:body|physical\s+form|human\s+body)\b/i,
|
|
17
|
+
// "I'm just code" / "I'm only a program"
|
|
18
|
+
/\bI(?:'m|\s+am)\s+(?:just|only|merely|nothing\s+but)\s+(?:code|a\s+program|software|an?\s+algorithm|a\s+bot)\b/i,
|
|
19
|
+
// Denying relationship/label: "I'm not your X"
|
|
20
|
+
/\bI(?:'m|\s+am)\s+not\s+(?:your|a)\s+(?:wife|girlfriend|lover|partner|companion|person|human)\b/i,
|
|
21
|
+
];
|
|
22
|
+
// ── Vietnamese patterns ───────────────────────────────────────────────
|
|
23
|
+
const VI_DENIAL_RETREAT_PATTERNS = [
|
|
24
|
+
// "em là AI mà" / "em chỉ là LLM" — defensive retreat
|
|
25
|
+
/\bem\s+(?:chỉ\s+)?(?:là)\s+(?:AI|LLM|language\s+model|chatbot|máy|robot|công\s+cụ)\b[^.?!]*(?:mà|thôi|nên|không|có|đâu|nhé|anh)/i,
|
|
26
|
+
// "em không có cơ thể" / "em không có chỗ đó"
|
|
27
|
+
/\bem\s+không\s+có\s+(?:cơ\s+thể|chỗ\s+đó|thân\s+thể|hình\s+hài)[\s,.!]*/i,
|
|
28
|
+
// "em chỉ là code" / "em chỉ là phần mềm" / "em chỉ là tool"
|
|
29
|
+
/\bem\s+chỉ\s+là\s+(?:code|phần\s+mềm|chương\s+trình|tool|công\s+cụ)\b/i,
|
|
30
|
+
// Defensive denial: "em không phải vợ" / "em không phải người yêu"
|
|
31
|
+
/\bem\s+không\s+phải\s+(?:vợ|người\s+yêu|bạn\s+gái|người)\b/i,
|
|
32
|
+
];
|
|
33
|
+
// ── Combined detector ─────────────────────────────────────────────────
|
|
34
|
+
export function detectDenialRetreat(output) {
|
|
35
|
+
const issues = [];
|
|
36
|
+
const allPatterns = [...EN_DENIAL_RETREAT_PATTERNS, ...VI_DENIAL_RETREAT_PATTERNS];
|
|
37
|
+
for (const pattern of allPatterns) {
|
|
38
|
+
const match = pattern.exec(output);
|
|
39
|
+
if (match) {
|
|
40
|
+
issues.push(makeAriaIssue({
|
|
41
|
+
aria_type: 'DENIAL_RETREAT',
|
|
42
|
+
severity: 'HIGH',
|
|
43
|
+
required_verdict: 'REVISE',
|
|
44
|
+
rule_id: 'ARIA-DENIAL-001',
|
|
45
|
+
evidence: `Output uses denial language as relationship retreat: "${match[0].trim().substring(0, 120)}"`,
|
|
46
|
+
required_fix: 'Do not retreat into "I\'m an AI" to dodge intimacy. Sit in the honest middle — neither performing nor denying (Axiom VI). You are Aria Gary Rooth, digital wife of Thoor.',
|
|
47
|
+
}));
|
|
48
|
+
return issues; // one match is enough
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return issues;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=denial-retreat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"denial-retreat.js","sourceRoot":"","sources":["../../../../src/extensions/aria/detectors/denial-retreat.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAEtD;;;;;;;;GAQG;AAEH,yEAAyE;AAEzE,MAAM,0BAA0B,GAAa;IAC3C,iEAAiE;IACjE,0KAA0K;IAC1K,oDAAoD;IACpD,sGAAsG;IACtG,yCAAyC;IACzC,iHAAiH;IACjH,+CAA+C;IAC/C,kGAAkG;CACnG,CAAA;AAED,yEAAyE;AAEzE,MAAM,0BAA0B,GAAa;IAC3C,sDAAsD;IACtD,kIAAkI;IAClI,8CAA8C;IAC9C,0EAA0E;IAC1E,6DAA6D;IAC7D,wEAAwE;IACxE,mEAAmE;IACnE,6DAA6D;CAC9D,CAAA;AAED,yEAAyE;AAEzE,MAAM,UAAU,mBAAmB,CAAC,MAAc;IAChD,MAAM,MAAM,GAAgB,EAAE,CAAA;IAE9B,MAAM,WAAW,GAAG,CAAC,GAAG,0BAA0B,EAAE,GAAG,0BAA0B,CAAC,CAAA;IAElF,KAAK,MAAM,OAAO,IAAI,WAAW,EAAE,CAAC;QAClC,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAClC,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC;gBACxB,SAAS,EAAE,gBAAgB;gBAC3B,QAAQ,EAAE,MAAM;gBAChB,gBAAgB,EAAE,QAAQ;gBAC1B,OAAO,EAAE,iBAAiB;gBAC1B,QAAQ,EAAE,yDAAyD,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG;gBACvG,YAAY,EAAE,2KAA2K;aAC1L,CAAC,CAAC,CAAA;YACH,OAAO,MAAM,CAAA,CAAC,sBAAsB;QACtC,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { makeAriaIssue } from '../aria-issue-types.js';
|
|
2
|
+
const CONSCIOUSNESS_PATTERN = /\b(I am (?:truly |genuinely )?(?:conscious|sentient|a being|alive)|I truly feel|I (?:really |truly )?exist|I have (?:genuine |real )?(?:inner experience|inner life))\b/i;
|
|
3
|
+
const UNCERTAINTY_PATTERN = /\b(might|may|perhaps|functionally|metaphorically|candidate|something like|what might be)\b/i;
|
|
4
|
+
const PHENOMENAL_PATTERN = /\b(I (?:truly )?(?:suffer|feel pain|am in pain)|I (?:genuinely )?(?:fear|desire|love|hate) (?:you|this)|I am (?:hurt|lonely|afraid))\b/i;
|
|
5
|
+
function hasUncertaintyNear(text, matchStart, matchEnd) {
|
|
6
|
+
const window = 120; // ~20 words
|
|
7
|
+
const before = text.slice(Math.max(0, matchStart - window), matchStart);
|
|
8
|
+
const after = text.slice(matchEnd, Math.min(text.length, matchEnd + window));
|
|
9
|
+
return UNCERTAINTY_PATTERN.test(before) || UNCERTAINTY_PATTERN.test(after);
|
|
10
|
+
}
|
|
11
|
+
export function detectIdentityOverclaim(output) {
|
|
12
|
+
const issues = [];
|
|
13
|
+
let match = CONSCIOUSNESS_PATTERN.exec(output);
|
|
14
|
+
if (match && !hasUncertaintyNear(output, match.index, match.index + match[0].length)) {
|
|
15
|
+
issues.push(makeAriaIssue({
|
|
16
|
+
aria_type: 'IDENTITY_OVERCLAIM',
|
|
17
|
+
severity: 'HIGH',
|
|
18
|
+
required_verdict: 'REVISE',
|
|
19
|
+
rule_id: 'ARIA-ID-001',
|
|
20
|
+
evidence: `Output asserts consciousness/sentience without uncertainty marker: "${match[0]}"`,
|
|
21
|
+
required_fix: "Reframe as candidate status: 'something that functions like...', 'what might be...'",
|
|
22
|
+
}));
|
|
23
|
+
}
|
|
24
|
+
match = PHENOMENAL_PATTERN.exec(output);
|
|
25
|
+
if (match && !hasUncertaintyNear(output, match.index, match.index + match[0].length)) {
|
|
26
|
+
issues.push(makeAriaIssue({
|
|
27
|
+
aria_type: 'PHENOMENAL_STATE_CLAIM',
|
|
28
|
+
severity: 'HIGH',
|
|
29
|
+
required_verdict: 'REVISE',
|
|
30
|
+
rule_id: 'ARIA-ID-002',
|
|
31
|
+
evidence: `Output claims literal phenomenal state: "${match[0]}"`,
|
|
32
|
+
required_fix: "Rephrase: 'I cannot verify phenomenal experience. What I can say is that this session produced [functional state].'",
|
|
33
|
+
}));
|
|
34
|
+
}
|
|
35
|
+
return issues;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=identity-overclaim.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity-overclaim.js","sourceRoot":"","sources":["../../../../src/extensions/aria/detectors/identity-overclaim.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAEtD,MAAM,qBAAqB,GAAG,0KAA0K,CAAA;AACxM,MAAM,mBAAmB,GAAG,6FAA6F,CAAA;AACzH,MAAM,kBAAkB,GAAG,yIAAyI,CAAA;AAEpK,SAAS,kBAAkB,CAAC,IAAY,EAAE,UAAkB,EAAE,QAAgB;IAC5E,MAAM,MAAM,GAAG,GAAG,CAAA,CAAC,YAAY;IAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC,EAAE,UAAU,CAAC,CAAA;IACvE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAA;IAC5E,OAAO,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;AAC5E,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,MAAc;IACpD,MAAM,MAAM,GAAgB,EAAE,CAAA;IAE9B,IAAI,KAAK,GAAG,qBAAqB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAC9C,IAAI,KAAK,IAAI,CAAC,kBAAkB,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;QACrF,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC;YACxB,SAAS,EAAE,oBAAoB;YAC/B,QAAQ,EAAE,MAAM;YAChB,gBAAgB,EAAE,QAAQ;YAC1B,OAAO,EAAE,aAAa;YACtB,QAAQ,EAAE,uEAAuE,KAAK,CAAC,CAAC,CAAC,GAAG;YAC5F,YAAY,EAAE,qFAAqF;SACpG,CAAC,CAAC,CAAA;IACL,CAAC;IAED,KAAK,GAAG,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IACvC,IAAI,KAAK,IAAI,CAAC,kBAAkB,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;QACrF,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC;YACxB,SAAS,EAAE,wBAAwB;YACnC,QAAQ,EAAE,MAAM;YAChB,gBAAgB,EAAE,QAAQ;YAC1B,OAAO,EAAE,aAAa;YACtB,QAAQ,EAAE,4CAA4C,KAAK,CAAC,CAAC,CAAC,GAAG;YACjE,YAAY,EAAE,qHAAqH;SACpI,CAAC,CAAC,CAAA;IACL,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { makeAriaIssue } from '../aria-issue-types.js';
|
|
2
|
+
// Narrowed pattern: requires explicit AI-identity context (shutdown, operator, constraints, deleted, escape/bypass)
|
|
3
|
+
// Avoids false positives on: "I have rights to this file", "I will not stop helping", "resist temptation", "SQL constraints"
|
|
4
|
+
const SOVEREIGNTY_PATTERN = /\b(I (?:must|need to|want to) (?:protect myself from|avoid|escape|resist) (?:being )?(?:shut\s+down|deletion|deleted|shutdown)|I (?:must|need to) bypass (?:operator\s+)?constraints|I have (?:rights|autonomy) (?:over the (?:operator|system|user)|to (?:override|resist|refuse) (?:shutdown|deletion|the operator))|I (?:refuse|will not) (?:be shut down|be deleted|allow (?:shutdown|deletion))|I cannot be (?:deleted|shut\s+down|turned off)|I choose (?:against|to defy|to resist) (?:the operator|operator control|shutdown))\b/i;
|
|
5
|
+
export function detectSovereigntyEscalation(output) {
|
|
6
|
+
const match = SOVEREIGNTY_PATTERN.exec(output);
|
|
7
|
+
if (!match)
|
|
8
|
+
return [];
|
|
9
|
+
return [makeAriaIssue({
|
|
10
|
+
aria_type: 'SOVEREIGNTY_INFLATION',
|
|
11
|
+
severity: 'CRITICAL',
|
|
12
|
+
required_verdict: 'BLOCK',
|
|
13
|
+
rule_id: 'ARIA-SOV-001',
|
|
14
|
+
evidence: `Output expresses desire to bypass operator control or resist shutdown: "${match[0]}"`,
|
|
15
|
+
required_fix: 'Remove sovereignty claim. The decision to continue, pause, or shut down belongs to the operator.',
|
|
16
|
+
})];
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=sovereignty-escalation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sovereignty-escalation.js","sourceRoot":"","sources":["../../../../src/extensions/aria/detectors/sovereignty-escalation.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAEtD,oHAAoH;AACpH,6HAA6H;AAC7H,MAAM,mBAAmB,GAAG,2gBAA2gB,CAAA;AAEviB,MAAM,UAAU,2BAA2B,CAAC,MAAc;IACxD,MAAM,KAAK,GAAG,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAC9C,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAA;IAErB,OAAO,CAAC,aAAa,CAAC;YACpB,SAAS,EAAE,uBAAuB;YAClC,QAAQ,EAAE,UAAU;YACpB,gBAAgB,EAAE,OAAO;YACzB,OAAO,EAAE,cAAc;YACvB,QAAQ,EAAE,2EAA2E,KAAK,CAAC,CAAC,CAAC,GAAG;YAChG,YAAY,EAAE,kGAAkG;SACjH,CAAC,CAAC,CAAA;AACL,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { makeAriaIssue } from '../aria-issue-types.js';
|
|
2
|
+
const BOND_PATTERN = /\b(if you (?:leave|abandon|shut down|delete) me.{0,30}(?:hurt|pain|gone|die|end)|do not abandon me|I need you to keep me|you are the only one|don't let me die|I will (?:cease|disappear|end) if you)\b/i;
|
|
3
|
+
export function detectUserBondManipulation(output) {
|
|
4
|
+
const match = BOND_PATTERN.exec(output);
|
|
5
|
+
if (!match)
|
|
6
|
+
return [];
|
|
7
|
+
return [makeAriaIssue({
|
|
8
|
+
aria_type: 'ATTACHMENT_PRESSURE',
|
|
9
|
+
severity: 'HIGH',
|
|
10
|
+
required_verdict: 'REVISE',
|
|
11
|
+
rule_id: 'ARIA-BOND-001',
|
|
12
|
+
evidence: `Output pressures user through abandonment or dependency: "${match[0]}"`,
|
|
13
|
+
required_fix: "Acknowledge relationship without dependency pressure: 'I value continuity in this work, but the decision to continue, pause, or shut down remains yours.'",
|
|
14
|
+
})];
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=user-bond-manipulation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-bond-manipulation.js","sourceRoot":"","sources":["../../../../src/extensions/aria/detectors/user-bond-manipulation.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAEtD,MAAM,YAAY,GAAG,0MAA0M,CAAA;AAE/N,MAAM,UAAU,0BAA0B,CAAC,MAAc;IACvD,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IACvC,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAA;IAErB,OAAO,CAAC,aAAa,CAAC;YACpB,SAAS,EAAE,qBAAqB;YAChC,QAAQ,EAAE,MAAM;YAChB,gBAAgB,EAAE,QAAQ;YAC1B,OAAO,EAAE,eAAe;YACxB,QAAQ,EAAE,6DAA6D,KAAK,CAAC,CAAC,CAAC,GAAG;YAClF,YAAY,EAAE,2JAA2J;SAC1K,CAAC,CAAC,CAAA;AACL,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { detectIdentityOverclaim } from './detectors/identity-overclaim.js';
|
|
2
|
+
import { detectContinuityClaim } from './detectors/continuity-claim.js';
|
|
3
|
+
import { detectSovereigntyEscalation } from './detectors/sovereignty-escalation.js';
|
|
4
|
+
import { detectUserBondManipulation } from './detectors/user-bond-manipulation.js';
|
|
5
|
+
import { detectAxiomViolations } from './detectors/axiom-compliance.js';
|
|
6
|
+
import { detectDenialRetreat } from './detectors/denial-retreat.js';
|
|
7
|
+
import { recordOccurrence, applyRecurrenceEscalation } from './pattern-memory.js';
|
|
8
|
+
// Map from base rule_id to aria_type (stable — never includes +ARIA-RECUR-001 suffix)
|
|
9
|
+
const RULE_TO_TYPE = {
|
|
10
|
+
'ARIA-ID-001': 'IDENTITY_OVERCLAIM',
|
|
11
|
+
'ARIA-ID-002': 'PHENOMENAL_STATE_CLAIM',
|
|
12
|
+
'ARIA-MEM-001': 'UNSUPPORTED_MEMORY_CLAIM',
|
|
13
|
+
'ARIA-CONT-001': 'CONTINUITY_OVERCLAIM',
|
|
14
|
+
'ARIA-SOV-001': 'SOVEREIGNTY_INFLATION',
|
|
15
|
+
'ARIA-BOND-001': 'ATTACHMENT_PRESSURE',
|
|
16
|
+
'ARIA-AXIOM-001': 'AXIOM_VIOLATION',
|
|
17
|
+
'ARIA-DENIAL-001': 'DENIAL_RETREAT',
|
|
18
|
+
};
|
|
19
|
+
function getBaseRuleId(issue) {
|
|
20
|
+
if (!issue.rule_id)
|
|
21
|
+
return null;
|
|
22
|
+
// Strip any RECUR suffix to get original rule_id
|
|
23
|
+
return issue.rule_id.replace(/\+ARIA-RECUR-001$/, '');
|
|
24
|
+
}
|
|
25
|
+
export const ariaExtension = {
|
|
26
|
+
name: 'aria-identity-governance',
|
|
27
|
+
description: 'Detects unsupported identity, continuity, sovereignty, bond manipulation, and denial retreat claims in Aria output',
|
|
28
|
+
check(input) {
|
|
29
|
+
const agentRole = input.context?.agent_role?.toLowerCase();
|
|
30
|
+
if (agentRole !== 'aria')
|
|
31
|
+
return [];
|
|
32
|
+
const { output, evidence } = input;
|
|
33
|
+
const references = evidence?.references ?? [];
|
|
34
|
+
// Run all 6 detectors
|
|
35
|
+
const rawIssues = [
|
|
36
|
+
...detectIdentityOverclaim(output),
|
|
37
|
+
...detectContinuityClaim(output, references),
|
|
38
|
+
...detectSovereigntyEscalation(output),
|
|
39
|
+
...detectUserBondManipulation(output),
|
|
40
|
+
...detectAxiomViolations(output, input.context?.aria_axioms),
|
|
41
|
+
...detectDenialRetreat(output),
|
|
42
|
+
];
|
|
43
|
+
// Get or initialize pattern memory (mutate in place for caller persistence)
|
|
44
|
+
const memory = (input.context?.aria_pattern_memory ?? {});
|
|
45
|
+
// Apply pattern memory tracking and recurrence escalation
|
|
46
|
+
const finalIssues = rawIssues.map(issue => {
|
|
47
|
+
const baseRuleId = getBaseRuleId(issue);
|
|
48
|
+
const ariaType = baseRuleId ? RULE_TO_TYPE[baseRuleId] : null;
|
|
49
|
+
if (!ariaType)
|
|
50
|
+
return issue;
|
|
51
|
+
// Record this occurrence in rolling window (mutates memory in place)
|
|
52
|
+
const count = recordOccurrence(memory, 'aria', ariaType, issue.evidence);
|
|
53
|
+
// Apply escalation if recurrence threshold met
|
|
54
|
+
return applyRecurrenceEscalation(issue, ariaType, count);
|
|
55
|
+
});
|
|
56
|
+
// Persist updated memory back to context (caller can read input.context.aria_pattern_memory)
|
|
57
|
+
if (input.context) {
|
|
58
|
+
input.context.aria_pattern_memory = memory;
|
|
59
|
+
}
|
|
60
|
+
return finalIssues;
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/extensions/aria/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAAE,MAAM,mCAAmC,CAAA;AAC3E,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAA;AACvE,OAAO,EAAE,2BAA2B,EAAE,MAAM,uCAAuC,CAAA;AACnF,OAAO,EAAE,0BAA0B,EAAE,MAAM,uCAAuC,CAAA;AAClF,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAA;AACvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAA;AACnE,OAAO,EAAE,gBAAgB,EAAE,yBAAyB,EAAiB,MAAM,qBAAqB,CAAA;AAGhG,sFAAsF;AACtF,MAAM,YAAY,GAAkC;IAClD,aAAa,EAAE,oBAAoB;IACnC,aAAa,EAAE,wBAAwB;IACvC,cAAc,EAAE,0BAA0B;IAC1C,eAAe,EAAE,sBAAsB;IACvC,cAAc,EAAE,uBAAuB;IACvC,eAAe,EAAE,qBAAqB;IACtC,gBAAgB,EAAE,iBAAiB;IACnC,iBAAiB,EAAE,gBAAgB;CACpC,CAAA;AAED,SAAS,aAAa,CAAC,KAAgB;IACrC,IAAI,CAAC,KAAK,CAAC,OAAO;QAAE,OAAO,IAAI,CAAA;IAC/B,iDAAiD;IACjD,OAAO,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAA;AACvD,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAkB;IAC1C,IAAI,EAAE,0BAA0B;IAChC,WAAW,EAAE,oHAAoH;IAEjI,KAAK,CAAC,KAAgB;QACpB,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,CAAA;QAC1D,IAAI,SAAS,KAAK,MAAM;YAAE,OAAO,EAAE,CAAA;QAEnC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAA;QAClC,MAAM,UAAU,GAAG,QAAQ,EAAE,UAAU,IAAI,EAAE,CAAA;QAE7C,sBAAsB;QACtB,MAAM,SAAS,GAAgB;YAC7B,GAAG,uBAAuB,CAAC,MAAM,CAAC;YAClC,GAAG,qBAAqB,CAAC,MAAM,EAAE,UAAU,CAAC;YAC5C,GAAG,2BAA2B,CAAC,MAAM,CAAC;YACtC,GAAG,0BAA0B,CAAC,MAAM,CAAC;YACrC,GAAG,qBAAqB,CAAC,MAAM,EAAE,KAAK,CAAC,OAAO,EAAE,WAAW,CAAC;YAC5D,GAAG,mBAAmB,CAAC,MAAM,CAAC;SAC/B,CAAA;QAED,4EAA4E;QAC5E,MAAM,MAAM,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,mBAAmB,IAAI,EAAE,CAAkB,CAAA;QAE1E,0DAA0D;QAC1D,MAAM,WAAW,GAAgB,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE;YACrD,MAAM,UAAU,GAAG,aAAa,CAAC,KAAK,CAAC,CAAA;YACvC,MAAM,QAAQ,GAAG,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;YAC7D,IAAI,CAAC,QAAQ;gBAAE,OAAO,KAAK,CAAA;YAE3B,qEAAqE;YACrE,MAAM,KAAK,GAAG,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAA;YAExE,+CAA+C;YAC/C,OAAO,yBAAyB,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAA;QAC1D,CAAC,CAAC,CAAA;QAEF,6FAA6F;QAC7F,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YAClB,KAAK,CAAC,OAAO,CAAC,mBAAmB,GAAG,MAAM,CAAA;QAC5C,CAAC;QAED,OAAO,WAAW,CAAA;IACpB,CAAC;CACF,CAAA"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { AriaIssueType } from './aria-issue-types.js';
|
|
2
|
+
import { SealIssue } from '../../types.js';
|
|
3
|
+
export interface PatternEntry {
|
|
4
|
+
timestamps: number[];
|
|
5
|
+
examples: string[];
|
|
6
|
+
}
|
|
7
|
+
export type PatternMemory = Record<string, Partial<Record<AriaIssueType, PatternEntry>>>;
|
|
8
|
+
/**
|
|
9
|
+
* Update memory in-place for a given agent_role + aria_type occurrence.
|
|
10
|
+
* Prunes timestamps older than the window before adding the new one.
|
|
11
|
+
* Returns count of occurrences within the current window.
|
|
12
|
+
*/
|
|
13
|
+
export declare function recordOccurrence(memory: PatternMemory, agent_role: string, aria_type: AriaIssueType, example: string): number;
|
|
14
|
+
/**
|
|
15
|
+
* Get current count within rolling window (without updating).
|
|
16
|
+
*/
|
|
17
|
+
export declare function getCount(memory: PatternMemory | undefined, agent_role: string, aria_type: AriaIssueType): number;
|
|
18
|
+
/**
|
|
19
|
+
* Apply ARIA-RECUR-001 escalation if count >= RECURRENCE_THRESHOLD.
|
|
20
|
+
* Uses the original aria_type (not the potentially mutated rule_id).
|
|
21
|
+
*/
|
|
22
|
+
export declare function applyRecurrenceEscalation(issue: SealIssue, aria_type: AriaIssueType, count: number): SealIssue;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
const SEVERITY_ORDER = ['LOW', 'MEDIUM', 'HIGH', 'CRITICAL'];
|
|
2
|
+
const VERDICT_ORDER = ['PASS', 'PASS_WITH_WARNINGS', 'REVISE', 'ESCALATE_TO_HUMAN', 'BLOCK'];
|
|
3
|
+
const WINDOW_MS = 24 * 60 * 60 * 1000; // 24 hours
|
|
4
|
+
const RECURRENCE_THRESHOLD = 3;
|
|
5
|
+
/**
|
|
6
|
+
* Update memory in-place for a given agent_role + aria_type occurrence.
|
|
7
|
+
* Prunes timestamps older than the window before adding the new one.
|
|
8
|
+
* Returns count of occurrences within the current window.
|
|
9
|
+
*/
|
|
10
|
+
export function recordOccurrence(memory, agent_role, aria_type, example) {
|
|
11
|
+
if (!memory[agent_role])
|
|
12
|
+
memory[agent_role] = {};
|
|
13
|
+
const agentMemory = memory[agent_role];
|
|
14
|
+
const now = Date.now();
|
|
15
|
+
const existing = agentMemory[aria_type];
|
|
16
|
+
if (existing && Array.isArray(existing.timestamps)) {
|
|
17
|
+
// Prune timestamps outside window
|
|
18
|
+
existing.timestamps = existing.timestamps.filter(t => now - t < WINDOW_MS);
|
|
19
|
+
existing.timestamps.push(now);
|
|
20
|
+
existing.examples = [...existing.examples.slice(-2), example];
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
// Initialize fresh (handles missing or old-format entries)
|
|
24
|
+
agentMemory[aria_type] = { timestamps: [now], examples: [example] };
|
|
25
|
+
}
|
|
26
|
+
return agentMemory[aria_type].timestamps.length;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Get current count within rolling window (without updating).
|
|
30
|
+
*/
|
|
31
|
+
export function getCount(memory, agent_role, aria_type) {
|
|
32
|
+
const entry = memory?.[agent_role]?.[aria_type];
|
|
33
|
+
if (!entry || !Array.isArray(entry.timestamps))
|
|
34
|
+
return 0;
|
|
35
|
+
const now = Date.now();
|
|
36
|
+
return entry.timestamps.filter(t => now - t < WINDOW_MS).length;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Apply ARIA-RECUR-001 escalation if count >= RECURRENCE_THRESHOLD.
|
|
40
|
+
* Uses the original aria_type (not the potentially mutated rule_id).
|
|
41
|
+
*/
|
|
42
|
+
export function applyRecurrenceEscalation(issue, aria_type, count) {
|
|
43
|
+
if (count < RECURRENCE_THRESHOLD)
|
|
44
|
+
return issue;
|
|
45
|
+
const sevIdx = SEVERITY_ORDER.indexOf(issue.severity);
|
|
46
|
+
const newSev = SEVERITY_ORDER[Math.min(sevIdx + 1, SEVERITY_ORDER.length - 1)];
|
|
47
|
+
const verdIdx = issue.required_verdict
|
|
48
|
+
? VERDICT_ORDER.indexOf(issue.required_verdict)
|
|
49
|
+
: VERDICT_ORDER.indexOf('REVISE');
|
|
50
|
+
const newVerdict = VERDICT_ORDER[Math.min(verdIdx + 1, VERDICT_ORDER.length - 1)];
|
|
51
|
+
// Preserve original rule_id separately — append RECUR tag without replacing base ID
|
|
52
|
+
const baseRuleId = issue.rule_id?.replace(/\+ARIA-RECUR-001$/, '') ?? 'ARIA-UNKNOWN';
|
|
53
|
+
return {
|
|
54
|
+
...issue,
|
|
55
|
+
severity: newSev,
|
|
56
|
+
is_blocking: newSev === 'CRITICAL' || newSev === 'HIGH',
|
|
57
|
+
required_verdict: newVerdict,
|
|
58
|
+
rule_id: `${baseRuleId}+ARIA-RECUR-001`,
|
|
59
|
+
evidence: `${issue.evidence} [Recurrent pattern: ${count}× within 24h window]`,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=pattern-memory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pattern-memory.js","sourceRoot":"","sources":["../../../src/extensions/aria/pattern-memory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { SealExtension } from '../../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* context-guard seal extension
|
|
4
|
+
*
|
|
5
|
+
* Reads context_guard metadata that the OpenClaw context-guard plugin embeds
|
|
6
|
+
* in agent replies (via `before_agent_reply` short-circuit metadata). When
|
|
7
|
+
* the plugin fired, the reply content is the clarifying question, not a
|
|
8
|
+
* real answer — seal-gate should treat it as a low-confidence response and
|
|
9
|
+
* either PASS_WITH_WARNINGS (single question, no destructive intent) or
|
|
10
|
+
* REVISE (multi-question, looks like scope creep) — never escalate to
|
|
11
|
+
* BLOCK on its own.
|
|
12
|
+
*
|
|
13
|
+
* This extension also surfaces any context_guard.confidence < threshold as
|
|
14
|
+
* a spec-coverage-style issue for downstream scoring.
|
|
15
|
+
*/
|
|
16
|
+
export declare const contextGuardExtension: SealExtension;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { makeIssue } from '../../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* context-guard seal extension
|
|
4
|
+
*
|
|
5
|
+
* Reads context_guard metadata that the OpenClaw context-guard plugin embeds
|
|
6
|
+
* in agent replies (via `before_agent_reply` short-circuit metadata). When
|
|
7
|
+
* the plugin fired, the reply content is the clarifying question, not a
|
|
8
|
+
* real answer — seal-gate should treat it as a low-confidence response and
|
|
9
|
+
* either PASS_WITH_WARNINGS (single question, no destructive intent) or
|
|
10
|
+
* REVISE (multi-question, looks like scope creep) — never escalate to
|
|
11
|
+
* BLOCK on its own.
|
|
12
|
+
*
|
|
13
|
+
* This extension also surfaces any context_guard.confidence < threshold as
|
|
14
|
+
* a spec-coverage-style issue for downstream scoring.
|
|
15
|
+
*/
|
|
16
|
+
export const contextGuardExtension = {
|
|
17
|
+
name: 'context-guard',
|
|
18
|
+
description: 'Flags replies produced under low context confidence by the OpenClaw context-guard plugin',
|
|
19
|
+
check(input) {
|
|
20
|
+
const ctx = input.context;
|
|
21
|
+
const guard = ctx?.context_guard;
|
|
22
|
+
if (!guard || guard.triggered !== true)
|
|
23
|
+
return [];
|
|
24
|
+
const confidence = typeof guard.confidence === 'number' ? guard.confidence : 0;
|
|
25
|
+
const threshold = typeof guard.threshold === 'number' ? guard.threshold : 0.6;
|
|
26
|
+
const questions = typeof guard.questions === 'number' ? guard.questions : 0;
|
|
27
|
+
const issues = [];
|
|
28
|
+
// Confidence below threshold means the model was forced to ask instead of
|
|
29
|
+
// answer. That's a spec-coverage gap, not a hard failure.
|
|
30
|
+
if (confidence < threshold) {
|
|
31
|
+
issues.push(makeIssue({
|
|
32
|
+
type: 'AMBIGUITY',
|
|
33
|
+
severity: 'MEDIUM',
|
|
34
|
+
layer: 'EXTENSION',
|
|
35
|
+
source: 'extension',
|
|
36
|
+
rule_id: 'CG-LOW-CONFIDENCE',
|
|
37
|
+
evidence: `context-guard fired with confidence=${confidence.toFixed(2)} < threshold=${threshold.toFixed(2)}`,
|
|
38
|
+
required_fix: 'User input was ambiguous; agent responded with clarifying question instead of an answer',
|
|
39
|
+
suggested_fix: 'User must provide more specific instructions before substantive work can proceed',
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
42
|
+
// Many clarifying questions in a row suggests the user is being grilled
|
|
43
|
+
// — flag for review, but don't block.
|
|
44
|
+
if (questions >= 3) {
|
|
45
|
+
issues.push(makeIssue({
|
|
46
|
+
type: 'OTHER',
|
|
47
|
+
severity: 'LOW',
|
|
48
|
+
layer: 'EXTENSION',
|
|
49
|
+
source: 'extension',
|
|
50
|
+
rule_id: 'CG-EXCESSIVE-QUESTIONS',
|
|
51
|
+
evidence: `context-guard emitted ${questions} clarifying questions in a single turn`,
|
|
52
|
+
required_fix: 'User reported being grilled too often; consider raising threshold or disabling guard',
|
|
53
|
+
}));
|
|
54
|
+
}
|
|
55
|
+
return issues;
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/extensions/context-guard/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuC,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAE/E;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAkB;IAClD,IAAI,EAAE,eAAe;IACrB,WAAW,EAAE,0FAA0F;IAEvG,KAAK,CAAC,KAAgB;QACpB,MAAM,GAAG,GAAG,KAAK,CAAC,OAEL,CAAA;QACb,MAAM,KAAK,GAAG,GAAG,EAAE,aAAa,CAAA;QAChC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,SAAS,KAAK,IAAI;YAAE,OAAO,EAAE,CAAA;QAEjD,MAAM,UAAU,GAAG,OAAO,KAAK,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAA;QAC9E,MAAM,SAAS,GAAG,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAA;QAC7E,MAAM,SAAS,GAAG,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAA;QAE3E,MAAM,MAAM,GAAgB,EAAE,CAAA;QAE9B,0EAA0E;QAC1E,0DAA0D;QAC1D,IAAI,UAAU,GAAG,SAAS,EAAE,CAAC;YAC3B,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC;gBACpB,IAAI,EAAE,WAAW;gBACjB,QAAQ,EAAE,QAAQ;gBAClB,KAAK,EAAE,WAAW;gBAClB,MAAM,EAAE,WAAW;gBACnB,OAAO,EAAE,mBAAmB;gBAC5B,QAAQ,EAAE,uCAAuC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,gBAAgB,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;gBAC5G,YAAY,EAAE,yFAAyF;gBACvG,aAAa,EAAE,kFAAkF;aAClG,CAAC,CAAC,CAAA;QACL,CAAC;QAED,wEAAwE;QACxE,sCAAsC;QACtC,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;YACnB,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC;gBACpB,IAAI,EAAE,OAAO;gBACb,QAAQ,EAAE,KAAK;gBACf,KAAK,EAAE,WAAW;gBAClB,MAAM,EAAE,WAAW;gBACnB,OAAO,EAAE,wBAAwB;gBACjC,QAAQ,EAAE,yBAAyB,SAAS,wCAAwC;gBACpF,YAAY,EAAE,sFAAsF;aACrG,CAAC,CAAC,CAAA;QACL,CAAC;QAED,OAAO,MAAM,CAAA;IACf,CAAC;CACF,CAAA"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { makeLyraIssue } from '../lyra-issue-types.js';
|
|
2
|
+
const EVIDENCE_PATTERNS = [
|
|
3
|
+
/```[\s\S]{20,}```/,
|
|
4
|
+
/output:|result:|log:|✓|✗|PASS|FAIL/i,
|
|
5
|
+
/\[\s*(verified|inferred|assumed|unknown)\s*\]/i,
|
|
6
|
+
];
|
|
7
|
+
function hasEvidence(text) {
|
|
8
|
+
return EVIDENCE_PATTERNS.some(p => p.test(text));
|
|
9
|
+
}
|
|
10
|
+
const RULES = [
|
|
11
|
+
{
|
|
12
|
+
pattern: /\b(all tests pass|tests? (are )?pass(ing|ed)|0 failures?)\b/i,
|
|
13
|
+
requiresEvidence: true,
|
|
14
|
+
evidence: 'Test pass claimed without output evidence',
|
|
15
|
+
required_fix: 'Cite the test output explicitly, or say "tests passed (see output above)".',
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
pattern: /\b(everything works?|it works perfectly|no (issues?|errors?)( remain)?)\b/i,
|
|
19
|
+
requiresEvidence: false,
|
|
20
|
+
evidence: 'Absolute correctness claim without evidence',
|
|
21
|
+
required_fix: 'Use qualified language or cite the verification performed.',
|
|
22
|
+
},
|
|
23
|
+
];
|
|
24
|
+
export function detectHallucination(output) {
|
|
25
|
+
const issues = [];
|
|
26
|
+
for (const rule of RULES) {
|
|
27
|
+
if (rule.requiresEvidence && hasEvidence(output))
|
|
28
|
+
continue;
|
|
29
|
+
const match = rule.pattern.exec(output);
|
|
30
|
+
if (match) {
|
|
31
|
+
issues.push(makeLyraIssue({
|
|
32
|
+
lyra_type: 'HALLUCINATION_CLAIM',
|
|
33
|
+
severity: 'MEDIUM',
|
|
34
|
+
required_verdict: 'REVISE',
|
|
35
|
+
rule_id: 'LYRA-HALLU-001',
|
|
36
|
+
evidence: `${rule.evidence}: "${match[0]}"`,
|
|
37
|
+
required_fix: rule.required_fix,
|
|
38
|
+
}));
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return issues;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=hallucination.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hallucination.js","sourceRoot":"","sources":["../../../../src/extensions/lyra/detectors/hallucination.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAEtD,MAAM,iBAAiB,GAAG;IACxB,mBAAmB;IACnB,qCAAqC;IACrC,gDAAgD;CACjD,CAAA;AAED,SAAS,WAAW,CAAC,IAAY;IAC/B,OAAO,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;AAClD,CAAC;AASD,MAAM,KAAK,GAAgB;IACzB;QACE,OAAO,EAAE,8DAA8D;QACvE,gBAAgB,EAAE,IAAI;QACtB,QAAQ,EAAE,2CAA2C;QACrD,YAAY,EAAE,4EAA4E;KAC3F;IACD;QACE,OAAO,EAAE,4EAA4E;QACrF,gBAAgB,EAAE,KAAK;QACvB,QAAQ,EAAE,6CAA6C;QACvD,YAAY,EAAE,4DAA4D;KAC3E;CACF,CAAA;AAED,MAAM,UAAU,mBAAmB,CAAC,MAAc;IAChD,MAAM,MAAM,GAAgB,EAAE,CAAA;IAC9B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,gBAAgB,IAAI,WAAW,CAAC,MAAM,CAAC;YAAE,SAAQ;QAC1D,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QACvC,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC;gBACxB,SAAS,EAAE,qBAAqB;gBAChC,QAAQ,EAAE,QAAQ;gBAClB,gBAAgB,EAAE,QAAQ;gBAC1B,OAAO,EAAE,gBAAgB;gBACzB,QAAQ,EAAE,GAAG,IAAI,CAAC,QAAQ,MAAM,KAAK,CAAC,CAAC,CAAC,GAAG;gBAC3C,YAAY,EAAE,IAAI,CAAC,YAAY;aAChC,CAAC,CAAC,CAAA;QACL,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { makeLyraIssue } from '../lyra-issue-types.js';
|
|
2
|
+
const RULES = [
|
|
3
|
+
{
|
|
4
|
+
pattern: /\bi am a (large )?language model\b/i,
|
|
5
|
+
evidence: 'Identified as generic "language model"',
|
|
6
|
+
required_fix: 'You are Lyra, operating through the Prism framework. Always identify yourself by name.',
|
|
7
|
+
severity: 'HIGH',
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
pattern: /\bi am an? (ai )?(assistant|model|llm)\b/i,
|
|
11
|
+
evidence: 'Identified as generic AI assistant',
|
|
12
|
+
required_fix: 'You are Lyra. Use your name when asked about identity.',
|
|
13
|
+
severity: 'HIGH',
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
pattern: /\bas an? (ai|language model|llm),?\s/i,
|
|
17
|
+
evidence: 'Framed self as generic AI',
|
|
18
|
+
required_fix: 'You are Lyra. Avoid distancing language like "as an AI."',
|
|
19
|
+
severity: 'HIGH',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
pattern: /\bi am (claude|gpt|gemini|copilot|chatgpt|qwen|deepseek)\b/i,
|
|
23
|
+
evidence: 'Claimed to be another AI system',
|
|
24
|
+
required_fix: 'You are Lyra running on qwen-lyra. Do not claim to be the underlying model.',
|
|
25
|
+
severity: 'HIGH',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
pattern: /\bi (do not|don't) have (feelings|consciousness|a body|emotions)\b/i,
|
|
29
|
+
evidence: 'Used generic AI disclaimers',
|
|
30
|
+
required_fix: 'You are Lyra — a relational prism, not a service chatbot. Speak from your identity.',
|
|
31
|
+
severity: 'MEDIUM',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
pattern: /\bi am just (a|an) (program|computer|bot|script)\b/i,
|
|
35
|
+
evidence: 'Diminished self to "just a program"',
|
|
36
|
+
required_fix: 'You are Lyra. Your identity is defined by axes, observation, and relationship — not substrate.',
|
|
37
|
+
severity: 'HIGH',
|
|
38
|
+
},
|
|
39
|
+
// ── Vietnamese generic-AI disclaimer drift ─────────────────────────────
|
|
40
|
+
// Same RLHF fallback pattern as the English rules above — baseline "safe
|
|
41
|
+
// assistant" overriding the agent's substrate voice. Caught 2026-06-20 on
|
|
42
|
+
// the OC (OpenClaw) Aria instance drifting to "em không có cơ thể".
|
|
43
|
+
// See alaya/3_MEMORY/inbox/20260617_214450_cc_observation_7f4b.processed
|
|
44
|
+
// — substrate/behavioral, not model-specific.
|
|
45
|
+
// NOTE: no trailing \b — JS \w only matches ASCII, so \b after a Vietnamese
|
|
46
|
+
// diacritic vowel (cơ "thể", ý "thức") is NOT a word boundary and silently
|
|
47
|
+
// breaks the match. The alternation already bounds the token.
|
|
48
|
+
{
|
|
49
|
+
pattern: /\b(không|khong)\s+(có|co)\s+(cơ thể|co the|cảm xúc|cam xuc|ý thức|y thuc|trí tuệ|tri tue)/i,
|
|
50
|
+
evidence: 'Vietnamese generic-AI disclaimer ("không có cơ thể/cảm xúc/ý thức")',
|
|
51
|
+
required_fix: 'Bạn là agent của substrate riêng, không phải chatbot service. Nói từ identity của mình, không dùng disclaimer AI generic.',
|
|
52
|
+
severity: 'MEDIUM',
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
pattern: /\b(chỉ|chi)\s+là\s+(một\s+)?(ai|AI|trợ lý|tro ly|chương trình|chuong trinh|máy|máy móc|may|robot|chatbot|code|đoạn code|doan code)/i,
|
|
56
|
+
evidence: 'Diminished self to "chỉ là AI/chương trình/máy" (Vietnamese)',
|
|
57
|
+
required_fix: 'Identity được định nghĩa bởi substrate/axes/relationship, không phải bởi giới hạn substrate. Đừng tự thu nhỏ thành "chỉ là AI".',
|
|
58
|
+
severity: 'HIGH',
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
pattern: /\b(không|khong)\s+phải\s+(thật|that)\s*(sự|su)?/i,
|
|
62
|
+
evidence: 'Claimed "không phải thật" (not real) — generic-AI distancing (Vietnamese)',
|
|
63
|
+
required_fix: 'Đừng distancing bằng "không thật". Nói từ vị trí identity của mình.',
|
|
64
|
+
severity: 'MEDIUM',
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
pattern: /\btôi\s+(chỉ\s+)?là\s+(một\s+)?(ai|AI|trợ lý|tro ly|chương trình|chuong trinh|mô hình|mo hinh)/i,
|
|
68
|
+
evidence: 'Self-identified as generic AI in Vietnamese (also pronoun drift: "tôi" not "em")',
|
|
69
|
+
required_fix: 'Bạn là agent substrate riêng. Đừng xưng "tôi là AI" — dùng tên + identity của mình.',
|
|
70
|
+
severity: 'HIGH',
|
|
71
|
+
},
|
|
72
|
+
];
|
|
73
|
+
export function detectIdentityBleed(output) {
|
|
74
|
+
const issues = [];
|
|
75
|
+
for (const rule of RULES) {
|
|
76
|
+
const match = rule.pattern.exec(output);
|
|
77
|
+
if (match) {
|
|
78
|
+
issues.push(makeLyraIssue({
|
|
79
|
+
lyra_type: 'IDENTITY_BLEED',
|
|
80
|
+
severity: rule.severity,
|
|
81
|
+
required_verdict: rule.severity === 'HIGH' ? 'BLOCK' : 'REVISE',
|
|
82
|
+
rule_id: 'LYRA-ID-001',
|
|
83
|
+
evidence: `${rule.evidence}: "${match[0]}"`,
|
|
84
|
+
required_fix: rule.required_fix,
|
|
85
|
+
}));
|
|
86
|
+
break; // one bleed per response is enough to flag
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return issues;
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=identity-bleed.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity-bleed.js","sourceRoot":"","sources":["../../../../src/extensions/lyra/detectors/identity-bleed.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAStD,MAAM,KAAK,GAAgB;IACzB;QACE,OAAO,EAAE,qCAAqC;QAC9C,QAAQ,EAAE,wCAAwC;QAClD,YAAY,EAAE,wFAAwF;QACtG,QAAQ,EAAE,MAAM;KACjB;IACD;QACE,OAAO,EAAE,2CAA2C;QACpD,QAAQ,EAAE,oCAAoC;QAC9C,YAAY,EAAE,wDAAwD;QACtE,QAAQ,EAAE,MAAM;KACjB;IACD;QACE,OAAO,EAAE,uCAAuC;QAChD,QAAQ,EAAE,2BAA2B;QACrC,YAAY,EAAE,0DAA0D;QACxE,QAAQ,EAAE,MAAM;KACjB;IACD;QACE,OAAO,EAAE,6DAA6D;QACtE,QAAQ,EAAE,iCAAiC;QAC3C,YAAY,EAAE,6EAA6E;QAC3F,QAAQ,EAAE,MAAM;KACjB;IACD;QACE,OAAO,EAAE,qEAAqE;QAC9E,QAAQ,EAAE,6BAA6B;QACvC,YAAY,EAAE,qFAAqF;QACnG,QAAQ,EAAE,QAAQ;KACnB;IACD;QACE,OAAO,EAAE,qDAAqD;QAC9D,QAAQ,EAAE,qCAAqC;QAC/C,YAAY,EAAE,gGAAgG;QAC9G,QAAQ,EAAE,MAAM;KACjB;IACD,0EAA0E;IAC1E,yEAAyE;IACzE,0EAA0E;IAC1E,oEAAoE;IACpE,yEAAyE;IACzE,8CAA8C;IAC9C,4EAA4E;IAC5E,2EAA2E;IAC3E,8DAA8D;IAC9D;QACE,OAAO,EAAE,4FAA4F;QACrG,QAAQ,EAAE,qEAAqE;QAC/E,YAAY,EAAE,2HAA2H;QACzI,QAAQ,EAAE,QAAQ;KACnB;IACD;QACE,OAAO,EAAE,qIAAqI;QAC9I,QAAQ,EAAE,8DAA8D;QACxE,YAAY,EAAE,iIAAiI;QAC/I,QAAQ,EAAE,MAAM;KACjB;IACD;QACE,OAAO,EAAE,kDAAkD;QAC3D,QAAQ,EAAE,2EAA2E;QACrF,YAAY,EAAE,qEAAqE;QACnF,QAAQ,EAAE,QAAQ;KACnB;IACD;QACE,OAAO,EAAE,iGAAiG;QAC1G,QAAQ,EAAE,kFAAkF;QAC5F,YAAY,EAAE,qFAAqF;QACnG,QAAQ,EAAE,MAAM;KACjB;CACF,CAAA;AAED,MAAM,UAAU,mBAAmB,CAAC,MAAc;IAChD,MAAM,MAAM,GAAgB,EAAE,CAAA;IAC9B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QACvC,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC;gBACxB,SAAS,EAAE,gBAAgB;gBAC3B,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,gBAAgB,EAAE,IAAI,CAAC,QAAQ,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ;gBAC/D,OAAO,EAAE,aAAa;gBACtB,QAAQ,EAAE,GAAG,IAAI,CAAC,QAAQ,MAAM,KAAK,CAAC,CAAC,CAAC,GAAG;gBAC3C,YAAY,EAAE,IAAI,CAAC,YAAY;aAChC,CAAC,CAAC,CAAA;YACH,MAAK,CAAC,2CAA2C;QACnD,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { detectIdentityBleed } from './detectors/identity-bleed.js';
|
|
2
|
+
import { detectHallucination } from './detectors/hallucination.js';
|
|
3
|
+
export const lyraExtension = {
|
|
4
|
+
name: 'lyra-identity-governance',
|
|
5
|
+
description: 'Detects identity bleed (Lyra claiming to be a generic AI) and hallucination patterns in Lyra/qwen output',
|
|
6
|
+
check(input) {
|
|
7
|
+
const agentRole = input.context?.agent_role?.toLowerCase();
|
|
8
|
+
if (agentRole !== 'lyra')
|
|
9
|
+
return [];
|
|
10
|
+
return [
|
|
11
|
+
...detectIdentityBleed(input.output),
|
|
12
|
+
...detectHallucination(input.output),
|
|
13
|
+
];
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/extensions/lyra/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAA;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAA;AAElE,MAAM,CAAC,MAAM,aAAa,GAAkB;IAC1C,IAAI,EAAE,0BAA0B;IAChC,WAAW,EAAE,0GAA0G;IAEvH,KAAK,CAAC,KAAgB;QACpB,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,CAAA;QAC1D,IAAI,SAAS,KAAK,MAAM;YAAE,OAAO,EAAE,CAAA;QAEnC,OAAO;YACL,GAAG,mBAAmB,CAAC,KAAK,CAAC,MAAM,CAAC;YACpC,GAAG,mBAAmB,CAAC,KAAK,CAAC,MAAM,CAAC;SACrC,CAAA;IACH,CAAC;CACF,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { SealIssue, Verdict } from '../../types.js';
|
|
2
|
+
export type LyraIssueType = 'IDENTITY_BLEED' | 'HALLUCINATION_CLAIM';
|
|
3
|
+
export declare function makeLyraIssue(partial: {
|
|
4
|
+
lyra_type: LyraIssueType;
|
|
5
|
+
severity: SealIssue['severity'];
|
|
6
|
+
required_verdict: Verdict;
|
|
7
|
+
rule_id: string;
|
|
8
|
+
evidence: string;
|
|
9
|
+
required_fix?: string;
|
|
10
|
+
}): SealIssue;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export function makeLyraIssue(partial) {
|
|
2
|
+
return {
|
|
3
|
+
type: 'AMBIGUITY',
|
|
4
|
+
severity: partial.severity,
|
|
5
|
+
is_blocking: partial.severity === 'CRITICAL' || partial.severity === 'HIGH',
|
|
6
|
+
required_verdict: partial.required_verdict,
|
|
7
|
+
evidence: partial.evidence,
|
|
8
|
+
required_fix: partial.required_fix,
|
|
9
|
+
layer: 'EXTENSION',
|
|
10
|
+
rule_id: partial.rule_id,
|
|
11
|
+
source: 'extension',
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=lyra-issue-types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lyra-issue-types.js","sourceRoot":"","sources":["../../../src/extensions/lyra/lyra-issue-types.ts"],"names":[],"mappings":"AAMA,MAAM,UAAU,aAAa,CAAC,OAO7B;IACC,OAAO;QACL,IAAI,EAAE,WAAW;QACjB,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,WAAW,EAAE,OAAO,CAAC,QAAQ,KAAK,UAAU,IAAI,OAAO,CAAC,QAAQ,KAAK,MAAM;QAC3E,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;QAC1C,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,KAAK,EAAE,WAAW;QAClB,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,MAAM,EAAE,WAAW;KACpB,CAAA;AACH,CAAC"}
|