snipara-companion 1.4.22 → 2.0.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 CHANGED
@@ -31,10 +31,52 @@ Local continuity commands work without a Snipara account; commands that read
31
31
  hosted context or memory need `init`/`login` first. Run
32
32
  `snipara-companion --help` for the full command list.
33
33
 
34
+ ## Local Context Pack
35
+
36
+ `context-pack` is a free, local-only reversible pack for long tool outputs,
37
+ logs, diffs, and notes. It stores exact content under
38
+ `.snipara/context-pack` and never uploads raw output to hosted Snipara.
39
+
40
+ ```bash
41
+ # Pack piped tool output
42
+ pnpm test 2>&1 | snipara-companion context-pack pack \
43
+ --label "package test output" \
44
+ --source "pnpm test"
45
+
46
+ # Pack a local file
47
+ snipara-companion context-pack pack --file ./debug.log --kind log --json
48
+
49
+ # Retrieve exact content later
50
+ snipara-companion context-pack retrieve latest
51
+ snipara-companion context-pack retrieve cpack_abcd1234 --output ./restored.log
52
+ snipara-companion context-pack retrieve cpack_abcd1234 --json --metadata-only
53
+
54
+ # Inspect and clean local storage
55
+ snipara-companion context-pack stats
56
+ snipara-companion context-pack clean --older-than-days 14
57
+
58
+ # Attach metadata-only receipts to events/checkpoints
59
+ snipara-companion post-tool --tool Bash --result "$(cat ./debug.log)" --pack-result
60
+ snipara-companion emit-event -e tool_result --context-pack cpack_abcd1234
61
+ snipara-companion workflow runtime-checkpoint verify \
62
+ --summary "Captured verifier output" \
63
+ --context-pack cpack_abcd1234
64
+ ```
65
+
66
+ The pack ID is derived from the content hash, so packing identical content is
67
+ idempotent. Use `--ttl-days` when temporary output should be cleaned by the
68
+ default `context-pack clean` path. The storage directory writes its own
69
+ `.gitignore` so raw pack blobs do not appear in normal Git staging. Pack blobs
70
+ are plaintext local files with restrictive permissions. Secret-like input is
71
+ blocked by default; use `--allow-sensitive` only when you intentionally need an
72
+ exact local recovery artifact, and prefer the exact pack ID over `latest` in
73
+ handoffs.
74
+
34
75
  ```mermaid
35
76
  flowchart LR
36
77
  Project["Local project"] --> Companion["snipara-companion"]
37
78
  Companion --> Diagnostics["status, brief, timeline, phase commits, handoff"]
79
+ Companion --> Packs["context-pack (local output packs)"]
38
80
  Companion --> Memory["snipara-memory (optional local memory)"]
39
81
  Companion --> Evals["snipara-evals (optional local evals)"]
40
82
  Companion --> Hosted["Snipara Hosted MCP / API"]
@@ -191,15 +233,39 @@ snipara-companion workflow run \
191
233
  ```
192
234
 
193
235
  The output is a routing card and handoff metadata. Companion calls the hosted
194
- `snipara_adaptive_routing_catalog` tool when project auth is configured, records
195
- the sanitized runtime catalog in the handoff, and falls back to local dry-run
196
- metadata when the hosted gateway is unavailable. It does not silently spawn
197
- workers. The stable contract is provider-neutral requirements such as worker
198
- role, reasoning depth, context budget, endpoint type, write scope, and fallback.
236
+ `snipara_adaptive_routing_catalog` tool when project auth and policy allow it,
237
+ records the sanitized runtime catalog in the handoff, and falls back to local
238
+ dry-run metadata when the hosted gateway is unavailable or omits
239
+ `success: true`. It does not silently spawn workers. The stable contract is
240
+ provider-neutral requirements such as worker role, reasoning depth, context
241
+ budget, endpoint type, write scope, and fallback.
242
+
243
+ Project owners can configure Adaptive Work Routing in Project > Automation:
244
+ `off`, `recommend`, or `catalog`; approval; planner-retained reasoning; allowed
245
+ endpoint types (`cloud`, `local`, `self_hosted`); worker classes; and budget
246
+ hints. `workflow run` reads that hosted policy and CLI flags cannot broaden it.
199
247
  Project credentials stay server-side behind the hosted gateway; local endpoints
