riftri 0.6.2 → 0.6.4
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/lib/client.d.ts +32 -1
- package/lib/client.js +32 -3
- package/lib/platform.js +12 -1
- package/package.json +9 -9
package/lib/client.d.ts
CHANGED
|
@@ -5,6 +5,9 @@ export const EXIT_OPERATIONAL: 1;
|
|
|
5
5
|
export const EXIT_USAGE: 2;
|
|
6
6
|
export const EXIT_POLICY: 3;
|
|
7
7
|
|
|
8
|
+
/** Resolve and validate the installed native executable, honoring RIFTRI_BINARY. Does not spawn. */
|
|
9
|
+
export function resolveBinary(): string;
|
|
10
|
+
|
|
8
11
|
/** One versioned failure receipt, as emitted by `--json-errors`. */
|
|
9
12
|
export interface FailureReceipt {
|
|
10
13
|
schemaVersion: number;
|
|
@@ -37,7 +40,9 @@ export class RiftriError extends Error {
|
|
|
37
40
|
/** The process was killed rather than exiting on its own. */
|
|
38
41
|
readonly wasSignalled: boolean;
|
|
39
42
|
readonly receipt: FailureReceipt | null;
|
|
40
|
-
/**
|
|
43
|
+
/** Parsed stdout on a nonzero exit (for example a failed post-checkout hook), or null. Validate before use. */
|
|
44
|
+
readonly report: unknown;
|
|
45
|
+
/** A native policy receipt confirms no mutation; an exit code alone is insufficient. */
|
|
41
46
|
readonly isPolicyRefusal: boolean;
|
|
42
47
|
/** The request was malformed; never retry it unchanged. */
|
|
43
48
|
readonly isUsageError: boolean;
|
|
@@ -110,6 +115,28 @@ export interface WorktreeInventory {
|
|
|
110
115
|
native_path_encoding: string;
|
|
111
116
|
}
|
|
112
117
|
|
|
118
|
+
export interface WorktreeOwner {
|
|
119
|
+
schema_version: 1;
|
|
120
|
+
/** Null only when no registered state claims the path. Errors reject. */
|
|
121
|
+
state_directory: string | null;
|
|
122
|
+
state_directory_native_hex: string | null;
|
|
123
|
+
native_path_encoding: string;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export interface WorktreeInspectionReport {
|
|
127
|
+
schema_version: 1;
|
|
128
|
+
native_path_encoding: string;
|
|
129
|
+
worktrees: Array<{
|
|
130
|
+
path: string;
|
|
131
|
+
path_native_hex: string;
|
|
132
|
+
state_directory: string | null;
|
|
133
|
+
state_directory_native_hex: string | null;
|
|
134
|
+
backend: string | null;
|
|
135
|
+
/** Null unless the managed backend needs a mount. Inspection never repairs. */
|
|
136
|
+
mount_status: "active" | "recovery-required" | "different-namespace" | "foreign" | "unavailable" | null;
|
|
137
|
+
}>;
|
|
138
|
+
}
|
|
139
|
+
|
|
113
140
|
export interface StateDiagnosticIssue {
|
|
114
141
|
path: string;
|
|
115
142
|
path_native_hex: string;
|
|
@@ -239,6 +266,10 @@ export class Riftri {
|
|
|
239
266
|
|
|
240
267
|
readonly worktree: {
|
|
241
268
|
add(destination: string, options?: AddOptions): Promise<AddReport>;
|
|
269
|
+
/** Advisory ownership lookup without disk accounting; mutations revalidate. */
|
|
270
|
+
owner(destination: string): Promise<WorktreeOwner>;
|
|
271
|
+
/** One read-only discovery pass; paths retain the requested order. */
|
|
272
|
+
inspect(destinations: readonly string[]): Promise<WorktreeInspectionReport>;
|
|
242
273
|
list(options: { allStates: true }): Promise<AllStatesWorktreeInventory>;
|
|
243
274
|
list(options?: { allStates?: false }): Promise<WorktreeInventory>;
|
|
244
275
|
/** Narrow schema_version when allStates is a runtime boolean. */
|
package/lib/client.js
CHANGED
|
@@ -29,7 +29,7 @@ const REPORTING = new Set([
|
|
|
29
29
|
]);
|
|
30
30
|
|
|
31
31
|
class RiftriError extends Error {
|
|
32
|
-
constructor(exitCode, receipt, stderr, signal = null) {
|
|
32
|
+
constructor(exitCode, receipt, stderr, signal = null, report = null) {
|
|
33
33
|
super(
|
|
34
34
|
// JSON is not a guarantee of a valid receipt. Coercing an object here
|
|
35
35
|
// can throw inside the child close handler instead of rejecting run().
|
|
@@ -43,6 +43,7 @@ class RiftriError extends Error {
|
|
|
43
43
|
this.exitCode = exitCode;
|
|
44
44
|
this.signal = signal;
|
|
45
45
|
this.receipt = receipt ?? null;
|
|
46
|
+
this.report = report;
|
|
46
47
|
}
|
|
47
48
|
|
|
48
49
|
/** The process was killed rather than exiting on its own. */
|
|
@@ -52,7 +53,12 @@ class RiftriError extends Error {
|
|
|
52
53
|
|
|
53
54
|
/** Riftri declined before touching anything. Falling back is safe. */
|
|
54
55
|
get isPolicyRefusal() {
|
|
55
|
-
return
|
|
56
|
+
// Hooks and `exec` children can return 3 after performing work. Only a
|
|
57
|
+
// native refusal receipt proves the operation stopped before mutation.
|
|
58
|
+
return this.exitCode === EXIT_POLICY && this.signal === null && this.report === null &&
|
|
59
|
+
this.receipt?.schemaVersion === 1 && this.receipt?.outcome === "failed" &&
|
|
60
|
+
this.receipt?.category === "policy" && this.receipt?.cleanup === "not-needed" &&
|
|
61
|
+
typeof this.receipt?.code === "string";
|
|
56
62
|
}
|
|
57
63
|
|
|
58
64
|
/** The request itself was malformed. Never retry unchanged. */
|
|
@@ -120,6 +126,8 @@ class Riftri {
|
|
|
120
126
|
this.worktree = {
|
|
121
127
|
add: this.#worktreeAdd.bind(this),
|
|
122
128
|
list: this.#worktreeList.bind(this),
|
|
129
|
+
owner: this.#worktreeOwner.bind(this),
|
|
130
|
+
inspect: this.#worktreeInspect.bind(this),
|
|
123
131
|
remove: this.#worktreeRemove.bind(this),
|
|
124
132
|
move: this.#worktreeMove.bind(this),
|
|
125
133
|
compact: this.#worktreeCompact.bind(this),
|
|
@@ -212,7 +220,18 @@ class Riftri {
|
|
|
212
220
|
// Plain text, as from a binary that predates usage receipts.
|
|
213
221
|
}
|
|
214
222
|
}
|
|
215
|
-
|
|
223
|
+
let report = null;
|
|
224
|
+
if (json && stdout.trim()) {
|
|
225
|
+
// A failed post-checkout hook leaves a created worktree in place.
|
|
226
|
+
// Preserve that report even though the hook's status rejects run().
|
|
227
|
+
try {
|
|
228
|
+
report = JSON.parse(stdout);
|
|
229
|
+
} catch {
|
|
230
|
+
// Malformed output cannot prove that a fallback is safe either.
|
|
231
|
+
}
|
|
232
|
+
receipt = null;
|
|
233
|
+
}
|
|
234
|
+
reject(new RiftriError(exitCode, receipt, stderr, null, report));
|
|
216
235
|
});
|
|
217
236
|
});
|
|
218
237
|
}
|
|
@@ -300,6 +319,15 @@ class Riftri {
|
|
|
300
319
|
return this.run(["worktree", "list", ...flagsFor(options), ...state]);
|
|
301
320
|
}
|
|
302
321
|
|
|
322
|
+
#worktreeOwner(destination) {
|
|
323
|
+
// Ownership always consults every registered state, not this.stateDir.
|
|
324
|
+
return this.run(["worktree", "owner", "--", destination]);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
#worktreeInspect(destinations) {
|
|
328
|
+
return this.run(["worktree", "inspect", "--", ...destinations]);
|
|
329
|
+
}
|
|
330
|
+
|
|
303
331
|
#worktreeRemove(destination, { force = false } = {}) {
|
|
304
332
|
const args = ["worktree", "remove"];
|
|
305
333
|
if (force) args.push("--force", "--yes");
|
|
@@ -322,6 +350,7 @@ class Riftri {
|
|
|
322
350
|
module.exports = {
|
|
323
351
|
Riftri,
|
|
324
352
|
RiftriError,
|
|
353
|
+
resolveBinary,
|
|
325
354
|
EXIT_SUCCESS,
|
|
326
355
|
EXIT_OPERATIONAL,
|
|
327
356
|
EXIT_USAGE,
|
package/lib/platform.js
CHANGED
|
@@ -75,6 +75,17 @@ function assertUsableBinary(candidate, source) {
|
|
|
75
75
|
return candidate;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
function unpackedElectronBinary(candidate) {
|
|
79
|
+
if (!process.versions.electron) return candidate;
|
|
80
|
+
const segments = candidate.split(path.sep);
|
|
81
|
+
const archive = segments.findLastIndex((segment) => segment.endsWith(".asar"));
|
|
82
|
+
if (archive < 0) return candidate;
|
|
83
|
+
// Electron can read an archived executable, but the OS cannot spawn it.
|
|
84
|
+
// Validate the physical file below instead of relying on Electron's virtual fs.
|
|
85
|
+
segments[archive] += ".unpacked";
|
|
86
|
+
return segments.join(path.sep);
|
|
87
|
+
}
|
|
88
|
+
|
|
78
89
|
function launcherVersion() {
|
|
79
90
|
for (const candidate of [
|
|
80
91
|
path.join(__dirname, "..", "package.json"),
|
|
@@ -141,7 +152,7 @@ function resolveBinary(options = {}) {
|
|
|
141
152
|
);
|
|
142
153
|
|
|
143
154
|
const candidate = path.join(path.dirname(packageJson), "bin", binaryName(platform));
|
|
144
|
-
return assertUsableBinary(candidate, packageName);
|
|
155
|
+
return assertUsableBinary(unpackedElectronBinary(candidate), packageName);
|
|
145
156
|
}
|
|
146
157
|
|
|
147
158
|
module.exports = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "riftri",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.4",
|
|
4
4
|
"description": "Experimental lightweight Git workspaces for parallel development",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Assistant UI contributors",
|
|
@@ -22,14 +22,14 @@
|
|
|
22
22
|
"typescript": "5.9.3"
|
|
23
23
|
},
|
|
24
24
|
"optionalDependencies": {
|
|
25
|
-
"riftri-darwin-arm64": "0.6.
|
|
26
|
-
"riftri-darwin-x64": "0.6.
|
|
27
|
-
"riftri-linux-arm64-gnu": "0.6.
|
|
28
|
-
"riftri-linux-arm64-musl": "0.6.
|
|
29
|
-
"riftri-linux-x64-gnu": "0.6.
|
|
30
|
-
"riftri-linux-x64-musl": "0.6.
|
|
31
|
-
"riftri-win32-arm64": "0.6.
|
|
32
|
-
"riftri-win32-x64": "0.6.
|
|
25
|
+
"riftri-darwin-arm64": "0.6.4",
|
|
26
|
+
"riftri-darwin-x64": "0.6.4",
|
|
27
|
+
"riftri-linux-arm64-gnu": "0.6.4",
|
|
28
|
+
"riftri-linux-arm64-musl": "0.6.4",
|
|
29
|
+
"riftri-linux-x64-gnu": "0.6.4",
|
|
30
|
+
"riftri-linux-x64-musl": "0.6.4",
|
|
31
|
+
"riftri-win32-arm64": "0.6.4",
|
|
32
|
+
"riftri-win32-x64": "0.6.4"
|
|
33
33
|
},
|
|
34
34
|
"repository": {
|
|
35
35
|
"type": "git",
|