@quantiya/codevibe-claude-plugin 2.0.75 → 2.0.77
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/.claude-plugin/plugin.json +1 -1
- package/node_modules/@quantiya/codevibe-core/dist/appsync/appsync-client.d.ts +41 -10
- package/node_modules/@quantiya/codevibe-core/dist/appsync/queries.d.ts +4 -0
- package/node_modules/@quantiya/codevibe-core/dist/appsync/session-freshness.d.ts +12 -0
- package/node_modules/@quantiya/codevibe-core/dist/index.js +643 -562
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/brainstorm-context.d.ts +11 -0
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/cli.d.ts +11 -1
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/cli.js +55632 -53046
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/conductor-reply.d.ts +37 -0
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/context-items.d.ts +64 -0
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/index.d.ts +44 -2
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/resume-modal.d.ts +19 -0
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/slash-router.d.ts +2 -0
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/types.d.ts +48 -2
- package/node_modules/@quantiya/codevibe-core/dist/session/pending-session-create.d.ts +31 -0
- package/node_modules/@quantiya/codevibe-core/dist/session-resume/ResumePicker.d.ts +21 -0
- package/node_modules/@quantiya/codevibe-core/dist/session-resume/carry-over.d.ts +81 -0
- package/node_modules/@quantiya/codevibe-core/dist/session-resume/clean-exit.d.ts +33 -0
- package/node_modules/@quantiya/codevibe-core/dist/session-resume/cli-resume.d.ts +41 -0
- package/node_modules/@quantiya/codevibe-core/dist/session-resume/completeness-copy.d.ts +52 -0
- package/node_modules/@quantiya/codevibe-core/dist/session-resume/create-outcome.d.ts +43 -0
- package/node_modules/@quantiya/codevibe-core/dist/session-resume/e2e-fault.d.ts +28 -0
- package/node_modules/@quantiya/codevibe-core/dist/session-resume/hosted-loader.d.ts +88 -0
- package/node_modules/@quantiya/codevibe-core/dist/session-resume/local-completeness.d.ts +10 -0
- package/node_modules/@quantiya/codevibe-core/dist/session-resume/local-records.d.ts +121 -0
- package/node_modules/@quantiya/codevibe-core/dist/session-resume/picker-rows.d.ts +17 -0
- package/node_modules/@quantiya/codevibe-core/dist/session-resume/publish-retire.d.ts +40 -0
- package/node_modules/@quantiya/codevibe-core/dist/session-resume/relaunch.d.ts +72 -0
- package/node_modules/@quantiya/codevibe-core/dist/session-resume/restore-conversation.d.ts +27 -0
- package/node_modules/@quantiya/codevibe-core/dist/session-resume/resume-candidates.d.ts +52 -0
- package/node_modules/@quantiya/codevibe-core/dist/session-resume/resume-chosen.d.ts +103 -0
- package/node_modules/@quantiya/codevibe-core/dist/session-resume/resume-create.d.ts +121 -0
- package/node_modules/@quantiya/codevibe-core/dist/session-resume/resume-entry.d.ts +87 -0
- package/node_modules/@quantiya/codevibe-core/dist/session-resume/resume-header.d.ts +25 -0
- package/node_modules/@quantiya/codevibe-core/dist/session-resume/resume-io.d.ts +34 -0
- package/node_modules/@quantiya/codevibe-core/dist/session-resume/resume-ledger.d.ts +107 -0
- package/node_modules/@quantiya/codevibe-core/dist/session-resume/resume-messages.d.ts +68 -0
- package/node_modules/@quantiya/codevibe-core/dist/session-resume/resume-rows.d.ts +24 -0
- package/node_modules/@quantiya/codevibe-core/dist/session-resume/resume-target.d.ts +65 -0
- package/node_modules/@quantiya/codevibe-core/dist/session-resume/shell-resume-io.d.ts +25 -0
- package/node_modules/@quantiya/codevibe-core/dist/session-resume/shell-resume.d.ts +34 -0
- package/node_modules/@quantiya/codevibe-core/dist/session-resume/source-choice.d.ts +37 -0
- package/node_modules/@quantiya/codevibe-core/dist/session-resume/successor-carry-over.d.ts +54 -0
- package/node_modules/@quantiya/codevibe-core/dist/session-resume/will-retire.d.ts +24 -0
- package/node_modules/@quantiya/codevibe-core/dist/substrate/sandbox-exec.d.ts +7 -0
- package/node_modules/@quantiya/codevibe-core/dist/types/session.d.ts +67 -0
- package/node_modules/@quantiya/codevibe-core/package.json +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* P61 §12.9 (S2-C4, C2-F2) — the conductor turn's text and its advisory
|
|
3
|
+
* segment boundaries.
|
|
4
|
+
*
|
|
5
|
+
* The persisted conductor `turn` joins every non-`localOnly` advisory of the
|
|
6
|
+
* turn (trimmed, blank-line separated). The join loses each advisory's
|
|
7
|
+
* boundaries, `source` and `handoffExcluded` flag, which the hand-off
|
|
8
|
+
* collectors use. `advisorySegments` records them in the item's telemetry —
|
|
9
|
+
* inside the encrypted envelope and the chain hash, outside the content
|
|
10
|
+
* address — so a resumed session can rebuild exactly the entries P had.
|
|
11
|
+
* The text is byte-identical to the join it replaces.
|
|
12
|
+
*/
|
|
13
|
+
export interface AdvisorySegment {
|
|
14
|
+
/** UTF-16 offsets into `body.text` (JavaScript string indices). */
|
|
15
|
+
start: number;
|
|
16
|
+
end: number;
|
|
17
|
+
source: 'planner' | 'shell';
|
|
18
|
+
handoffExcluded?: true;
|
|
19
|
+
}
|
|
20
|
+
interface AdvisoryLike {
|
|
21
|
+
kind: string;
|
|
22
|
+
text?: string;
|
|
23
|
+
source?: 'planner' | 'shell';
|
|
24
|
+
localOnly?: boolean;
|
|
25
|
+
handoffExcluded?: boolean;
|
|
26
|
+
}
|
|
27
|
+
export declare function buildConductorReply(delta: readonly AdvisoryLike[]): {
|
|
28
|
+
text: string;
|
|
29
|
+
segments: AdvisorySegment[];
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Read `advisorySegments` back from a carried conductor turn. Returns null
|
|
33
|
+
* when the field is absent or does not exactly tile the text, so the caller
|
|
34
|
+
* applies the conservative per-item legacy rule (§12.4).
|
|
35
|
+
*/
|
|
36
|
+
export declare function parseAdvisorySegments(text: string, telemetry: unknown): AdvisorySegment[] | null;
|
|
37
|
+
export {};
|
|
@@ -135,6 +135,8 @@ export declare const CONTEXT_ITEM_TTL_SECONDS: number;
|
|
|
135
135
|
export declare function ensureContextItemsSessionDirectoryDurable(sessionId: string, beforeParentFsync?: (parent: string, child: string) => Promise<void>): Promise<void>;
|
|
136
136
|
/** Exported for the A1f retention sweep (`gcContextItemLogs`). */
|
|
137
137
|
export declare function contextItemsRootDir(): string;
|
|
138
|
+
/** Filesystem-safe per-session dir key (session ids are opaque routing ids). */
|
|
139
|
+
export declare function sessionDirKey(sessionId: string): string;
|
|
138
140
|
/** Exported for tests + diagnostics. */
|
|
139
141
|
export declare function contextItemsLogPath(sessionId: string): string;
|
|
140
142
|
/**
|
|
@@ -173,6 +175,15 @@ export declare function getContextItemLog(sessionId: string): {
|
|
|
173
175
|
readDurableSnapshot: () => Promise<string | null>;
|
|
174
176
|
commitAndVerifyAgentTurnBatch: (humanOccurrence: ContextItemOccurrence, drafts: CanonicalAgentTurnDraft[]) => Promise<ContextDurabilityReceipt>;
|
|
175
177
|
};
|
|
178
|
+
/**
|
|
179
|
+
* P61 clean-exit tail for the INACTIVE update (design §9.4, §12.7). Reads the
|
|
180
|
+
* session's log only if this process already holds it — it never creates a
|
|
181
|
+
* writer — and returns null when there is none or its tail is unknown.
|
|
182
|
+
*/
|
|
183
|
+
export declare function getContextItemLogTail(sessionId: string): {
|
|
184
|
+
seq: string;
|
|
185
|
+
itemSha256: string;
|
|
186
|
+
} | null;
|
|
176
187
|
/**
|
|
177
188
|
* Append one typed item to the session's canonical log (the deterministic-
|
|
178
189
|
* emitter write path). Convenience over `getContextItemLog`.
|
|
@@ -213,6 +224,59 @@ export interface VerifiedContextItemsResult extends ChainVerificationResult {
|
|
|
213
224
|
/** The full parsed chain — EMPTY unless `ok === true` (fail-closed). */
|
|
214
225
|
items: ContextItem[];
|
|
215
226
|
}
|
|
227
|
+
/** P61 B-8 — the outcome of a read-only read of a session's local log. */
|
|
228
|
+
export type ReadOnlyContextLogResult = {
|
|
229
|
+
status: 'ok';
|
|
230
|
+
items: ContextItem[];
|
|
231
|
+
/** The chain's end, as the clean-exit `contextTail` would name it; null for an empty log. */
|
|
232
|
+
tail: {
|
|
233
|
+
seq: string;
|
|
234
|
+
itemSha256: string;
|
|
235
|
+
} | null;
|
|
236
|
+
/** An uncommitted AGENT_TURN batch was left out in memory (the writer would truncate it). */
|
|
237
|
+
virtualRollback: boolean;
|
|
238
|
+
} | {
|
|
239
|
+
status: 'absent';
|
|
240
|
+
} | {
|
|
241
|
+
status: 'unreadable';
|
|
242
|
+
/**
|
|
243
|
+
* `key-unavailable`, `read-error`, `recovery-journal` and
|
|
244
|
+
* `unsealable-line` (a sealed line that will not unseal while the key is
|
|
245
|
+
* available — §8.1's "unreadable local log") all fall back to the hosted
|
|
246
|
+
* copy. `integrity` (every line unseals, the chain does not verify) is
|
|
247
|
+
* refused with no fallback.
|
|
248
|
+
*/
|
|
249
|
+
reason: 'read-error' | 'key-unavailable' | 'recovery-journal' | 'unsealable-line' | 'integrity';
|
|
250
|
+
chainReason?: ChainVerificationResult['reason'];
|
|
251
|
+
};
|
|
252
|
+
/**
|
|
253
|
+
* P61 B-8 (design §8.1, INV-3) — read a session's local log **without ever
|
|
254
|
+
* writing**: no writer is created, nothing is flushed, truncated, rotated or
|
|
255
|
+
* unlinked. A crash-interrupted AGENT_TURN batch is resolved in memory by the
|
|
256
|
+
* writer's own rule (`recoverAgentTurnTransaction`): a pending journal with
|
|
257
|
+
* its matching commit keeps the log only at the journaled post-size; without
|
|
258
|
+
* the commit, only the bytes before the journaled pre-size count. Anything the
|
|
259
|
+
* writer would block on is `unreadable` here, never guessed.
|
|
260
|
+
*/
|
|
261
|
+
export declare function readContextLogReadOnly(sessionId: string): Promise<ReadOnlyContextLogResult>;
|
|
262
|
+
/**
|
|
263
|
+
* One context-log line after unsealing: its plaintext JSON and whether it was
|
|
264
|
+
* a sealed envelope, or `null` when it could not be unsealed.
|
|
265
|
+
*/
|
|
266
|
+
export type ContextLogLineEntry = {
|
|
267
|
+
json: string;
|
|
268
|
+
wasEnvelope: boolean;
|
|
269
|
+
} | null;
|
|
270
|
+
/**
|
|
271
|
+
* P61 §8.1 — the single, PURE chain verifier (extracted unchanged from the
|
|
272
|
+
* disk reader above). It checks, line by line and in this order: unsealed,
|
|
273
|
+
* sealed envelope, parseable, REQUIRED shape, session match, `prev_hash`
|
|
274
|
+
* linkage, strictly increasing `seq`, content address. The first failing line
|
|
275
|
+
* decides; any failure returns no items. It hashes the plaintext JSON, so it
|
|
276
|
+
* runs unchanged over decrypted hosted rows (pass `wasEnvelope: true`) and
|
|
277
|
+
* over a read-only snapshot that never creates a log writer.
|
|
278
|
+
*/
|
|
279
|
+
export declare function verifyContextLogEntries(sessionId: string, entries: ContextLogLineEntry[]): VerifiedContextItemsResult;
|
|
216
280
|
export declare function readVerifiedContextItems(sessionId: string): Promise<VerifiedContextItemsResult>;
|
|
217
281
|
/**
|
|
218
282
|
* §4.2 chain authority (a) — the ON-DEVICE `verify_chain` over decrypted
|
|
@@ -24,6 +24,9 @@ import { AdvisoryAttachmentJournal } from './advisory-attachment-journal';
|
|
|
24
24
|
import type { ImageAttachment } from './types';
|
|
25
25
|
import { type GateDecisionSubmitDeps, type GroupDecisionSubmitDeps } from './gate-decision-submit';
|
|
26
26
|
import { type WorkspaceOutcomeSinkTap } from './workspace-terminal-coordinator';
|
|
27
|
+
import { runShellResumeInShell } from '../session-resume/shell-resume-io';
|
|
28
|
+
import type { ShellResumeOutcome } from '../session-resume/shell-resume';
|
|
29
|
+
import { type RelaunchRequest } from '../session-resume/relaunch';
|
|
27
30
|
export { executeGitStatusSummary } from './git-status-summary';
|
|
28
31
|
import { type ContinuationCliResult, type ContinuationCliDeps } from './slash-routes/continuation';
|
|
29
32
|
import { loadReviewerWizardData } from './slash-routes/reviewers';
|
|
@@ -111,6 +114,35 @@ export interface RunOrchestrationShellArgs {
|
|
|
111
114
|
* teardown `finally` is armed; until then the admitting CLI owns retirement.
|
|
112
115
|
*/
|
|
113
116
|
acceptSessionLifecycleOwnership?: () => void;
|
|
117
|
+
/**
|
|
118
|
+
* P61 §12.4/§5.4 — present when this shell continues a resumed session S.
|
|
119
|
+
* The shell seeds the carried exchanges (`RESTORE_CONVERSATION`) under the
|
|
120
|
+
* §5.4 header before any turn exists, records the carry-over marker's `seq`
|
|
121
|
+
* for the clean-exit flag, and calls `onStarted` once it owns S's lifecycle
|
|
122
|
+
* (the resume entry point then releases P's resume lock).
|
|
123
|
+
*/
|
|
124
|
+
resume?: {
|
|
125
|
+
restoredItems: import('./context-items').ContextItem[];
|
|
126
|
+
markerSeq: string;
|
|
127
|
+
header: {
|
|
128
|
+
top: string;
|
|
129
|
+
warnings: string[];
|
|
130
|
+
bottom: string;
|
|
131
|
+
};
|
|
132
|
+
onStarted?: () => void | Promise<void>;
|
|
133
|
+
};
|
|
134
|
+
/**
|
|
135
|
+
* @internal P61 §5.3 — set by `runOrchestrationShell` itself. A `/resume`
|
|
136
|
+
* switch records P and the lock hand-off token here; teardown marks
|
|
137
|
+
* `converged` when every phase finished (the same point as the owner
|
|
138
|
+
* record's finished mark).
|
|
139
|
+
*/
|
|
140
|
+
resumeSwitch?: {
|
|
141
|
+
request: RelaunchRequest | null;
|
|
142
|
+
converged: boolean;
|
|
143
|
+
};
|
|
144
|
+
/** @internal Test seam for `/resume` (defaults to the production bindings). */
|
|
145
|
+
runShellResumeFn?: (opts: Parameters<typeof runShellResumeInShell>[0]) => Promise<ShellResumeOutcome>;
|
|
114
146
|
/** @internal isolated durable advisory-attachment authority for tests. */
|
|
115
147
|
advisoryAttachmentJournal?: AdvisoryAttachmentJournal;
|
|
116
148
|
/**
|
|
@@ -376,12 +408,22 @@ export declare function wireTeamMergeAuditSummary(store: OrchestrationStore, tar
|
|
|
376
408
|
fn?: (summary: any) => void;
|
|
377
409
|
onTeamMergeAuditSummary?: (summary: any) => void;
|
|
378
410
|
}): void;
|
|
411
|
+
/** P61 B-12 — what the shell asks its caller to do after it ends. */
|
|
412
|
+
export interface ShellExitResult {
|
|
413
|
+
/** A `/resume` switch whose teardown converged: relaunch as `--resume <P>` (§12.6). */
|
|
414
|
+
relaunch?: RelaunchRequest;
|
|
415
|
+
/** A `/resume` switch whose teardown did not converge: print the command (§5.3 step 2). */
|
|
416
|
+
switchFailedFor?: string;
|
|
417
|
+
/** With `relaunch`: the session C that just ended, named if the child fails (§10). */
|
|
418
|
+
currentSessionId?: string;
|
|
419
|
+
}
|
|
379
420
|
/**
|
|
380
421
|
* §5 lines 336-365 LOCK + §16 LOCK #14. Single entrypoint that wires
|
|
381
422
|
* the store + emit chokepoint + slash router and either mounts the
|
|
382
|
-
* Ink TUI (TTY) or falls back to line-log (non-TTY).
|
|
423
|
+
* Ink TUI (TTY) or falls back to line-log (non-TTY). P61 B-12: returns the
|
|
424
|
+
* relaunch for a `/resume` switch only after a converged teardown.
|
|
383
425
|
*/
|
|
384
|
-
export declare function runOrchestrationShell(args: RunOrchestrationShellArgs): Promise<
|
|
426
|
+
export declare function runOrchestrationShell(args: RunOrchestrationShellArgs): Promise<ShellExitResult | undefined>;
|
|
385
427
|
/**
|
|
386
428
|
* PHASE-CP-1-F.1 Part B (LOCK L7) — the bound on the async per-round summary
|
|
387
429
|
* fetch fired AFTER a final-approval prompt is queued. The decision never
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* P61 §5.2/§5.3 — the in-shell `/resume` picker and §8.4 continue/cancel
|
|
3
|
+
* choice. A pre-shell launch mounts its own Ink render (`ResumePicker.tsx`);
|
|
4
|
+
* inside the running shell the same components replace the `<InputBar>`
|
|
5
|
+
* through store state, and the awaiting `/resume` handler is resolved by the
|
|
6
|
+
* component's callbacks. One modal per store at a time.
|
|
7
|
+
*/
|
|
8
|
+
import type { PickerRow } from '../session-resume/picker-rows';
|
|
9
|
+
import type { OrchestrationAction } from './types';
|
|
10
|
+
type Dispatch = {
|
|
11
|
+
dispatch(action: OrchestrationAction): void;
|
|
12
|
+
};
|
|
13
|
+
/** The picker: resolves the chosen session ID, or null on Esc. */
|
|
14
|
+
export declare function pickInShell(store: Dispatch, rows: PickerRow[]): Promise<string | null>;
|
|
15
|
+
/** The §8.4 choice: true for "Continue without …"; Cancel (the default) is false. */
|
|
16
|
+
export declare function chooseInShell(store: Dispatch, prompt: string, continueLabel: string): Promise<boolean>;
|
|
17
|
+
/** Called by the rendered modal (and by teardown, with null): close it and resolve the waiter. */
|
|
18
|
+
export declare function settleResumeModal(store: Dispatch, value: string | boolean | null): void;
|
|
19
|
+
export {};
|
|
@@ -41,6 +41,8 @@ export interface SlashCommandInfo {
|
|
|
41
41
|
*/
|
|
42
42
|
export declare const USER_RULE_PIN_PENDING = "PENDING \u2014 entrypoint pins the rule";
|
|
43
43
|
export declare const USER_RULES_LIST_PENDING = "PENDING \u2014 entrypoint lists pinned rules";
|
|
44
|
+
/** P61 §5.3 — the entrypoint resolves the target and runs the switch. */
|
|
45
|
+
export declare const RESUME_PENDING = "PENDING \u2014 entrypoint resumes a session";
|
|
44
46
|
export declare const USER_RULES_FORGET_PENDING = "PENDING \u2014 entrypoint retires a pinned rule";
|
|
45
47
|
/** True if `command` is a shell-exit command (`/quit` / `/exit`). */
|
|
46
48
|
export declare function isExitCommand(command: string): boolean;
|
|
@@ -339,6 +339,8 @@ export type ConversationEntry = {
|
|
|
339
339
|
* rewrite needs. Carried into `pending.attachmentPaths` when a clarification mints.
|
|
340
340
|
*/
|
|
341
341
|
imagePaths?: string[];
|
|
342
|
+
/** P61 §12.4 — seeded from a resumed session's carry-over; never part of a turn delta. */
|
|
343
|
+
restored?: true;
|
|
342
344
|
} | {
|
|
343
345
|
kind: 'planner-decision';
|
|
344
346
|
id: string;
|
|
@@ -348,6 +350,8 @@ export type ConversationEntry = {
|
|
|
348
350
|
rationale: string;
|
|
349
351
|
taskId?: string;
|
|
350
352
|
brainstorm?: BrainstormContextMetadata;
|
|
353
|
+
/** P61 §12.4 — seeded from a resumed session's carry-over. */
|
|
354
|
+
restored?: true;
|
|
351
355
|
} | {
|
|
352
356
|
kind: 'subagent-event';
|
|
353
357
|
id: string;
|
|
@@ -378,6 +382,11 @@ export type ConversationEntry = {
|
|
|
378
382
|
final: true;
|
|
379
383
|
command: string;
|
|
380
384
|
output: string;
|
|
385
|
+
/**
|
|
386
|
+
* P61 §5.3 — this output ends the shell like `/exit` (a `/resume` switch).
|
|
387
|
+
* The exit detectors honour it as well as `/exit` and `/quit`.
|
|
388
|
+
*/
|
|
389
|
+
exit?: true;
|
|
381
390
|
} | {
|
|
382
391
|
kind: 'advisory';
|
|
383
392
|
id: string;
|
|
@@ -387,6 +396,8 @@ export type ConversationEntry = {
|
|
|
387
396
|
text: string;
|
|
388
397
|
localOnly?: true;
|
|
389
398
|
handoffExcluded?: true;
|
|
399
|
+
/** P61 §12.4 — seeded from a resumed session's carry-over. */
|
|
400
|
+
restored?: true;
|
|
390
401
|
} | {
|
|
391
402
|
kind: 'gate-prompt';
|
|
392
403
|
id: string;
|
|
@@ -559,8 +570,9 @@ export interface PendingPlannerOffer {
|
|
|
559
570
|
* team (`launchTeamFromWorkItems`), so both paths share the numbering. A team
|
|
560
571
|
* group is one number (its child tasks render `#n.1`, `#n.2` via `state.team`).
|
|
561
572
|
* `retryOf` links a `#n retry` task (P46a C2/C3) to the `apply_failed` original.
|
|
562
|
-
* In-memory only
|
|
563
|
-
*
|
|
573
|
+
* In-memory only; nothing is persisted. Every launch is a new session with its
|
|
574
|
+
* own numbering, and so is a resume: it creates a successor session whose task
|
|
575
|
+
* numbers restart at #1 (P61 SESSION-RESUME-DESIGN §5.4, §7; amends P46 §2.4/A8).
|
|
564
576
|
*/
|
|
565
577
|
export interface TaskOrdinalRecord {
|
|
566
578
|
readonly ordinal: number;
|
|
@@ -858,6 +870,13 @@ export interface OrchestrationState {
|
|
|
858
870
|
* `<OrchestrationApp>` renders `<ImplementorSetupWizard>` in place of `<InputBar>`.
|
|
859
871
|
*/
|
|
860
872
|
implementorWizard: ImplementorWizardState | null;
|
|
873
|
+
/**
|
|
874
|
+
* P61 §5.2/§5.3 — the in-shell `/resume` picker or §8.4 continue/cancel
|
|
875
|
+
* choice. While non-null, `<OrchestrationApp>` renders it in place of the
|
|
876
|
+
* `<InputBar>`. Optional so existing state fixtures stay valid; absent and
|
|
877
|
+
* null both mean no modal.
|
|
878
|
+
*/
|
|
879
|
+
resumeModal?: ResumeModalState | null;
|
|
861
880
|
/**
|
|
862
881
|
* `[ADDITIVE WIDENING — O1 C1 (#652)]` per
|
|
863
882
|
* PHASE-O1-C1-SAFETY-OBSERVABILITY-DESIGN.md §3.1 item 1: the shell used to
|
|
@@ -981,11 +1000,23 @@ export interface ImplementorWizardState {
|
|
|
981
1000
|
* NEW variant or required field is tagged here before the reducer
|
|
982
1001
|
* consumes it.
|
|
983
1002
|
*/
|
|
1003
|
+
export type RestoredConversationEntry = Extract<ConversationEntry, {
|
|
1004
|
+
kind: 'user-message';
|
|
1005
|
+
} | {
|
|
1006
|
+
kind: 'advisory';
|
|
1007
|
+
} | {
|
|
1008
|
+
kind: 'planner-decision';
|
|
1009
|
+
}> & {
|
|
1010
|
+
restored: true;
|
|
1011
|
+
};
|
|
984
1012
|
export type OrchestrationAction = {
|
|
985
1013
|
type: 'USER_INPUT';
|
|
986
1014
|
text: string;
|
|
987
1015
|
attachments?: ImageAttachment[];
|
|
988
1016
|
imagePaths?: string[];
|
|
1017
|
+
} | {
|
|
1018
|
+
type: 'RESTORE_CONVERSATION';
|
|
1019
|
+
entries: ReadonlyArray<RestoredConversationEntry>;
|
|
989
1020
|
} | {
|
|
990
1021
|
type: 'PLANNER_DECISION';
|
|
991
1022
|
decision: PlannerDecision;
|
|
@@ -1012,6 +1043,7 @@ export type OrchestrationAction = {
|
|
|
1012
1043
|
type: 'SLASH_OUTPUT';
|
|
1013
1044
|
command: string;
|
|
1014
1045
|
output: string;
|
|
1046
|
+
exit?: true;
|
|
1015
1047
|
} | {
|
|
1016
1048
|
type: 'CLARIFICATION_ANSWERED';
|
|
1017
1049
|
answer: string;
|
|
@@ -1168,6 +1200,11 @@ export type OrchestrationAction = {
|
|
|
1168
1200
|
wizard: ImplementorWizardState;
|
|
1169
1201
|
} | {
|
|
1170
1202
|
type: 'IMPLEMENTOR_WIZARD_CLOSE';
|
|
1203
|
+
} | {
|
|
1204
|
+
type: 'RESUME_MODAL_OPEN';
|
|
1205
|
+
modal: ResumeModalState;
|
|
1206
|
+
} | {
|
|
1207
|
+
type: 'RESUME_MODAL_CLOSE';
|
|
1171
1208
|
} | {
|
|
1172
1209
|
type: 'AUDIT_FLAG_INDEX_RETAINED';
|
|
1173
1210
|
index: AuditFlagIndex;
|
|
@@ -1193,3 +1230,12 @@ export interface LastModeFile {
|
|
|
1193
1230
|
* `src/types/auth.ts` already.
|
|
1194
1231
|
*/
|
|
1195
1232
|
export type Tier = 'FREE' | 'PRO' | 'MAX';
|
|
1233
|
+
/** P61 §5.2/§5.3 — what the in-shell `/resume` modal shows. */
|
|
1234
|
+
export type ResumeModalState = {
|
|
1235
|
+
kind: 'picker';
|
|
1236
|
+
rows: import('../session-resume/picker-rows').PickerRow[];
|
|
1237
|
+
} | {
|
|
1238
|
+
kind: 'choice';
|
|
1239
|
+
prompt: string;
|
|
1240
|
+
continueLabel: string;
|
|
1241
|
+
};
|
|
@@ -21,6 +21,37 @@ declare function fingerprintIntent(intent: PendingSessionCreateIntent): string;
|
|
|
21
21
|
declare function readPending(sessionId: string): Promise<PendingSessionCreateRecord | null>;
|
|
22
22
|
declare function removePending(sessionId: string, record?: PendingSessionCreateRecord): Promise<void>;
|
|
23
23
|
declare function findPendingForIntent(intent: PendingSessionCreateIntent, logger: Logger): Promise<PendingSessionCreateRecord | null>;
|
|
24
|
+
export declare function localSigningFingerprint(publicKeyB64: string): string;
|
|
25
|
+
/**
|
|
26
|
+
* How the backend resolved a createSession call, relative to the sealed request.
|
|
27
|
+
* - `exact` — the backend admitted THIS sealed create byte-for-byte (it echoed
|
|
28
|
+
* our envelopes): our locally-generated key is authoritative.
|
|
29
|
+
* - `resume` — §4.9 resume-not-overwrite: a same-owner row already existed and
|
|
30
|
+
* the backend returned it verbatim, wrapping a DIFFERENT generation's
|
|
31
|
+
* key (K1) than we sealed (K2). The caller reconciles the key from
|
|
32
|
+
* the returned encryptedKeys (#229 / #230 Finding 1) and fails closed
|
|
33
|
+
* if this device is absent — never caching our local phantom.
|
|
34
|
+
*/
|
|
35
|
+
export type CreateResponseClass = 'exact' | 'resume';
|
|
36
|
+
/**
|
|
37
|
+
* Classify a backend createSession response against the sealed request, throwing
|
|
38
|
+
* `SESSION_CREATE_RESPONSE_MISMATCH` for anything that is NEITHER provably our own
|
|
39
|
+
* sealed create NOR a legitimate same-owner resume-not-overwrite.
|
|
40
|
+
*
|
|
41
|
+
* A syntactically valid response is not proof that this exact sealed create was
|
|
42
|
+
* admitted. Kill-switch sentinels (random `__blocked__` userId), cross-owner rows
|
|
43
|
+
* (the backend throws `Unauthorized`, but defense-in-depth here too), and
|
|
44
|
+
* stale/wrong-session responses must remain replayable instead of consuming the
|
|
45
|
+
* only durable request and caching a key under the wrong identity.
|
|
46
|
+
*
|
|
47
|
+
* The fresh-vs-resume signal is `envelopesMatch`. A real resume can NEVER echo our
|
|
48
|
+
* freshly-generated envelopes (K1 ≠ K2, wrapped anew every create), so:
|
|
49
|
+
* - divergent envelopes from the same owner → the resume (accept, `resume`);
|
|
50
|
+
* - matching envelopes (our own key) that still diverge on another identity field
|
|
51
|
+
* → corruption, not a resume (reject).
|
|
52
|
+
* §4.5 X3-AMEND-1 / §4.9 (tool-event consolidation #229 / #230 Finding 1).
|
|
53
|
+
*/
|
|
54
|
+
export declare function classifyCreateResponse(session: Session, request: CreateSessionInput): CreateResponseClass;
|
|
24
55
|
/**
|
|
25
56
|
* Persist one exact create envelope before network I/O and replay it unchanged
|
|
26
57
|
* after an ambiguous transport failure or process restart.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* P61 §5.2 — the resume picker and the §8.4 continue/cancel choice (Ink).
|
|
3
|
+
* Callers `await initInkRuntime()` first. Rows come from `toPickerRows`.
|
|
4
|
+
*/
|
|
5
|
+
import * as React from 'react';
|
|
6
|
+
import { type PickerRow } from './picker-rows';
|
|
7
|
+
export declare function ResumePicker(props: {
|
|
8
|
+
rows: PickerRow[];
|
|
9
|
+
onSelect: (sessionId: string) => void;
|
|
10
|
+
onCancel: () => void;
|
|
11
|
+
}): React.ReactElement;
|
|
12
|
+
export declare function ResumeChoice(props: {
|
|
13
|
+
prompt: string;
|
|
14
|
+
/** "Continue without them" (default) or, for a missing carry-over, "Continue without it". */
|
|
15
|
+
continueLabel?: string;
|
|
16
|
+
onChoose: (continueWithout: boolean) => void;
|
|
17
|
+
}): React.ReactElement;
|
|
18
|
+
/** Mount the picker before the shell; resolves with the chosen ID, or null on Esc. */
|
|
19
|
+
export declare function runResumePicker(rows: PickerRow[]): Promise<string | null>;
|
|
20
|
+
/** Mount the §8.4 choice; resolves true for "Continue without …". */
|
|
21
|
+
export declare function runResumeChoice(prompt: string, continueLabel?: string): Promise<boolean>;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* P61 session resume — select and re-author the carry-over
|
|
3
|
+
* (SESSION-RESUME-DESIGN.md §7, §8.2, §8.3; DD-2: N = 20).
|
|
4
|
+
*
|
|
5
|
+
* Selection is pure over P's VERIFIED items. Re-authoring appends the chosen
|
|
6
|
+
* items to S's log through the single-writer path in P's seq order, remapping
|
|
7
|
+
* content-id refs and the one body field that names another item (a rule
|
|
8
|
+
* retirement's occurrence `seq`), and ends with one `session_resumed` marker.
|
|
9
|
+
*/
|
|
10
|
+
import type { ContextItem, ContextItemDraft } from '../orchestration-shell/context-items';
|
|
11
|
+
export declare const CARRY_OVER_EXCHANGES = 20;
|
|
12
|
+
export declare const CARRY_OVER_MAX_BYTES: number;
|
|
13
|
+
export declare const SESSION_RESUMED_ACTION = "session_resumed";
|
|
14
|
+
/** True when `item` is the carry-over marker of a resume of `fromSessionId` (§8.4 "S's marker"). */
|
|
15
|
+
export declare function isResumeMarkerFor(item: ContextItem, fromSessionId: string): boolean;
|
|
16
|
+
export interface CarryOverPlan {
|
|
17
|
+
/** P's items to re-author, in P's seq order. */
|
|
18
|
+
items: ContextItem[];
|
|
19
|
+
counts: {
|
|
20
|
+
exchanges: number;
|
|
21
|
+
droppedExchanges: number;
|
|
22
|
+
rules: number;
|
|
23
|
+
openQuestions: number;
|
|
24
|
+
taskNotes: number;
|
|
25
|
+
};
|
|
26
|
+
/** True when the rules, closure and marker alone exceeded the cap (§8.2). */
|
|
27
|
+
rulesOnly: boolean;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* §8.2 — choose the carry-over from P's verified items.
|
|
31
|
+
* - Every live rule (readLiveUserRules semantics); never dropped.
|
|
32
|
+
* - Exchanges: the N most recent human turns, each with every later
|
|
33
|
+
* session-scoped turn/decision/open question up to the next human turn
|
|
34
|
+
* (rule decisions and earlier markers excluded; they enter only below).
|
|
35
|
+
* - Rule-retirement closure (S2-C1): every retired rule occurrence whose
|
|
36
|
+
* source human turn is carried, with each retirement of a carried occurrence.
|
|
37
|
+
* - Task notes: task-scoped task_spec/verdict/artifact_ref/decision items of
|
|
38
|
+
* tasks first seen inside a carried exchange (display and audit only).
|
|
39
|
+
* - Excluded: repo_state, rationale, earlier `session_resumed` markers.
|
|
40
|
+
* - 1 MiB over every carried item as serialized: rules first, then exchange
|
|
41
|
+
* groups newest first; the oldest are dropped first (DD-2 loss boundary).
|
|
42
|
+
*/
|
|
43
|
+
export declare function planCarryOver(items: readonly ContextItem[], exchangesWanted?: number, maxBytes?: number): CarryOverPlan;
|
|
44
|
+
export interface ReauthorResult {
|
|
45
|
+
/** S's items as appended, in order; the last is the marker. */
|
|
46
|
+
appended: ContextItem[];
|
|
47
|
+
marker: ContextItem;
|
|
48
|
+
}
|
|
49
|
+
export declare class CarryOverAppendError extends Error {
|
|
50
|
+
readonly at: number;
|
|
51
|
+
constructor(at: number);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* §8.3 — append the plan to S's log, in P's seq order, then the marker. Any
|
|
55
|
+
* null append aborts (durability gate step 1); the caller removes S's
|
|
56
|
+
* directory by exact path and claims nothing.
|
|
57
|
+
*/
|
|
58
|
+
export declare function reauthorCarryOver(args: {
|
|
59
|
+
successorSessionId: string;
|
|
60
|
+
predecessorSessionId: string;
|
|
61
|
+
plan: CarryOverPlan;
|
|
62
|
+
sourceComplete: boolean;
|
|
63
|
+
/**
|
|
64
|
+
* §8.4 step 2: the plan's items were read from this session (the
|
|
65
|
+
* predecessor's own predecessor), not from `predecessorSessionId`.
|
|
66
|
+
*/
|
|
67
|
+
rebuiltFrom?: string;
|
|
68
|
+
append: (sessionId: string, draft: ContextItemDraft) => Promise<ContextItem | null>;
|
|
69
|
+
}): Promise<ReauthorResult>;
|
|
70
|
+
/** The tail descriptor (`contextTail`) of a context item. */
|
|
71
|
+
export declare function itemTail(item: ContextItem): {
|
|
72
|
+
seq: string;
|
|
73
|
+
itemSha256: string;
|
|
74
|
+
};
|
|
75
|
+
/** §8.2: the header line when only standing rules could be carried (P61B-S1-F7). */
|
|
76
|
+
export declare const RULES_ONLY_WARNING = "Only standing rules were restored; the conversation was too large.";
|
|
77
|
+
/**
|
|
78
|
+
* Whether a carry-over marker records the §8.2 rules-only case: no exchange carried and at least
|
|
79
|
+
* one dropped (the plan's `rulesOnly`, as the ledger-replay path sees it, from the marker alone).
|
|
80
|
+
*/
|
|
81
|
+
export declare function markerRecordsRulesOnly(marker: ContextItem): boolean;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { UpdateSessionInput } from '../types/session';
|
|
2
|
+
/** Characters of the last human prompt kept in the picker preview (§9.4). */
|
|
3
|
+
export declare const LAST_PROMPT_PREVIEW_CHARS = 60;
|
|
4
|
+
/** The backend's cap on the preview's ciphertext. */
|
|
5
|
+
export declare const ENCRYPTED_LAST_PROMPT_MAX_BYTES = 1024;
|
|
6
|
+
export type CleanExitFields = Pick<UpdateSessionInput, 'contextTail' | 'contextTailIsResumeMarker' | 'encryptedLastPrompt'>;
|
|
7
|
+
/** Record the session's most recent human turn (called once it is appended). */
|
|
8
|
+
export declare function recordLastHumanPrompt(sessionId: string, text: string): void;
|
|
9
|
+
/**
|
|
10
|
+
* The `encryptedLastPrompt` for a prompt and a key in hand: a published-then-retired S, whose shell
|
|
11
|
+
* never ran here (P61B-S1-L12). Same preview rule and cap as the shell's. Never throws.
|
|
12
|
+
*/
|
|
13
|
+
export declare function encryptedPromptPreview(text: string, sessionKey: string): string | undefined;
|
|
14
|
+
/** Record the `seq` of the carry-over marker a resume wrote into this session's log. */
|
|
15
|
+
export declare function recordResumeMarkerSeq(sessionId: string, seq: string): void;
|
|
16
|
+
/**
|
|
17
|
+
* The fields to add to this session's INACTIVE update, on the ordered
|
|
18
|
+
* retirement and on the last-ditch one alike. Never throws.
|
|
19
|
+
*/
|
|
20
|
+
export declare function buildCleanExitFields(sessionId: string): Promise<CleanExitFields>;
|
|
21
|
+
/** Fire-and-forget at a resumed shell's start. Read-only (B-8): never initializes or rotates the writer. Never throws. */
|
|
22
|
+
export declare function primeDurableTail(sessionId: string): Promise<void>;
|
|
23
|
+
/** How long a startup-failure retirement waits for the start-time read (P61B-S1-E1). */
|
|
24
|
+
export declare const PRIME_WAIT_MAX_MS = 1000;
|
|
25
|
+
/**
|
|
26
|
+
* The clean-exit fields for the retirement of a session whose shell failed while starting
|
|
27
|
+
* (P61B-S1-E1, found by E2E-1 round 2): a resumed S can fail right after its seeding, before the
|
|
28
|
+
* fire-and-forget `primeDurableTail` read has finished. Waits at most `PRIME_WAIT_MAX_MS` for that
|
|
29
|
+
* read, then answers as `buildCleanExitFields`. A plain session has no clean-exit state, so it gets
|
|
30
|
+
* `{}` at once. Never throws.
|
|
31
|
+
*/
|
|
32
|
+
export declare function cleanExitFieldsAfterPrime(sessionId: string, maxWaitMs?: number): Promise<CleanExitFields>;
|
|
33
|
+
export declare function resetCleanExitStateForTests(): void;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* P61 — the CLI half of `--continue` / `--resume [<id>]` (design §5.1): run the
|
|
3
|
+
* entry point, then hand S to the shell with its seeding, header and lock
|
|
4
|
+
* release. Returns an exit code instead when no shell should start.
|
|
5
|
+
*/
|
|
6
|
+
import type { AppSyncClient } from '../appsync/appsync-client';
|
|
7
|
+
import type { Logger } from '../logger';
|
|
8
|
+
import type { Session } from '../types/session';
|
|
9
|
+
import { type ResumeStart } from './resume-entry';
|
|
10
|
+
import type { ResumeEntryPoint } from './resume-target';
|
|
11
|
+
export interface ResumeShellArgs {
|
|
12
|
+
restoredItems: ResumeStart['restoredItems'];
|
|
13
|
+
markerSeq: string;
|
|
14
|
+
header: {
|
|
15
|
+
top: string;
|
|
16
|
+
warnings: string[];
|
|
17
|
+
bottom: string;
|
|
18
|
+
};
|
|
19
|
+
onStarted: () => Promise<void>;
|
|
20
|
+
}
|
|
21
|
+
export declare function resumeEntryFromArgs(args: {
|
|
22
|
+
resume?: {
|
|
23
|
+
id?: string;
|
|
24
|
+
};
|
|
25
|
+
continue?: true;
|
|
26
|
+
}, cwd: string): ResumeEntryPoint | null;
|
|
27
|
+
export declare function startResumedSession(opts: {
|
|
28
|
+
client: AppSyncClient;
|
|
29
|
+
entry: ResumeEntryPoint;
|
|
30
|
+
cwd: string;
|
|
31
|
+
isTTY: boolean;
|
|
32
|
+
logger: Logger;
|
|
33
|
+
ownSessionId?: string;
|
|
34
|
+
}): Promise<{
|
|
35
|
+
kind: 'exit';
|
|
36
|
+
code: number;
|
|
37
|
+
} | {
|
|
38
|
+
kind: 'start';
|
|
39
|
+
session: Session;
|
|
40
|
+
shell: ResumeShellArgs;
|
|
41
|
+
}>;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* P61 §8.4 completeness decisions and the §8.1 failure copy for P's chosen
|
|
3
|
+
* source. Pure. `<device>` is P's creator computer as this account names it;
|
|
4
|
+
* when it is this computer (the resume fell back to the hosted copy here),
|
|
5
|
+
* the copy follows the §8.1 fallback reason instead.
|
|
6
|
+
*/
|
|
7
|
+
import type { HostedFallbackReason } from './source-choice';
|
|
8
|
+
export type CompletenessKind = 'complete' | 'continues-past-tail' | 'cut-at-tail' | 'short' | 'no-tail' | 'integrity' | 'ambiguous';
|
|
9
|
+
export interface CopyContext {
|
|
10
|
+
/** P's creator computer as listed for this account, e.g. "MacBook Pro" or "(unknown device)". */
|
|
11
|
+
deviceLabel: string;
|
|
12
|
+
/** True when P's creator computer is this one. */
|
|
13
|
+
deviceIsThisComputer: boolean;
|
|
14
|
+
/** Why the hosted copy is being read on the computer where P ran (null elsewhere, or for a local read). */
|
|
15
|
+
fallbackReason: HostedFallbackReason | null;
|
|
16
|
+
}
|
|
17
|
+
export declare const CONTINUE_WITHOUT_THEM = "Continue without them";
|
|
18
|
+
export declare const CONTINUE_WITHOUT_IT = "Continue without it";
|
|
19
|
+
export type ContinueLabel = typeof CONTINUE_WITHOUT_THEM | typeof CONTINUE_WITHOUT_IT;
|
|
20
|
+
export type CompletenessDecision = {
|
|
21
|
+
kind: 'proceed';
|
|
22
|
+
warning?: string;
|
|
23
|
+
}
|
|
24
|
+
/** Arrow-key choice; Cancel is the default and a launch without a terminal cancels. */
|
|
25
|
+
| {
|
|
26
|
+
kind: 'choose';
|
|
27
|
+
prompt: string;
|
|
28
|
+
continueLabel: typeof CONTINUE_WITHOUT_THEM;
|
|
29
|
+
cancelLabel: 'Cancel';
|
|
30
|
+
} | {
|
|
31
|
+
kind: 'refuse';
|
|
32
|
+
text: string;
|
|
33
|
+
};
|
|
34
|
+
export declare const CUT_AT_TAIL_WARNING = "This session's last moments are ambiguous and were left out.";
|
|
35
|
+
export declare const NO_TAIL_WARNING = "This session didn't end cleanly; its last moments may be missing.";
|
|
36
|
+
export declare const INTEGRITY_REFUSAL = "This session's saved context failed its integrity check, so it can't be resumed.";
|
|
37
|
+
export declare const KEYCHAIN_REFUSAL = "This computer's keychain is locked or unavailable. Unlock it and try again.";
|
|
38
|
+
export declare const UNREADABLE_LOCAL_REFUSAL = "This session's saved context on this computer can't be read (it may be damaged, or this computer's CodeVibe identity may have been reset), and its online copy can't be used, so it can't be resumed.";
|
|
39
|
+
/** §8.1: the refusal when the hosted copy itself cannot be used (integrity or ambiguous). */
|
|
40
|
+
export declare function hostedFailureRefusal(kind: 'integrity' | 'ambiguous', ctx: CopyContext): string;
|
|
41
|
+
/**
|
|
42
|
+
* The "chain ends before contextTail" prompt. Also §8.4 step 2's prompt for a
|
|
43
|
+
* resumed session's own items when its carry-over is rebuilt from P.
|
|
44
|
+
*/
|
|
45
|
+
export declare function shortPrompt(ctx: CopyContext): string;
|
|
46
|
+
export declare function completenessDecision(kind: CompletenessKind, ctx: CopyContext): CompletenessDecision;
|
|
47
|
+
/**
|
|
48
|
+
* §8.4 step 3: a resumed session S whose chain lacks its marker, when its
|
|
49
|
+
* carry-over cannot be rebuilt from P. `ctx` describes S's own copy (S's
|
|
50
|
+
* computer and S's fallback reason); `<P>` is S's predecessor.
|
|
51
|
+
*/
|
|
52
|
+
export declare function missingCarryOverPrompt(predecessorSessionId: string, ctx: CopyContext): string;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* P61 session resume — classify a resume create's failure (SESSION-RESUME-DESIGN.md
|
|
3
|
+
* §10 class table, §12.2.4; Phase B implementation design B-3).
|
|
4
|
+
*
|
|
5
|
+
* The plain-launch ledger's definitive-rejection sets are deliberately NOT
|
|
6
|
+
* reused: they treat `Unauthorized` as definitive (a resume keeps S's
|
|
7
|
+
* directory and ledger then, because an earlier attempt may have admitted S)
|
|
8
|
+
* and they miss wire codes the resume path must recognise. AppSync strips a
|
|
9
|
+
* Lambda error's type, so every class is matched on `errorType` OR the stable
|
|
10
|
+
* message code that leads the GraphQL error message.
|
|
11
|
+
*/
|
|
12
|
+
export type ResumeRefusalReason = 'NOT_FOUND' | 'NOT_ORCHESTRATION' | 'STILL_ACTIVE' | 'ALREADY_RESUMED' | 'WINDOW_CLOSED';
|
|
13
|
+
export type ResumeCreateOutcome =
|
|
14
|
+
/** S was never admitted: remove S's prepared directory by exact path, drop the ledger. */
|
|
15
|
+
{
|
|
16
|
+
kind: 'rejected';
|
|
17
|
+
cause: 'resume-not-allowed';
|
|
18
|
+
reason: ResumeRefusalReason;
|
|
19
|
+
successorSessionId?: string;
|
|
20
|
+
} | {
|
|
21
|
+
kind: 'rejected';
|
|
22
|
+
cause: 'limit' | 'rate' | 'account-deletion' | 'session-id-reserved' | 'invalid-status' | 'old-backend' | 'invalid-request' | 'resume-unavailable';
|
|
23
|
+
}
|
|
24
|
+
/** Keep S's directory and the ledger: the outcome is unknown until a definitive answer. */
|
|
25
|
+
| {
|
|
26
|
+
kind: 'ambiguous';
|
|
27
|
+
cause: 'unauthorized' | 'transient';
|
|
28
|
+
}
|
|
29
|
+
/** Keep S's directory, drop the ledger. */
|
|
30
|
+
| {
|
|
31
|
+
kind: 'conflict';
|
|
32
|
+
cause: 'creation-request-conflict';
|
|
33
|
+
}
|
|
34
|
+
/** S WAS admitted and then retired before its shell ran: keep the directory (its only carry-over), drop the ledger. */
|
|
35
|
+
| {
|
|
36
|
+
kind: 'admitted-then-retired';
|
|
37
|
+
};
|
|
38
|
+
/** Parse the backend's definitive claim refusal, if this error is one. */
|
|
39
|
+
export declare function parseResumeNotAllowed(error: unknown): {
|
|
40
|
+
reason: ResumeRefusalReason;
|
|
41
|
+
successorSessionId?: string;
|
|
42
|
+
} | null;
|
|
43
|
+
export declare function classifyResumeCreateFailure(error: unknown): ResumeCreateOutcome;
|