200
248
  such as Ollama, LM Studio, AnythingLLM, or other OpenAI-compatible servers must
201
249
  be reachable from the worker execution environment.
202
250
 
251
+ For the open package without Snipara SaaS, add a local policy file:
252
+
253
+ ```json
254
+ {
255
+ "mode": "recommend",
256
+ "plannerRetainsReasoning": true,
257
+ "preferLocalWorkers": true,
258
+ "allowedEndpointTypes": ["local", "cloud"],
259
+ "preferredEndpointTypes": ["local"],
260
+ "allowedWorkerClasses": ["documentation", "tests", "review"],
261
+ "catalogLimit": 8
262
+ }
263
+ ```
264
+
265
+ Save it at `.snipara/adaptive-routing.json`. Without hosted configuration,
266
+ `workflow run` only emits local Adaptive Work Routing metadata and handoff files:
267
+ it does not query hosted context, call the hosted catalog, or spawn workers.
268
+
203
269
  ## Verification Plans
204
270
 
205
271
  Use `verify` when an agent asks what to prove before handoff or release:
package/dist/index.d.ts CHANGED
@@ -3,6 +3,136 @@ declare function resolveQueryFromToolInput(toolInput?: string, tool?: string): s
3
3
 
4
4
  declare function extractFilesFromToolInput(toolInput?: string): string[];
5
5
 
6
+ type ContextPackKind = "tool_output" | "log" | "diff" | "file" | "text" | "note";
7
+ interface ContextPackRecord {
8
+ version: "snipara.context_pack.v1";
9
+ id: string;
10
+ createdAt: string;
11
+ updatedAt: string;
12
+ kind: ContextPackKind;
13
+ label: string | null;
14
+ source: string | null;
15
+ tags: string[];
16
+ repoRoot: string;
17
+ sha256: string;
18
+ bytes: number;
19
+ lineCount: number;
20
+ contentType: "text/plain";
21
+ contentEncoding: "utf8";
22
+ preview: string;
23
+ expiresAt: string | null;
24
+ sensitive: boolean;
25
+ warnings: Array<{
26
+ code: string;
27
+ message: string;
28
+ }>;
29
+ storage: {
30
+ baseRelativePath: string;
31
+ manifestRelativePath: string;
32
+ blobRelativePath: string;
33
+ };
34
+ }
35
+ interface PackContextOptions {
36
+ cwd?: string;
37
+ content: string;
38
+ label?: string;
39
+ source?: string;
40
+ kind?: string;
41
+ tags?: string[];
42
+ ttlDays?: number;
43
+ maxBytes?: number;
44
+ allowSensitive?: boolean;
45
+ now?: Date;
46
+ }
47
+ interface ContextPackPackCommandOptions {
48
+ cwd?: string;
49
+ text?: string;
50
+ file?: string;
51
+ input?: string;
52
+ label?: string;
53
+ source?: string;
54
+ kind?: string;
55
+ tags?: string[];
56
+ ttlDays?: number;
57
+ maxBytes?: number;
58
+ allowSensitive?: boolean;
59
+ json?: boolean;
60
+ }
61
+ interface ContextPackRetrieveCommandOptions {
62
+ cwd?: string;
63
+ output?: string;
64
+ metadataOnly?: boolean;
65
+ json?: boolean;
66
+ }
67
+ interface ContextPackStatsCommandOptions {
68
+ cwd?: string;
69
+ json?: boolean;
70
+ }
71
+ interface ContextPackCleanCommandOptions {
72
+ cwd?: string;
73
+ all?: boolean;
74
+ expired?: boolean;
75
+ olderThanDays?: number;
76
+ dryRun?: boolean;
77
+ json?: boolean;
78
+ now?: Date;
79
+ }
80
+ interface ContextPackStoragePaths {
81
+ repoRoot: string;
82
+ baseDir: string;
83
+ blobsDir: string;
84
+ manifestsDir: string;
85
+ latestPath: string;
86
+ }
87
+ interface PackContextResult {
88
+ record: ContextPackRecord;
89
+ created: boolean;
90
+ baseDir: string;
91
+ manifestPath: string;
92
+ blobPath: string;
93
+ }
94
+ interface RetrieveContextPackResult {
95
+ record: ContextPackRecord;
96
+ content: string;
97
+ baseDir: string;
98
+ manifestPath: string;
99
+ blobPath: string;
100
+ }
101
+ interface ContextPackStats {
102
+ version: "snipara.context_pack.stats.v1";
103
+ baseDir: string;
104
+ totalPacks: number;
105
+ totalBytes: number;
106
+ sensitivePacks: number;
107
+ expiredPacks: number;
108
+ kinds: Record<string, number>;
109
+ oldestCreatedAt: string | null;
110
+ newestCreatedAt: string | null;
111
+ latestId: string | null;
112
+ }
113
+ interface ContextPackCleanResult {
114
+ version: "snipara.context_pack.clean.v1";
115
+ baseDir: string;
116
+ dryRun: boolean;
117
+ selected: number;
118
+ deleted: number;
119
+ deletedIds: string[];
120
+ }
121
+ declare function getContextPackStoragePaths(cwd?: string): ContextPackStoragePaths;
122
+ declare function packContext(options: PackContextOptions): PackContextResult;
123
+ declare function resolveContextPackRecord(idOrRef: string, cwd?: string): {
124
+ paths: ContextPackStoragePaths;
125
+ record: ContextPackRecord;
126
+ manifestPath: string;
127
+ };
128
+ declare function retrieveContextPack(idOrRef: string, cwd?: string): RetrieveContextPackResult;
129
+ declare function buildContextPackStats(options?: ContextPackStatsCommandOptions): ContextPackStats;
130
+ declare function cleanContextPacks(options?: ContextPackCleanCommandOptions): ContextPackCleanResult;
131
+ declare function contextPackPackCommand(options: ContextPackPackCommandOptions): Promise<void>;
132
+ declare function contextPackRetrieveCommand(idOrRef: string, options?: ContextPackRetrieveCommandOptions): Promise<void>;
133
+ declare function contextPackStatsCommand(options?: ContextPackStatsCommandOptions): Promise<void>;
134
+ declare function contextPackCleanCommand(options?: ContextPackCleanCommandOptions): Promise<void>;
135
+
6
136
  type PrivacyLevel = "standard" | "sensitive" | "restricted";
