@tiphys/kernel 0.1.0 → 0.2.0
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/AGENTS.md +56 -4
- package/assurance-modes.yaml +23 -2
- package/dist/bin/tiphys.js +86 -8
- package/dist/src/adapters/load.d.ts +202 -0
- package/dist/src/adapters/load.js +440 -0
- package/dist/src/brief.js +27 -20
- package/dist/src/checks.d.ts +720 -9
- package/dist/src/checks.js +1874 -163
- package/dist/src/cli.js +11 -0
- package/dist/src/commands/brief.js +27 -4
- package/dist/src/commands/cutover.d.ts +35 -0
- package/dist/src/commands/cutover.js +448 -0
- package/dist/src/commands/doctor.d.ts +229 -0
- package/dist/src/commands/doctor.js +968 -27
- package/dist/src/commands/init.d.ts +3 -3
- package/dist/src/commands/init.js +57 -8
- package/dist/src/commands/lock.d.ts +33 -0
- package/dist/src/commands/lock.js +117 -6
- package/dist/src/commands/next.d.ts +130 -0
- package/dist/src/commands/next.js +597 -0
- package/dist/src/commands/pool.js +12 -1
- package/dist/src/commands/resume.d.ts +1 -0
- package/dist/src/commands/resume.js +88 -0
- package/dist/src/commands/spawn.js +51 -2
- package/dist/src/commands/status.d.ts +6 -4
- package/dist/src/commands/status.js +6 -4
- package/dist/src/commands/sync.d.ts +47 -0
- package/dist/src/commands/sync.js +341 -0
- package/dist/src/commands/teardown.js +10 -2
- package/dist/src/commands/validate.js +70 -0
- package/dist/src/cutover.d.ts +584 -0
- package/dist/src/cutover.js +1444 -0
- package/dist/src/exclusion.d.ts +389 -0
- package/dist/src/exclusion.js +843 -0
- package/dist/src/exec/env.d.ts +152 -2
- package/dist/src/exec/env.js +146 -2
- package/dist/src/fleet.d.ts +172 -0
- package/dist/src/fleet.js +219 -1
- package/dist/src/gates/citations.js +7 -1
- package/dist/src/gates/coverage.d.ts +113 -22
- package/dist/src/gates/coverage.js +166 -31
- package/dist/src/gates/credentials.d.ts +159 -0
- package/dist/src/gates/credentials.js +221 -2
- package/dist/src/gates/gate-classes.d.ts +56 -0
- package/dist/src/gates/gate-classes.js +633 -0
- package/dist/src/gates/merge-preconditions.d.ts +319 -0
- package/dist/src/gates/merge-preconditions.js +932 -0
- package/dist/src/gates/red-witness.js +105 -13
- package/dist/src/gates/run.d.ts +49 -1
- package/dist/src/gates/run.js +83 -5
- package/dist/src/gates/schemas/phase-declaration.schema.json +45 -0
- package/dist/src/gates/suite.js +48 -7
- package/dist/src/hooks.d.ts +55 -3
- package/dist/src/hooks.js +69 -6
- package/dist/src/index.d.ts +31 -0
- package/dist/src/index.js +30 -0
- package/dist/src/lock.d.ts +82 -4
- package/dist/src/lock.js +314 -22
- package/dist/src/model-resolution.d.ts +159 -0
- package/dist/src/model-resolution.js +307 -0
- package/dist/src/path-identity.d.ts +32 -0
- package/dist/src/path-identity.js +38 -0
- package/dist/src/pool.d.ts +197 -1
- package/dist/src/pool.js +289 -22
- package/dist/src/roles.d.ts +31 -0
- package/dist/src/roles.js +42 -0
- package/dist/src/spawn.d.ts +307 -2
- package/dist/src/spawn.js +690 -19
- package/dist/src/status.d.ts +27 -2
- package/dist/src/status.js +34 -5
- package/dist/src/task.d.ts +295 -55
- package/dist/src/task.js +125 -123
- package/dist/src/teardown.d.ts +7 -0
- package/dist/src/teardown.js +120 -12
- package/dist/src/validate.d.ts +44 -11
- package/dist/src/validate.js +44 -34
- package/dist/src/watcher.js +1 -11
- package/dist/src/witness/run.d.ts +32 -7
- package/dist/src/witness/run.js +76 -30
- package/dist/src/witness/spec.d.ts +168 -0
- package/dist/src/witness/spec.js +240 -18
- package/dist/tsconfig.src.tsbuildinfo +1 -1
- package/gate-registry.yaml +136 -0
- package/gates.manifest.json +63 -1
- package/package.json +18 -3
- package/roles/implementer.md +3 -0
- package/schemas/README.md +1 -0
- package/schemas/assurance-modes.schema.json +1 -1
- package/schemas/charter.schema.json +19 -0
- package/schemas/cutover-state.schema.json +64 -0
- package/schemas/executor-record.schema.json +36 -0
- package/schemas/model-resolution.schema.json +362 -0
- package/schemas/verdict.schema.json +9 -3
- package/schemas/write-bypass.schema.json +69 -0
package/dist/src/hooks.js
CHANGED
|
@@ -29,9 +29,71 @@ export function turnEndHookPath(fleet, taskId) {
|
|
|
29
29
|
}
|
|
30
30
|
/**
|
|
31
31
|
* Generate the hook script. The turn-end path is baked in as a literal,
|
|
32
|
-
* so the hook needs no fleet resolution
|
|
32
|
+
* so the hook needs no fleet resolution.
|
|
33
|
+
*
|
|
34
|
+
* THE CHILD-OBSERVED POINTER RECORD (CR-B-001, the half that closes the hole
|
|
35
|
+
* rather than the half that stops mis-asserting it).
|
|
36
|
+
*
|
|
37
|
+
* `observeNames`, when given, is baked in as a literal array and the hook
|
|
38
|
+
* writes an `env` object holding what each of those names ACTUALLY IS in the
|
|
39
|
+
* environment the hook was launched with, or `null` where the name is unset.
|
|
40
|
+
* The kernel compares those against the harness-owned paths it handed over.
|
|
41
|
+
*
|
|
42
|
+
* WHY THIS IS STRONGER THAN AN ADAPTER'S REPORT AND WHY IT IS NOT PROOF.
|
|
43
|
+
* This script is written BY THE KERNEL and, for every adapter that honours
|
|
44
|
+
* the documented contract, runs in the SAME environment as the payload (the
|
|
45
|
+
* built-in adapter spreads the same `request.env` into both spawnSync calls,
|
|
46
|
+
* and M2R-004 edit 4 is the record of why a second unscrubbed launch is
|
|
47
|
+
* itself the leak). Against an adapter that does not invoke this script at
|
|
48
|
+
* all it proves nothing, and the record no longer says otherwise.
|
|
49
|
+
*
|
|
50
|
+
* THE COST SENTENCE THAT STOOD HERE IS WITHDRAWN, BECAUSE IT WAS REFUTED BY
|
|
51
|
+
* MEASUREMENT (CR-F-CRED-001, MEDIUM).
|
|
52
|
+
*
|
|
53
|
+
* It read: an adapter that quietly reverted `HOME` for the payload "has to
|
|
54
|
+
* revert it for the payload and NOT for the hook, which means launching two
|
|
55
|
+
* children with two different environments and is a substantially different
|
|
56
|
+
* act from passing a mutated copy once". Two children is one way to do it and
|
|
57
|
+
* it is not the cheap way. The cheap way is ONE child with the mutated
|
|
58
|
+
* environment plus a single `writeFileSync` of the turn-end path, which is
|
|
59
|
+
* STRICTLY LESS work than the honest path, because the honest path also
|
|
60
|
+
* spawns the hook. The turn-end path is handed to the adapter beside
|
|
61
|
+
* `hookPath`, and this generated script names it as a literal, so an adapter
|
|
62
|
+
* that never runs it can still produce a byte-identical record.
|
|
63
|
+
*
|
|
64
|
+
* WHY A NONCE DOES NOT CLOSE THIS, stated because it is the obvious repair and
|
|
65
|
+
* it was considered and refused rather than overlooked. Baking a per-task
|
|
66
|
+
* secret into this script and requiring it in the record moves the forgery
|
|
67
|
+
* from "know the path" to "read the file", and the adapter is HANDED the path
|
|
68
|
+
* of this file: it runs at the same uid, on the same filesystem, in a
|
|
69
|
+
* directory it must be able to read to invoke the hook at all. A guard whose
|
|
70
|
+
* condition the adversary can satisfy by reading one file is green and
|
|
71
|
+
* worthless, which is this repository's own recorded shape (T-008's
|
|
72
|
+
* postscript, the red-witness rule one level up). No artifact this script can
|
|
73
|
+
* write is unforgeable by a party that can read this script.
|
|
74
|
+
*
|
|
75
|
+
* So the repair is on the RECORD rather than on the check: the value is
|
|
76
|
+
* `turn-end-record`, it names the artifact the values were read from, and
|
|
77
|
+
* `CredentialHandoverRecord` (src/task.ts) says the artifact is
|
|
78
|
+
* adapter-reachable. A dishonest adapter is still not caught here, and that
|
|
79
|
+
* residue is declared at delivery/work-history/m4-p8.md item 3; what changed
|
|
80
|
+
* is that `meta.json` no longer positively asserts a child-side observation
|
|
81
|
+
* that no child made.
|
|
82
|
+
*
|
|
83
|
+
* The hook still reads no environment it was not told to read, and a hook
|
|
84
|
+
* generated with no `observeNames` behaves exactly as it did before.
|
|
33
85
|
*/
|
|
34
|
-
export function renderTurnEndHook(turnEndFile) {
|
|
86
|
+
export function renderTurnEndHook(turnEndFile, observeNames) {
|
|
87
|
+
const observing = observeNames !== undefined && observeNames.length > 0;
|
|
88
|
+
const envLines = observing
|
|
89
|
+
? `const observed = {};
|
|
90
|
+
for (const name of ${JSON.stringify([...observeNames])}) {
|
|
91
|
+
const value = process.env[name];
|
|
92
|
+
observed[name] = typeof value === "string" ? value : null;
|
|
93
|
+
}
|
|
94
|
+
record.env = observed;
|
|
95
|
+
`
|
|
96
|
+
: "";
|
|
35
97
|
return `#!/usr/bin/env node
|
|
36
98
|
// Generated by tiphys spawn (kernel plan v1, M1-P4 step 3). Invoked by the
|
|
37
99
|
// executor adapter when the payload command exits, with the payload's exit
|
|
@@ -46,16 +108,17 @@ if (!Number.isInteger(exitCode)) {
|
|
|
46
108
|
);
|
|
47
109
|
process.exit(64);
|
|
48
110
|
}
|
|
49
|
-
|
|
111
|
+
const record = { endedAt: new Date().toISOString(), exitCode };
|
|
112
|
+
${envLines}writeFileSync(
|
|
50
113
|
${JSON.stringify(turnEndFile)},
|
|
51
|
-
\`\${JSON.stringify(
|
|
114
|
+
\`\${JSON.stringify(record, null, 2)}\\n\`,
|
|
52
115
|
);
|
|
53
116
|
`;
|
|
54
117
|
}
|
|
55
118
|
/** Write the hook for a task and return its path. */
|
|
56
|
-
export function writeTurnEndHook(fleet, taskId) {
|
|
119
|
+
export function writeTurnEndHook(fleet, taskId, observeNames) {
|
|
57
120
|
const path = turnEndHookPath(fleet, taskId);
|
|
58
|
-
writeFileSync(path, renderTurnEndHook(turnEndPath(fleet, taskId)), {
|
|
121
|
+
writeFileSync(path, renderTurnEndHook(turnEndPath(fleet, taskId), observeNames), {
|
|
59
122
|
mode: 0o755,
|
|
60
123
|
});
|
|
61
124
|
return path;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE KERNEL'S PUBLIC ENTRY POINT (kernel plan M4, M4-P4 criteria 7 and 8).
|
|
3
|
+
*
|
|
4
|
+
* Until this phase `@tiphys/kernel` declared `bin` and nothing else
|
|
5
|
+
* (package.json:14): no `main`, no `exports`, no `types`, and no
|
|
6
|
+
* `src/index.ts`. A separately published plugin could therefore not import
|
|
7
|
+
* `ExecutorAdapter` at all, which made the executor seam unreachable from
|
|
8
|
+
* outside this repository however well the interface was written.
|
|
9
|
+
*
|
|
10
|
+
* WHAT IS PUBLISHED HERE IS A COMMITMENT AND IS DELIBERATELY SMALL. An
|
|
11
|
+
* `exports` map is a semver promise and a patch release cannot take one back,
|
|
12
|
+
* so this file names the adapter CONTRACT and nothing else. In particular it
|
|
13
|
+
* does not export `spawnTask`, the fleet accessors, the gate runner or
|
|
14
|
+
* anything under `src/exec/`: those are the kernel's internals, they change
|
|
15
|
+
* without notice, and `package.json`'s `exports` map has no wildcard subpath
|
|
16
|
+
* precisely so that they stay unreachable through the package name
|
|
17
|
+
* (criterion 8, whose dangerous state is an `exports` map written
|
|
18
|
+
* `"./*": "./dist/src/*"`, which satisfies criterion 7 and publishes the
|
|
19
|
+
* entire kernel as API).
|
|
20
|
+
*
|
|
21
|
+
* THE TWO VALUES ARE PART OF THE CONTRACT, not a convenience. An adapter
|
|
22
|
+
* author has to answer two questions that types cannot answer at runtime:
|
|
23
|
+
* which names may appear in `requires` (the closed set the kernel checks
|
|
24
|
+
* against, src/spawn.ts's `requirableRequestFields`), and which name is
|
|
25
|
+
* reserved for the built-in adapter (`BUILT_IN_ADAPTER_NAME`, refused by the
|
|
26
|
+
* loader). Publishing the answers is cheaper than publishing a document that
|
|
27
|
+
* drifts from them.
|
|
28
|
+
*/
|
|
29
|
+
export type { ExecutorAdapter, ExecutorRecord, ExecutorRequest, LaunchOutcome, } from "./spawn.ts";
|
|
30
|
+
export { requirableRequestFields } from "./spawn.ts";
|
|
31
|
+
export { BUILT_IN_ADAPTER_NAME } from "./adapters/load.ts";
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE KERNEL'S PUBLIC ENTRY POINT (kernel plan M4, M4-P4 criteria 7 and 8).
|
|
3
|
+
*
|
|
4
|
+
* Until this phase `@tiphys/kernel` declared `bin` and nothing else
|
|
5
|
+
* (package.json:14): no `main`, no `exports`, no `types`, and no
|
|
6
|
+
* `src/index.ts`. A separately published plugin could therefore not import
|
|
7
|
+
* `ExecutorAdapter` at all, which made the executor seam unreachable from
|
|
8
|
+
* outside this repository however well the interface was written.
|
|
9
|
+
*
|
|
10
|
+
* WHAT IS PUBLISHED HERE IS A COMMITMENT AND IS DELIBERATELY SMALL. An
|
|
11
|
+
* `exports` map is a semver promise and a patch release cannot take one back,
|
|
12
|
+
* so this file names the adapter CONTRACT and nothing else. In particular it
|
|
13
|
+
* does not export `spawnTask`, the fleet accessors, the gate runner or
|
|
14
|
+
* anything under `src/exec/`: those are the kernel's internals, they change
|
|
15
|
+
* without notice, and `package.json`'s `exports` map has no wildcard subpath
|
|
16
|
+
* precisely so that they stay unreachable through the package name
|
|
17
|
+
* (criterion 8, whose dangerous state is an `exports` map written
|
|
18
|
+
* `"./*": "./dist/src/*"`, which satisfies criterion 7 and publishes the
|
|
19
|
+
* entire kernel as API).
|
|
20
|
+
*
|
|
21
|
+
* THE TWO VALUES ARE PART OF THE CONTRACT, not a convenience. An adapter
|
|
22
|
+
* author has to answer two questions that types cannot answer at runtime:
|
|
23
|
+
* which names may appear in `requires` (the closed set the kernel checks
|
|
24
|
+
* against, src/spawn.ts's `requirableRequestFields`), and which name is
|
|
25
|
+
* reserved for the built-in adapter (`BUILT_IN_ADAPTER_NAME`, refused by the
|
|
26
|
+
* loader). Publishing the answers is cheaper than publishing a document that
|
|
27
|
+
* drifts from them.
|
|
28
|
+
*/
|
|
29
|
+
export { requirableRequestFields } from "./spawn.js";
|
|
30
|
+
export { BUILT_IN_ADAPTER_NAME } from "./adapters/load.js";
|
package/dist/src/lock.d.ts
CHANGED
|
@@ -51,9 +51,19 @@
|
|
|
51
51
|
*
|
|
52
52
|
* Exclusion domain (PR-201, DR-0007 stated honestly): the lease excludes
|
|
53
53
|
* within one filesystem and one clock, the fleet home the lock file lives
|
|
54
|
-
* in.
|
|
55
|
-
*
|
|
56
|
-
*
|
|
54
|
+
* in. Mutations of the lock file made outside this module (manual edits)
|
|
55
|
+
* are not covered by the contract.
|
|
56
|
+
*
|
|
57
|
+
* CROSS-ENVIRONMENT EXCLUSION IS A SECOND LAYER ABOVE THIS ONE (M4-P21),
|
|
58
|
+
* and it is OFF unless the fleet home declares it. When the fleet's own
|
|
59
|
+
* `package.json` carries `tiphys.sharedExclusion`, every mutation below
|
|
60
|
+
* first asks `src/exclusion.ts` for a verdict from the shared register on
|
|
61
|
+
* the fleet's git remote, and only a won verdict reaches the local lease.
|
|
62
|
+
* With the field ABSENT, `readSharedExclusion` returns before spawning
|
|
63
|
+
* anything and every path in this module behaves exactly as it did, which
|
|
64
|
+
* is the property M4-P21 criterion 1 asserts. The refusal never touches the
|
|
65
|
+
* lock file, which is what makes the fail-closed behaviour on an
|
|
66
|
+
* unreachable register observable (criterion 7): no local lease appears.
|
|
57
67
|
*
|
|
58
68
|
* Renewal discipline (PR-203): the default lease lasts 900 seconds and
|
|
59
69
|
* the holder renews at or before half-life (renewByMs). Holdership on
|
|
@@ -77,15 +87,39 @@ export type ObservedLease = {
|
|
|
77
87
|
raw: string;
|
|
78
88
|
lease: Lease | undefined;
|
|
79
89
|
};
|
|
90
|
+
/**
|
|
91
|
+
* What the shared exclusion layer decided. Present only when the fleet home
|
|
92
|
+
* declares the layer; the CLI prints `line` verbatim, and `line` always
|
|
93
|
+
* names which of the two staleness bases reached the verdict, which is
|
|
94
|
+
* M4-P21 criterion 6.
|
|
95
|
+
*
|
|
96
|
+
* THE VERDICT IS CARRIED AS TEXT ON PURPOSE, not as a discriminated field.
|
|
97
|
+
* The C-2 structural inspection over this file (test/lock.test.ts:534,
|
|
98
|
+
* M1-P3 criterion 10) forbids a whole vocabulary of process-probing words
|
|
99
|
+
* from `src/lock.ts`, and it is a blunt case-insensitive grep, which is the
|
|
100
|
+
* property that makes it hard to defeat by accident. Naming the field after
|
|
101
|
+
* that vocabulary would have reddened it for a reason that has nothing to do
|
|
102
|
+
* with C-2, and widening the grep to let this through would weaken a guard
|
|
103
|
+
* this module is the whole reason for. The classification itself lives in
|
|
104
|
+
* `src/exclusion.ts`, which no such grep covers, and any caller needing it
|
|
105
|
+
* as a value reads it there.
|
|
106
|
+
*/
|
|
107
|
+
export interface SharedNote {
|
|
108
|
+
line: string;
|
|
109
|
+
envId: string;
|
|
110
|
+
}
|
|
80
111
|
export type LeaseOutcome = {
|
|
81
112
|
ok: true;
|
|
82
113
|
lease: Lease;
|
|
114
|
+
shared?: SharedNote;
|
|
83
115
|
} | {
|
|
84
116
|
ok: true;
|
|
85
117
|
lease: null;
|
|
118
|
+
shared?: SharedNote;
|
|
86
119
|
} | {
|
|
87
120
|
ok: false;
|
|
88
121
|
reason: string;
|
|
122
|
+
shared?: SharedNote;
|
|
89
123
|
/**
|
|
90
124
|
* True when the operation failed because a mutation claim file
|
|
91
125
|
* was still present after the bounded wait (CR-204). A stale
|
|
@@ -97,8 +131,40 @@ export type LeaseOutcome = {
|
|
|
97
131
|
claimTimeout?: boolean;
|
|
98
132
|
};
|
|
99
133
|
export declare function renderLease(lease: Lease): string;
|
|
100
|
-
/**
|
|
134
|
+
/**
|
|
135
|
+
* Read the current lock file state: absent, or present with raw bytes.
|
|
136
|
+
*
|
|
137
|
+
* THE ENTRY TYPE IS ESTABLISHED BEFORE THE OPEN (T-008's shape in shipped
|
|
138
|
+
* code). A bare `readFileSync` here blocked FOREVER with zero output on a
|
|
139
|
+
* named pipe at the lease path, and took `lock status`, `lock acquire`,
|
|
140
|
+
* `lock renew` and `lock release` with it, while `tiphys doctor` returned in
|
|
141
|
+
* the same second against the same FIFO with "is a named pipe, not a regular
|
|
142
|
+
* file, so it was not opened". Two readers of one path, one of which
|
|
143
|
+
* established the type; this is now the same reader.
|
|
144
|
+
*
|
|
145
|
+
* A refusal THROWS rather than returning a fourth `ObservedLease` variant.
|
|
146
|
+
* The function already threw on every non-ENOENT error, so the contract its
|
|
147
|
+
* callers were written against is unchanged, and bin/tiphys.ts turns the
|
|
148
|
+
* throw into one diagnostic line and a nonzero exit.
|
|
149
|
+
*/
|
|
101
150
|
export declare function observeLease(lockPath: string): ObservedLease;
|
|
151
|
+
/**
|
|
152
|
+
* THE ONE EXPIRY COMPARISON IN THE KERNEL (M4-P17 criterion 2).
|
|
153
|
+
*
|
|
154
|
+
* `isExpired` below needs a whole `Lease`, and doctor's lock check does not
|
|
155
|
+
* have one: it reads the lease file defensively and holds only `holderId` and
|
|
156
|
+
* `expiresAt`, because a lease file that fails `parseLease` must still produce
|
|
157
|
+
* a diagnosis rather than nothing. Before this phase that forced doctor to
|
|
158
|
+
* carry its own `Date.parse(...) <= Date.now()`, which is a SECOND comparison
|
|
159
|
+
* of the same property, free to drift from this one. The boundary is where
|
|
160
|
+
* that drift shows: `<=` makes expiry INCLUSIVE, so a lease whose `expiresAt`
|
|
161
|
+
* is exactly the current millisecond is expired, and a second copy written
|
|
162
|
+
* with `<` disagrees for exactly one millisecond and agrees everywhere else.
|
|
163
|
+
* A disagreement that narrow is not something a reviewer finds by reading.
|
|
164
|
+
*
|
|
165
|
+
* So the comparison lives here once and both callers reach it.
|
|
166
|
+
*/
|
|
167
|
+
export declare function expiryHasPassed(expiresAt: string, nowMs: number): boolean;
|
|
102
168
|
export declare function isExpired(lease: Lease, nowMs: number): boolean;
|
|
103
169
|
/** The renew-by deadline (half-life of the current term), for holders. */
|
|
104
170
|
export declare function renewByMs(lease: Lease): number;
|
|
@@ -126,6 +192,12 @@ export interface AcquireOptions {
|
|
|
126
192
|
takeover?: boolean;
|
|
127
193
|
durationSeconds?: number;
|
|
128
194
|
nowMs?: number;
|
|
195
|
+
/**
|
|
196
|
+
* The fleet home this lock belongs to. Derived from lockPath when absent;
|
|
197
|
+
* named explicitly only by callers whose lock path is not the fleet's
|
|
198
|
+
* canonical one.
|
|
199
|
+
*/
|
|
200
|
+
fleetRoot?: string;
|
|
129
201
|
/**
|
|
130
202
|
* Staging seam for deterministic race witnesses: the decision is made
|
|
131
203
|
* against this pre-observed state instead of a fresh read, and the
|
|
@@ -142,6 +214,8 @@ export declare function acquireLease(lockPath: string, options?: AcquireOptions)
|
|
|
142
214
|
export interface RenewOptions {
|
|
143
215
|
durationSeconds?: number;
|
|
144
216
|
nowMs?: number;
|
|
217
|
+
/** See AcquireOptions.fleetRoot. */
|
|
218
|
+
fleetRoot?: string;
|
|
145
219
|
/** Staging seam for deterministic race witnesses; see AcquireOptions. */
|
|
146
220
|
observed?: ObservedLease;
|
|
147
221
|
}
|
|
@@ -156,6 +230,10 @@ export declare function renewLease(lockPath: string, holderId: string, options?:
|
|
|
156
230
|
export interface ReleaseOptions {
|
|
157
231
|
/** Staging seam for deterministic race witnesses; see AcquireOptions. */
|
|
158
232
|
observed?: ObservedLease;
|
|
233
|
+
/** See AcquireOptions.fleetRoot. */
|
|
234
|
+
fleetRoot?: string;
|
|
235
|
+
/** Decision clock, for the shared layer. Defaults to Date.now(). */
|
|
236
|
+
nowMs?: number;
|
|
159
237
|
}
|
|
160
238
|
/**
|
|
161
239
|
* Release the lease held by holderId. Expiry does not block a release
|