sela-core 1.0.7 β 1.0.9
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/README.md +27 -17
- package/dist/cli/ErrorHandler.d.ts +1 -1
- package/dist/cli/ErrorHandler.js +14 -14
- package/dist/cli/commands/bulk.d.ts +1 -1
- package/dist/cli/commands/bulk.d.ts.map +1 -1
- package/dist/cli/commands/bulk.js +51 -33
- package/dist/cli/commands/init.d.ts +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +26 -18
- package/dist/cli/commands/merge.d.ts +13 -0
- package/dist/cli/commands/merge.d.ts.map +1 -0
- package/dist/cli/commands/merge.js +119 -0
- package/dist/cli/commands/showReport.d.ts +1 -1
- package/dist/cli/commands/showReport.d.ts.map +1 -1
- package/dist/cli/commands/showReport.js +12 -10
- package/dist/cli/commands/status.d.ts +1 -1
- package/dist/cli/commands/status.d.ts.map +1 -1
- package/dist/cli/commands/status.js +8 -8
- package/dist/cli/commands/sync.d.ts +1 -1
- package/dist/cli/commands/sync.d.ts.map +1 -1
- package/dist/cli/commands/sync.js +38 -30
- package/dist/cli/index.js +12 -9
- package/dist/cli/ui/DnaTable.d.ts +1 -1
- package/dist/cli/ui/DnaTable.d.ts.map +1 -1
- package/dist/cli/ui/DnaTable.js +23 -16
- package/dist/cli/ui/RefactorWizard.d.ts +3 -3
- package/dist/cli/ui/RefactorWizard.d.ts.map +1 -1
- package/dist/cli/ui/RefactorWizard.js +108 -82
- package/dist/config/ConfigLoader.d.ts +2 -2
- package/dist/config/ConfigLoader.d.ts.map +1 -1
- package/dist/config/ConfigLoader.js +15 -15
- package/dist/config/DryRunGuard.d.ts +1 -1
- package/dist/config/DryRunGuard.js +7 -7
- package/dist/config/SelaConfig.d.ts +13 -17
- package/dist/config/SelaConfig.d.ts.map +1 -1
- package/dist/config/SelaConfig.js +32 -26
- package/dist/engine/HealingRegistry.d.ts +1 -1
- package/dist/engine/HealingRegistry.js +3 -3
- package/dist/engine/SelaEngine.d.ts +1 -1
- package/dist/engine/SelaEngine.d.ts.map +1 -1
- package/dist/engine/SelaEngine.js +117 -51
- package/dist/errors/SelaError.d.ts +8 -1
- package/dist/errors/SelaError.d.ts.map +1 -1
- package/dist/errors/SelaError.js +14 -7
- package/dist/fixtures/expectProxy.d.ts +2 -2
- package/dist/fixtures/expectProxy.js +16 -16
- package/dist/fixtures/index.d.ts +18 -2
- package/dist/fixtures/index.d.ts.map +1 -1
- package/dist/fixtures/index.js +47 -27
- package/dist/fixtures/moduleExpect.js +7 -7
- package/dist/fixtures/proxyTag.d.ts +1 -1
- package/dist/fixtures/proxyTag.js +4 -4
- package/dist/index.d.ts +8 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -4
- package/dist/reporter/SelaReporter.d.ts +45 -12
- package/dist/reporter/SelaReporter.d.ts.map +1 -1
- package/dist/reporter/SelaReporter.js +139 -39
- package/dist/services/ASTSourceUpdater.d.ts +48 -3
- package/dist/services/ASTSourceUpdater.d.ts.map +1 -1
- package/dist/services/ASTSourceUpdater.js +283 -105
- package/dist/services/AnchorResolver.d.ts +157 -0
- package/dist/services/AnchorResolver.d.ts.map +1 -0
- package/dist/services/AnchorResolver.js +289 -0
- package/dist/services/ArgumentTypeAnalyzer.js +7 -7
- package/dist/services/BlastRadiusAnalyzer.d.ts.map +1 -1
- package/dist/services/BlastRadiusAnalyzer.js +5 -2
- package/dist/services/ChainValidator.js +22 -22
- package/dist/services/CrossFileHealer.js +7 -7
- package/dist/services/DecisionEngine.d.ts +51 -0
- package/dist/services/DecisionEngine.d.ts.map +1 -0
- package/dist/services/DecisionEngine.js +260 -0
- package/dist/services/DefinitionTracer.d.ts +1 -1
- package/dist/services/DefinitionTracer.d.ts.map +1 -1
- package/dist/services/DefinitionTracer.js +28 -13
- package/dist/services/DnaEditorService.d.ts +2 -2
- package/dist/services/DnaEditorService.d.ts.map +1 -1
- package/dist/services/DnaEditorService.js +81 -62
- package/dist/services/DnaIndexService.d.ts +1 -1
- package/dist/services/DnaIndexService.d.ts.map +1 -1
- package/dist/services/DnaIndexService.js +14 -14
- package/dist/services/HealReportService.d.ts +31 -55
- package/dist/services/HealReportService.d.ts.map +1 -1
- package/dist/services/HealReportService.js +864 -1240
- package/dist/services/HealingAdvisory.d.ts +9 -1
- package/dist/services/HealingAdvisory.d.ts.map +1 -1
- package/dist/services/HealingAdvisory.js +9 -1
- package/dist/services/HealingCacheService.d.ts +8 -8
- package/dist/services/HealingCacheService.d.ts.map +1 -1
- package/dist/services/HealingCacheService.js +24 -24
- package/dist/services/HealthReportService.d.ts +1 -1
- package/dist/services/HealthReportService.d.ts.map +1 -1
- package/dist/services/HealthReportService.js +25 -25
- package/dist/services/InitializerUpdater.d.ts.map +1 -1
- package/dist/services/InitializerUpdater.js +12 -2
- package/dist/services/IntentAuditor.d.ts.map +1 -1
- package/dist/services/IntentAuditor.js +32 -21
- package/dist/services/InteractiveReview.d.ts +8 -17
- package/dist/services/InteractiveReview.d.ts.map +1 -1
- package/dist/services/InteractiveReview.js +34 -124
- package/dist/services/LLMService.d.ts +1 -1
- package/dist/services/LLMService.js +16 -16
- package/dist/services/MutationApplier.d.ts +55 -0
- package/dist/services/MutationApplier.d.ts.map +1 -0
- package/dist/services/MutationApplier.js +322 -0
- package/dist/services/PRAutomationService.d.ts +2 -2
- package/dist/services/PRAutomationService.d.ts.map +1 -1
- package/dist/services/PRAutomationService.js +43 -39
- package/dist/services/PendingPromptLedger.d.ts +9 -2
- package/dist/services/PendingPromptLedger.d.ts.map +1 -1
- package/dist/services/PendingPromptLedger.js +31 -6
- package/dist/services/ReportGenerator.d.ts +116 -30
- package/dist/services/ReportGenerator.d.ts.map +1 -1
- package/dist/services/ReportGenerator.js +149 -62
- package/dist/services/ReportMergeService.d.ts +95 -0
- package/dist/services/ReportMergeService.d.ts.map +1 -0
- package/dist/services/ReportMergeService.js +0 -0
- package/dist/services/SafetyGuard.d.ts +4 -7
- package/dist/services/SafetyGuard.d.ts.map +1 -1
- package/dist/services/SafetyGuard.js +29 -106
- package/dist/services/SelectorSanitizer.d.ts +52 -0
- package/dist/services/SelectorSanitizer.d.ts.map +1 -0
- package/dist/services/SelectorSanitizer.js +318 -0
- package/dist/services/SnapshotService.js +6 -6
- package/dist/services/SourceLinkService.d.ts +2 -2
- package/dist/services/SourceLinkService.d.ts.map +1 -1
- package/dist/services/SourceLinkService.js +31 -22
- package/dist/services/SourceUpdater.d.ts +1 -1
- package/dist/services/SourceUpdater.d.ts.map +1 -1
- package/dist/services/SourceUpdater.js +44 -26
- package/dist/services/TemplateDiffService.d.ts.map +1 -1
- package/dist/services/TemplateDiffService.js +18 -15
- package/dist/services/TraceBackEngine.d.ts +67 -0
- package/dist/services/TraceBackEngine.d.ts.map +1 -0
- package/dist/services/TraceBackEngine.js +672 -0
- package/dist/services/WorkspaceSnapshotService.d.ts +6 -6
- package/dist/services/WorkspaceSnapshotService.d.ts.map +1 -1
- package/dist/services/WorkspaceSnapshotService.js +10 -12
- package/dist/types/index.d.ts +1 -1
- package/dist/utils/DOMUtils.d.ts +18 -2
- package/dist/utils/DOMUtils.d.ts.map +1 -1
- package/dist/utils/DOMUtils.js +335 -49
- package/dist/utils/IsolatedDiff.d.ts +2 -2
- package/dist/utils/IsolatedDiff.d.ts.map +1 -1
- package/dist/utils/IsolatedDiff.js +13 -10
- package/package.json +2 -2
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { type HistoricalRun, type ReportData } from "./ReportGenerator.js";
|
|
2
|
+
import { type HealEvent } from "./HealReportService.js";
|
|
3
|
+
export interface MergeOptions {
|
|
4
|
+
/**
|
|
5
|
+
* Explicit shard report files (`sela-report.json` shape, or a bare event
|
|
6
|
+
* array). When empty, the caller is expected to have discovered files via
|
|
7
|
+
* {@link discoverShardFiles}.
|
|
8
|
+
*/
|
|
9
|
+
shardFiles: string[];
|
|
10
|
+
/** Where the merged report + rolling history are written. */
|
|
11
|
+
targetDir: string;
|
|
12
|
+
/**
|
|
13
|
+
* Single dedup key for the merged history row. Defaults to
|
|
14
|
+
* GITHUB_RUN_ID ?? CI_PIPELINE_ID ?? ISO timestamp (resolved by
|
|
15
|
+
* ReportGenerator). Pass explicitly in CI so retries overwrite cleanly.
|
|
16
|
+
*/
|
|
17
|
+
runId?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Number of shards the pipeline launched. When provided and more than the
|
|
20
|
+
* number of readable shard files, the merge is flagged as partial.
|
|
21
|
+
*/
|
|
22
|
+
expectedShards?: number;
|
|
23
|
+
/**
|
|
24
|
+
* Optional logger seam (tests inject a spy). Defaults to console.
|
|
25
|
+
*/
|
|
26
|
+
logger?: {
|
|
27
|
+
warn: (msg: string) => void;
|
|
28
|
+
info: (msg: string) => void;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export interface MergeResult {
|
|
32
|
+
htmlPath: string;
|
|
33
|
+
/** Total events read across all shard files BEFORE dedup. */
|
|
34
|
+
totalEvents: number;
|
|
35
|
+
/** Events surviving content-identity dedup (== payload event count). */
|
|
36
|
+
uniqueEvents: number;
|
|
37
|
+
/** totalEvents - uniqueEvents. */
|
|
38
|
+
duplicatesDropped: number;
|
|
39
|
+
/** Shard files successfully parsed. */
|
|
40
|
+
shardsRead: number;
|
|
41
|
+
/** Shard files that existed/were passed but failed to parse. */
|
|
42
|
+
shardsSkipped: number;
|
|
43
|
+
/** expectedShards echoed back, or null when not supplied. */
|
|
44
|
+
shardsExpected: number | null;
|
|
45
|
+
/** max(0, expectedShards - shardsRead); 0 when not supplied. */
|
|
46
|
+
shardsMissing: number;
|
|
47
|
+
/** True when shardsMissing > 0 β the report is built from partial data. */
|
|
48
|
+
partial: boolean;
|
|
49
|
+
/** Human-readable advisories surfaced during the merge. */
|
|
50
|
+
warnings: string[];
|
|
51
|
+
/** The full computed payload (handy for tests / programmatic callers). */
|
|
52
|
+
data: ReportData;
|
|
53
|
+
}
|
|
54
|
+
export declare class ReportMergeService {
|
|
55
|
+
/**
|
|
56
|
+
* Discover shard report files inside `dir` whose filename matches `glob`.
|
|
57
|
+
* Only a single `*` wildcard is supported (e.g. `sela-shard-*.json`) β we
|
|
58
|
+
* deliberately avoid pulling in a glob dependency. Returns absolute paths,
|
|
59
|
+
* sorted for deterministic ordering.
|
|
60
|
+
*/
|
|
61
|
+
static discoverShardFiles(dir: string, glob?: string): string[];
|
|
62
|
+
/**
|
|
63
|
+
* Content identity for an event. A retried test replayed on a different
|
|
64
|
+
* shard yields an identical identity and is collapsed to one. Timestamp is
|
|
65
|
+
* intentionally EXCLUDED β clock skew across runners must not defeat dedup.
|
|
66
|
+
*/
|
|
67
|
+
static eventIdentity(e: HealEvent): string;
|
|
68
|
+
/**
|
|
69
|
+
* Read one shard file and return its events array.
|
|
70
|
+
* Accepts the `sela-report.json` shape (`{ events: [...] }`) or a bare
|
|
71
|
+
* `HealEvent[]`. Throws SelaError(SHARD_UNREADABLE) on malformed input so
|
|
72
|
+
* the caller can decide whether a single bad shard is fatal (it is not β
|
|
73
|
+
* `merge()` catches and flags it).
|
|
74
|
+
*/
|
|
75
|
+
static readShardEvents(file: string): HealEvent[];
|
|
76
|
+
/**
|
|
77
|
+
* Read the prior rolling history with a STRICT integrity guard.
|
|
78
|
+
* β’ Absent file β [] (first run / clean bootstrap).
|
|
79
|
+
* β’ Present, valid JSON array β the array.
|
|
80
|
+
* β’ Present but NOT a JSON array (corrupt / truncated / wrong shape)
|
|
81
|
+
* β THROW.
|
|
82
|
+
*
|
|
83
|
+
* The throw is the whole point: in the artifact flow the prior history was
|
|
84
|
+
* just downloaded; if it is corrupt we must NOT overwrite the durable copy
|
|
85
|
+
* with a fresh 1-entry window. Aborting forces an operator to look instead
|
|
86
|
+
* of silently destroying the trend.
|
|
87
|
+
*/
|
|
88
|
+
static readPriorHistory(targetDir: string): HistoricalRun[];
|
|
89
|
+
/**
|
|
90
|
+
* Merge N shard reports into a single coherent history row + report.
|
|
91
|
+
* See the file header for the full rationale.
|
|
92
|
+
*/
|
|
93
|
+
static merge(opts: MergeOptions): MergeResult;
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=ReportMergeService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ReportMergeService.d.ts","sourceRoot":"","sources":["../../src/services/ReportMergeService.ts"],"names":[],"mappings":"AAyCA,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,UAAU,EAChB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAqB,KAAK,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAQ3E,MAAM,WAAW,YAAY;IAC3B;;;;OAIG;IACH,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,6DAA6D;IAC7D,SAAS,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;OAEG;IACH,MAAM,CAAC,EAAE;QAAE,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;QAAC,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE,CAAC;CACvE;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,WAAW,EAAE,MAAM,CAAC;IACpB,wEAAwE;IACxE,YAAY,EAAE,MAAM,CAAC;IACrB,kCAAkC;IAClC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,uCAAuC;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,gEAAgE;IAChE,aAAa,EAAE,MAAM,CAAC;IACtB,6DAA6D;IAC7D,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,gEAAgE;IAChE,aAAa,EAAE,MAAM,CAAC;IACtB,2EAA2E;IAC3E,OAAO,EAAE,OAAO,CAAC;IACjB,2DAA2D;IAC3D,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,0EAA0E;IAC1E,IAAI,EAAE,UAAU,CAAC;CAClB;AAMD,qBAAa,kBAAkB;IAC7B;;;;;OAKG;IACH,MAAM,CAAC,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,SAAsB,GAAG,MAAM,EAAE;IAe5E;;;;OAIG;IACH,MAAM,CAAC,aAAa,CAAC,CAAC,EAAE,SAAS,GAAG,MAAM;IAO1C;;;;;;OAMG;IACH,MAAM,CAAC,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE;IA2CjD;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa,EAAE;IAuC3D;;;OAGG;IACH,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,YAAY,GAAG,WAAW;CA6F9C"}
|
|
Binary file
|
|
@@ -11,7 +11,7 @@ export interface HealContext {
|
|
|
11
11
|
}
|
|
12
12
|
export interface AIFixSummary {
|
|
13
13
|
/**
|
|
14
|
-
* Raw AI confidence 0-100. `undefined` when the LLM omitted the field
|
|
14
|
+
* Raw AI confidence 0-100. `undefined` when the LLM omitted the field -
|
|
15
15
|
* SafetyGuard's hard-stop / review-threshold logic treats absence as the
|
|
16
16
|
* conservative worst case (0) so unverified heals are NOT silently let
|
|
17
17
|
* through, while downstream report renderers display "n/a".
|
|
@@ -24,9 +24,9 @@ export interface AIFixSummary {
|
|
|
24
24
|
explanation?: string;
|
|
25
25
|
/** Live innerText of the new selector fetched directly from the browser. */
|
|
26
26
|
liveText?: string;
|
|
27
|
-
/** Baseline text from the DNA snapshot
|
|
27
|
+
/** Baseline text from the DNA snapshot - what the element showed before. */
|
|
28
28
|
dnaBaselineText?: string;
|
|
29
|
-
/** ARIA role from the DNA snapshot
|
|
29
|
+
/** ARIA role from the DNA snapshot - used by the Intent Auditor. */
|
|
30
30
|
dnaRole?: string;
|
|
31
31
|
/** Visibility info captured from the candidate element (new selector). */
|
|
32
32
|
liveVisibility?: VisibilityInfo;
|
|
@@ -51,7 +51,7 @@ export interface SafetyDecision {
|
|
|
51
51
|
* REQUIRES_REVIEW) may omit it.
|
|
52
52
|
*/
|
|
53
53
|
code?: SafetyGuardCode;
|
|
54
|
-
/** Structured info for policy-aware log messages in
|
|
54
|
+
/** Structured info for policy-aware log messages in SelaEngine. */
|
|
55
55
|
meta?: {
|
|
56
56
|
auditorVerdict?: "CONSISTENT" | "SUSPICIOUS" | "INCONSISTENT";
|
|
57
57
|
auditorConfidence?: number;
|
|
@@ -89,9 +89,6 @@ export declare class SafetyGuard {
|
|
|
89
89
|
evaluate(context: HealContext, aiFix: AIFixSummary): Promise<SafetyDecision>;
|
|
90
90
|
private isSemanticOpposite;
|
|
91
91
|
classifyFunctionalRole(text: string): FunctionalRole;
|
|
92
|
-
computeSemanticSimilarity(a: string, b: string): number;
|
|
93
|
-
private levenshteinDistance;
|
|
94
|
-
private jaccardSimilarity;
|
|
95
92
|
}
|
|
96
93
|
export {};
|
|
97
94
|
//# sourceMappingURL=SafetyGuard.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SafetyGuard.d.ts","sourceRoot":"","sources":["../../src/services/SafetyGuard.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACpE,OAAO,EAAsB,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAM1E,MAAM,MAAM,QAAQ,GAAG,WAAW,GAAG,QAAQ,CAAC;AAE9C,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IACrD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oEAAoE;IACpE,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,0EAA0E;IAC1E,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,uEAAuE;IACvE,YAAY,CAAC,EAAE,YAAY,EAAE,CAAC;IAC9B,6DAA6D;IAC7D,WAAW,CAAC,EAAE,UAAU,CAAC;IACzB,4CAA4C;IAC5C,WAAW,CAAC,EAAE,YAAY,EAAE,CAAC;IAC7B,+CAA+C;IAC/C,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB;AAED,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,iBAAiB,GAAG,WAAW,GAAG,SAAS,CAAC;AAE7E,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,SAAS,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,OAAO,CAAC;IACpB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,
|
|
1
|
+
{"version":3,"file":"SafetyGuard.d.ts","sourceRoot":"","sources":["../../src/services/SafetyGuard.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACpE,OAAO,EAAsB,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAM1E,MAAM,MAAM,QAAQ,GAAG,WAAW,GAAG,QAAQ,CAAC;AAE9C,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IACrD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oEAAoE;IACpE,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,0EAA0E;IAC1E,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,uEAAuE;IACvE,YAAY,CAAC,EAAE,YAAY,EAAE,CAAC;IAC9B,6DAA6D;IAC7D,WAAW,CAAC,EAAE,UAAU,CAAC;IACzB,4CAA4C;IAC5C,WAAW,CAAC,EAAE,YAAY,EAAE,CAAC;IAC7B,+CAA+C;IAC/C,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB;AAED,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,iBAAiB,GAAG,WAAW,GAAG,SAAS,CAAC;AAE7E,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,SAAS,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,OAAO,CAAC;IACpB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,mEAAmE;IACnE,IAAI,CAAC,EAAE;QACL,cAAc,CAAC,EAAE,YAAY,GAAG,YAAY,GAAG,cAAc,CAAC;QAC9D,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,qFAAqF;QACrF,mBAAmB,CAAC,EAAE;YACpB,aAAa,EAAE,MAAM,CAAC;YACtB,OAAO,EAAE,MAAM,CAAC;YAChB,KAAK,EAAE,MAAM,CAAC;YACd,kBAAkB,EAAE,MAAM,CAAC;SAC5B,CAAC;KACH,CAAC;CACH;AA4DD,KAAK,cAAc,GACf,QAAQ,GACR,QAAQ,GACR,QAAQ,GACR,UAAU,GACV,MAAM,GACN,iBAAiB,GACjB,iBAAiB,GACjB,SAAS,CAAC;AA6Jd;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC,UAAU,CAAC,EAAE,kBAAkB,CAAC;IAChC,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,UAAU,CAAqB;IAEvC;;;;OAIG;gBACS,GAAG,CAAC,EAAE,kBAAkB,GAAG,kBAAkB;IAMzD,OAAO,CAAC,MAAM,CAAC,aAAa;IAgBtB,QAAQ,CACZ,OAAO,EAAE,WAAW,EACpB,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,cAAc,CAAC;IAyS1B,OAAO,CAAC,kBAAkB;IAwB1B,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc;CAUrD"}
|
|
@@ -10,12 +10,11 @@ const SelaError_1 = require("../errors/SelaError");
|
|
|
10
10
|
const DEFAULT_THRESHOLDS = {
|
|
11
11
|
confidenceHardStop: 85,
|
|
12
12
|
confidenceReviewThreshold: 95,
|
|
13
|
-
assertionSimilarityFloor: 0.7,
|
|
14
13
|
auditorConfidenceMin: 75,
|
|
15
14
|
allowSuspicious: false,
|
|
16
15
|
auditorStrictness: "balanced",
|
|
17
16
|
};
|
|
18
|
-
// Binary semantic opposites
|
|
17
|
+
// Binary semantic opposites - always trigger FAIL_HARD regardless of mode,
|
|
19
18
|
// because they indicate a state inversion (passβfail, successβerror, etc.)
|
|
20
19
|
// that almost certainly masks a real logical regression.
|
|
21
20
|
const SEMANTIC_OPPOSITE_PAIRS = new Set([
|
|
@@ -190,7 +189,7 @@ const ROLE_KEYWORDS = new Map([
|
|
|
190
189
|
],
|
|
191
190
|
]);
|
|
192
191
|
// Pre-compiled word-boundary regexes for the role classifier. Built
|
|
193
|
-
// once at module load
|
|
192
|
+
// once at module load - classifyFunctionalRole() is on the hot heal
|
|
194
193
|
// path, so we don't pay for regex construction per call.
|
|
195
194
|
const ROLE_KEYWORD_REGEXES = Array.from(ROLE_KEYWORDS, ([role, keywords]) => ({
|
|
196
195
|
role,
|
|
@@ -242,7 +241,7 @@ class SafetyGuard {
|
|
|
242
241
|
return {
|
|
243
242
|
level: "FAIL_HARD",
|
|
244
243
|
code: SelaError_1.SAFETY_GUARD_CODES.FAIL_HARD_VISIBILITY_GHOST,
|
|
245
|
-
reason: `Visibility Gate: candidate element is a Ghost (${vis.ghostReason})
|
|
244
|
+
reason: `Visibility Gate: candidate element is a Ghost (${vis.ghostReason}) - ` +
|
|
246
245
|
`functionally absent from the user's perspective`,
|
|
247
246
|
canProceed: false,
|
|
248
247
|
};
|
|
@@ -253,12 +252,12 @@ class SafetyGuard {
|
|
|
253
252
|
return {
|
|
254
253
|
level: "FAIL_HARD",
|
|
255
254
|
code: SelaError_1.SAFETY_GUARD_CODES.FAIL_HARD_VISIBILITY_OCCLUDED,
|
|
256
|
-
reason: `Visibility Gate: candidate element is occluded by an overlay on branch "${context.branch}"
|
|
255
|
+
reason: `Visibility Gate: candidate element is occluded by an overlay on branch "${context.branch}" - ` +
|
|
257
256
|
`hard-fail policy active on main`,
|
|
258
257
|
canProceed: false,
|
|
259
258
|
};
|
|
260
259
|
}
|
|
261
|
-
console.warn(`[SafetyGuard] β οΈ Occlusion detected on branch "${context.branch ?? "unknown"}"
|
|
260
|
+
console.warn(`[SafetyGuard] β οΈ Occlusion detected on branch "${context.branch ?? "unknown"}" - ` +
|
|
262
261
|
`escalating to REQUIRES_REVIEW (not hard-failing on non-main branch)`);
|
|
263
262
|
return {
|
|
264
263
|
level: "REQUIRES_REVIEW",
|
|
@@ -273,7 +272,7 @@ class SafetyGuard {
|
|
|
273
272
|
return {
|
|
274
273
|
level: "BLOCKED",
|
|
275
274
|
code: SelaError_1.SAFETY_GUARD_CODES.BLOCKED_LOW_CONFIDENCE,
|
|
276
|
-
reason: `Confidence too low (${confidence}/100 < ${this.thresholds.confidenceHardStop})
|
|
275
|
+
reason: `Confidence too low (${confidence}/100 < ${this.thresholds.confidenceHardStop}) - refusing to heal`,
|
|
277
276
|
canProceed: false,
|
|
278
277
|
};
|
|
279
278
|
}
|
|
@@ -284,16 +283,18 @@ class SafetyGuard {
|
|
|
284
283
|
//
|
|
285
284
|
// When liveText + dnaBaselineText are both available and differ, we
|
|
286
285
|
// synthesise a contentChange pair and apply the full inversion-check
|
|
287
|
-
// pipeline on it
|
|
286
|
+
// pipeline on it - regardless of what the AI reported.
|
|
288
287
|
//
|
|
289
288
|
// If the AI DID report contentChange we use that (more precise than raw
|
|
290
289
|
// innerText, which may include child element noise).
|
|
291
290
|
let effectiveContentChange = aiFix.contentChange;
|
|
292
|
-
if (!effectiveContentChange &&
|
|
291
|
+
if (!effectiveContentChange &&
|
|
292
|
+
liveText !== undefined &&
|
|
293
|
+
dnaBaselineText !== undefined) {
|
|
293
294
|
const normLive = liveText.trim();
|
|
294
295
|
const normDNA = dnaBaselineText.trim();
|
|
295
296
|
if (normLive !== normDNA && normLive.length > 0 && normDNA.length > 0) {
|
|
296
|
-
console.warn(`[SafetyGuard] π¨ Zero-Trust override
|
|
297
|
+
console.warn(`[SafetyGuard] π¨ Zero-Trust override - AI omitted contentChange but live DOM differs:\n` +
|
|
297
298
|
` DNA baseline : "${normDNA}"\n` +
|
|
298
299
|
` Live text : "${normLive}"`);
|
|
299
300
|
effectiveContentChange = { oldText: normDNA, newText: normLive };
|
|
@@ -301,7 +302,9 @@ class SafetyGuard {
|
|
|
301
302
|
}
|
|
302
303
|
// ββ 3. Structural-only heal (no text change detected) ββββββββ
|
|
303
304
|
if (!effectiveContentChange) {
|
|
304
|
-
const level = confidence < this.thresholds.confidenceReviewThreshold
|
|
305
|
+
const level = confidence < this.thresholds.confidenceReviewThreshold
|
|
306
|
+
? "REQUIRES_REVIEW"
|
|
307
|
+
: "SAFE";
|
|
305
308
|
return {
|
|
306
309
|
level,
|
|
307
310
|
reason: `Structural selector change only (confidence=${confidence})`,
|
|
@@ -313,12 +316,12 @@ class SafetyGuard {
|
|
|
313
316
|
console.log(`[SafetyGuard] π¬ Content change (${source}): "${oldText}" β "${newText}"`);
|
|
314
317
|
// ββ 4. Binary semantic-opposite guard ββββββββββββββββββββββββ
|
|
315
318
|
// Applies in ALL modes: "Enabled"β"Disabled", "Success"β"Error", etc.
|
|
316
|
-
// These always indicate a state inversion
|
|
319
|
+
// These always indicate a state inversion - never safe to auto-heal.
|
|
317
320
|
if (this.isSemanticOpposite(oldText, newText)) {
|
|
318
321
|
return {
|
|
319
322
|
level: "FAIL_HARD",
|
|
320
323
|
code: SelaError_1.SAFETY_GUARD_CODES.FAIL_HARD_SEMANTIC_INVERSION,
|
|
321
|
-
reason: `Semantic inversion detected: "${oldText}" β "${newText}"
|
|
324
|
+
reason: `Semantic inversion detected: "${oldText}" β "${newText}" - ` +
|
|
322
325
|
`state inversions mask logical regressions`,
|
|
323
326
|
canProceed: false,
|
|
324
327
|
};
|
|
@@ -334,30 +337,28 @@ class SafetyGuard {
|
|
|
334
337
|
return {
|
|
335
338
|
level: "FAIL_HARD",
|
|
336
339
|
code: SelaError_1.SAFETY_GUARD_CODES.FAIL_HARD_STATUS_INVERSION,
|
|
337
|
-
reason: `Status inversion: "${oldText}" (${oldRole}) β "${newText}" (${newRole})
|
|
340
|
+
reason: `Status inversion: "${oldText}" (${oldRole}) β "${newText}" (${newRole}) - ` +
|
|
338
341
|
`masking a logic failure is not permitted`,
|
|
339
342
|
canProceed: false,
|
|
340
343
|
};
|
|
341
344
|
}
|
|
342
345
|
// Cross-role swap (e.g. DELETE β CANCEL, SUBMIT β NAVIGATE)
|
|
343
|
-
if (oldRole !== "UNKNOWN" &&
|
|
344
|
-
newRole !== "UNKNOWN" &&
|
|
345
|
-
oldRole !== newRole) {
|
|
346
|
+
if (oldRole !== "UNKNOWN" && newRole !== "UNKNOWN" && oldRole !== newRole) {
|
|
346
347
|
if (mode === "assertion") {
|
|
347
348
|
// Assertion explicitly checked the old functional text; a different
|
|
348
349
|
// function being found is almost certainly a wrong element fix.
|
|
349
350
|
return {
|
|
350
351
|
level: "BLOCKED",
|
|
351
352
|
code: SelaError_1.SAFETY_GUARD_CODES.BLOCKED_ROLE_SWAP_ASSERTION,
|
|
352
|
-
reason: `Functional role swap in assertion: "${oldText}" (${oldRole}) β "${newText}" (${newRole})
|
|
353
|
+
reason: `Functional role swap in assertion: "${oldText}" (${oldRole}) β "${newText}" (${newRole}) - ` +
|
|
353
354
|
`the assertion was verifying a specific functional state`,
|
|
354
355
|
canProceed: false,
|
|
355
356
|
};
|
|
356
357
|
}
|
|
357
|
-
// Action mode: allow with warning
|
|
358
|
+
// Action mode: allow with warning - a UI refactor may rename a control
|
|
358
359
|
// (e.g. "Delete" button renamed "Remove" or merged into a menu)
|
|
359
360
|
console.warn(`[SafetyGuard] β οΈ Functional role change in action: ` +
|
|
360
|
-
`"${oldText}" (${oldRole}) β "${newText}" (${newRole})
|
|
361
|
+
`"${oldText}" (${oldRole}) β "${newText}" (${newRole}) - review recommended`);
|
|
361
362
|
return {
|
|
362
363
|
level: "REQUIRES_REVIEW",
|
|
363
364
|
reason: `Functional role change in action: "${oldText}" (${oldRole}) β "${newText}" (${newRole})`,
|
|
@@ -392,7 +393,7 @@ class SafetyGuard {
|
|
|
392
393
|
return {
|
|
393
394
|
level: "FAIL_HARD",
|
|
394
395
|
code: SelaError_1.SAFETY_GUARD_CODES.FAIL_HARD_AUDITOR_INCONSISTENT,
|
|
395
|
-
reason: `Intent Auditor
|
|
396
|
+
reason: `Intent Auditor - INCONSISTENT: ${auditVerdict.reason}` +
|
|
396
397
|
(auditVerdict.inversionType
|
|
397
398
|
? ` [inversion: ${auditVerdict.inversionType}]`
|
|
398
399
|
: ""),
|
|
@@ -409,23 +410,23 @@ class SafetyGuard {
|
|
|
409
410
|
return {
|
|
410
411
|
level: "BLOCKED",
|
|
411
412
|
code: SelaError_1.SAFETY_GUARD_CODES.BLOCKED_AUDITOR_SUSPICIOUS,
|
|
412
|
-
reason: `Intent Auditor
|
|
413
|
+
reason: `Intent Auditor - SUSPICIOUS in assertion mode: ${auditVerdict.reason}`,
|
|
413
414
|
canProceed: false,
|
|
414
415
|
meta,
|
|
415
416
|
};
|
|
416
417
|
}
|
|
417
418
|
if (this.thresholds.allowSuspicious && mode === "assertion") {
|
|
418
|
-
console.log(`[SafetyGuard] βΉοΈ allowSuspicious=true
|
|
419
|
+
console.log(`[SafetyGuard] βΉοΈ allowSuspicious=true - SUSPICIOUS in assertion mode escalated to REQUIRES_REVIEW`);
|
|
419
420
|
}
|
|
420
421
|
return {
|
|
421
422
|
level: "REQUIRES_REVIEW",
|
|
422
|
-
reason: `Intent Auditor
|
|
423
|
+
reason: `Intent Auditor - SUSPICIOUS in ${mode} mode: ${auditVerdict.reason}`,
|
|
423
424
|
canProceed: true,
|
|
424
425
|
meta,
|
|
425
426
|
};
|
|
426
427
|
}
|
|
427
|
-
// CONSISTENT
|
|
428
|
-
console.log(`[SafetyGuard] β
Intent Auditor
|
|
428
|
+
// CONSISTENT - fall through to confidence tiers
|
|
429
|
+
console.log(`[SafetyGuard] β
Intent Auditor - CONSISTENT (${auditVerdict.confidence}%): ${auditVerdict.reason}`);
|
|
429
430
|
if (auditVerdict.scoreBreakdown) {
|
|
430
431
|
const { rawConfidence, penalty, bonus } = auditVerdict.scoreBreakdown;
|
|
431
432
|
if (penalty !== 0 || bonus !== 0) {
|
|
@@ -440,32 +441,11 @@ class SafetyGuard {
|
|
|
440
441
|
}
|
|
441
442
|
}
|
|
442
443
|
}
|
|
443
|
-
// ββ 8.
|
|
444
|
-
// For same-role pairs (e.g. SUBMITβSUBMIT: "Submit"β"Send") we skip
|
|
445
|
-
// the similarity gate entirely β the role match is sufficient proof
|
|
446
|
-
// of functional equivalence.
|
|
447
|
-
//
|
|
448
|
-
// The gate is only applied when BOTH roles are UNKNOWN in assertion
|
|
449
|
-
// mode, where we have no functional category to fall back on.
|
|
450
|
-
if (mode === "assertion" && oldRole === "UNKNOWN" && newRole === "UNKNOWN") {
|
|
451
|
-
const similarity = this.computeSemanticSimilarity(oldText, newText);
|
|
452
|
-
console.log(`[SafetyGuard] π Similarity: "${oldText}" β "${newText}" = ${(similarity * 100).toFixed(1)}%`);
|
|
453
|
-
if (similarity < this.thresholds.assertionSimilarityFloor) {
|
|
454
|
-
return {
|
|
455
|
-
level: "BLOCKED",
|
|
456
|
-
code: SelaError_1.SAFETY_GUARD_CODES.BLOCKED_SIMILARITY_FLOOR,
|
|
457
|
-
reason: `Text divergence too high in assertion: "${oldText}" β "${newText}" ` +
|
|
458
|
-
`(similarity=${(similarity * 100).toFixed(1)}% < ${(this.thresholds.assertionSimilarityFloor * 100).toFixed(0)}%) β ` +
|
|
459
|
-
`possible content regression`,
|
|
460
|
-
canProceed: false,
|
|
461
|
-
};
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
// ββ 9. Confidence tiers ββββββββββββββββββββββββββββββββββββββ
|
|
444
|
+
// ββ 8. Confidence tiers ββββββββββββββββββββββββββββββββββββββ
|
|
465
445
|
if (confidence < this.thresholds.confidenceReviewThreshold) {
|
|
466
446
|
return {
|
|
467
447
|
level: "REQUIRES_REVIEW",
|
|
468
|
-
reason: `Low-confidence fix (${confidence}/100)
|
|
448
|
+
reason: `Low-confidence fix (${confidence}/100) - tagging for manual review`,
|
|
469
449
|
canProceed: true,
|
|
470
450
|
meta: localAuditMeta,
|
|
471
451
|
};
|
|
@@ -515,62 +495,5 @@ class SafetyGuard {
|
|
|
515
495
|
}
|
|
516
496
|
return "UNKNOWN";
|
|
517
497
|
}
|
|
518
|
-
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
519
|
-
// SEMANTIC SIMILARITY (no external dependencies)
|
|
520
|
-
//
|
|
521
|
-
// Combined score: 0.5 Γ levenshtein_similarity + 0.5 Γ jaccard_similarity
|
|
522
|
-
//
|
|
523
|
-
// Levenshtein captures character-level similarity (typos, abbreviations).
|
|
524
|
-
// Jaccard captures word-level overlap (shared vocabulary, different order).
|
|
525
|
-
// The 50/50 blend is robust against short labels where one metric misleads.
|
|
526
|
-
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
527
|
-
computeSemanticSimilarity(a, b) {
|
|
528
|
-
const na = a.toLowerCase().trim();
|
|
529
|
-
const nb = b.toLowerCase().trim();
|
|
530
|
-
if (na === nb)
|
|
531
|
-
return 1;
|
|
532
|
-
const maxLen = Math.max(na.length, nb.length);
|
|
533
|
-
const levSim = maxLen === 0 ? 1 : 1 - this.levenshteinDistance(na, nb) / maxLen;
|
|
534
|
-
const jaccard = this.jaccardSimilarity(na, nb);
|
|
535
|
-
return 0.5 * levSim + 0.5 * jaccard;
|
|
536
|
-
}
|
|
537
|
-
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
538
|
-
// PRIVATE: Levenshtein distance (space-optimised two-row DP)
|
|
539
|
-
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
540
|
-
levenshteinDistance(a, b) {
|
|
541
|
-
const m = a.length;
|
|
542
|
-
const n = b.length;
|
|
543
|
-
if (m === 0)
|
|
544
|
-
return n;
|
|
545
|
-
if (n === 0)
|
|
546
|
-
return m;
|
|
547
|
-
let prev = Array.from({ length: n + 1 }, (_, i) => i);
|
|
548
|
-
let curr = new Array(n + 1);
|
|
549
|
-
for (let i = 1; i <= m; i++) {
|
|
550
|
-
curr[0] = i;
|
|
551
|
-
for (let j = 1; j <= n; j++) {
|
|
552
|
-
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
553
|
-
curr[j] = Math.min(curr[j - 1] + 1, prev[j] + 1, prev[j - 1] + cost);
|
|
554
|
-
}
|
|
555
|
-
[prev, curr] = [curr, prev];
|
|
556
|
-
}
|
|
557
|
-
return prev[n];
|
|
558
|
-
}
|
|
559
|
-
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
560
|
-
// PRIVATE: Jaccard word-set similarity
|
|
561
|
-
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
562
|
-
jaccardSimilarity(a, b) {
|
|
563
|
-
const setA = new Set(a.split(/\s+/).filter(Boolean));
|
|
564
|
-
const setB = new Set(b.split(/\s+/).filter(Boolean));
|
|
565
|
-
if (setA.size === 0 && setB.size === 0)
|
|
566
|
-
return 1;
|
|
567
|
-
let intersection = 0;
|
|
568
|
-
for (const w of setA) {
|
|
569
|
-
if (setB.has(w))
|
|
570
|
-
intersection++;
|
|
571
|
-
}
|
|
572
|
-
const union = setA.size + setB.size - intersection;
|
|
573
|
-
return union === 0 ? 1 : intersection / union;
|
|
574
|
-
}
|
|
575
498
|
}
|
|
576
499
|
exports.SafetyGuard = SafetyGuard;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* True when `value` is (or contains, in a `>>` chain) a Playwright internal
|
|
3
|
+
* engine selector. These start with the `internal:` engine prefix.
|
|
4
|
+
*/
|
|
5
|
+
export declare function isInternalEngineSelector(value: string): boolean;
|
|
6
|
+
interface MethodDescriptor {
|
|
7
|
+
method: string;
|
|
8
|
+
primaryArg: string;
|
|
9
|
+
options?: Record<string, string | boolean | number>;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Parse a SINGLE internal selector segment into a method descriptor, or null
|
|
13
|
+
* when it is not a recognised internal form (so callers REFUSE rather than
|
|
14
|
+
* guess). Mirrors the engineβpublic mapping used by ASTSourceUpdater.
|
|
15
|
+
*/
|
|
16
|
+
export declare function parseInternalSelector(selector: string): MethodDescriptor | null;
|
|
17
|
+
export declare function buildMethodCall(receiver: string, desc: MethodDescriptor): string;
|
|
18
|
+
/**
|
|
19
|
+
* Translate an internal selector string into an idiomatic Playwright method
|
|
20
|
+
* expression rooted at `receiver`. Handles `>>` chains by chaining each
|
|
21
|
+
* segment. Returns null when ANY segment is an unrecognised internal form
|
|
22
|
+
* (frame `internal:control=β¦` plumbing, unknown engines) β the caller must
|
|
23
|
+
* then refuse rather than emit something fragile.
|
|
24
|
+
*/
|
|
25
|
+
export declare function internalToMethodExpression(selector: string, receiver?: string): string | null;
|
|
26
|
+
/**
|
|
27
|
+
* Convert an internal engine selector into a VALID PUBLIC `.locator()` string,
|
|
28
|
+
* preserving `>>` chaining. Returns null when ANY internal segment has no
|
|
29
|
+
* public string engine (so the caller must method-shift or refuse instead of
|
|
30
|
+
* stuffing an unusable string into a constant).
|
|
31
|
+
*
|
|
32
|
+
* Example: `internal:role=button[name="Update System"i]`
|
|
33
|
+
* β `role=button[name="Update System"]`
|
|
34
|
+
*/
|
|
35
|
+
export declare function internalToPublicSelectorString(selector: string): string | null;
|
|
36
|
+
export interface SanitizeResult {
|
|
37
|
+
/** The (possibly rewritten) expression text. */
|
|
38
|
+
text: string;
|
|
39
|
+
/** True when the original contained an internal selector that was rewritten. */
|
|
40
|
+
sanitized: boolean;
|
|
41
|
+
/** False when an internal selector remained that could NOT be translated. */
|
|
42
|
+
safe: boolean;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Rewrite any `recv.locator("internal:β¦")` / `recv.frameLocator("internal:β¦")`
|
|
46
|
+
* inside `expr` to its idiomatic method form. Returns `safe:false` when an
|
|
47
|
+
* internal selector remains that cannot be translated, so the caller refuses
|
|
48
|
+
* to write it.
|
|
49
|
+
*/
|
|
50
|
+
export declare function sanitizeLocatorExpression(expr: string): SanitizeResult;
|
|
51
|
+
export {};
|
|
52
|
+
//# sourceMappingURL=SelectorSanitizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SelectorSanitizer.d.ts","sourceRoot":"","sources":["../../src/services/SelectorSanitizer.ts"],"names":[],"mappings":"AAoCA;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAK/D;AAMD,UAAU,gBAAgB;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC,CAAC;CACrD;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CA6D/E;AAWD,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,GAAG,MAAM,CAyBhF;AAMD;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,MAAM,EAChB,QAAQ,SAAS,GAChB,MAAM,GAAG,IAAI,CAmBf;AAgDD;;;;;;;;GAQG;AACH,wBAAgB,8BAA8B,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkB9E;AAMD,MAAM,WAAW,cAAc;IAC7B,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,gFAAgF;IAChF,SAAS,EAAE,OAAO,CAAC;IACnB,6EAA6E;IAC7E,IAAI,EAAE,OAAO,CAAC;CACf;AAID;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAgEtE"}
|