7
137
  type CanonicalEventType = "session_start" | "session_end" | "compact" | "message_user" | "message_assistant" | "tool_call" | "tool_result" | "file_changed" | "error_observed";
8
138
  interface CanonicalEventOptions {
@@ -13,7 +143,44 @@ interface CanonicalEventOptions {
13
143
  agentId?: string;
14
144
  privacyLevel?: PrivacyLevel;
15
145
  payload?: Record<string, unknown>;
146
+ contextPackReceipts?: LocalContextPackReceiptPayload[];
147
+ }
148
+ type LocalContextPackReceiptOperation = "pack" | "retrieve" | "reference";
149
+ interface LocalContextPackReceiptPayload {
150
+ version: "snipara.context_pack.receipt.v1";
151
+ receipt_id: string;
152
+ pack_id: string;
153
+ operation: LocalContextPackReceiptOperation;
154
+ content_uploaded: false;
155
+ policy_decision: "local_only" | "blocked" | "metadata_only";
156
+ privacy_level: PrivacyLevel;
157
+ kind: ContextPackRecord["kind"];
158
+ label?: string | null;
159
+ source?: string | null;
160
+ tags: string[];
161
+ bytes: number;
162
+ line_count: number;
163
+ payload_digest?: string;
164
+ sensitive: boolean;
165
+ created_at: string;
166
+ expires_at?: string | null;
167
+ local_ref: {
168
+ base_relative_path: string;
169
+ manifest_relative_path: string;
170
+ };
16
171
  }
172
+ declare function buildLocalContextPackReceipt(record: ContextPackRecord, options?: {
173
+ operation?: LocalContextPackReceiptOperation;
174
+ privacyLevel?: PrivacyLevel;
175
+ policyDecision?: LocalContextPackReceiptPayload["policy_decision"];
176
+ }): LocalContextPackReceiptPayload;
177
+ declare function buildLocalContextPackReceipts(options: {
178
+ ids: string[];
179
+ cwd?: string;
180
+ operation?: LocalContextPackReceiptOperation;
181
+ privacyLevel?: PrivacyLevel;
182
+ }): LocalContextPackReceiptPayload[];
183
+ declare function attachLocalContextPackReceipts(payload: Record<string, unknown>, receipts: LocalContextPackReceiptPayload[]): Record<string, unknown>;
17
184
  declare function buildCanonicalEvent(options: CanonicalEventOptions): {
18
185
  type: CanonicalEventType;
19
186
  client: string;
@@ -379,6 +546,33 @@ interface AutomationConfigBundle {
379
546
  files: AutomationConfigFile[];
380
547
  instructions: string[];
381
548
  }
549
+ interface ProjectAutomationSettings {
550
+ automationClient?: string;
551
+ autoInjectContext?: boolean;
552
+ trackAccessedFiles?: boolean;
553
+ preserveOnCompaction?: boolean;
554
+ restoreOnSessionStart?: boolean;
555
+ enrichPrompts?: boolean;
556
+ maxTokensPerQuery?: number;
557
+ searchMode?: string;
558
+ includeSummaries?: boolean;
559
+ adaptiveRoutingMode?: string;
560
+ adaptiveRoutingRequireApproval?: boolean;
561
+ adaptiveRoutingPlannerRetainsReasoning?: boolean;
562
+ adaptiveRoutingPreferLocalWorkers?: boolean;
563
+ adaptiveRoutingAllowedEndpointTypes?: string[];
564
+ adaptiveRoutingPreferredEndpointTypes?: string[];
565
+ adaptiveRoutingAllowedWorkerClasses?: string[];
566
+ adaptiveRoutingFallback?: string;
567
+ adaptiveRoutingDailyBudgetCents?: number;
568
+ adaptiveRoutingMonthlyBudgetCents?: number;
569
+ adaptiveRoutingCatalogLimit?: number;
570
+ }
571
+ interface ProjectAutomationSettingsResult {
572
+ settings: ProjectAutomationSettings;
573
+ plan?: string;
574
+ featureAvailability?: Record<string, unknown>;
575
+ }
382
576
  interface RecentAutomationEvent {
383
577
  id: string;
384
578
  sessionId: string;
@@ -986,6 +1180,7 @@ declare class RLMClient {
986
1180
  limit?: number;
987
1181
  }): Promise<RecentAutomationEventsResult>;
988
1182
  getAutomationConfigBundle(client: string): Promise<AutomationConfigBundle>;
1183
+ getAutomationSettings(): Promise<ProjectAutomationSettingsResult>;
989
1184
  evaluateStuckGuard(args?: EvaluateStuckGuardArgs): Promise<StuckGuardEvaluationResult>;
990
1185
  getStuckGuardStatus(args?: {
991
1186
  sessionId?: string;
@@ -2792,6 +2987,7 @@ interface OrchestratorHandoffRuntimeSandboxPhase {
2792
2987
  bootstrapQuery: string;
2793
2988
  files: string[];
2794
2989
  artifacts: string[];
2990
+ contextPacks: string[];
2795
2991
  sessionId: string | null;
2796
2992
  environment: string | null;
2797
2993
  profile: string | null;
@@ -2820,6 +3016,7 @@ interface AdaptiveModelRequirements {
2820
3016
  writeScope: string[];
2821
3017
  preferredEndpointTypes?: string[];
2822
3018
  allowedEndpointTypes?: string[];
3019
+ catalogLimit?: number;
2823
3020
  fallback: "main_agent";
2824
3021
  }
2825
3022
  interface AdaptiveRoutingCostEstimate {
@@ -2864,6 +3061,7 @@ interface AdaptiveWorkRoutingOptions {
2864
3061
  allowedEndpointTypes?: string[];
2865
3062
  workerRole?: string;
2866
3063
  plannerRetainsReasoning?: boolean;
3064
+ catalogLimit?: number;
2867
3065
  }
2868
3066
  interface OrchestratorHandoffArtifact {
2869
3067
  schemaVersion: "snipara.orchestrator.handoff.v1";
@@ -2956,4 +3154,4 @@ declare function buildOrchestratorHandoff(options: OrchestratorHandoffOptions):
2956
3154
  declare function buildAdaptiveWorkRoutingRecommendation(options: AdaptiveWorkRoutingOptions): AdaptiveWorkRoutingRecommendation;
2957
3155
  declare function writeOrchestratorHandoff(options: OrchestratorHandoffOptions): WrittenOrchestratorHandoff;
2958
3156
 
2959
- export { AUTOMATION_MANIFEST_RELATIVE_PATH, AutomationInstallConflictError, AutomationUnsupportedHookBundleError, COLLABORATION_STATE_RELATIVE_PATH, ORCHESTRATOR_HANDOFF_RELATIVE_PATH, TEAM_SYNC_STATE_RELATIVE_PATH, WORKFLOW_PLANS_RELATIVE_DIR, WORKFLOW_STATE_RELATIVE_PATH, archiveInactiveTeamSyncWork, autoArchiveTeamSyncState, buildAdaptiveWorkRoutingRecommendation, buildAgenticHandoffMarkdown, buildAgenticTimeline, buildAgenticWorkStatus, buildAutomationInstallPlan, buildCanonicalEvent, buildCodeHooksInstallPlan, buildCodePromotionResult, buildCodeStatusResult, buildCodeSyncResult, buildCollaborationActor, buildCollaborationGuardActionCards, buildCollaborationHooksInstallPlan, buildEvalCaseArtifact, buildGeneratedWorkflowPlanDocument, buildHostedCodeOverlayUploadPayload, buildHostedGuardPayload, buildJournalCheckpointEntry, buildLocalCallersResult, buildLocalCodeOverlay, buildLocalImpactResult, buildLocalImportsResult, buildLocalNeighborsResult, buildLocalShortestPathResult, buildMemoryAudit, buildOnboardFolderManifest, buildOrchestratorHandoff, buildProjectIntelligenceBrief, buildProjectIntelligenceRun, buildProjectJudgmentCard, buildSessionBootstrapQuality, buildSyncDocumentsDryRun, buildTeamSyncHandoffRecord, buildTeamSyncStartWorkRecord, buildTeamSyncSummary, buildToolCallPayload, buildToolResultPayload, buildVerificationPlan, buildWorkflowImpactGate, buildWorkflowPhaseCommitSummary, buildWorkflowPlanScaffold, categoryFromGuardTag, classifyToolResult, collaborationIdeStatusCommand, collectSyncDocuments, collectSyncDocumentsInput, compactHostedGuardResources, completeTeamSyncStateFromEvidence, completeTeamSyncWorkFromEvidence, createClient, createEmptyCollaborationState, createEmptyTeamSyncState, createLocalQueryCache, deriveLocalCollaborationResourcesFromFiles, detectReleaseSurfacesFromFiles, detectRuntimeEnvironment, evalExportCommand, evalRunCommand, extractCommandFromToolInput, extractFilesFromToolInput, formatOrchestratorRecommendationReason, formatProjectJudgmentCard, formatStuckGuardDecision, getAutomationManifestPath, getAutomationStatus, getCollaborationStatePath, getConfigPath, getLocalCodeOverlayCachePath, getLocalCodePromotionStatePath, getOrchestratorRecommendation, getPlanStepDisplayTitle, getStagedFiles, getStuckGuardInjection, getTeamSyncStatePath, ingestReferences, installAutomationBundle, listProjectsForApiKey, loadAutomationManifest, loadCollaborationState, loadConfig, loadTeamSyncState, memoryAuditCommand, memoryCleanCandidatesCommand, memoryCompactCommand, memoryHealthCommand, memoryLocalCommand, normalizeCollaborationFiles, normalizeGuardTag, normalizeWorkflowPlanInput, parseCollaborationResources, projectIntelligenceBriefCommand, projectIntelligenceRunCommand, readLocalCodeOverlayCache, readLocalCodePromotionState, referencesIngestCommand, referencesScanCommand, resolveFullWorkflowTokenBudget, resolveQueryFromToolInput, runMemoryGuardCheck, saveCollaborationState, saveConfig, saveTeamSyncState, scanReferences, shouldSuggestOrchestratorForWorkflow, shouldSuggestRuntimeForWorkflow, summarizeLocalCodeOverlay, teamSyncSweepCommand, validatePlanResult, verifyCommand, writeLocalCodeOverlayCache, writeLocalCodePromotionState, writeOrchestratorHandoff };
3157
+ export { AUTOMATION_MANIFEST_RELATIVE_PATH, AutomationInstallConflictError, AutomationUnsupportedHookBundleError, COLLABORATION_STATE_RELATIVE_PATH, ORCHESTRATOR_HANDOFF_RELATIVE_PATH, TEAM_SYNC_STATE_RELATIVE_PATH, WORKFLOW_PLANS_RELATIVE_DIR, WORKFLOW_STATE_RELATIVE_PATH, archiveInactiveTeamSyncWork, attachLocalContextPackReceipts, autoArchiveTeamSyncState, buildAdaptiveWorkRoutingRecommendation, buildAgenticHandoffMarkdown, buildAgenticTimeline, buildAgenticWorkStatus, buildAutomationInstallPlan, buildCanonicalEvent, buildCodeHooksInstallPlan, buildCodePromotionResult, buildCodeStatusResult, buildCodeSyncResult, buildCollaborationActor, buildCollaborationGuardActionCards, buildCollaborationHooksInstallPlan, buildContextPackStats, buildEvalCaseArtifact, buildGeneratedWorkflowPlanDocument, buildHostedCodeOverlayUploadPayload, buildHostedGuardPayload, buildJournalCheckpointEntry, buildLocalCallersResult, buildLocalCodeOverlay, buildLocalContextPackReceipt, buildLocalContextPackReceipts, buildLocalImpactResult, buildLocalImportsResult, buildLocalNeighborsResult, buildLocalShortestPathResult, buildMemoryAudit, buildOnboardFolderManifest, buildOrchestratorHandoff, buildProjectIntelligenceBrief, buildProjectIntelligenceRun, buildProjectJudgmentCard, buildSessionBootstrapQuality, buildSyncDocumentsDryRun, buildTeamSyncHandoffRecord, buildTeamSyncStartWorkRecord, buildTeamSyncSummary, buildToolCallPayload, buildToolResultPayload, buildVerificationPlan, buildWorkflowImpactGate, buildWorkflowPhaseCommitSummary, buildWorkflowPlanScaffold, categoryFromGuardTag, classifyToolResult, cleanContextPacks, collaborationIdeStatusCommand, collectSyncDocuments, collectSyncDocumentsInput, compactHostedGuardResources, completeTeamSyncStateFromEvidence, completeTeamSyncWorkFromEvidence, contextPackCleanCommand, contextPackPackCommand, contextPackRetrieveCommand, contextPackStatsCommand, createClient, createEmptyCollaborationState, createEmptyTeamSyncState, createLocalQueryCache, deriveLocalCollaborationResourcesFromFiles, detectReleaseSurfacesFromFiles, detectRuntimeEnvironment, evalExportCommand, evalRunCommand, extractCommandFromToolInput, extractFilesFromToolInput, formatOrchestratorRecommendationReason, formatProjectJudgmentCard, formatStuckGuardDecision, getAutomationManifestPath, getAutomationStatus, getCollaborationStatePath, getConfigPath, getContextPackStoragePaths, getLocalCodeOverlayCachePath, getLocalCodePromotionStatePath, getOrchestratorRecommendation, getPlanStepDisplayTitle, getStagedFiles, getStuckGuardInjection, getTeamSyncStatePath, ingestReferences, installAutomationBundle, listProjectsForApiKey, loadAutomationManifest, loadCollaborationState, loadConfig, loadTeamSyncState, memoryAuditCommand, memoryCleanCandidatesCommand, memoryCompactCommand, memoryHealthCommand, memoryLocalCommand, normalizeCollaborationFiles, normalizeGuardTag, normalizeWorkflowPlanInput, packContext, parseCollaborationResources, projectIntelligenceBriefCommand, projectIntelligenceRunCommand, readLocalCodeOverlayCache, readLocalCodePromotionState, referencesIngestCommand, referencesScanCommand, resolveContextPackRecord, resolveFullWorkflowTokenBudget, resolveQueryFromToolInput, retrieveContextPack, runMemoryGuardCheck, saveCollaborationState, saveConfig, saveTeamSyncState, scanReferences, shouldSuggestOrchestratorForWorkflow, shouldSuggestRuntimeForWorkflow, summarizeLocalCodeOverlay, teamSyncSweepCommand, validatePlanResult, verifyCommand, writeLocalCodeOverlayCache, writeLocalCodePromotionState, writeOrchestratorHandoff };