sela-core 0.1.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +103 -0
- package/bin/sela.js +3 -0
- package/dist/cli/ErrorHandler.d.ts +10 -0
- package/dist/cli/ErrorHandler.d.ts.map +1 -0
- package/dist/cli/ErrorHandler.js +70 -0
- package/dist/cli/commands/bulk.d.ts +3 -0
- package/dist/cli/commands/bulk.d.ts.map +1 -0
- package/dist/cli/commands/bulk.js +158 -0
- package/dist/cli/commands/find.d.ts +3 -0
- package/dist/cli/commands/find.d.ts.map +1 -0
- package/dist/cli/commands/find.js +51 -0
- package/dist/cli/commands/init.d.ts +3 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +166 -0
- package/dist/cli/commands/list.d.ts +3 -0
- package/dist/cli/commands/list.d.ts.map +1 -0
- package/dist/cli/commands/list.js +56 -0
- 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/refactor.d.ts +3 -0
- package/dist/cli/commands/refactor.d.ts.map +1 -0
- package/dist/cli/commands/refactor.js +30 -0
- package/dist/cli/commands/showReport.d.ts +3 -0
- package/dist/cli/commands/showReport.d.ts.map +1 -0
- package/dist/cli/commands/showReport.js +82 -0
- package/dist/cli/commands/status.d.ts +3 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/status.js +51 -0
- package/dist/cli/commands/sync.d.ts +3 -0
- package/dist/cli/commands/sync.d.ts.map +1 -0
- package/dist/cli/commands/sync.js +131 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +94 -0
- package/dist/cli/ui/DnaTable.d.ts +3 -0
- package/dist/cli/ui/DnaTable.d.ts.map +1 -0
- package/dist/cli/ui/DnaTable.js +77 -0
- package/dist/cli/ui/LocatorPicker.d.ts +8 -0
- package/dist/cli/ui/LocatorPicker.d.ts.map +1 -0
- package/dist/cli/ui/LocatorPicker.js +33 -0
- package/dist/cli/ui/ProgressReporter.d.ts +11 -0
- package/dist/cli/ui/ProgressReporter.d.ts.map +1 -0
- package/dist/cli/ui/ProgressReporter.js +33 -0
- package/dist/cli/ui/RefactorWizard.d.ts +26 -0
- package/dist/cli/ui/RefactorWizard.d.ts.map +1 -0
- package/dist/cli/ui/RefactorWizard.js +295 -0
- package/dist/config/ConfigLoader.d.ts +16 -0
- package/dist/config/ConfigLoader.d.ts.map +1 -0
- package/dist/config/ConfigLoader.js +185 -0
- package/dist/config/DryRunGuard.d.ts +14 -0
- package/dist/config/DryRunGuard.d.ts.map +1 -0
- package/dist/config/DryRunGuard.js +80 -0
- package/dist/config/PathScopeGuard.d.ts +42 -0
- package/dist/config/PathScopeGuard.d.ts.map +1 -0
- package/dist/config/PathScopeGuard.js +192 -0
- package/dist/config/SelaConfig.d.ts +178 -0
- package/dist/config/SelaConfig.d.ts.map +1 -0
- package/dist/config/SelaConfig.js +141 -0
- package/dist/config/defineConfig.d.ts +3 -0
- package/dist/config/defineConfig.d.ts.map +1 -0
- package/dist/config/defineConfig.js +9 -0
- package/dist/engine/FixwrightEngine.d.ts +24 -0
- package/dist/engine/FixwrightEngine.d.ts.map +1 -0
- package/dist/engine/FixwrightEngine.js +403 -0
- package/dist/engine/HealingRegistry.d.ts +40 -0
- package/dist/engine/HealingRegistry.d.ts.map +1 -0
- package/dist/engine/HealingRegistry.js +99 -0
- package/dist/engine/SelaEngine.d.ts +57 -0
- package/dist/engine/SelaEngine.d.ts.map +1 -0
- package/dist/engine/SelaEngine.js +1146 -0
- package/dist/engine/singleton.d.ts +3 -0
- package/dist/engine/singleton.d.ts.map +1 -0
- package/dist/engine/singleton.js +5 -0
- package/dist/errors/SelaError.d.ts +146 -0
- package/dist/errors/SelaError.d.ts.map +1 -0
- package/dist/errors/SelaError.js +168 -0
- package/dist/fixtures/expectProxy.d.ts +12 -0
- package/dist/fixtures/expectProxy.d.ts.map +1 -0
- package/dist/fixtures/expectProxy.js +246 -0
- package/dist/fixtures/index.d.ts +30 -0
- package/dist/fixtures/index.d.ts.map +1 -0
- package/dist/fixtures/index.js +765 -0
- package/dist/fixtures/moduleExpect.d.ts +2 -0
- package/dist/fixtures/moduleExpect.d.ts.map +1 -0
- package/dist/fixtures/moduleExpect.js +54 -0
- package/dist/fixtures/proxyTag.d.ts +12 -0
- package/dist/fixtures/proxyTag.d.ts.map +1 -0
- package/dist/fixtures/proxyTag.js +45 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/reporter/SelaReporter.d.ts +165 -0
- package/dist/reporter/SelaReporter.d.ts.map +1 -0
- package/dist/reporter/SelaReporter.js +517 -0
- package/dist/services/ASTSourceUpdater.d.ts +143 -0
- package/dist/services/ASTSourceUpdater.d.ts.map +1 -0
- package/dist/services/ASTSourceUpdater.js +3514 -0
- 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.d.ts +26 -0
- package/dist/services/ArgumentTypeAnalyzer.d.ts.map +1 -0
- package/dist/services/ArgumentTypeAnalyzer.js +92 -0
- package/dist/services/BlastRadiusAnalyzer.d.ts +15 -0
- package/dist/services/BlastRadiusAnalyzer.d.ts.map +1 -0
- package/dist/services/BlastRadiusAnalyzer.js +107 -0
- package/dist/services/ChainValidator.d.ts +76 -0
- package/dist/services/ChainValidator.d.ts.map +1 -0
- package/dist/services/ChainValidator.js +570 -0
- package/dist/services/CrossFileHealer.d.ts +6 -0
- package/dist/services/CrossFileHealer.d.ts.map +1 -0
- package/dist/services/CrossFileHealer.js +135 -0
- 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 +41 -0
- package/dist/services/DefinitionTracer.d.ts.map +1 -0
- package/dist/services/DefinitionTracer.js +366 -0
- package/dist/services/DnaEditorService.d.ts +31 -0
- package/dist/services/DnaEditorService.d.ts.map +1 -0
- package/dist/services/DnaEditorService.js +217 -0
- package/dist/services/DnaIndexService.d.ts +24 -0
- package/dist/services/DnaIndexService.d.ts.map +1 -0
- package/dist/services/DnaIndexService.js +131 -0
- package/dist/services/HealBudget.d.ts +32 -0
- package/dist/services/HealBudget.d.ts.map +1 -0
- package/dist/services/HealBudget.js +85 -0
- package/dist/services/HealReportService.d.ts +161 -0
- package/dist/services/HealReportService.d.ts.map +1 -0
- package/dist/services/HealReportService.js +1039 -0
- package/dist/services/HealingAdvisory.d.ts +30 -0
- package/dist/services/HealingAdvisory.d.ts.map +1 -0
- package/dist/services/HealingAdvisory.js +51 -0
- package/dist/services/HealingCacheService.d.ts +135 -0
- package/dist/services/HealingCacheService.d.ts.map +1 -0
- package/dist/services/HealingCacheService.js +404 -0
- package/dist/services/HealthReportService.d.ts +10 -0
- package/dist/services/HealthReportService.d.ts.map +1 -0
- package/dist/services/HealthReportService.js +84 -0
- package/dist/services/InitializerUpdater.d.ts +16 -0
- package/dist/services/InitializerUpdater.d.ts.map +1 -0
- package/dist/services/InitializerUpdater.js +73 -0
- package/dist/services/IntentAuditor.d.ts +56 -0
- package/dist/services/IntentAuditor.d.ts.map +1 -0
- package/dist/services/IntentAuditor.js +326 -0
- package/dist/services/InteractiveReview.d.ts +15 -0
- package/dist/services/InteractiveReview.d.ts.map +1 -0
- package/dist/services/InteractiveReview.js +128 -0
- package/dist/services/LLMService.d.ts +121 -0
- package/dist/services/LLMService.d.ts.map +1 -0
- package/dist/services/LLMService.js +475 -0
- package/dist/services/MutationApplier.d.ts +69 -0
- package/dist/services/MutationApplier.d.ts.map +1 -0
- package/dist/services/MutationApplier.js +360 -0
- package/dist/services/PRAutomationService.d.ts +50 -0
- package/dist/services/PRAutomationService.d.ts.map +1 -0
- package/dist/services/PRAutomationService.js +760 -0
- package/dist/services/PendingPromptLedger.d.ts +51 -0
- package/dist/services/PendingPromptLedger.d.ts.map +1 -0
- package/dist/services/PendingPromptLedger.js +205 -0
- package/dist/services/ReportGenerator.d.ts +156 -0
- package/dist/services/ReportGenerator.d.ts.map +1 -0
- package/dist/services/ReportGenerator.js +278 -0
- 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 +112 -0
- package/dist/services/SafetyGuard.d.ts.map +1 -0
- package/dist/services/SafetyGuard.js +87 -0
- package/dist/services/Sanitizer.d.ts +28 -0
- package/dist/services/Sanitizer.d.ts.map +1 -0
- package/dist/services/Sanitizer.js +142 -0
- package/dist/services/SanitizingAnthropic.d.ts +19 -0
- package/dist/services/SanitizingAnthropic.d.ts.map +1 -0
- package/dist/services/SanitizingAnthropic.js +84 -0
- 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.d.ts +11 -0
- package/dist/services/SnapshotService.d.ts.map +1 -0
- package/dist/services/SnapshotService.js +352 -0
- package/dist/services/SourceLinkService.d.ts +26 -0
- package/dist/services/SourceLinkService.d.ts.map +1 -0
- package/dist/services/SourceLinkService.js +165 -0
- package/dist/services/SourceUpdater.d.ts +45 -0
- package/dist/services/SourceUpdater.d.ts.map +1 -0
- package/dist/services/SourceUpdater.js +1091 -0
- package/dist/services/TemplateDiffService.d.ts +25 -0
- package/dist/services/TemplateDiffService.d.ts.map +1 -0
- package/dist/services/TemplateDiffService.js +334 -0
- 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 +71 -0
- package/dist/services/WorkspaceSnapshotService.d.ts.map +1 -0
- package/dist/services/WorkspaceSnapshotService.js +200 -0
- package/dist/services/safety/PipelineContext.d.ts +63 -0
- package/dist/services/safety/PipelineContext.d.ts.map +1 -0
- package/dist/services/safety/PipelineContext.js +34 -0
- package/dist/services/safety/roleClassifier.d.ts +4 -0
- package/dist/services/safety/roleClassifier.d.ts.map +1 -0
- package/dist/services/safety/roleClassifier.js +233 -0
- package/dist/services/safety/rules/ConfidenceTierRule.d.ts +3 -0
- package/dist/services/safety/rules/ConfidenceTierRule.d.ts.map +1 -0
- package/dist/services/safety/rules/ConfidenceTierRule.js +32 -0
- package/dist/services/safety/rules/DangerousSinkRule.d.ts +10 -0
- package/dist/services/safety/rules/DangerousSinkRule.d.ts.map +1 -0
- package/dist/services/safety/rules/DangerousSinkRule.js +53 -0
- package/dist/services/safety/rules/FunctionalRoleRule.d.ts +3 -0
- package/dist/services/safety/rules/FunctionalRoleRule.d.ts.map +1 -0
- package/dist/services/safety/rules/FunctionalRoleRule.js +64 -0
- package/dist/services/safety/rules/HardConfidenceRule.d.ts +3 -0
- package/dist/services/safety/rules/HardConfidenceRule.d.ts.map +1 -0
- package/dist/services/safety/rules/HardConfidenceRule.js +22 -0
- package/dist/services/safety/rules/IntentAuditorRule.d.ts +3 -0
- package/dist/services/safety/rules/IntentAuditorRule.d.ts.map +1 -0
- package/dist/services/safety/rules/IntentAuditorRule.js +97 -0
- package/dist/services/safety/rules/SemanticOppositeRule.d.ts +3 -0
- package/dist/services/safety/rules/SemanticOppositeRule.d.ts.map +1 -0
- package/dist/services/safety/rules/SemanticOppositeRule.js +30 -0
- package/dist/services/safety/rules/StructuralOnlyRule.d.ts +3 -0
- package/dist/services/safety/rules/StructuralOnlyRule.d.ts.map +1 -0
- package/dist/services/safety/rules/StructuralOnlyRule.js +38 -0
- package/dist/services/safety/rules/VisibilityRule.d.ts +3 -0
- package/dist/services/safety/rules/VisibilityRule.d.ts.map +1 -0
- package/dist/services/safety/rules/VisibilityRule.js +53 -0
- package/dist/services/safety/rules/ZeroTrustRule.d.ts +3 -0
- package/dist/services/safety/rules/ZeroTrustRule.d.ts.map +1 -0
- package/dist/services/safety/rules/ZeroTrustRule.js +37 -0
- package/dist/services/safety/rules/index.d.ts +3 -0
- package/dist/services/safety/rules/index.d.ts.map +1 -0
- package/dist/services/safety/rules/index.js +34 -0
- package/dist/services/types.d.ts +59 -0
- package/dist/services/types.d.ts.map +1 -0
- package/dist/services/types.js +2 -0
- package/dist/storage/SnapshotManager.d.ts +5 -0
- package/dist/storage/SnapshotManager.d.ts.map +1 -0
- package/dist/storage/SnapshotManager.js +32 -0
- package/dist/types/index.d.ts +95 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +7 -0
- package/dist/utils/DOMUtils.d.ts +49 -0
- package/dist/utils/DOMUtils.d.ts.map +1 -0
- package/dist/utils/DOMUtils.js +466 -0
- package/dist/utils/FileLock.d.ts +44 -0
- package/dist/utils/FileLock.d.ts.map +1 -0
- package/dist/utils/FileLock.js +189 -0
- package/dist/utils/IsolatedDiff.d.ts +45 -0
- package/dist/utils/IsolatedDiff.d.ts.map +1 -0
- package/dist/utils/IsolatedDiff.js +382 -0
- package/dist/utils/StackUtils.d.ts +11 -0
- package/dist/utils/StackUtils.d.ts.map +1 -0
- package/dist/utils/StackUtils.js +120 -0
- package/dist/utils/SummaryTable.d.ts +17 -0
- package/dist/utils/SummaryTable.d.ts.map +1 -0
- package/dist/utils/SummaryTable.js +37 -0
- package/dist/utils/atomicWrite.d.ts +9 -0
- package/dist/utils/atomicWrite.d.ts.map +1 -0
- package/dist/utils/atomicWrite.js +83 -0
- package/dist/utils/logger.d.ts +59 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +123 -0
- package/dist/vendor/enquirer.d.ts +33 -0
- package/dist/vendor/enquirer.d.ts.map +1 -0
- package/dist/vendor/enquirer.js +11 -0
- package/package.json +71 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"singleton.d.ts","sourceRoot":"","sources":["../../src/engine/singleton.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,eAAO,MAAM,YAAY,YAAmB,CAAC"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
export type SelaSubsystem = "SafetyGuard" | "IntentAuditor" | "ASTUpdater" | "Proxy" | "LLMService" | "Registry" | "ChainValidator" | "Engine" | "Report";
|
|
2
|
+
export interface SelaErrorContext {
|
|
3
|
+
filePath?: string;
|
|
4
|
+
line?: number;
|
|
5
|
+
column?: number;
|
|
6
|
+
selector?: string;
|
|
7
|
+
healedSelector?: string;
|
|
8
|
+
stableId?: string;
|
|
9
|
+
testTitle?: string;
|
|
10
|
+
testFile?: string;
|
|
11
|
+
branch?: string;
|
|
12
|
+
/** SafetyGuard verdict level when the error originated in SafetyGuard. */
|
|
13
|
+
safetyLevel?: "BLOCKED" | "FAIL_HARD" | "REQUIRES_REVIEW" | "SAFE";
|
|
14
|
+
/** Auditor verdict surfaced in the context for SafetyGuard rejections. */
|
|
15
|
+
auditorVerdict?: "CONSISTENT" | "INCONSISTENT" | "SUSPICIOUS";
|
|
16
|
+
/** Raw + adjusted LLM confidence so downstream telemetry can plot drift. */
|
|
17
|
+
aiConfidence?: number;
|
|
18
|
+
auditorConfidence?: number;
|
|
19
|
+
/** Free-form extension slot. Prefer adding a named field above when possible. */
|
|
20
|
+
[key: string]: unknown;
|
|
21
|
+
}
|
|
22
|
+
export interface SelaErrorJSON {
|
|
23
|
+
name: string;
|
|
24
|
+
subsystem: SelaSubsystem;
|
|
25
|
+
code: string;
|
|
26
|
+
reason: string;
|
|
27
|
+
message: string;
|
|
28
|
+
context: SelaErrorContext;
|
|
29
|
+
stack?: string;
|
|
30
|
+
cause?: string;
|
|
31
|
+
}
|
|
32
|
+
export interface SelaErrorInit {
|
|
33
|
+
subsystem: SelaSubsystem;
|
|
34
|
+
/**
|
|
35
|
+
* Stable machine-readable error code. Must match `[A-Z][A-Z0-9_]+`.
|
|
36
|
+
* Recommended convention: short subsystem-prefix + verb/noun.
|
|
37
|
+
* See SELA_ERROR_CODES below for the canonical catalogue.
|
|
38
|
+
*/
|
|
39
|
+
code: string;
|
|
40
|
+
/** Human-readable explanation. Becomes the tail of the formatted message. */
|
|
41
|
+
reason: string;
|
|
42
|
+
context?: SelaErrorContext;
|
|
43
|
+
/** Original error wrapped by this SelaError, if any. */
|
|
44
|
+
cause?: unknown;
|
|
45
|
+
}
|
|
46
|
+
export declare class SelaError extends Error {
|
|
47
|
+
readonly subsystem: SelaSubsystem;
|
|
48
|
+
readonly code: string;
|
|
49
|
+
readonly reason: string;
|
|
50
|
+
readonly context: SelaErrorContext;
|
|
51
|
+
constructor(init: SelaErrorInit);
|
|
52
|
+
static formatMessage(subsystem: SelaSubsystem, code: string, reason: string): string;
|
|
53
|
+
toJSON(): SelaErrorJSON;
|
|
54
|
+
}
|
|
55
|
+
export declare function isSelaError(err: unknown): err is SelaError;
|
|
56
|
+
export declare function isSelaErrorFrom(err: unknown, subsystem: SelaSubsystem): err is SelaError;
|
|
57
|
+
export declare const SAFETY_GUARD_CODES: {
|
|
58
|
+
readonly FAIL_HARD_VISIBILITY_GHOST: "SG_FAIL_HARD_VISIBILITY_GHOST";
|
|
59
|
+
readonly FAIL_HARD_VISIBILITY_OCCLUDED: "SG_FAIL_HARD_VISIBILITY_OCCLUDED";
|
|
60
|
+
readonly BLOCKED_LOW_CONFIDENCE: "SG_BLOCKED_LOW_CONFIDENCE";
|
|
61
|
+
readonly FAIL_HARD_SEMANTIC_INVERSION: "SG_FAIL_HARD_SEMANTIC_INVERSION";
|
|
62
|
+
readonly FAIL_HARD_STATUS_INVERSION: "SG_FAIL_HARD_STATUS_INVERSION";
|
|
63
|
+
readonly BLOCKED_ROLE_SWAP_ASSERTION: "SG_BLOCKED_ROLE_SWAP_ASSERTION";
|
|
64
|
+
readonly FAIL_HARD_AUDITOR_INCONSISTENT: "SG_FAIL_HARD_AUDITOR_INCONSISTENT";
|
|
65
|
+
readonly BLOCKED_AUDITOR_SUSPICIOUS: "SG_BLOCKED_AUDITOR_SUSPICIOUS";
|
|
66
|
+
/**
|
|
67
|
+
* Heal was REQUIRES_REVIEW → quarantined (decision #1): proposed but not
|
|
68
|
+
* written to source and not executed this run, pending explicit approval.
|
|
69
|
+
* Distinct from a block so the report renders it as an amber proposal.
|
|
70
|
+
*/
|
|
71
|
+
readonly HELD_FOR_REVIEW: "SG_HELD_FOR_REVIEW";
|
|
72
|
+
/** Generic dispatcher when SafetyDecision arrives without an explicit code. */
|
|
73
|
+
readonly GENERIC_REJECTION: "SG_GENERIC_REJECTION";
|
|
74
|
+
};
|
|
75
|
+
export type SafetyGuardCode = (typeof SAFETY_GUARD_CODES)[keyof typeof SAFETY_GUARD_CODES];
|
|
76
|
+
export declare const INTENT_AUDITOR_CODES: {
|
|
77
|
+
/** Caller asked for an audit but no Anthropic client was configured. */
|
|
78
|
+
readonly DISABLED: "IA_DISABLED";
|
|
79
|
+
readonly INVALID_JSON: "IA_INVALID_JSON";
|
|
80
|
+
readonly CALL_FAILED: "IA_CALL_FAILED";
|
|
81
|
+
};
|
|
82
|
+
export type IntentAuditorCode = (typeof INTENT_AUDITOR_CODES)[keyof typeof INTENT_AUDITOR_CODES];
|
|
83
|
+
export declare const LLM_SERVICE_CODES: {
|
|
84
|
+
readonly NO_API_KEY: "LLM_NO_API_KEY";
|
|
85
|
+
readonly INVALID_JSON: "LLM_INVALID_JSON";
|
|
86
|
+
readonly MISSING_SEGMENTS: "LLM_MISSING_SEGMENTS";
|
|
87
|
+
readonly NOT_FOUND: "LLM_NOT_FOUND";
|
|
88
|
+
readonly API_CALL_FAILED: "LLM_API_CALL_FAILED";
|
|
89
|
+
};
|
|
90
|
+
export type LLMServiceCode = (typeof LLM_SERVICE_CODES)[keyof typeof LLM_SERVICE_CODES];
|
|
91
|
+
export declare const AST_UPDATER_CODES: {
|
|
92
|
+
readonly UNSUPPORTED_NODE: "AST_UNSUPPORTED_NODE";
|
|
93
|
+
readonly TEMPLATE_LITERAL_SKIP: "AST_TEMPLATE_LITERAL_SKIP";
|
|
94
|
+
readonly CIRCULAR_RECEIVER: "AST_CIRCULAR_RECEIVER";
|
|
95
|
+
readonly DEFINITION_NOT_FOUND: "AST_DEFINITION_NOT_FOUND";
|
|
96
|
+
readonly MAX_DEPTH_EXCEEDED: "AST_MAX_DEPTH_EXCEEDED";
|
|
97
|
+
readonly SAVE_FAILED: "AST_SAVE_FAILED";
|
|
98
|
+
/**
|
|
99
|
+
* Developer pinned the failing statement with `// sela-fail-fast`.
|
|
100
|
+
* Heal pipeline is aborted before any LLM call; FailedEvent is
|
|
101
|
+
* recorded with category "Skipped by Developer".
|
|
102
|
+
*/
|
|
103
|
+
readonly HEAL_DISABLED_BY_DIRECTIVE: "AST_HEAL_DISABLED_BY_DIRECTIVE";
|
|
104
|
+
};
|
|
105
|
+
export type ASTUpdaterCode = (typeof AST_UPDATER_CODES)[keyof typeof AST_UPDATER_CODES];
|
|
106
|
+
export declare const PROXY_CODES: {
|
|
107
|
+
readonly FRAME_SCOPED: "PRX_FRAME_SCOPED";
|
|
108
|
+
readonly REBUILD_FAILED: "PRX_REBUILD_FAILED";
|
|
109
|
+
readonly NON_LOCATOR_TARGET: "PRX_NON_LOCATOR_TARGET";
|
|
110
|
+
};
|
|
111
|
+
export type ProxyCode = (typeof PROXY_CODES)[keyof typeof PROXY_CODES];
|
|
112
|
+
export declare const REGISTRY_CODES: {
|
|
113
|
+
readonly CONTEXT_MISMATCH: "REG_CONTEXT_MISMATCH";
|
|
114
|
+
readonly FINGERPRINT_COLLISION: "REG_FINGERPRINT_COLLISION";
|
|
115
|
+
};
|
|
116
|
+
export type RegistryCode = (typeof REGISTRY_CODES)[keyof typeof REGISTRY_CODES];
|
|
117
|
+
export declare const REPORT_CODES: {
|
|
118
|
+
/** Event passed to the validator was null, undefined, or not an object. */
|
|
119
|
+
readonly MALFORMED_EVENT: "REP_MALFORMED_EVENT";
|
|
120
|
+
/** Event.kind is not one of HEALED|FAILED|PROTECTED. */
|
|
121
|
+
readonly UNKNOWN_KIND: "REP_UNKNOWN_KIND";
|
|
122
|
+
/** Event is missing a field declared mandatory for its kind. */
|
|
123
|
+
readonly MISSING_FIELD: "REP_MISSING_FIELD";
|
|
124
|
+
/** Event contains a field of the wrong type. */
|
|
125
|
+
readonly INVALID_FIELD_TYPE: "REP_INVALID_FIELD_TYPE";
|
|
126
|
+
/** Disk write failed during flushToDisk(). */
|
|
127
|
+
readonly FLUSH_FAILED: "REP_FLUSH_FAILED";
|
|
128
|
+
/**
|
|
129
|
+
* A prior `.sela-history.json` existed on disk but could not be parsed as
|
|
130
|
+
* a JSON array. The merge path refuses to silently overwrite it with a
|
|
131
|
+
* fresh window (which would destroy the rolling history), so it aborts.
|
|
132
|
+
*/
|
|
133
|
+
readonly HISTORY_CORRUPT: "REP_HISTORY_CORRUPT";
|
|
134
|
+
/** A shard report file existed but was not valid JSON / had no events array. */
|
|
135
|
+
readonly SHARD_UNREADABLE: "REP_SHARD_UNREADABLE";
|
|
136
|
+
};
|
|
137
|
+
export type ReportCode = (typeof REPORT_CODES)[keyof typeof REPORT_CODES];
|
|
138
|
+
export declare const CHAIN_VALIDATOR_CODES: {
|
|
139
|
+
readonly TYPE_FLOW: "CV_TYPE_FLOW";
|
|
140
|
+
readonly SCHEMA: "CV_SCHEMA";
|
|
141
|
+
readonly RECEIVER: "CV_RECEIVER";
|
|
142
|
+
readonly PLACEMENT: "CV_PLACEMENT";
|
|
143
|
+
readonly SEMANTIC_DOWNGRADE: "CV_SEMANTIC_DOWNGRADE";
|
|
144
|
+
};
|
|
145
|
+
export type ChainValidatorCode = (typeof CHAIN_VALIDATOR_CODES)[keyof typeof CHAIN_VALIDATOR_CODES];
|
|
146
|
+
//# sourceMappingURL=SelaError.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SelaError.d.ts","sourceRoot":"","sources":["../../src/errors/SelaError.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// src/errors/SelaError.ts
|
|
3
|
+
//
|
|
4
|
+
// Structured error hierarchy for Sela.
|
|
5
|
+
//
|
|
6
|
+
// Every error thrown across the heal pipeline MUST be a SelaError so that:
|
|
7
|
+
// 1. Callers can branch on `err.subsystem` and `err.code` without
|
|
8
|
+
// string-parsing `err.message`.
|
|
9
|
+
// 2. Telemetry / report layers get a machine-readable JSON shape.
|
|
10
|
+
// 3. The canonical message format is enforced by the constructor and
|
|
11
|
+
// cannot drift over time: `[Sela-<Subsystem>] <CODE>: <reason>`
|
|
12
|
+
//
|
|
13
|
+
// Public message regex (used by tests/unit/engine/error-indicativity.test.ts):
|
|
14
|
+
// /^\[Sela-(SafetyGuard|IntentAuditor|ASTUpdater|Proxy|LLMService|Registry|ChainValidator|Engine)\] [A-Z][A-Z0-9_]+: .+$/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.CHAIN_VALIDATOR_CODES = exports.REPORT_CODES = exports.REGISTRY_CODES = exports.PROXY_CODES = exports.AST_UPDATER_CODES = exports.LLM_SERVICE_CODES = exports.INTENT_AUDITOR_CODES = exports.SAFETY_GUARD_CODES = exports.SelaError = void 0;
|
|
17
|
+
exports.isSelaError = isSelaError;
|
|
18
|
+
exports.isSelaErrorFrom = isSelaErrorFrom;
|
|
19
|
+
// ───────────────────────────────────────────────────────────────────
|
|
20
|
+
// SelaError - single class for the whole hierarchy.
|
|
21
|
+
//
|
|
22
|
+
// We intentionally avoid a tree of subclasses; `instanceof SelaError` +
|
|
23
|
+
// `err.subsystem === "X"` is more flexible for callers and keeps the
|
|
24
|
+
// surface area tiny.
|
|
25
|
+
// ───────────────────────────────────────────────────────────────────
|
|
26
|
+
const CODE_PATTERN = /^[A-Z][A-Z0-9_]+$/;
|
|
27
|
+
class SelaError extends Error {
|
|
28
|
+
subsystem;
|
|
29
|
+
code;
|
|
30
|
+
reason;
|
|
31
|
+
context;
|
|
32
|
+
constructor(init) {
|
|
33
|
+
if (!CODE_PATTERN.test(init.code)) {
|
|
34
|
+
throw new Error(`[SelaError] invalid code "${init.code}" - must match ${CODE_PATTERN}`);
|
|
35
|
+
}
|
|
36
|
+
const formatted = SelaError.formatMessage(init.subsystem, init.code, init.reason);
|
|
37
|
+
super(formatted);
|
|
38
|
+
this.name = `SelaError(${init.subsystem})`;
|
|
39
|
+
this.subsystem = init.subsystem;
|
|
40
|
+
this.code = init.code;
|
|
41
|
+
this.reason = init.reason;
|
|
42
|
+
this.context = init.context ?? {};
|
|
43
|
+
if (init.cause !== undefined) {
|
|
44
|
+
this.cause = init.cause;
|
|
45
|
+
}
|
|
46
|
+
// Maintain prototype chain through transpilation (ES5 target).
|
|
47
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
48
|
+
if (typeof Error.captureStackTrace ===
|
|
49
|
+
"function") {
|
|
50
|
+
Error.captureStackTrace(this, new.target);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
static formatMessage(subsystem, code, reason) {
|
|
54
|
+
return `[Sela-${subsystem}] ${code}: ${reason}`;
|
|
55
|
+
}
|
|
56
|
+
toJSON() {
|
|
57
|
+
return {
|
|
58
|
+
name: this.name,
|
|
59
|
+
subsystem: this.subsystem,
|
|
60
|
+
code: this.code,
|
|
61
|
+
reason: this.reason,
|
|
62
|
+
message: this.message,
|
|
63
|
+
context: this.context,
|
|
64
|
+
stack: this.stack,
|
|
65
|
+
cause: this.cause instanceof Error
|
|
66
|
+
? this.cause.message
|
|
67
|
+
: undefined,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
exports.SelaError = SelaError;
|
|
72
|
+
// ───────────────────────────────────────────────────────────────────
|
|
73
|
+
// Type guards
|
|
74
|
+
// ───────────────────────────────────────────────────────────────────
|
|
75
|
+
function isSelaError(err) {
|
|
76
|
+
return err instanceof SelaError;
|
|
77
|
+
}
|
|
78
|
+
function isSelaErrorFrom(err, subsystem) {
|
|
79
|
+
return err instanceof SelaError && err.subsystem === subsystem;
|
|
80
|
+
}
|
|
81
|
+
// ───────────────────────────────────────────────────────────────────
|
|
82
|
+
// Canonical code catalogue
|
|
83
|
+
//
|
|
84
|
+
// Tests assert against these constants - never hand-write code strings
|
|
85
|
+
// at throw sites. Adding a new code requires adding it here first so
|
|
86
|
+
// the catalogue stays in sync with the error-indicativity contract.
|
|
87
|
+
// ───────────────────────────────────────────────────────────────────
|
|
88
|
+
exports.SAFETY_GUARD_CODES = {
|
|
89
|
+
FAIL_HARD_VISIBILITY_GHOST: "SG_FAIL_HARD_VISIBILITY_GHOST",
|
|
90
|
+
FAIL_HARD_VISIBILITY_OCCLUDED: "SG_FAIL_HARD_VISIBILITY_OCCLUDED",
|
|
91
|
+
BLOCKED_LOW_CONFIDENCE: "SG_BLOCKED_LOW_CONFIDENCE",
|
|
92
|
+
FAIL_HARD_SEMANTIC_INVERSION: "SG_FAIL_HARD_SEMANTIC_INVERSION",
|
|
93
|
+
FAIL_HARD_STATUS_INVERSION: "SG_FAIL_HARD_STATUS_INVERSION",
|
|
94
|
+
BLOCKED_ROLE_SWAP_ASSERTION: "SG_BLOCKED_ROLE_SWAP_ASSERTION",
|
|
95
|
+
FAIL_HARD_AUDITOR_INCONSISTENT: "SG_FAIL_HARD_AUDITOR_INCONSISTENT",
|
|
96
|
+
BLOCKED_AUDITOR_SUSPICIOUS: "SG_BLOCKED_AUDITOR_SUSPICIOUS",
|
|
97
|
+
/**
|
|
98
|
+
* Heal was REQUIRES_REVIEW → quarantined (decision #1): proposed but not
|
|
99
|
+
* written to source and not executed this run, pending explicit approval.
|
|
100
|
+
* Distinct from a block so the report renders it as an amber proposal.
|
|
101
|
+
*/
|
|
102
|
+
HELD_FOR_REVIEW: "SG_HELD_FOR_REVIEW",
|
|
103
|
+
/** Generic dispatcher when SafetyDecision arrives without an explicit code. */
|
|
104
|
+
GENERIC_REJECTION: "SG_GENERIC_REJECTION",
|
|
105
|
+
};
|
|
106
|
+
exports.INTENT_AUDITOR_CODES = {
|
|
107
|
+
/** Caller asked for an audit but no Anthropic client was configured. */
|
|
108
|
+
DISABLED: "IA_DISABLED",
|
|
109
|
+
INVALID_JSON: "IA_INVALID_JSON",
|
|
110
|
+
CALL_FAILED: "IA_CALL_FAILED",
|
|
111
|
+
};
|
|
112
|
+
exports.LLM_SERVICE_CODES = {
|
|
113
|
+
NO_API_KEY: "LLM_NO_API_KEY",
|
|
114
|
+
INVALID_JSON: "LLM_INVALID_JSON",
|
|
115
|
+
MISSING_SEGMENTS: "LLM_MISSING_SEGMENTS",
|
|
116
|
+
NOT_FOUND: "LLM_NOT_FOUND",
|
|
117
|
+
API_CALL_FAILED: "LLM_API_CALL_FAILED",
|
|
118
|
+
};
|
|
119
|
+
exports.AST_UPDATER_CODES = {
|
|
120
|
+
UNSUPPORTED_NODE: "AST_UNSUPPORTED_NODE",
|
|
121
|
+
TEMPLATE_LITERAL_SKIP: "AST_TEMPLATE_LITERAL_SKIP",
|
|
122
|
+
CIRCULAR_RECEIVER: "AST_CIRCULAR_RECEIVER",
|
|
123
|
+
DEFINITION_NOT_FOUND: "AST_DEFINITION_NOT_FOUND",
|
|
124
|
+
MAX_DEPTH_EXCEEDED: "AST_MAX_DEPTH_EXCEEDED",
|
|
125
|
+
SAVE_FAILED: "AST_SAVE_FAILED",
|
|
126
|
+
/**
|
|
127
|
+
* Developer pinned the failing statement with `// sela-fail-fast`.
|
|
128
|
+
* Heal pipeline is aborted before any LLM call; FailedEvent is
|
|
129
|
+
* recorded with category "Skipped by Developer".
|
|
130
|
+
*/
|
|
131
|
+
HEAL_DISABLED_BY_DIRECTIVE: "AST_HEAL_DISABLED_BY_DIRECTIVE",
|
|
132
|
+
};
|
|
133
|
+
exports.PROXY_CODES = {
|
|
134
|
+
FRAME_SCOPED: "PRX_FRAME_SCOPED",
|
|
135
|
+
REBUILD_FAILED: "PRX_REBUILD_FAILED",
|
|
136
|
+
NON_LOCATOR_TARGET: "PRX_NON_LOCATOR_TARGET",
|
|
137
|
+
};
|
|
138
|
+
exports.REGISTRY_CODES = {
|
|
139
|
+
CONTEXT_MISMATCH: "REG_CONTEXT_MISMATCH",
|
|
140
|
+
FINGERPRINT_COLLISION: "REG_FINGERPRINT_COLLISION",
|
|
141
|
+
};
|
|
142
|
+
exports.REPORT_CODES = {
|
|
143
|
+
/** Event passed to the validator was null, undefined, or not an object. */
|
|
144
|
+
MALFORMED_EVENT: "REP_MALFORMED_EVENT",
|
|
145
|
+
/** Event.kind is not one of HEALED|FAILED|PROTECTED. */
|
|
146
|
+
UNKNOWN_KIND: "REP_UNKNOWN_KIND",
|
|
147
|
+
/** Event is missing a field declared mandatory for its kind. */
|
|
148
|
+
MISSING_FIELD: "REP_MISSING_FIELD",
|
|
149
|
+
/** Event contains a field of the wrong type. */
|
|
150
|
+
INVALID_FIELD_TYPE: "REP_INVALID_FIELD_TYPE",
|
|
151
|
+
/** Disk write failed during flushToDisk(). */
|
|
152
|
+
FLUSH_FAILED: "REP_FLUSH_FAILED",
|
|
153
|
+
/**
|
|
154
|
+
* A prior `.sela-history.json` existed on disk but could not be parsed as
|
|
155
|
+
* a JSON array. The merge path refuses to silently overwrite it with a
|
|
156
|
+
* fresh window (which would destroy the rolling history), so it aborts.
|
|
157
|
+
*/
|
|
158
|
+
HISTORY_CORRUPT: "REP_HISTORY_CORRUPT",
|
|
159
|
+
/** A shard report file existed but was not valid JSON / had no events array. */
|
|
160
|
+
SHARD_UNREADABLE: "REP_SHARD_UNREADABLE",
|
|
161
|
+
};
|
|
162
|
+
exports.CHAIN_VALIDATOR_CODES = {
|
|
163
|
+
TYPE_FLOW: "CV_TYPE_FLOW",
|
|
164
|
+
SCHEMA: "CV_SCHEMA",
|
|
165
|
+
RECEIVER: "CV_RECEIVER",
|
|
166
|
+
PLACEMENT: "CV_PLACEMENT",
|
|
167
|
+
SEMANTIC_DOWNGRADE: "CV_SEMANTIC_DOWNGRADE",
|
|
168
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Locator } from "@playwright/test";
|
|
2
|
+
import { SelaEngine } from "../engine/SelaEngine";
|
|
3
|
+
/**
|
|
4
|
+
* createHealingExpect - drop-in replacement for Playwright's expect().
|
|
5
|
+
*
|
|
6
|
+
* @param resolveProxy Optional callback that unwraps a Sela proxy
|
|
7
|
+
* to its current live Locator. Supplied by
|
|
8
|
+
* fixtures/index.ts which owns proxyToActiveLocator.
|
|
9
|
+
*/
|
|
10
|
+
export declare function createHealingExpect(engine: SelaEngine, page: import("@playwright/test").Page, filePath: string, initialLine: number, // השורה מהפיקסצ'ר (לרוב תהיה לא מדויקת או 0)
|
|
11
|
+
resolveProxy?: (value: unknown) => Locator | null): (locatorOrValue: unknown) => any;
|
|
12
|
+
//# sourceMappingURL=expectProxy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expectProxy.d.ts","sourceRoot":"","sources":["../../src/fixtures/expectProxy.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,OAAO,EAER,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAkOlD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,OAAO,kBAAkB,EAAE,IAAI,EACrC,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EAAE,6CAA6C;AAClE,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,GAAG,IAAI,GAChD,CAAC,cAAc,EAAE,OAAO,KAAK,GAAG,CAsElC"}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// src/fixtures/expectProxy.ts - full replacement
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.createHealingExpect = createHealingExpect;
|
|
5
|
+
const test_1 = require("@playwright/test");
|
|
6
|
+
const HealingRegistry_1 = require("../engine/HealingRegistry");
|
|
7
|
+
const proxyTag_1 = require("./proxyTag");
|
|
8
|
+
const logger_1 = require("../utils/logger");
|
|
9
|
+
const ELEMENT_NOT_FOUND_PATTERNS = [
|
|
10
|
+
/element.*not found/i,
|
|
11
|
+
/locator.*resolved to.*\d+ element/i,
|
|
12
|
+
/waiting for.*locator/i,
|
|
13
|
+
/timeout.*exceeded/i,
|
|
14
|
+
];
|
|
15
|
+
function isElementNotFoundError(err) {
|
|
16
|
+
if (!(err instanceof Error))
|
|
17
|
+
return false;
|
|
18
|
+
return ELEMENT_NOT_FOUND_PATTERNS.some((p) => p.test(err.message));
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Returns true only for genuine Playwright Locator instances -
|
|
22
|
+
* not FrameLocator proxies or Sela proxy objects.
|
|
23
|
+
*
|
|
24
|
+
* A real Locator has _frame internally.
|
|
25
|
+
* A FrameLocator has _frameSelector instead.
|
|
26
|
+
* We must NOT intercept frame-scoped locators because we cannot
|
|
27
|
+
* safely rebuild them from a bare selector string on page.locator().
|
|
28
|
+
*/
|
|
29
|
+
function isRealLocator(value) {
|
|
30
|
+
if (value === null || value === undefined)
|
|
31
|
+
return false;
|
|
32
|
+
if (typeof value !== "object")
|
|
33
|
+
return false;
|
|
34
|
+
// Sela locator proxies expose `_selaSelector`. The proxy forwards
|
|
35
|
+
// `_frame` via Reflect.get so `hasFrame` would lie - explicitly reject them
|
|
36
|
+
// here. Callers should unwrap via `resolveProxy` first.
|
|
37
|
+
if (value._selaSelector !== undefined)
|
|
38
|
+
return false;
|
|
39
|
+
const hasFrame = value._frame !== undefined ||
|
|
40
|
+
value._impl?._frame !== undefined;
|
|
41
|
+
const isFrameLocator = value._frameSelector !== undefined ||
|
|
42
|
+
value._impl?._frameSelector !== undefined;
|
|
43
|
+
return hasFrame && !isFrameLocator;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Detect whether a locator is frame-scoped by checking its internal
|
|
47
|
+
* selector string for frame-related segments.
|
|
48
|
+
*/
|
|
49
|
+
function isFrameScopedLocator(locator) {
|
|
50
|
+
const sel = locator._selector ?? locator["_impl"]?._selector ?? "";
|
|
51
|
+
return (typeof sel === "string" &&
|
|
52
|
+
(sel.includes("internal:control=enter-frame") ||
|
|
53
|
+
sel.includes(">> internal:control=enter-frame")));
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Extracts the internal Playwright selector string from a real Locator.
|
|
57
|
+
*/
|
|
58
|
+
function extractSelectorFromLocator(locator) {
|
|
59
|
+
const internal = locator._selector ?? locator["_impl"]?._selector;
|
|
60
|
+
return typeof internal === "string" ? internal : null;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Rebuild a locator from a healed selector string that may contain
|
|
64
|
+
* frame segments (e.g. "#modern-frame-container >> #status-label-v2").
|
|
65
|
+
*
|
|
66
|
+
* A plain page.locator() call with a frame >> element string is NOT
|
|
67
|
+
* a valid locator for frame content - Playwright rejects it with
|
|
68
|
+
* "toHaveText can be only used with Locator object".
|
|
69
|
+
*
|
|
70
|
+
* This function correctly chains frameLocator() calls for each frame
|
|
71
|
+
* segment, then calls .locator() for the final element segment.
|
|
72
|
+
*
|
|
73
|
+
* Convention used by SelaEngine segments:
|
|
74
|
+
* - Frame segments look like CSS selectors for iframes (#id, .class)
|
|
75
|
+
* but produce a FrameLocator, not a Locator.
|
|
76
|
+
* - The last segment is always the element selector.
|
|
77
|
+
* - "internal:control=enter-frame" segments are implicit in
|
|
78
|
+
* Playwright's FrameLocator and should be skipped.
|
|
79
|
+
*
|
|
80
|
+
* Examples:
|
|
81
|
+
* "#modern-frame-container >> #status-label-v2"
|
|
82
|
+
* → page.frameLocator("#modern-frame-container").locator("#status-label-v2")
|
|
83
|
+
*
|
|
84
|
+
* "#outer >> #inner-frame >> .button"
|
|
85
|
+
* → page.frameLocator("#outer").frameLocator("#inner-frame").locator(".button")
|
|
86
|
+
*
|
|
87
|
+
* "#simple-element"
|
|
88
|
+
* → page.locator("#simple-element")
|
|
89
|
+
*/
|
|
90
|
+
function rebuildLocator(page, healedSelector) {
|
|
91
|
+
// --- הוספת השורה הזו ---
|
|
92
|
+
// מוודא שאנחנו עובדים עם האובייקט האמיתי של פליירייט ולא עם הפרוקסי שלנו
|
|
93
|
+
const rawPage = page._rawPage || page;
|
|
94
|
+
const segments = healedSelector
|
|
95
|
+
.split(" >> ")
|
|
96
|
+
.map((s) => s.trim())
|
|
97
|
+
.filter((s) => s.length > 0 && s !== "internal:control=enter-frame");
|
|
98
|
+
if (segments.length === 0)
|
|
99
|
+
return rawPage.locator(healedSelector);
|
|
100
|
+
if (segments.length === 1)
|
|
101
|
+
return rawPage.locator(segments[0]);
|
|
102
|
+
const frameSegments = segments.slice(0, segments.length - 1);
|
|
103
|
+
const elementSegment = segments[segments.length - 1];
|
|
104
|
+
let context = null;
|
|
105
|
+
for (const frameSel of frameSegments) {
|
|
106
|
+
if (context === null) {
|
|
107
|
+
context = rawPage.frameLocator(frameSel);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
context = context.frameLocator(frameSel);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
// כאן אנחנו מחזירים לוקטור שנוצר ישירות מה-rawPage
|
|
114
|
+
return context.locator(elementSegment);
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Wrap a single matcher so that element-not-found errors trigger the
|
|
118
|
+
* heal cycle and retry the assertion once on the correctly rebuilt locator.
|
|
119
|
+
*/
|
|
120
|
+
function wrapMatcher(matcher, locator, matcherName, engine, page, ctx) {
|
|
121
|
+
return (async (...args) => {
|
|
122
|
+
try {
|
|
123
|
+
return await matcher(...args);
|
|
124
|
+
}
|
|
125
|
+
catch (err) {
|
|
126
|
+
if (!isElementNotFoundError(err))
|
|
127
|
+
throw err;
|
|
128
|
+
const rawSelector = extractSelectorFromLocator(locator);
|
|
129
|
+
if (!rawSelector)
|
|
130
|
+
throw err;
|
|
131
|
+
logger_1.logger.debug(`Assertion failed for "${rawSelector}", attempting heal…`);
|
|
132
|
+
// Fast path - already healed in this test via registry
|
|
133
|
+
const resolved = HealingRegistry_1.HealingRegistry.getInstance().resolveSelector(rawSelector, ctx);
|
|
134
|
+
let healedSelector = resolved;
|
|
135
|
+
if (resolved === rawSelector) {
|
|
136
|
+
// Slow path - ask the engine + LLM.
|
|
137
|
+
// engine.heal() writes the fix to disk AND returns the canonical
|
|
138
|
+
// healedLocatorString from SourceUpdater - the exact same string
|
|
139
|
+
// that was saved to the file. This is the handshake that guarantees
|
|
140
|
+
// disk and runtime are in sync (no "ghost failures").
|
|
141
|
+
const stableId = require("crypto")
|
|
142
|
+
.createHash("md5")
|
|
143
|
+
.update(rawSelector)
|
|
144
|
+
.digest("hex");
|
|
145
|
+
try {
|
|
146
|
+
healedSelector = await engine.heal(page, rawSelector, rawSelector, stableId, ctx.filePath, ctx.line, "assertion");
|
|
147
|
+
}
|
|
148
|
+
catch (healErr) {
|
|
149
|
+
if (healErr instanceof Error &&
|
|
150
|
+
healErr.message.includes("[SafetyGuard]")) {
|
|
151
|
+
throw healErr;
|
|
152
|
+
}
|
|
153
|
+
throw err;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
if (!healedSelector || healedSelector === rawSelector)
|
|
157
|
+
throw err;
|
|
158
|
+
// Rebuild the locator from the canonical selector returned by the
|
|
159
|
+
// updater. rebuildLocator() correctly chains frameLocator() calls
|
|
160
|
+
// for each frame segment, then .locator() for the final element,
|
|
161
|
+
// ensuring page/frame/locator variables are scoped correctly at runtime.
|
|
162
|
+
const newLocator = rebuildLocator(page, healedSelector);
|
|
163
|
+
const newExpectation = (0, test_1.expect)(newLocator);
|
|
164
|
+
const retryMatcher = newExpectation[matcherName];
|
|
165
|
+
if (typeof retryMatcher !== "function")
|
|
166
|
+
throw err;
|
|
167
|
+
logger_1.logger.debug(`Retrying assertion with healed selector: "${healedSelector}"`);
|
|
168
|
+
return await retryMatcher.apply(newExpectation, args);
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
const WRAPPED_MATCHERS = [
|
|
173
|
+
"toBeVisible",
|
|
174
|
+
"toBeHidden",
|
|
175
|
+
"toBeEnabled",
|
|
176
|
+
"toBeDisabled",
|
|
177
|
+
"toHaveText",
|
|
178
|
+
"toContainText",
|
|
179
|
+
"toHaveValue",
|
|
180
|
+
"toHaveAttribute",
|
|
181
|
+
"toHaveCount",
|
|
182
|
+
"toBeChecked",
|
|
183
|
+
"toBeFocused",
|
|
184
|
+
];
|
|
185
|
+
/**
|
|
186
|
+
* createHealingExpect - drop-in replacement for Playwright's expect().
|
|
187
|
+
*
|
|
188
|
+
* @param resolveProxy Optional callback that unwraps a Sela proxy
|
|
189
|
+
* to its current live Locator. Supplied by
|
|
190
|
+
* fixtures/index.ts which owns proxyToActiveLocator.
|
|
191
|
+
*/
|
|
192
|
+
function createHealingExpect(engine, page, filePath, initialLine, // השורה מהפיקסצ'ר (לרוב תהיה לא מדויקת או 0)
|
|
193
|
+
resolveProxy) {
|
|
194
|
+
return function expect(locatorOrValue) {
|
|
195
|
+
// 1. חילוץ דינמי של שורת הקוד האמיתית בזמן קריאת ה-expect
|
|
196
|
+
const getCallerLine = () => {
|
|
197
|
+
const err = new Error();
|
|
198
|
+
const stack = err.stack?.split("\n") || [];
|
|
199
|
+
// מחפשים את הקריאה הראשונה בשרשרת שמגיעה מקובץ הטסט ולא מקובץ הפרוקסי
|
|
200
|
+
const specLine = stack.find((l) => l.includes(filePath) && !l.includes("expectProxy"));
|
|
201
|
+
if (specLine) {
|
|
202
|
+
const match = specLine.match(/:(\d+):(\d+)/);
|
|
203
|
+
return match ? parseInt(match[1], 10) : initialLine;
|
|
204
|
+
}
|
|
205
|
+
return initialLine;
|
|
206
|
+
};
|
|
207
|
+
const actualLine = getCallerLine(); // כאן אנחנו מקבלים את השורה הנכונה!
|
|
208
|
+
// Step 1 - unwrap Sela proxy to real active Locator
|
|
209
|
+
let resolved = locatorOrValue;
|
|
210
|
+
if (resolveProxy) {
|
|
211
|
+
const unwrapped = resolveProxy(locatorOrValue);
|
|
212
|
+
if (unwrapped)
|
|
213
|
+
resolved = unwrapped;
|
|
214
|
+
}
|
|
215
|
+
const base = (0, test_1.expect)(resolved);
|
|
216
|
+
// Defensive: if for any reason `base` is not an object, return it as-is
|
|
217
|
+
// rather than crashing inside `new Proxy(...)`.
|
|
218
|
+
if (base === null || typeof base !== "object") {
|
|
219
|
+
return base;
|
|
220
|
+
}
|
|
221
|
+
// Step 2 - only wrap matchers for genuine page-level Locator objects.
|
|
222
|
+
if (!isRealLocator(resolved)) {
|
|
223
|
+
return base;
|
|
224
|
+
}
|
|
225
|
+
const locator = resolved;
|
|
226
|
+
// משתמשים בשורה האמיתית שחילצנו עבור ה-Context שמועבר ל-Engine
|
|
227
|
+
const ctx = { filePath, line: actualLine };
|
|
228
|
+
const proxy = new Proxy(base, {
|
|
229
|
+
get(target, prop) {
|
|
230
|
+
// Sela proxy identity - honored before any string-only branch so
|
|
231
|
+
// callers can detect a Sela expect proxy via Symbol.for("sela.proxy").
|
|
232
|
+
if (prop === proxyTag_1.SELA_PROXY)
|
|
233
|
+
return "expect";
|
|
234
|
+
if (typeof prop !== "string")
|
|
235
|
+
return target[prop];
|
|
236
|
+
const val = target[prop];
|
|
237
|
+
if (typeof val === "function" &&
|
|
238
|
+
WRAPPED_MATCHERS.includes(prop)) {
|
|
239
|
+
return wrapMatcher(val.bind(target), locator, prop, engine, page, ctx);
|
|
240
|
+
}
|
|
241
|
+
return val;
|
|
242
|
+
},
|
|
243
|
+
});
|
|
244
|
+
return proxy;
|
|
245
|
+
};
|
|
246
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Locator, Page } from "@playwright/test";
|
|
2
|
+
import { createHealingExpect } from "./expectProxy";
|
|
3
|
+
export declare function resolveSelaProxy(value: unknown): Locator | null;
|
|
4
|
+
export declare function createFrameLocatorProxy(rawFrameLocator: any, frameSelector: string, rawPage: Page, testTitle: string, actionCounter: {
|
|
5
|
+
value: number;
|
|
6
|
+
}, parentChain: string): any;
|
|
7
|
+
export declare function createLocatorProxy(rawLocator: Locator, selector: string, rawPage: Page, testTitle: string, actionCounter: {
|
|
8
|
+
value: number;
|
|
9
|
+
}, elementSelectorOnly?: string): any;
|
|
10
|
+
export declare const test: import("@playwright/test").TestType<import("@playwright/test").PlaywrightTestArgs & import("@playwright/test").PlaywrightTestOptions & {
|
|
11
|
+
expect: ReturnType<typeof createHealingExpect>;
|
|
12
|
+
}, import("@playwright/test").PlaywrightWorkerArgs & import("@playwright/test").PlaywrightWorkerOptions & {
|
|
13
|
+
/**
|
|
14
|
+
* Worker-scoped lifecycle anchor. Its teardown runs EXACTLY ONCE per
|
|
15
|
+
* worker process - after every test in that worker has finished - which
|
|
16
|
+
* is the only correct place to flush the suite-wide healing report.
|
|
17
|
+
*
|
|
18
|
+
* Why a worker fixture and not the reporter's onEnd():
|
|
19
|
+
* Playwright runs tests in worker processes; the reporter lives in the
|
|
20
|
+
* main process. The `sharedHealReport` buffer, `HealingRegistry`, and
|
|
21
|
+
* `sharedWorkspaceSnapshot` singletons that accumulate heal events all
|
|
22
|
+
* live in the WORKER. The main-process reporter cannot see them, so the
|
|
23
|
+
* flush MUST happen worker-side. The reporter's cross-process
|
|
24
|
+
* PendingPromptLedger (written here, drained in onEnd) is what carries
|
|
25
|
+
* the DX-review summary back to the main process.
|
|
26
|
+
*/
|
|
27
|
+
_selaWorkerLifecycle: void;
|
|
28
|
+
}>;
|
|
29
|
+
export { createHealingExpect } from "./expectProxy";
|
|
30
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/fixtures/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAK/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAYpD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,GAAG,IAAI,CAI/D;AA2jBD,wBAAgB,uBAAuB,CACrC,eAAe,EAAE,GAAG,EACpB,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,IAAI,EACb,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,EAChC,WAAW,EAAE,MAAM,GAClB,GAAG,CAuCL;AAaD,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,OAAO,EACnB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,IAAI,EACb,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,EAChC,mBAAmB,CAAC,EAAE,MAAM,GAC3B,GAAG,CAkPL;AAQD,eAAO,MAAM,IAAI;YAEL,UAAU,CAAC,OAAO,mBAAmB,CAAC;;IAG9C;;;;;;;;;;;;;OAaG;0BACmB,IAAI;EAmI5B,CAAC;AAGH,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC"}
|