@sentropic/h2a 0.97.9 → 0.97.11

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "h2a",
3
3
  "description": "H2A coordination with one MCP endpoint (including Track read tools) and the H2A, Track, and Harness operating skills.",
4
- "version": "0.97.9",
4
+ "version": "0.97.11",
5
5
  "author": {
6
6
  "name": "Fabien Antoine"
7
7
  },
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "h2a",
3
- "version": "0.97.9",
3
+ "version": "0.97.11",
4
4
  "description": "Coordinate Claude, Codex and other CLI agents through the local h2a bus, objective loops and track system of record.",
5
5
  "author": {
6
6
  "name": "Fabien Antoine"
@@ -0,0 +1,162 @@
1
+ /**
2
+ * Succession lock (v4) — single-machine succession protocol.
3
+ *
4
+ * Extracted from `runtime/upgrade/index.ts` (Lot 4, step 1: neutral
5
+ * intra-package move — zero behaviour change). This is the shared lock primitive
6
+ * used by the auto-upgrade prefix lock today, and (later lots) by the identity
7
+ * binding lock. It is a LEAF: it imports only `node:fs/os/crypto/child_process`
8
+ * and nothing from the store, so `upgrade/index.ts` and `local-files/locks.ts`
9
+ * import it directly by file, never via `local-files/index.js`.
10
+ *
11
+ * The full protocol proof-sketch (I1–I7, Lemmas A–C) lives with the code below,
12
+ * moved unchanged from its original location.
13
+ */
14
+ /**
15
+ * R2 staleness-alert threshold. An upgrade held under the lock completes in seconds to
16
+ * a few minutes (bounded tarball fetch + stage + atomic swap), so a lock far older than
17
+ * that whose holder reads "live" ONLY for want of a comparable start time is worth
18
+ * surfacing (a reused PID may be masking a dead holder). Set well above any legitimate
19
+ * hold. It NEVER triggers a reclaim — purely diagnostic (I7: `at` informs, never decides).
20
+ */
21
+ export declare const STALE_LOCK_ALERT_MS: number;
22
+ /** Acquire rounds before giving up (a retry means a rival won meanwhile). */
23
+ export declare const PREFIX_LOCK_MAX_ROUNDS = 3;
24
+ /** Succession chain depth before failing closed with a diagnostic. */
25
+ export declare const PREFIX_LOCK_MAX_CHAIN = 8;
26
+ /** Holder-only GC age for abandoned TMP files (debris, never a decision). */
27
+ export declare const PREFIX_LOCK_TMP_DEBRIS_MAX_AGE_MS: number;
28
+ /** Fallback age for the residue sweep when no owner can be identified. */
29
+ export declare const UPGRADE_RESIDUE_MAX_AGE_MS: number;
30
+ /** Why acquisition failed: live holder, undecidable owner, or an OS error. */
31
+ export type PrefixLockReason = "busy" | "dead-undecidable" | `error:${string}`;
32
+ /** Lease on the global prefix. `token` is present only when acquired. */
33
+ export interface PrefixLockLease {
34
+ readonly acquired: boolean;
35
+ release(): void;
36
+ readonly reason?: PrefixLockReason;
37
+ /** Winning token; present only when acquired. Never republished (I2). */
38
+ readonly token?: string;
39
+ }
40
+ /** Observation window for one deterministic-test hook invocation. */
41
+ export interface PrefixLockHookContext {
42
+ readonly prefix: string;
43
+ readonly lockPath: string;
44
+ /** File the window is about: LOCK for publish/unlink, SUCC(t) after election. */
45
+ readonly path: string;
46
+ /** Our fresh token being published (or held). */
47
+ readonly token?: string;
48
+ /** Succession target g (afterPublishSucc / retire windows). */
49
+ readonly target?: string;
50
+ readonly round: number;
51
+ readonly depth: number;
52
+ }
53
+ /**
54
+ * Critical-section hooks for deterministic tests ONLY. Passed as the 2nd
55
+ * argument of `acquirePrefixLock(prefix, hooks)` by the test; never enabled
56
+ * via environment or configuration (there is no env/config reader for them),
57
+ * and production calls without hooks so every hook is a no-op at zero cost.
58
+ */
59
+ export interface PrefixLockHooks {
60
+ /** Just BEFORE the initial publish(LOCK) (round 0) — initial race window. */
61
+ readonly beforePublishLock?: (ctx: PrefixLockHookContext) => void;
62
+ /** Just AFTER a publish(SUCC(t)) success, BEFORE retire — unique successor elected. */
63
+ readonly afterPublishSucc?: (ctx: PrefixLockHookContext) => void;
64
+ /** In retire(), around the targeted unlink(LOCK) (removal-to-republish window). */
65
+ readonly beforeRetireUnlink?: (ctx: PrefixLockHookContext) => void;
66
+ readonly afterRetireUnlink?: (ctx: PrefixLockHookContext) => void;
67
+ }
68
+ interface LockIdent {
69
+ readonly host: string;
70
+ readonly boot: string | null;
71
+ readonly ns: string | null;
72
+ /** Reader's time namespace; gates proc-sourced start comparisons (B2). */
73
+ readonly timeNs: string | null;
74
+ readonly pid: number;
75
+ readonly start: string | null;
76
+ }
77
+ interface LockRec extends LockIdent {
78
+ readonly token: string;
79
+ readonly target?: string;
80
+ /** Diagnostic only, never decides (I7). */
81
+ readonly at: number;
82
+ }
83
+ export declare function lockPathFor(prefix: string): string;
84
+ export declare function errnoOf(e: unknown): string;
85
+ export declare function safeAtIso(at: number): string;
86
+ export declare function readPidNs(platform?: NodeJS.Platform, readLink?: (p: string) => string): string | null;
87
+ export declare function readTimeNs(platform?: NodeJS.Platform, readLink?: (p: string) => string): string | null;
88
+ /**
89
+ * Process start identity, prefixed by its source ("proc:" from Linux /proc
90
+ * field 22, "ps:" from `ps lstart`). The prefix is part of the stored value
91
+ * so a reader using a different source never concludes "dead" from a
92
+ * format/TZ-fragile comparison (C1).
93
+ */
94
+ export declare function procStartInfo(pid: number, platform?: NodeJS.Platform, mapsToSelf?: () => boolean): {
95
+ state?: string;
96
+ start?: string;
97
+ } | undefined;
98
+ interface SelfIdent extends LockIdent {
99
+ readonly pid: number;
100
+ }
101
+ /** This process's identity, computed once and memoized. */
102
+ export declare function me(): SelfIdent;
103
+ export declare function makeLockRec(token: string, target?: string): LockRec;
104
+ export declare function parseLockRec(raw: unknown): LockRec;
105
+ /** opus `read`: ENOENT -> absent, anything else unreadable -> corrupt (I1). */
106
+ export declare function readLockRecord(path: string): LockRec | "absent" | "corrupt";
107
+ type PublishStatus = {
108
+ status: "ok";
109
+ } | {
110
+ status: "exists";
111
+ } | {
112
+ status: "retry";
113
+ } | {
114
+ status: "error";
115
+ code: string;
116
+ };
117
+ /**
118
+ * opus `publish` (I1): a name appears only with complete, durable content.
119
+ * Write tmp (wx + byte-count-checked write + fsync + close), then `link(2)`;
120
+ * EEXIST -> "exists", ENOENT at link -> "retry" (tmp reaped before link),
121
+ * any other failure -> "error" with the errno (no hard links -> fail closed).
122
+ * The tmp never contains `.succ.` (C2).
123
+ */
124
+ export declare function publishLockRecord(path: string, rec: LockRec): PublishStatus;
125
+ type Liveness = "dead" | "live" | "undecidable";
126
+ /** Injected only by tests (platform / start-probe sims); production passes none. */
127
+ interface LivenessDeps {
128
+ readonly platform?: NodeJS.Platform;
129
+ readonly probe?: (pid: number) => {
130
+ state?: string;
131
+ start?: string;
132
+ } | undefined;
133
+ }
134
+ /**
135
+ * A "live" verdict is `datable` when it came from a CONFIRMED, comparable start
136
+ * (same source, known equal time namespace) — the holder is provably the recorded
137
+ * process. It is NOT datable when "live" was reached only because the start was
138
+ * undatable (source mismatch, unknown/differing time namespace, or no start) — there
139
+ * a reused PID could be masking a dead holder. This bit is used solely to target the
140
+ * staleness alert (R2); it must never influence a reclaim decision.
141
+ */
142
+ interface LivenessInfo {
143
+ readonly verdict: Liveness;
144
+ readonly datable: boolean;
145
+ }
146
+ /**
147
+ * Single liveness classifier. `livenessOf` and `isCertainlyDead` are exactly its
148
+ * "verdict"/"dead" arm, and the R2 staleness alert reads its `datable` bit, so none
149
+ * of them can drift from this one decision. Never derives "dead" from a fragile
150
+ * comparison: a source mismatch or an unknown/differing time namespace both yield a
151
+ * safe "live" (undatable), and a corrupt "legacy" start yields "undecidable" (C1).
152
+ */
153
+ export declare function classifyLiveness(r: LockRec, self: SelfIdent, deps?: LivenessDeps): LivenessInfo;
154
+ export declare function livenessOf(r: LockRec, self: SelfIdent, deps?: LivenessDeps): Liveness;
155
+ /** No false positive: true implies certainly dead; any doubt is alive (I3). */
156
+ export declare function isCertainlyDead(r: LockRec): boolean;
157
+ /** opus `acquirePrefixLock`, plus M5 reasons and test-only critical hooks. */
158
+ export declare function acquirePrefixLock(prefix: string, hooks?: PrefixLockHooks): PrefixLockLease;
159
+ /** True when the path is older than the threshold; false when unstated. */
160
+ export declare function isOlderThan(path: string, now: number, maxAgeMs: number): boolean;
161
+ export {};
162
+ //# sourceMappingURL=succession-lock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"succession-lock.d.ts","sourceRoot":"","sources":["../../../src/runtime/local-files/succession-lock.ts"],"names":[],"mappings":"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"}