sela-core 0.1.0-alpha.3 → 0.1.0-alpha.31

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.
@@ -63,6 +63,10 @@ export declare const SAFETY_GUARD_CODES: {
63
63
  readonly BLOCKED_ROLE_SWAP_ASSERTION: "SG_BLOCKED_ROLE_SWAP_ASSERTION";
64
64
  readonly FAIL_HARD_AUDITOR_INCONSISTENT: "SG_FAIL_HARD_AUDITOR_INCONSISTENT";
65
65
  readonly BLOCKED_AUDITOR_SUSPICIOUS: "SG_BLOCKED_AUDITOR_SUSPICIOUS";
66
+ /** Structural pre-LLM check: old element had a destructive/auth role and
67
+ * the candidate does not — replacing a DELETE/AUTH action is always
68
+ * semantically inconsistent regardless of AI confidence. */
69
+ readonly FAIL_HARD_DESTRUCTIVE_ROLE_INVERSION: "SG_FAIL_HARD_DESTRUCTIVE_ROLE_INVERSION";
66
70
  /**
67
71
  * Heal was REQUIRES_REVIEW → quarantined (decision #1): proposed but not
68
72
  * written to source and not executed this run, pending explicit approval.
@@ -1 +1 @@
1
- {"version":3,"file":"SelaError.d.ts","sourceRoot":"","sources":["../../src/errors/SelaError.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SelaError.d.ts","sourceRoot":"","sources":["../../src/errors/SelaError.ts"],"names":[],"mappings":"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"}
@@ -94,6 +94,10 @@ exports.SAFETY_GUARD_CODES = {
94
94
  BLOCKED_ROLE_SWAP_ASSERTION: "SG_BLOCKED_ROLE_SWAP_ASSERTION",
95
95
  FAIL_HARD_AUDITOR_INCONSISTENT: "SG_FAIL_HARD_AUDITOR_INCONSISTENT",
96
96
  BLOCKED_AUDITOR_SUSPICIOUS: "SG_BLOCKED_AUDITOR_SUSPICIOUS",
97
+ /** Structural pre-LLM check: old element had a destructive/auth role and
98
+ * the candidate does not — replacing a DELETE/AUTH action is always
99
+ * semantically inconsistent regardless of AI confidence. */
100
+ FAIL_HARD_DESTRUCTIVE_ROLE_INVERSION: "SG_FAIL_HARD_DESTRUCTIVE_ROLE_INVERSION",
97
101
  /**
98
102
  * Heal was REQUIRES_REVIEW → quarantined (decision #1): proposed but not
99
103
  * written to source and not executed this run, pending explicit approval.
@@ -115,6 +115,7 @@ export declare class SafetyGuard {
115
115
  constructor(arg?: ResolvedThresholds | SafetyGuardOptions);
116
116
  private static normalizeArgs;
117
117
  evaluate(context: HealContext, aiFix: AIFixSummary): Promise<SafetyDecision>;
118
+ private applyTextDriftGuard;
118
119
  classifyFunctionalRole(text: string): FunctionalRole;
119
120
  }
120
121
  //# sourceMappingURL=SafetyGuard.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SafetyGuard.d.ts","sourceRoot":"","sources":["../../src/services/SafetyGuard.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SafetyGuard.d.ts","sourceRoot":"","sources":["../../src/services/SafetyGuard.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,7 @@ const IntentAuditor_1 = require("./IntentAuditor");
7
7
  const PipelineContext_1 = require("./safety/PipelineContext");
8
8
  const rules_1 = require("./safety/rules");
9
9
  const roleClassifier_1 = require("./safety/roleClassifier");
10
+ const logger_1 = require("../utils/logger");
10
11
  function dispositionFor(level) {
11
12
  switch (level) {
12
13
  case "SAFE":
@@ -61,6 +62,24 @@ class SafetyGuard {
61
62
  // ─────────────────────────────────────────────────────────────
62
63
  async evaluate(context, aiFix) {
63
64
  const ctx = (0, PipelineContext_1.buildContext)(context, aiFix, this.thresholds, this.intentAuditor);
65
+ // ── Text-Drift Pre-Flight ─────────────────────────────────────
66
+ // Compare DNA baseline text vs live candidate text BEFORE any rule
67
+ // runs. This is the primary defence against the "Delete System →
68
+ // Update System same-container mis-identification" class of bug:
69
+ //
70
+ // 1. Drift confirmed (both texts present, differ):
71
+ // synthesise effectiveContentChange so StructuralOnlyRule
72
+ // cannot short-circuit to SAFE, and set forceAudit so the
73
+ // Intent Auditor is mandatory regardless of confidence.
74
+ //
75
+ // 2. Drift unverifiable (DNA text present but liveText absent
76
+ // AND AI did not self-report a contentChange):
77
+ // set forceAudit so StructuralOnlyRule downgrades SAFE → HOLD.
78
+ //
79
+ // This guard runs once, synchronously, before the rule loop.
80
+ // ZeroTrustRule (step 2) may re-derive effectiveContentChange from
81
+ // the same inputs; that is harmless — it will set the same value.
82
+ this.applyTextDriftGuard(ctx, aiFix);
64
83
  for (const rule of rules_1.SAFETY_RULES) {
65
84
  const decision = await rule.run(ctx);
66
85
  if (decision) {
@@ -73,6 +92,28 @@ class SafetyGuard {
73
92
  // Unreachable: ConfidenceTierRule is terminal and always decides.
74
93
  throw new Error("[SafetyGuard] rule pipeline exhausted without a decision - this is a bug");
75
94
  }
95
+ applyTextDriftGuard(ctx, aiFix) {
96
+ const dnaText = aiFix.dnaBaselineText?.trim();
97
+ const liveText = aiFix.liveText?.trim();
98
+ if (dnaText && liveText && dnaText !== liveText) {
99
+ // Drift confirmed — synthesise contentChange if ZeroTrustRule has not
100
+ // yet run (it will run next and will produce the same pair; no conflict).
101
+ if (!ctx.effectiveContentChange) {
102
+ ctx.effectiveContentChange = { oldText: dnaText, newText: liveText };
103
+ }
104
+ ctx.forceAudit = true;
105
+ logger_1.logger.warn(`SafetyGuard text-drift pre-flight: DNA="${dnaText}" ≠ live="${liveText}" — ` +
106
+ `forceAudit=true, Intent Auditor is mandatory`);
107
+ }
108
+ else if (dnaText && !liveText && !aiFix.contentChange) {
109
+ // Cannot verify: DNA baseline exists but live text could not be fetched
110
+ // and the AI did not self-report a contentChange. Conservative stance:
111
+ // force a hold so StructuralOnlyRule cannot silently approve as SAFE.
112
+ ctx.forceAudit = true;
113
+ logger_1.logger.warn(`SafetyGuard text-drift pre-flight: liveText unavailable, ` +
114
+ `DNA="${dnaText}" unverified — forceAudit=true`);
115
+ }
116
+ }
76
117
  // ─────────────────────────────────────────────────────────────
77
118
  // FUNCTIONAL ROLE CLASSIFICATION (public for tests / external use)
78
119
  //
@@ -1,10 +1,18 @@
1
1
  import type { FunctionalRole } from "../roleClassifier";
2
2
  import type { SafetyRule } from "../PipelineContext";
3
3
  /**
4
- * Roles whose ARRIVAL is treated as high-risk: a control that did not
5
- * obviously mean "delete" or "authenticate" before, but now does.
4
+ * Roles whose arrival OR departure is treated as high-risk.
6
5
  */
7
6
  export declare const DANGEROUS_SINK_ROLES: ReadonlySet<FunctionalRole>;
7
+ /** Transition INTO a dangerous role (e.g. UNKNOWN → DELETE). */
8
8
  export declare function isDangerousSinkTransition(oldRole: FunctionalRole, newRole: FunctionalRole): boolean;
9
+ /**
10
+ * Transition OUT OF a dangerous role (e.g. DELETE → UNKNOWN / SUBMIT).
11
+ *
12
+ * Replacing a destructive/auth control with any other role is semantically
13
+ * inconsistent: the test was authored against a destructive action and the
14
+ * proposed candidate performs a different operation.
15
+ */
16
+ export declare function isDangerousSourceTransition(oldRole: FunctionalRole, newRole: FunctionalRole): boolean;
9
17
  export declare const DangerousSinkRule: SafetyRule;
10
18
  //# sourceMappingURL=DangerousSinkRule.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"DangerousSinkRule.d.ts","sourceRoot":"","sources":["../../../../src/services/safety/rules/DangerousSinkRule.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD,OAAO,KAAK,EAAE,UAAU,EAAqC,MAAM,oBAAoB,CAAC;AAExF;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,WAAW,CAAC,cAAc,CAG3D,CAAC;AAEH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,cAAc,GACtB,OAAO,CAET;AAED,eAAO,MAAM,iBAAiB,EAAE,UAmB/B,CAAC"}
1
+ {"version":3,"file":"DangerousSinkRule.d.ts","sourceRoot":"","sources":["../../../../src/services/safety/rules/DangerousSinkRule.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD,OAAO,KAAK,EAAE,UAAU,EAAqC,MAAM,oBAAoB,CAAC;AAExF;;GAEG;AACH,eAAO,MAAM,oBAAoB,EAAE,WAAW,CAAC,cAAc,CAG3D,CAAC;AAEH,gEAAgE;AAChE,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,cAAc,GACtB,OAAO,CAET;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,cAAc,GACtB,OAAO,CAET;AAED,eAAO,MAAM,iBAAiB,EAAE,UA4B/B,CAAC"}
@@ -1,40 +1,55 @@
1
1
  "use strict";
2
2
  // src/services/safety/rules/DangerousSinkRule.ts
3
3
  //
4
- // Step 5.5 - Dangerous-Sink escalation (context-mutator, returns null).
4
+ // Step 5.5 - Dangerous-Sink / Dangerous-Source escalation (context-mutator,
5
+ // returns null).
5
6
  //
6
- // Closes the headline blind spot from the incident: a heal that transitions
7
- // INTO a destructive or auth role (e.g. "Update System"(UNKNOWN) →
8
- // "delete System"(DELETE)) sailed through as SAFE because:
9
- // - the cross-role swap rule (step 5) only fires when BOTH roles are known,
10
- // - the auditor gate (step 6) only fired for zero-trust / assertion /
11
- // both-UNKNOWN, none of which matched.
7
+ // Closes two related blind spots:
8
+ //
9
+ // SINK (X DELETE/AUTH): a control that did not obviously mean "delete"
10
+ // or "authenticate" before, but now does. The cross-role swap rule
11
+ // (step 5) only fires when BOTH roles are known; this catches
12
+ // UNKNOWN DELETE.
13
+ //
14
+ // SOURCE (DELETE/AUTH → X): replacing a destructive/auth control with a
15
+ // non-destructive one (e.g. "Delete System" → "Update System")
16
+ // is equally dangerous — it masks the test's original destructive
17
+ // intent. FunctionalRoleRule misses this because newRole=UNKNOWN
18
+ // fails its "both roles known" guard.
12
19
  //
13
20
  // Per design decision #2, this rule does NOT decide on its own; it FORCES
14
- // the Intent Auditor to run (ctx.forceAudit = true) whenever the new role is
15
- // a dangerous sink and differs from the old role. The auditor's existing
21
+ // the Intent Auditor to run (ctx.forceAudit = true). The auditor's existing
16
22
  // verdict mapping then applies: INCONSISTENT → FAIL_HARD, SUSPICIOUS →
17
- // BLOCKED/REQUIRES_REVIEW, CONSISTENT → continue.
18
- //
19
- // Note on coverage: a swap between two KNOWN roles (e.g. SUBMIT → DELETE)
20
- // is already short-circuited by FunctionalRoleRule before reaching here, so
21
- // in practice this rule fires for the UNKNOWN→sink case it was built for.
23
+ // BLOCKED/REQUIRES_REVIEW, CONSISTENT → continue. In practice the
24
+ // pre-LLM structural check in IntentAuditorRule will FAIL_HARD immediately
25
+ // for SOURCE transitions before the LLM is even consulted.
22
26
  Object.defineProperty(exports, "__esModule", { value: true });
23
27
  exports.DangerousSinkRule = exports.DANGEROUS_SINK_ROLES = void 0;
24
28
  exports.isDangerousSinkTransition = isDangerousSinkTransition;
29
+ exports.isDangerousSourceTransition = isDangerousSourceTransition;
25
30
  const roleClassifier_1 = require("../roleClassifier");
26
31
  const logger_1 = require("../../../utils/logger");
27
32
  /**
28
- * Roles whose ARRIVAL is treated as high-risk: a control that did not
29
- * obviously mean "delete" or "authenticate" before, but now does.
33
+ * Roles whose arrival OR departure is treated as high-risk.
30
34
  */
31
35
  exports.DANGEROUS_SINK_ROLES = new Set([
32
36
  "DELETE",
33
37
  "AUTH",
34
38
  ]);
39
+ /** Transition INTO a dangerous role (e.g. UNKNOWN → DELETE). */
35
40
  function isDangerousSinkTransition(oldRole, newRole) {
36
41
  return exports.DANGEROUS_SINK_ROLES.has(newRole) && newRole !== oldRole;
37
42
  }
43
+ /**
44
+ * Transition OUT OF a dangerous role (e.g. DELETE → UNKNOWN / SUBMIT).
45
+ *
46
+ * Replacing a destructive/auth control with any other role is semantically
47
+ * inconsistent: the test was authored against a destructive action and the
48
+ * proposed candidate performs a different operation.
49
+ */
50
+ function isDangerousSourceTransition(oldRole, newRole) {
51
+ return exports.DANGEROUS_SINK_ROLES.has(oldRole) && newRole !== oldRole;
52
+ }
38
53
  exports.DangerousSinkRule = {
39
54
  id: "dangerous-sink-escalation",
40
55
  run(ctx) {
@@ -48,6 +63,12 @@ exports.DangerousSinkRule = {
48
63
  `forcing Intent Auditor`);
49
64
  ctx.forceAudit = true;
50
65
  }
66
+ if (isDangerousSourceTransition(oldRole, newRole)) {
67
+ logger_1.logger.warn(`SafetyGuard dangerous-source transition: ` +
68
+ `"${ctx.oldText}" (${oldRole}) → "${ctx.newText}" (${newRole}) - ` +
69
+ `outbound from destructive role, forcing Intent Auditor`);
70
+ ctx.forceAudit = true;
71
+ }
51
72
  return null;
52
73
  },
53
74
  };
@@ -1 +1 @@
1
- {"version":3,"file":"IntentAuditorRule.d.ts","sourceRoot":"","sources":["../../../../src/services/safety/rules/IntentAuditorRule.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,UAAU,EAAqC,MAAM,oBAAoB,CAAC;AAExF,eAAO,MAAM,iBAAiB,EAAE,UAoG/B,CAAC"}
1
+ {"version":3,"file":"IntentAuditorRule.d.ts","sourceRoot":"","sources":["../../../../src/services/safety/rules/IntentAuditorRule.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,UAAU,EAAqC,MAAM,oBAAoB,CAAC;AAExF,eAAO,MAAM,iBAAiB,EAAE,UAoI/B,CAAC"}
@@ -5,18 +5,25 @@
5
5
  // LLM auditor when:
6
6
  // a) zero-trust synthesized the contentChange (AI silent → extra scrutiny), OR
7
7
  // b) we are in assertion mode (the test explicitly checked the text), OR
8
- // c) both roles are UNKNOWN (no functional category to fall back on).
8
+ // c) both roles are UNKNOWN (no functional category to fall back on), OR
9
+ // d) forceAudit was set by the text-drift pre-flight or DangerousSinkRule.
10
+ //
11
+ // PRE-LLM STRUCTURAL CHECK (runs before shouldAudit):
12
+ // Transitioning OUT of a destructive/auth role into any non-destructive role
13
+ // is always semantically inconsistent — the test was authored against a
14
+ // DELETE/AUTH action and the candidate performs a different operation. This
15
+ // is caught here rather than relying solely on the LLM auditor because the
16
+ // LLM can return CONSISTENT for superficially similar labels (e.g. "Delete
17
+ // System" → "Update System" sharing the same container at 95% confidence).
9
18
  //
10
19
  // INCONSISTENT → FAIL_HARD. SUSPICIOUS → BLOCKED in assertion (unless
11
20
  // allowSuspicious) else REQUIRES_REVIEW. CONSISTENT → fall through,
12
21
  // stashing the auditor score breakdown on the context for the final tier.
13
- //
14
- // Extracted verbatim - identical trigger condition, reasons, codes,
15
- // logs, and meta shape.
16
22
  Object.defineProperty(exports, "__esModule", { value: true });
17
23
  exports.IntentAuditorRule = void 0;
18
24
  const SelaError_1 = require("../../../errors/SelaError");
19
25
  const logger_1 = require("../../../utils/logger");
26
+ const DangerousSinkRule_1 = require("./DangerousSinkRule");
20
27
  exports.IntentAuditorRule = {
21
28
  id: "intent-auditor-gate",
22
29
  async run(ctx) {
@@ -24,6 +31,31 @@ exports.IntentAuditorRule = {
24
31
  const newText = ctx.newText;
25
32
  const oldRole = ctx.oldRole;
26
33
  const newRole = ctx.newRole;
34
+ // ── Pre-LLM structural check: destructive role inversion ─────────
35
+ // When the DNA element had a destructive/auth role and the candidate does
36
+ // NOT, reject immediately without consulting the LLM. AI confidence is
37
+ // irrelevant — no valid heal should replace a DELETE/AUTH control with a
38
+ // non-destructive one. The LLM can return CONSISTENT for "Delete System →
39
+ // Update System" because both appear in the same container; this pure-code
40
+ // gate closes that bypass regardless of the shouldAudit flag below.
41
+ if (DangerousSinkRule_1.DANGEROUS_SINK_ROLES.has(oldRole) &&
42
+ !DangerousSinkRule_1.DANGEROUS_SINK_ROLES.has(newRole)) {
43
+ logger_1.logger.warn(`SafetyGuard destructive role inversion (pre-LLM): ` +
44
+ `"${oldText}" (${oldRole}) → "${newText}" (${newRole}) - FAIL_HARD`);
45
+ return {
46
+ level: "FAIL_HARD",
47
+ code: SelaError_1.SAFETY_GUARD_CODES.FAIL_HARD_DESTRUCTIVE_ROLE_INVERSION,
48
+ reason: `Destructive role inversion: "${oldText}" (${oldRole}) → "${newText}" (${newRole}) — ` +
49
+ `replacing a ${oldRole} action is semantically inconsistent regardless of confidence`,
50
+ canProceed: false,
51
+ meta: {
52
+ auditorVerdict: "INCONSISTENT",
53
+ auditorConfidence: 100,
54
+ auditorReason: `Source role ${oldRole} is destructive/auth; ` +
55
+ `candidate role ${newRole} is not — structural semantic mismatch`,
56
+ },
57
+ };
58
+ }
27
59
  const shouldAudit = ctx.forceAudit === true ||
28
60
  ctx.source === "zero-trust" ||
29
61
  ctx.mode === "assertion" ||
@@ -1 +1 @@
1
- {"version":3,"file":"StructuralOnlyRule.d.ts","sourceRoot":"","sources":["../../../../src/services/safety/rules/StructuralOnlyRule.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,UAAU,EAAqC,MAAM,oBAAoB,CAAC;AAExF,eAAO,MAAM,kBAAkB,EAAE,UAyBhC,CAAC"}
1
+ {"version":3,"file":"StructuralOnlyRule.d.ts","sourceRoot":"","sources":["../../../../src/services/safety/rules/StructuralOnlyRule.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,UAAU,EAAqC,MAAM,oBAAoB,CAAC;AAExF,eAAO,MAAM,kBAAkB,EAAE,UAwChC,CAAC"}
@@ -19,6 +19,19 @@ exports.StructuralOnlyRule = {
19
19
  id: "structural-only-heal",
20
20
  run(ctx) {
21
21
  if (!ctx.effectiveContentChange) {
22
+ // Text-drift pre-flight set forceAudit because live text was unavailable
23
+ // and we cannot verify the candidate has the same text as the DNA
24
+ // baseline. Approving as SAFE here would bypass every downstream guard
25
+ // (semantic-opposite, functional-role, intent-auditor). Downgrade to
26
+ // REQUIRES_REVIEW (HOLD) so the heal is quarantined pending manual review.
27
+ if (ctx.forceAudit) {
28
+ return {
29
+ level: "REQUIRES_REVIEW",
30
+ reason: `Text drift unverifiable: DNA baseline present but live text unavailable ` +
31
+ `— cannot approve as structural-only (confidence=${ctx.confidence})`,
32
+ canProceed: true,
33
+ };
34
+ }
22
35
  const level = ctx.confidence < ctx.thresholds.confidenceReviewThreshold
23
36
  ? "REQUIRES_REVIEW"
24
37
  : "SAFE";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sela-core",
3
- "version": "0.1.0-alpha.3",
3
+ "version": "0.1.0-alpha.31",
4
4
  "description": "AI self-healing Playwright wrapper - drop-in replacement for @playwright/test",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",