@quantiya/codevibe-core 2.0.91 → 2.0.93
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/dist/adapter/registry.d.ts +2 -2
- package/dist/appsync/sync-deferred-inputs.d.ts +2 -2
- package/dist/appsync/sync-desktop-registration.d.ts +2 -2
- package/dist/appsync/sync-mobile-echo.d.ts +16 -16
- package/dist/appsync/sync-prompt-publication.d.ts +8 -8
- package/dist/appsync/sync-shell-source.d.ts +18 -18
- package/dist/appsync/sync-source-cursor.d.ts +30 -30
- package/dist/commerce/upgrade-handoff.d.ts +11 -0
- package/dist/companion-mode/codex-native-question-reply.d.ts +22 -0
- package/dist/companion-mode/codex-native-state.d.ts +132 -114
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2605 -2306
- package/dist/local-executor/anchored-cas.d.ts +78 -6
- package/dist/local-executor/anchored-fs.d.ts +32 -0
- package/dist/local-executor/blob-store.d.ts +95 -0
- package/dist/local-executor/change-manifest-store.d.ts +32 -0
- package/dist/local-executor/change-manifest.d.ts +50 -0
- package/dist/local-executor/durable-store.d.ts +72 -15
- package/dist/local-executor/implementor-argv.d.ts +43 -7
- package/dist/local-executor/local-executor-impl.d.ts +57 -1
- package/dist/local-executor/nolink-apply.d.ts +22 -2
- package/dist/local-executor/revert-runner.d.ts +3 -0
- package/dist/local-executor/shadow-apply-capabilities.d.ts +31 -2
- package/dist/local-executor/shadow-free-space.d.ts +25 -0
- package/dist/local-executor/shadow-protocol.d.ts +117 -18
- package/dist/local-executor/shadow-recovery.d.ts +28 -3
- package/dist/local-executor/shadow-task-intent.d.ts +29 -0
- package/dist/local-executor/shadow-volume-probe.d.ts +0 -14
- package/dist/local-executor/sharded-list.d.ts +32 -0
- package/dist/local-executor/snapshot-merge.d.ts +18 -0
- package/dist/local-executor/spawn-sweep-binary.d.ts +33 -0
- package/dist/local-executor/spawn-sweep.d.ts +3 -0
- package/dist/local-executor/store-dir-anchor.d.ts +48 -0
- package/dist/local-executor/tier-self-test.d.ts +57 -0
- package/dist/local-executor/types.d.ts +26 -0
- package/dist/local-executor/verification-gates/diff-sanity.d.ts +6 -0
- package/dist/local-executor/workspace-materializer.d.ts +17 -1
- package/dist/local-executor/workspace-shadow.d.ts +209 -7
- package/dist/orchestration-shell/audit-summary.d.ts +22 -0
- package/dist/orchestration-shell/bounded-shutdown.d.ts +2 -0
- package/dist/orchestration-shell/cli.js +64053 -57609
- package/dist/orchestration-shell/components/OrchestrationApp.d.ts +6 -1
- package/dist/orchestration-shell/decision-attempt-recovery.d.ts +14 -0
- package/dist/orchestration-shell/engine-projection.d.ts +98 -0
- package/dist/orchestration-shell/exit-guard.d.ts +18 -0
- package/dist/orchestration-shell/gate-decision-submit.d.ts +2 -0
- package/dist/orchestration-shell/index.d.ts +18 -0
- package/dist/orchestration-shell/quorum-loop.d.ts +265 -21
- package/dist/orchestration-shell/review-bundle.d.ts +77 -0
- package/dist/orchestration-shell/review-receipts.d.ts +100 -0
- package/dist/orchestration-shell/reviewer-seat-self-test.d.ts +43 -0
- package/dist/orchestration-shell/team-decompose.d.ts +1 -0
- package/dist/orchestration-shell/types.d.ts +24 -0
- package/dist/reviewer/provider.d.ts +28 -0
- package/dist/reviewer/providers/antigravity.d.ts +4 -2
- package/dist/reviewer/providers/claude.d.ts +7 -2
- package/dist/reviewer/providers/codex.d.ts +1 -1
- package/dist/session-resume/cli-resume.d.ts +1 -0
- package/dist/substrate/bwrap.d.ts +85 -0
- package/dist/substrate/command-runner.d.ts +1 -0
- package/dist/substrate/docker.d.ts +21 -0
- package/dist/substrate/grant-rule.d.ts +71 -0
- package/dist/substrate/pasta-isolation-check.d.ts +60 -0
- package/dist/substrate/pasta.d.ts +8 -0
- package/dist/substrate/relay-channel.d.ts +80 -0
- package/dist/substrate/review-mask.d.ts +20 -0
- package/dist/substrate/sandbox-exec.d.ts +48 -1
- package/dist/substrate/seatbelt-grants.d.ts +46 -0
- package/dist/substrate/spawn-records.d.ts +95 -0
- package/dist/substrate/tier-relay-main.d.ts +1 -0
- package/dist/substrate/tier-relay.d.ts +7 -0
- package/dist/substrate/tier-relay.js +3 -0
- package/dist/substrate/types.d.ts +48 -1
- package/dist/substrate-launch/engage-substrate.d.ts +16 -2
- package/dist/substrate-launch/fallback-ladder.d.ts +109 -12
- package/dist/substrate-launch/index.d.ts +1 -1
- package/dist/substrate-launch/task-folder.d.ts +26 -0
- package/native/linux-arm64/codevibe-spawn-sweep +0 -0
- package/native/linux-x64/codevibe-spawn-sweep +0 -0
- package/native/spawn-sweep.json +8 -0
- package/package.json +10 -5
|
@@ -15,6 +15,7 @@ import type { ConflictResolverContext } from './merge-conflict-resolve';
|
|
|
15
15
|
import { type ContentCipher } from './conflict-resolution-durable-store';
|
|
16
16
|
import type { PromoteManifestInput, SnapshotPromotionJournalV1, TrackTipsView } from './durable-store';
|
|
17
17
|
import { type ReviewedShadowDiffFile, type ShadowEnv } from './workspace-shadow';
|
|
18
|
+
import type { BlobStore } from './blob-store';
|
|
18
19
|
/**
|
|
19
20
|
* CP-7 W2 Stage-2 HIGH (Finding 2) — STRICT delivery sink for the
|
|
20
21
|
* `tier:'none'` (moat-OFF) reduced-trust badge.
|
|
@@ -74,7 +75,7 @@ export interface MergeGateContentEncryptor {
|
|
|
74
75
|
*/
|
|
75
76
|
export type SubstrateEngageResult = {
|
|
76
77
|
mode: 'substrate';
|
|
77
|
-
tier: 'docker' | 'sandbox_exec';
|
|
78
|
+
tier: 'docker' | 'sandbox_exec' | 'bubblewrap';
|
|
78
79
|
reducedTrust: boolean;
|
|
79
80
|
reducedTrustReason?: string;
|
|
80
81
|
substrateHandle: SubstrateHandle;
|
|
@@ -113,9 +114,13 @@ export type SubstrateEngager = (input: {
|
|
|
113
114
|
*/
|
|
114
115
|
requireConfined?: boolean;
|
|
115
116
|
writableWorkdir?: boolean;
|
|
117
|
+
/** P63 Slice 2 (§8.2) — the spawn's task-owned capture dir, granted read-write beside a read-only view. */
|
|
118
|
+
captureDir?: string;
|
|
116
119
|
webBrowsingActive?: boolean;
|
|
117
120
|
/** F-P46a-4 — the spawn's process-tree id, folded into the sandbox environment. */
|
|
118
121
|
processTreeId?: string;
|
|
122
|
+
/** P63 §6.1 / §6.2 — the user's real project folder (`SpawnArgs.projectRoot`). */
|
|
123
|
+
projectRoot?: string;
|
|
119
124
|
}) => Promise<SubstrateEngageResult>;
|
|
120
125
|
/** Backend lease is 15 minutes; three renewal opportunities fit inside it. */
|
|
121
126
|
export declare const TEAM_TRACK_HEARTBEAT_INTERVAL_MS: number;
|
|
@@ -253,6 +258,27 @@ export interface LocalExecutorImplDeps {
|
|
|
253
258
|
* + the GEMINI reduced-trust case.
|
|
254
259
|
*/
|
|
255
260
|
substrateEngager?: SubstrateEngager;
|
|
261
|
+
/**
|
|
262
|
+
* P63 Slice 2 (§8.2) — the per-task folder (`taskFolderFor`, Stream A's layout): a read-only-view Codex spawn's
|
|
263
|
+
* capture dir is created at `<task folder>/capture/<spawn>/`. Absent (tests, embedders) → a fresh `os.tmpdir()`
|
|
264
|
+
* folder, so no test writes the real cache.
|
|
265
|
+
*/
|
|
266
|
+
taskFolder?: (taskId: string) => string;
|
|
267
|
+
/**
|
|
268
|
+
* P63 §6.4 — the per-mode tier self-test: before the first real implementor of an agent version runs in a tier in a
|
|
269
|
+
* mode, the same engage runs it against a throwaway one-file view; a failure refuses the spawn (§6.4). Production
|
|
270
|
+
* wires it (`cli.ts`); absent → no self-test (tests and embedders with fake substrates).
|
|
271
|
+
*/
|
|
272
|
+
tierSelfTest?: {
|
|
273
|
+
/** Where results are cached (`~/.codevibe/substrate-checks`). */
|
|
274
|
+
cacheDir: string;
|
|
275
|
+
/** Where the throwaway view is made (the real copy location). */
|
|
276
|
+
viewParent: () => Promise<string>;
|
|
277
|
+
/** `<agent> --version` (default: runs the binary; tests inject it). */
|
|
278
|
+
readAgentVersion?: (binary: string) => Promise<string>;
|
|
279
|
+
/** The Linux bubblewrap tier's key parts (filter SHA, bwrap version, setpriv/bash paths, pasta SHA). */
|
|
280
|
+
linuxKeyParts?: (open: boolean) => Promise<Pick<import('./tier-self-test').TierSelfTestKeyInput, 'filterSha256' | 'bwrapVersion' | 'setprivPath' | 'bashPath' | 'pastaSha256'>>;
|
|
281
|
+
};
|
|
256
282
|
/**
|
|
257
283
|
* CP-7 W2 Stage-2 HIGH (Finding 2) — STRICT delivery sink for the
|
|
258
284
|
* `tier:'none'` (moat-OFF) reduced-trust badge. When supplied (production
|
|
@@ -319,6 +345,8 @@ export interface LocalExecutorImplDeps {
|
|
|
319
345
|
readTrackTips?: (taskGroupId: string) => Promise<TrackTipsView>;
|
|
320
346
|
/** Git-independent reviewed track bundles (the default team merge inputs). */
|
|
321
347
|
readTrackBundles?: (taskGroupId: string) => Promise<SnapshotBundlesView>;
|
|
348
|
+
/** §9.4 — the group's content store (bundle post-images and merge results as blobs; see `runSnapshotMergeGate`). */
|
|
349
|
+
snapshotContentStore?: (taskGroupId: string) => BlobStore;
|
|
322
350
|
/** Durable all-generation/cross-process fence around gate + hosted submission. */
|
|
323
351
|
withSnapshotMergeGateFence?: <T>(taskGroupId: string, operation: () => Promise<T>, signal?: AbortSignal) => Promise<T>;
|
|
324
352
|
/** Persist merged pre-images before the one group promotion mutates user files. */
|
|
@@ -364,6 +392,16 @@ export interface LocalExecutorImplDeps {
|
|
|
364
392
|
conflicts: readonly string[];
|
|
365
393
|
writeErrors: readonly string[];
|
|
366
394
|
}) => void;
|
|
395
|
+
/** The tracks' changes could not be merged, before anything was applied. */
|
|
396
|
+
onTeamMergeConflict?: (info: {
|
|
397
|
+
taskGroupId: string;
|
|
398
|
+
paths: readonly string[];
|
|
399
|
+
workLimit: boolean;
|
|
400
|
+
}) => void;
|
|
401
|
+
/** The merge could not be finished and its verdict is withheld: some of its files may already be in the folder. */
|
|
402
|
+
onTeamMergeUnresolved?: (info: {
|
|
403
|
+
taskGroupId: string;
|
|
404
|
+
}) => void;
|
|
367
405
|
/**
|
|
368
406
|
* Legacy-named TEST SEAM around the merge-gate body. Production defaults to
|
|
369
407
|
* the reviewed-bundle filesystem snapshot implementation.
|
|
@@ -525,6 +563,11 @@ export declare class LocalExecutorImpl implements LocalExecutor {
|
|
|
525
563
|
private readonly logger;
|
|
526
564
|
private readonly teamModeEnabled;
|
|
527
565
|
private readonly substrateEngager?;
|
|
566
|
+
private readonly taskFolder?;
|
|
567
|
+
private readonly tierSelfTestConfig?;
|
|
568
|
+
/** One self-test per key at a time; concurrent spawns of the same key share it. */
|
|
569
|
+
private readonly tierSelfTestsInFlight;
|
|
570
|
+
private readonly agentVersions;
|
|
528
571
|
private readonly strictBadgeSink?;
|
|
529
572
|
constructor(deps: LocalExecutorImplDeps);
|
|
530
573
|
/**
|
|
@@ -596,6 +639,19 @@ export declare class LocalExecutorImpl implements LocalExecutor {
|
|
|
596
639
|
* takes the legacy path.
|
|
597
640
|
*/
|
|
598
641
|
private engageSubstrateForSpawn;
|
|
642
|
+
/**
|
|
643
|
+
* P63 §6.4 — the reason this agent FAILED its cached execute-mode self-test in this tier, or null (no result yet, or
|
|
644
|
+
* a pass). The pre-start preflight consults it, so a task whose agent failed its self-test is refused before it
|
|
645
|
+
* starts and the user is offered the unconfined run.
|
|
646
|
+
*/
|
|
647
|
+
tierSelfTestFailure(agentKind: AgentKind, tier: 'docker' | 'sandbox_exec' | 'bubblewrap'): Promise<string | null>;
|
|
648
|
+
/** P63 §6.4 — the cached tier self-test for (agent, version, tier, mode, argv template, tier binaries). */
|
|
649
|
+
private ensureTierSelfTest;
|
|
650
|
+
/**
|
|
651
|
+
* P63 Slice 2 (§8.2) — create a spawn's capture dir exclusively: `<task folder>/capture/<spawn>/` (0700), or a fresh
|
|
652
|
+
* `os.tmpdir()` folder when no task folder is wired. Returned canonical (Seatbelt grants match canonical paths).
|
|
653
|
+
*/
|
|
654
|
+
private createCaptureDir;
|
|
599
655
|
/**
|
|
600
656
|
* CP-7 PART F — surface the PROMINENT reduced-trust badge (§6 Q2). The moat
|
|
601
657
|
* being OFF (or coarse) MUST be visible + auditable, never silent: a
|
|
@@ -3,6 +3,8 @@ export type NoLinkOperation = 'replace' | 'create' | 'delete';
|
|
|
3
3
|
export type NoLinkState = 'prepared' | 'moved' | 'placing' | 'restoring' | 'restoring-link' | 'pending-restore' | 'create-conflict' | 'done';
|
|
4
4
|
export interface NoLinkJournalEntry {
|
|
5
5
|
version: 1;
|
|
6
|
+
/** §17: the versioned no-link journal form. Absent on an entry a released desktop left open; any other value is refused. */
|
|
7
|
+
casMode?: 'nolink';
|
|
6
8
|
token: string;
|
|
7
9
|
op: NoLinkOperation;
|
|
8
10
|
/** The target's path relative to the workspace root, for reporting; the helper uses only its basename. */
|
|
@@ -43,6 +45,16 @@ interface NoLinkHelperSpec {
|
|
|
43
45
|
name: string;
|
|
44
46
|
token: string;
|
|
45
47
|
content?: string;
|
|
48
|
+
/**
|
|
49
|
+
* P63 Slice 2 (§9.4): the intended post-image as a blob in the instance's content store (`store-<uuid>/` in the
|
|
50
|
+
* journal's directory, F-S2-4) — replaces `content`. The parent opens it on apply only (recovery restores or completes
|
|
51
|
+
* renames and never needs it) and passes it as the helper's fd 3; the helper hashes it while writing and writes nothing
|
|
52
|
+
* on a mismatch.
|
|
53
|
+
*/
|
|
54
|
+
blob?: {
|
|
55
|
+
name: string;
|
|
56
|
+
size: number;
|
|
57
|
+
};
|
|
46
58
|
mode?: number;
|
|
47
59
|
baseHash: string | null;
|
|
48
60
|
intendedHash: string | null;
|
|
@@ -108,8 +120,8 @@ export declare class NoLinkJournalStore {
|
|
|
108
120
|
write(entry: NoLinkJournalEntry): Promise<void>;
|
|
109
121
|
read(token: string): Promise<NoLinkJournalEntry | null>;
|
|
110
122
|
/**
|
|
111
|
-
* Every entry not yet `done`.
|
|
112
|
-
*
|
|
123
|
+
* Every entry not yet `done`. They are recovered at every `promote()` — each retry and the startup reconcile (R1-F1)
|
|
124
|
+
* — and, for a step left pending, every 10 seconds while the desktop runs (§9.3, `retryPendingNoLinkRestores`).
|
|
113
125
|
*/
|
|
114
126
|
open(): Promise<NoLinkJournalEntry[]>;
|
|
115
127
|
}
|
|
@@ -117,6 +129,8 @@ export declare class NoLinkJournalStore {
|
|
|
117
129
|
export declare function parseNoLinkJournalEntry(text: string, token: string): NoLinkJournalEntry;
|
|
118
130
|
/** The token of a `<prefix>-<token>.json` journal file name, or null when the name is not one. */
|
|
119
131
|
export declare function journalTokenOf(name: string, prefix: string): string | null;
|
|
132
|
+
/** §9.3: where a pending step's original is, relative to the workspace root — the name the user is told. */
|
|
133
|
+
export declare function noLinkMovedPath(rel: string, token: string): string;
|
|
120
134
|
/** The CodeVibe token for one operation: the same 48-hex shape as the link-based helper's `.codevibe-cas-<token>`. */
|
|
121
135
|
export declare function noLinkToken(rootCanonicalPath: string, rel: string, op: NoLinkOperation, baseHash: string | null, intendedHash: string | null): string;
|
|
122
136
|
export interface NoLinkRunOptions {
|
|
@@ -138,6 +152,12 @@ export interface NoLinkRunOptions {
|
|
|
138
152
|
export declare function applyNoLink(opts: NoLinkRunOptions & {
|
|
139
153
|
op: NoLinkOperation;
|
|
140
154
|
content?: string;
|
|
155
|
+
/** P63 Slice 2 (§9.4): the post-image as a blob in the journal's directory, instead of `content`. */
|
|
156
|
+
blob?: {
|
|
157
|
+
name: string;
|
|
158
|
+
size: number;
|
|
159
|
+
sha256: string;
|
|
160
|
+
};
|
|
141
161
|
mode?: number;
|
|
142
162
|
/** Stage 2 R2-F3: the name's base mode, compared by the helper where modes are tracked. */
|
|
143
163
|
baseMode?: number | null;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { RevertManifestStore } from './durable-store';
|
|
2
2
|
import { type CasHelperCrashStage } from './workspace-shadow';
|
|
3
|
+
import { applyFileNoLink } from './shadow-apply-capabilities';
|
|
3
4
|
/** The outcome of a group revert (Fork A: clean-where-safe + surface). */
|
|
4
5
|
export interface RevertResult {
|
|
5
6
|
/** Paths reverted (created→deleted, modified/deleted→restored) THIS pass. */
|
|
@@ -20,6 +21,8 @@ export interface RevertRunnerEnv {
|
|
|
20
21
|
testCrashHelperStage?: (path: string) => CasHelperCrashStage | undefined;
|
|
21
22
|
/** @internal swap/race seam before each manifest/journal filesystem proof. */
|
|
22
23
|
beforeJournalFileRead?: (path: string) => Promise<void> | void;
|
|
24
|
+
/** @internal F-S2-5: the §9.3 helper's crash/fault controls for one no-link reverse step (interruption tests). */
|
|
25
|
+
noLinkTest?: (path: string) => Parameters<typeof applyFileNoLink>[0]['test'] | undefined;
|
|
23
26
|
}
|
|
24
27
|
/**
|
|
25
28
|
* Revert the whole group's applied tree off its durable manifest + journal.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { applyNoLink, type NoLinkResult } from './nolink-apply';
|
|
1
|
+
import { applyNoLink, type NoLinkOperation, type NoLinkResult } from './nolink-apply';
|
|
2
2
|
import type { WorkspaceRootAuthority } from './workspace-authority';
|
|
3
3
|
import { type VolumeCapabilities } from './shadow-volume-probe';
|
|
4
4
|
export interface ApplyArtifactNames {
|
|
@@ -11,6 +11,24 @@ export interface ApplyArtifactNames {
|
|
|
11
11
|
export declare function applyArtifactNames(stateDir: string, shadowDir: string): ApplyArtifactNames;
|
|
12
12
|
/** §5.2/§7.4: this instance's flat start-record file prefix (`start-record-<uuid>`). */
|
|
13
13
|
export declare function startRecordPrefix(shadowDir: string): string;
|
|
14
|
+
/**
|
|
15
|
+
* P63 Slice 2 (§9.4, F-S2-4) — this instance's content store: a directory of its own inside the task state directory
|
|
16
|
+
* (`store-<uuid>/`), holding its blobs and change-manifest shards. Not flat beside the markers: capture writes hundreds
|
|
17
|
+
* of blobs a second, and every task start and recovery sweep on this machine enumerates each task state directory and
|
|
18
|
+
* fails closed if it changes during the read — so a capturing task must leave its state directory itself untouched.
|
|
19
|
+
*/
|
|
20
|
+
export declare function instanceStoreDir(stateDir: string, shadowDir: string): string;
|
|
21
|
+
/** P63 Slice 2 (§9.4) — this instance's blob namespace in its content store (`blob-store.ts`). */
|
|
22
|
+
export declare function blobStoreFor(stateDir: string, shadowDir: string): {
|
|
23
|
+
dir: string;
|
|
24
|
+
prefix: string;
|
|
25
|
+
};
|
|
26
|
+
/** P63 Slice 2 (§9.4) — this instance's change-manifest shard namespace in its content store (`change-manifest-store.ts`). */
|
|
27
|
+
export declare function manifestStoreFor(stateDir: string, shadowDir: string): {
|
|
28
|
+
dir: string;
|
|
29
|
+
prefix: string;
|
|
30
|
+
};
|
|
31
|
+
export declare function _setStoreRetireSeamForTests(seam: (() => Promise<void>) | undefined): void;
|
|
14
32
|
/** Test override: run the no-link path on a volume that has links, as SP-C's "APFS forced copy" did. */
|
|
15
33
|
export interface ForcedApplyCapabilities {
|
|
16
34
|
mode: 'nolink';
|
|
@@ -22,6 +40,7 @@ export interface ForcedApplyCapabilities {
|
|
|
22
40
|
export type ResolvedApplyCapabilities = VolumeCapabilities & {
|
|
23
41
|
linkVolume: boolean;
|
|
24
42
|
};
|
|
43
|
+
export declare function writeDurable(file: string, body: string): Promise<void>;
|
|
25
44
|
/**
|
|
26
45
|
* The volume's capabilities for this snapshot's apply: read back if this snapshot already probed (a resumed or
|
|
27
46
|
* recovered promotion never probes twice), otherwise probed now — after approval, never at task start (§9.1).
|
|
@@ -31,7 +50,9 @@ export declare class NoLinkPendingError extends Error {
|
|
|
31
50
|
readonly rel: string;
|
|
32
51
|
readonly result: NoLinkResult;
|
|
33
52
|
readonly code = "ENOLINKPENDING";
|
|
34
|
-
|
|
53
|
+
/** Where the original is now, relative to the workspace root; absent for a create, which moved nothing. */
|
|
54
|
+
readonly temporarilyAt?: string;
|
|
55
|
+
constructor(rel: string, result: NoLinkResult, op: NoLinkOperation, token: string);
|
|
35
56
|
}
|
|
36
57
|
/**
|
|
37
58
|
* Apply one reviewed file on a no-link volume. Returns true when the name now holds the post-image (applied, or
|
|
@@ -47,6 +68,12 @@ export declare function applyFileNoLink(args: {
|
|
|
47
68
|
rel: string;
|
|
48
69
|
/** null = delete. */
|
|
49
70
|
content: string | null;
|
|
71
|
+
/** P63 Slice 2 (§9.4): the post-image as a blob in `stateDir`; the journal names it instead of carrying `content`. */
|
|
72
|
+
blob?: {
|
|
73
|
+
name: string;
|
|
74
|
+
size: number;
|
|
75
|
+
sha256: string;
|
|
76
|
+
};
|
|
50
77
|
/**
|
|
51
78
|
* Stage 1 R1-F4: the mode the placed file must carry where the volume tracks modes (§9.1 `modesTracked`); the
|
|
52
79
|
* helper sets it on the file it writes. Ignored where modes are untracked (exFAT, FAT, drvfs).
|
|
@@ -83,6 +110,8 @@ export declare function recoverOpenNoLinkEntries(args: {
|
|
|
83
110
|
onKept?: (rel: string, kept: string[]) => void;
|
|
84
111
|
onClosed?: (rel: string, result: NoLinkResult) => void;
|
|
85
112
|
onError?: (rel: string, err: Error) => void;
|
|
113
|
+
/** §9.3: a step still pending whose original sits at `movedPath` (never called for a create, which moved nothing). */
|
|
114
|
+
onMoved?: (rel: string, movedPath: string) => void;
|
|
86
115
|
}): Promise<string[]>;
|
|
87
116
|
/** Open (not `done`) §9.3 journal entries of this snapshot — non-empty blocks discard. */
|
|
88
117
|
export declare function openNoLinkEntries(stateDir: string, shadowDir: string): Promise<import("./nolink-apply").NoLinkJournalEntry[]>;
|
|
@@ -25,7 +25,24 @@ export type CopySpaceVerdict = {
|
|
|
25
25
|
short: FilesystemSpace;
|
|
26
26
|
requiredBytes: number;
|
|
27
27
|
reservedBytes: number;
|
|
28
|
+
/** The bytes the copy needs, and what they are for — the structured fields `reason` is built from. */
|
|
29
|
+
bytesToCopy: number;
|
|
30
|
+
purpose: string;
|
|
28
31
|
};
|
|
32
|
+
/**
|
|
33
|
+
* §5.5 refusal text, built only from the verdict's structured fields (sizes, the short filesystem's path, the
|
|
34
|
+
* purpose), so a caller that relays it — the implementor-round failure label shown on the desktop and the phone —
|
|
35
|
+
* never forwards free-form error text.
|
|
36
|
+
*/
|
|
37
|
+
export declare function copySpaceRefusalText(v: Extract<CopySpaceVerdict, {
|
|
38
|
+
ok: false;
|
|
39
|
+
}>,
|
|
40
|
+
/**
|
|
41
|
+
* How the short filesystem is named (default: its path). A message that crosses the start-error sanitizer names it in
|
|
42
|
+
* words instead: the sanitizer redacts an absolute path and its scan runs on past the path's end (lfree4: "… and
|
|
43
|
+
* [path] MiB free."), which would drop the free space §5.5 requires the message to name.
|
|
44
|
+
*/
|
|
45
|
+
location?: string): string;
|
|
29
46
|
export interface CopySpaceRequest {
|
|
30
47
|
/** The copy location (§5.1). The space test runs here. */
|
|
31
48
|
copyLocation: string;
|
|
@@ -42,6 +59,8 @@ export interface CopySpaceRequest {
|
|
|
42
59
|
*/
|
|
43
60
|
alsoRequireOn?: string[];
|
|
44
61
|
statfs?: StatfsFn;
|
|
62
|
+
/** What the bytes are for, in the refusal ("copy this folder" by default; capture and review copies say so). */
|
|
63
|
+
purpose?: string;
|
|
45
64
|
}
|
|
46
65
|
/** §5.5's pre-copy check. A refusal means the task does not start, with this message. */
|
|
47
66
|
export declare function checkCopySpace(req: CopySpaceRequest): Promise<CopySpaceVerdict>;
|
|
@@ -62,6 +81,12 @@ export type WatchdogVerdict = {
|
|
|
62
81
|
* virtual disk can look roomy while the drive that backs it is nearly full.
|
|
63
82
|
*/
|
|
64
83
|
export declare function watchdogTick(paths: string[], statfs?: StatfsFn): Promise<WatchdogVerdict>;
|
|
84
|
+
/**
|
|
85
|
+
* P63 Slice 2 R1-F10 (§8.1 "counted in the free-space check", §5.5) — the same condition for a copy a running task
|
|
86
|
+
* makes after its start (captured post-images and base versions into its content store, a review bundle), on the
|
|
87
|
+
* filesystem that receives it and, on WSL2, the Windows drive too. Throws {@link InsufficientCopySpaceError}.
|
|
88
|
+
*/
|
|
89
|
+
export declare function assertCopySpace(copyLocation: string, bytesToCopy: number, purpose: string, statfs?: StatfsFn): Promise<void>;
|
|
65
90
|
/** A task that §5.5 refuses to start. The message names the folder size and the free space. */
|
|
66
91
|
export declare class InsufficientCopySpaceError extends Error {
|
|
67
92
|
readonly verdict: Extract<CopySpaceVerdict, {
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import * as fs from 'node:fs/promises';
|
|
2
|
-
import
|
|
2
|
+
import type { BlobRef } from './change-manifest';
|
|
3
|
+
import type { ChangeManifestRecord } from './change-manifest-store';
|
|
4
|
+
import { type AnchoredReadSession, type AnchoredFsIdentity, type AnchoredPathIdentity, type AnchoredWritePrecondition } from './anchored-fs';
|
|
3
5
|
import { type ProcessCleanupOwner } from './process-tree';
|
|
4
6
|
import { type ProcessIdentity } from './process-identity';
|
|
7
|
+
import { type MetadataBudget } from './bounded-directory';
|
|
5
8
|
import { type WorkspaceRootAuthority } from './workspace-authority';
|
|
6
9
|
import { type MaterializationHangStage } from './workspace-materializer';
|
|
7
10
|
/** Directories never materialized into a new filesystem snapshot. */
|
|
@@ -88,13 +91,17 @@ export declare const MAX_TRACKED_WORKSPACE_LOGICAL_BYTES: number;
|
|
|
88
91
|
export declare const MAX_TRACKED_FILE_COUNT = 5000000;
|
|
89
92
|
export declare const MAX_TRACKED_PATH_BYTES: number;
|
|
90
93
|
/**
|
|
91
|
-
* The bound on a CHANGE SET — reviewed
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
94
|
+
* The bound on a CHANGE SET — the captured and reviewed diff, the promoted set, recovery authority, declared-test
|
|
95
|
+
* drift, merge plans and diff-sanity budgets. §5.6 lifts the historical 100,000-entry / 16 MiB-path cap in Slice 2:
|
|
96
|
+
* persisted change sets live in the sharded change manifest (§9.4) and markers hold only its shard hashes, so what
|
|
97
|
+
* remains is the in-memory sanity bound. A change set is a subset of the walked folder, so it shares the traversal
|
|
98
|
+
* ceiling above rather than carrying a product limit of its own (P63 Slice 2, E2E-4b: 300,000 changed paths).
|
|
99
|
+
* Persisted durable-store records keep the orchestration default (`createMetadataBudget()`, SB-37).
|
|
95
100
|
*/
|
|
96
|
-
export declare const MAX_CHANGE_SET_FILE_COUNT =
|
|
101
|
+
export declare const MAX_CHANGE_SET_FILE_COUNT = 5000000;
|
|
97
102
|
export declare const MAX_CHANGE_SET_PATH_BYTES: number;
|
|
103
|
+
/** Budget for validating one in-memory change set (see {@link MAX_CHANGE_SET_FILE_COUNT}). */
|
|
104
|
+
export declare function createChangeSetBudget(): MetadataBudget;
|
|
98
105
|
/** Reviewed text is intentionally bounded before any whole-file decode/read. */
|
|
99
106
|
export declare const MAX_REVIEW_FILE_BYTES: number;
|
|
100
107
|
export declare const MAX_PROMOTION_PREIMAGE_AGGREGATE_BYTES: number;
|
|
@@ -117,7 +124,67 @@ export interface ShadowDiffFile {
|
|
|
117
124
|
content: string;
|
|
118
125
|
/** POSIX permission bits for the reviewed post-image (omitted by legacy records). */
|
|
119
126
|
mode?: number;
|
|
127
|
+
/**
|
|
128
|
+
* P63 Slice 2 (§9.4) — the captured post-image in the task's blob store (`blobStoreFor`), written through the
|
|
129
|
+
* anchored copy. Absent for deletions and for records written before Slice 2.
|
|
130
|
+
*/
|
|
131
|
+
blob?: BlobRef;
|
|
120
132
|
}
|
|
133
|
+
/**
|
|
134
|
+
* P63 Slice 2 (§9.4) — a diff entry's optional blob reference is well formed and agrees with its inline content:
|
|
135
|
+
* never on a deletion, a 64-hex SHA-256 and a byte size equal to the content's UTF-8 length.
|
|
136
|
+
*/
|
|
137
|
+
export declare function assertDiffBlobRef(file: {
|
|
138
|
+
change_kind: unknown;
|
|
139
|
+
content: unknown;
|
|
140
|
+
blob?: unknown;
|
|
141
|
+
}, label: string): void;
|
|
142
|
+
/**
|
|
143
|
+
* P63 Slice 2 (§9.4) — text above this many bytes is carried as a blob reference only (`content: ''`): it is never
|
|
144
|
+
* held in memory whole, never 3-way line-merged (whole-file, like a binary — §10.3), and only excerpted for review.
|
|
145
|
+
*/
|
|
146
|
+
export declare const LARGE_TEXT_BYTES: number;
|
|
147
|
+
/**
|
|
148
|
+
* P63 Slice 2 (§5.6, §9.4) — no per-file size limit on a captured, deleted or promoted file: §5.6 replaces the 16 MiB cap
|
|
149
|
+
* with the blob store, so a file is bounded by disk (the §5.5 free-space check and watchdog), never by a fixed number.
|
|
150
|
+
* Content above LARGE_TEXT_BYTES is streamed in 1 MiB chunks and never held in memory. The value is the largest byte
|
|
151
|
+
* count the anchored helpers' integer checks accept (S2-C8, Stage 2 R1: a 4 GiB cap here contradicted §5.6).
|
|
152
|
+
*/
|
|
153
|
+
export declare const MAX_CAPTURE_FILE_BYTES: number;
|
|
154
|
+
/**
|
|
155
|
+
* §9.4 — a diff entry whose post-image lives only in the blob store: the desktop's records and in-memory structures
|
|
156
|
+
* hold references only. Its text is read from the blob when a consumer needs it — the ≤ LARGE_TEXT_BYTES 3-way merge,
|
|
157
|
+
* a projection excerpt, a revise brief — one file at a time, never kept.
|
|
158
|
+
*/
|
|
159
|
+
export declare function isReferenceDiffFile(file: {
|
|
160
|
+
change_kind: string;
|
|
161
|
+
content: string;
|
|
162
|
+
blob?: unknown;
|
|
163
|
+
}): boolean;
|
|
164
|
+
/** A reference entry above LARGE_TEXT_BYTES: never read whole, never line-merged (whole-file, §10.3), only excerpted. */
|
|
165
|
+
export declare function isLargeDiffFile(file: {
|
|
166
|
+
change_kind: string;
|
|
167
|
+
content: string;
|
|
168
|
+
blob?: {
|
|
169
|
+
size: number;
|
|
170
|
+
};
|
|
171
|
+
}): boolean;
|
|
172
|
+
/** The post-image SHA-256 of a diff entry (null for a deletion) — from its blob reference when it has one. */
|
|
173
|
+
export declare function diffPostHash(file: {
|
|
174
|
+
change_kind: string;
|
|
175
|
+
content: string;
|
|
176
|
+
blob?: {
|
|
177
|
+
blob: string;
|
|
178
|
+
};
|
|
179
|
+
}): string | null;
|
|
180
|
+
/** The post-image byte size of a diff entry (0 for a deletion). */
|
|
181
|
+
export declare function diffPostSize(file: {
|
|
182
|
+
change_kind: string;
|
|
183
|
+
content: string;
|
|
184
|
+
blob?: {
|
|
185
|
+
size: number;
|
|
186
|
+
};
|
|
187
|
+
}): number;
|
|
121
188
|
/** A reviewed change plus the exact real-tree pre-image expected at promotion. */
|
|
122
189
|
export interface ReviewedShadowDiffFile extends ShadowDiffFile {
|
|
123
190
|
/** SHA-256 of the pre-task file, or null when the path was absent. */
|
|
@@ -146,9 +213,18 @@ export interface CasRecoveryAuthority {
|
|
|
146
213
|
postHash: string | null;
|
|
147
214
|
postMode: number | null;
|
|
148
215
|
}
|
|
216
|
+
/**
|
|
217
|
+
* P63 Slice 2 (§17 versioned state, R1-F11) — the marker version this desktop writes. Version 3 is the first schema
|
|
218
|
+
* with complete snapshot-incarnation authority (Slice 1); version 4 is Slice 2's — reviewed and promoted sets as
|
|
219
|
+
* shard-backed manifests in the instance's content store (`store-<uuid>/`), post-images as blob references. A Slice 1
|
|
220
|
+
* desktop accepts only 3 and protects a marker it cannot read. With {@link EXPOSURE_RETENTION_MARKER_VERSION}, which
|
|
221
|
+
* keeps it from reclaiming the copy through the exposure record, it leaves a Slice 2 task alone. This desktop reads both;
|
|
222
|
+
* every marker it writes is 4.
|
|
223
|
+
*/
|
|
224
|
+
export declare const SHADOW_STATE_MARKER_VERSION = 4;
|
|
149
225
|
export interface ShadowStateFileV2 {
|
|
150
|
-
/**
|
|
151
|
-
version: 3;
|
|
226
|
+
/** 3: Slice 1 (read only); 4: Slice 2 — see {@link SHADOW_STATE_MARKER_VERSION}. */
|
|
227
|
+
version: 3 | 4;
|
|
152
228
|
taskId: string;
|
|
153
229
|
shadowDir: string;
|
|
154
230
|
workingDir: string;
|
|
@@ -199,6 +275,12 @@ export interface ShadowStateFileV2 {
|
|
|
199
275
|
}>;
|
|
200
276
|
/** Names + byte identities needed to resolve any post-COMMIT helper death. */
|
|
201
277
|
casRecovery?: CasRecoveryAuthority[];
|
|
278
|
+
/**
|
|
279
|
+
* P63 Slice 2 (§9.4, S2-9) — the promoted set as a shard-backed change manifest (shard hashes + root), written
|
|
280
|
+
* before the APPLYING marker. Replaces `promotePostHashes` + `casRecovery` (never both): post-images are the
|
|
281
|
+
* entries' blob references and the CAS authority is recomputed from them, so the marker stays O(shards).
|
|
282
|
+
*/
|
|
283
|
+
promoteManifest?: ChangeManifestRecord;
|
|
202
284
|
/** Full snapshot incarnation claimed by immutable DISPOSING authority. */
|
|
203
285
|
disposalSnapshotAuthority?: WorkspaceRootAuthority;
|
|
204
286
|
/** Legacy v3 field: protected fail-closed, never accepted for deletion. */
|
|
@@ -209,7 +291,19 @@ export interface ShadowStateFileV2 {
|
|
|
209
291
|
* authority from mutable snapshot bytes.
|
|
210
292
|
*/
|
|
211
293
|
reviewedDiff?: ShadowDiffFile[];
|
|
294
|
+
/**
|
|
295
|
+
* P63 Slice 2 (§9.4) — the reviewed artifact as a shard-backed change manifest (shard hashes + root); its content
|
|
296
|
+
* lives in the instance's blob store. Replaces `reviewedDiff` for new markers (never both), so the marker no longer
|
|
297
|
+
* grows with the size or number of reviewed files.
|
|
298
|
+
*/
|
|
299
|
+
reviewedManifest?: ChangeManifestRecord;
|
|
212
300
|
}
|
|
301
|
+
/**
|
|
302
|
+
* P63 Slice 2 (§16 C4, §17, F-ROLLBACK-EXPOSURE-REAP) — the exposure retention version this desktop writes. A Slice 1
|
|
303
|
+
* desktop accepts 1 and 2, and with the owner dead it removes the copy such a record names; it retains a record of any
|
|
304
|
+
* other version and keeps its name protected. Version 3 has version 2's fields. This desktop reads all three.
|
|
305
|
+
*/
|
|
306
|
+
export declare const EXPOSURE_RETENTION_MARKER_VERSION = 3;
|
|
213
307
|
/**
|
|
214
308
|
* Non-operational authority published before a private snapshot name becomes
|
|
215
309
|
* visible. It never authorizes use of `finalShadowDir`; it only prevents that
|
|
@@ -217,7 +311,8 @@ export interface ShadowStateFileV2 {
|
|
|
217
311
|
* that CodeVibe may reclaim.
|
|
218
312
|
*/
|
|
219
313
|
export interface ExposureRetentionMarker {
|
|
220
|
-
|
|
314
|
+
/** 1 and 2: Slice 1 (read only); 3: Slice 2 — see {@link EXPOSURE_RETENTION_MARKER_VERSION}. */
|
|
315
|
+
version: 1 | 2 | 3;
|
|
221
316
|
taskId: string;
|
|
222
317
|
finalShadowDir: string;
|
|
223
318
|
originalSnapshotAuthority: WorkspaceRootAuthority;
|
|
@@ -321,11 +416,6 @@ export interface ShadowEnv {
|
|
|
321
416
|
failReservationCleanup?: number;
|
|
322
417
|
onSeam?: (name: string, parentDir: string) => Promise<void>;
|
|
323
418
|
} | undefined;
|
|
324
|
-
/** @internal Test injection: `/proc/self/mountinfo` text for the drvfs apply refusal (SB-51), and its platform. */
|
|
325
|
-
applyMountinfo?: {
|
|
326
|
-
mountinfo: string;
|
|
327
|
-
platform: NodeJS.Platform;
|
|
328
|
-
};
|
|
329
419
|
/** @internal Control runs only: clone file by file, as before §5.3 batching (SB-36). */
|
|
330
420
|
disableDarwinBatchClones?: boolean;
|
|
331
421
|
/**
|
|
@@ -335,6 +425,8 @@ export interface ShadowEnv {
|
|
|
335
425
|
materializerLanes?: number;
|
|
336
426
|
/** @internal Lower the inline-baseline threshold so tests exercise sharded markers (default 8 MiB). */
|
|
337
427
|
baselineInlineMaxBytes?: number;
|
|
428
|
+
/** @internal R1-F10: a lower check interval for copies into the content store (tests). */
|
|
429
|
+
copySpaceCheckBytes?: number;
|
|
338
430
|
/** @internal Test injection for §5.5's free-space check (`statfs` of the copy location). */
|
|
339
431
|
copySpaceStatfs?: (path: string) => Promise<{
|
|
340
432
|
bavail: number | bigint;
|
|
@@ -368,8 +460,6 @@ export interface ShadowEnv {
|
|
|
368
460
|
killChildrenInShadow?: (shadowDir: string) => Promise<void>;
|
|
369
461
|
/** @internal lower deterministic aggregate quota for tests. */
|
|
370
462
|
maxSessionPhysicalCopyBytes?: number;
|
|
371
|
-
/** @internal lower deterministic aggregate pre-image quota for tests. */
|
|
372
|
-
maxPromotionPreImageAggregateBytes?: number;
|
|
373
463
|
/** Test seam after the stable source handle is opened but before physical streaming. */
|
|
374
464
|
beforePhysicalCopy?: (source: string) => Promise<void>;
|
|
375
465
|
/** @internal force the production helper's bounded physical-copy branch. */
|
|
@@ -402,8 +492,14 @@ export interface ShadowEnv {
|
|
|
402
492
|
afterPromotionParentValidation?: (path: string) => Promise<void>;
|
|
403
493
|
/** @internal lower deterministic CAS-helper deadline for tests. */
|
|
404
494
|
promotionHelperTimeoutMs?: number;
|
|
495
|
+
/** F-APPLY-RETRY: delays before each retry of a transiently failed placement; absent = 1 s, 5 s, 15 s; [] = no retry. */
|
|
496
|
+
promotionRetryDelaysMs?: readonly number[];
|
|
497
|
+
/** Test-only: retry even after a fault the test injected (hang/crash stage). */
|
|
498
|
+
retryInjectedPromotionFaults?: boolean;
|
|
499
|
+
/** Test-only: inject the hang/crash stage on the first placement attempt only. */
|
|
500
|
+
injectPromotionFaultOnFirstAttemptOnly?: boolean;
|
|
405
501
|
/** @internal deterministic CAS-helper target-filesystem stall seam. */
|
|
406
|
-
testHangPromotionHelperStage?: (path: string) => 'root' | 'parent' | 'target' | undefined;
|
|
502
|
+
testHangPromotionHelperStage?: (path: string) => 'root' | 'parent' | 'target' | 'prepared' | undefined;
|
|
407
503
|
/** @internal deterministic helper-death seam after COMMIT/mutation. */
|
|
408
504
|
testCrashPromotionHelperStage?: (path: string) => CasHelperCrashStage | undefined;
|
|
409
505
|
/** Test seam after the exact target is displaced but before replacement/deletion. */
|
|
@@ -488,6 +584,7 @@ export declare function assertSafeRelativePath(rel: string): void;
|
|
|
488
584
|
export declare function isInternalShadowPath(rel: string): boolean;
|
|
489
585
|
export declare function assertNotInternalShadowPath(rel: string): void;
|
|
490
586
|
export declare function normalizeFileMode(mode: number): number;
|
|
587
|
+
export declare function decodeStrictUtf8(bytes: Buffer, rel: string): string;
|
|
491
588
|
/**
|
|
492
589
|
* PHASE-589/469 W3.1 (C1) — read a real-tree file's CONTENT + hash by RELATIVE
|
|
493
590
|
* path BEFORE the promote mutates it; `{ content: null, hash: null }` if absent
|
|
@@ -498,7 +595,9 @@ export declare function readRealFileForManifest(workingDir: string, rel: string,
|
|
|
498
595
|
hash: string | null;
|
|
499
596
|
mode: number | null;
|
|
500
597
|
}>;
|
|
501
|
-
export declare function readRealFileMetadata(workingDir: string, rel: string, expectedRoot: AnchoredFsIdentity | WorkspaceRootAuthority
|
|
598
|
+
export declare function readRealFileMetadata(workingDir: string, rel: string, expectedRoot: AnchoredFsIdentity | WorkspaceRootAuthority,
|
|
599
|
+
/** F-CAS-BATCH: read through this pass's one helper. */
|
|
600
|
+
session?: AnchoredReadSession): Promise<{
|
|
502
601
|
hash: string | null;
|
|
503
602
|
mode: number | null;
|
|
504
603
|
}>;
|
|
@@ -7,6 +7,7 @@ import { type WorkspaceRootAuthority } from './workspace-authority';
|
|
|
7
7
|
import { type MaterializedFileMetadata } from './workspace-materializer';
|
|
8
8
|
import { type DurableDirectoryIdentity } from './durable-directory';
|
|
9
9
|
import { CasRecoveryAuthority, DisplacedShadowMarkerRecord, ExposureRetentionMarker, RetainedStateFileAuthority, ShadowDiffFile, ShadowEnv, ShadowPromoteState, ShadowStateFileV2, SnapshotIncarnationIndex, StructurallyBoundStateSnapshot, UnresolvedBundlePublicationRetention } from './shadow-protocol';
|
|
10
|
+
import { type ChangeManifestRecord } from './change-manifest-store';
|
|
10
11
|
/** A recovered shadow state (read from the durable per-task marker). */
|
|
11
12
|
export interface RecoveredShadow {
|
|
12
13
|
taskId: string;
|
|
@@ -43,10 +44,14 @@ export interface RecoveredShadow {
|
|
|
43
44
|
mode?: number | null;
|
|
44
45
|
}>;
|
|
45
46
|
casRecovery?: CasRecoveryAuthority[];
|
|
47
|
+
/** P63 Slice 2 (S2-9) — shard-backed promotion authority (replaces the two inline lists above). */
|
|
48
|
+
promoteManifest?: ChangeManifestRecord;
|
|
46
49
|
disposalSnapshotAuthority?: WorkspaceRootAuthority;
|
|
47
50
|
disposalShadowIdentity?: AnchoredFsIdentity;
|
|
48
51
|
/** Exact reviewed artifact persisted before authorization could resolve. */
|
|
49
52
|
reviewedDiff?: ShadowDiffFile[];
|
|
53
|
+
/** P63 Slice 2 (§9.4) — the reviewed artifact as a shard-backed manifest (replaces `reviewedDiff`). */
|
|
54
|
+
reviewedManifest?: ChangeManifestRecord;
|
|
50
55
|
cleanupBlocked?: boolean;
|
|
51
56
|
cleanupOwners?: ProcessCleanupOwner[];
|
|
52
57
|
unresolvedAuthorityRetention?: UnresolvedBundlePublicationRetention;
|
|
@@ -175,11 +180,31 @@ export declare function copyStatTuple(stat: {
|
|
|
175
180
|
ino: string;
|
|
176
181
|
mode: string;
|
|
177
182
|
}): string;
|
|
183
|
+
/** P63 Slice 2 R1-F6 — what a snapshot walk leaves out, for the review INDEX (§5.7). */
|
|
184
|
+
export interface ShadowPrivateEntries {
|
|
185
|
+
folders: Array<{
|
|
186
|
+
path: string;
|
|
187
|
+
group: 'hidden' | 'dependencies' | 'rebuild-output' | 'codevibe';
|
|
188
|
+
}>;
|
|
189
|
+
notApplicable: string[];
|
|
190
|
+
}
|
|
191
|
+
/** The §5.7 group of a skipped folder name. */
|
|
192
|
+
export declare function privateFolderGroup(name: string): ShadowPrivateEntries['folders'][number]['group'];
|
|
178
193
|
export declare function listShadowRegularFiles(shadowDir: string, shadowRootAuthority: WorkspaceRootAuthority,
|
|
179
194
|
/** §7.1: when given, receives every listed file's stat tuple (from the same isolated enumeration — no extra I/O). */
|
|
180
|
-
statsOut?: Map<string, string
|
|
181
|
-
|
|
182
|
-
|
|
195
|
+
statsOut?: Map<string, string>,
|
|
196
|
+
/**
|
|
197
|
+
* P63 Slice 2 R1-F6 (§5.7): when given, receives the private folders the walk skips (with their group) and every
|
|
198
|
+
* entry that is neither a file nor a directory — the review INDEX lists both as never applied.
|
|
199
|
+
*/
|
|
200
|
+
privateOut?: ShadowPrivateEntries,
|
|
201
|
+
/**
|
|
202
|
+
* F-EXIT-WAITS-CAPTURE (tick): a caller-owned budget. A listing larger than it stops at the first folder past the
|
|
203
|
+
* limit, and the caller reads `budget.entries > budget.maxEntries` to tell that apart from any other failure.
|
|
204
|
+
*/
|
|
205
|
+
callerBudget?: PathBudget): Promise<string[]>;
|
|
206
|
+
export type PathBudget = MetadataBudget;
|
|
207
|
+
export declare function createPathBudget(maxEntries?: number): PathBudget;
|
|
183
208
|
export declare function assertPathCollectionBounds(paths: readonly string[], label: string): void;
|
|
184
209
|
export declare function isWithinRoot(root: string, candidate: string): boolean;
|
|
185
210
|
export declare function assertSafeStateComponent(value: string): void;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export declare const TASK_INTENT_VERSION = 1;
|
|
2
|
+
/** How long a stopped task's copy waits for a resume: the session resume window, not the 24 h orphan TTL. */
|
|
3
|
+
export declare const INTERRUPTED_TASK_RETENTION_MS: number;
|
|
4
|
+
export interface TaskIntent {
|
|
5
|
+
version: typeof TASK_INTENT_VERSION;
|
|
6
|
+
sessionId: string;
|
|
7
|
+
brief: string;
|
|
8
|
+
request?: string;
|
|
9
|
+
agent: string;
|
|
10
|
+
decision: unknown;
|
|
11
|
+
/**
|
|
12
|
+
* S2-C3 (Stage 2 R1): the task was started opted in to run UNCONFINED (§6.4). History, not permission: a reopened
|
|
13
|
+
* task keeps the after-run check of the user's folder and the summary's disclosure, and is never itself allowed to
|
|
14
|
+
* run an agent unconfined because of it.
|
|
15
|
+
*/
|
|
16
|
+
ranUnconfined?: true;
|
|
17
|
+
}
|
|
18
|
+
export type ReadTaskIntent = {
|
|
19
|
+
kind: 'none';
|
|
20
|
+
}
|
|
21
|
+
/** §17: a version this desktop does not know is listed and never acted on. */
|
|
22
|
+
| {
|
|
23
|
+
kind: 'newer';
|
|
24
|
+
} | {
|
|
25
|
+
kind: 'intent';
|
|
26
|
+
intent: TaskIntent;
|
|
27
|
+
};
|
|
28
|
+
export declare function writeTaskIntent(stateDir: string, shadowDir: string, intent: TaskIntent): Promise<void>;
|
|
29
|
+
export declare function readTaskIntent(stateDir: string, shadowDir: string): Promise<ReadTaskIntent>;
|
|
@@ -26,17 +26,3 @@ export declare function probeVolumeCapabilities(projectRoot: string, journalProb
|
|
|
26
26
|
export declare function removeJournaledProbeEntry(projectRoot: string, name: string): Promise<void>;
|
|
27
27
|
/** §9.1: inodes count as identity only with the flag, in the same boot, on the same device. */
|
|
28
28
|
export declare function inodesTrustedNow(journaled: Pick<VolumeCapabilities, 'inodeStable' | 'bootId' | 'dev'>, projectRoot: string, platform?: NodeJS.Platform): Promise<boolean>;
|
|
29
|
-
/**
|
|
30
|
-
* P63 SB-51 (Hendry, 2026-10-24: "fail closed on drvfs"): applying into a Windows drive from WSL2 is refused in
|
|
31
|
-
* Slice 1 — no WSL2 host was available to qualify §9.3 on a real drvfs volume. Nothing is applied; the copy is kept.
|
|
32
|
-
*/
|
|
33
|
-
export declare const DRVFS_APPLY_REFUSAL = "Applying into a Windows drive from WSL2 (drvfs) isn't supported yet \u2014 nothing was applied; the task's copy is kept.";
|
|
34
|
-
/**
|
|
35
|
-
* True when `target` lives on a WSL drvfs mount: the longest `/proc/self/mountinfo` mount point containing its
|
|
36
|
-
* real path has filesystem type `drvfs` (WSL1, some WSL2 builds) or `9p` with `aname=drvfs` (WSL2). Only Linux
|
|
37
|
-
* has drvfs; elsewhere this is false without reading anything.
|
|
38
|
-
*/
|
|
39
|
-
export declare function isDrvfsPath(target: string, opts?: {
|
|
40
|
-
mountinfo?: string;
|
|
41
|
-
platform?: NodeJS.Platform;
|
|
42
|
-
}): Promise<boolean>;
|