instar 1.3.693 → 1.3.694

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.
@@ -0,0 +1,61 @@
1
+ /**
2
+ * MESH-SELF-HEAL G1 — the serve-progress watermark (MESH-SELF-HEAL-SPEC §3.1).
3
+ *
4
+ * `serveProgressedMonoMs` is the THIRD liveness signal — stamped when a fetched
5
+ * update is dispatched/served/durably-enqueued (proves end-to-end progress, closes
6
+ * the "fetched-and-dropped" gap, finding Adv-F4). It CANNOT share the lifeline's
7
+ * `lifeline-poll-active.json` (that record is the lifeline PROCESS's, atomically
8
+ * rewritten on every poll-state change with no serve field — a second-process write
9
+ * would clobber it). So it lives in its OWN single-writer record `state/serve-progress.json`,
10
+ * written by the dispatch seam and read cross-process by the relinquish evaluator
11
+ * (round-2 Int2-D / round-3 Les3-F1 — net-new, deliberately-acknowledged plumbing).
12
+ *
13
+ * THE LOAD-BEARING SAFETY: a **boot-epoch fence** (round-4 Adv4-B). Because this is a
14
+ * persisted file (one process can't read another's memory), a stamp written by a
15
+ * PRIOR incarnation must NEVER read as fresh after a crash/restart — else a
16
+ * crash-stale stamp would mask a non-serving new process (re-creating the zombie).
17
+ * The record carries a `bootId`; the reader discards any stamp whose `bootId` ≠ the
18
+ * current incarnation (a boot-epoch fence — NOT a raw monotonic compare, which
19
+ * across incarnations would be an invalid cross-domain subtraction). Within ONE
20
+ * incarnation the monotonic stamps share a clock domain, so the freshness compare is
21
+ * valid. The field is a single machine-global monotonic-MAX watermark (NOT per-topic
22
+ * state) — concurrent dispatch-seam writers are benign because it only ever advances
23
+ * (round-4 Adv4-A).
24
+ *
25
+ * Threat model + write posture mirror `pollIntent.ts`: local same-uid IPC, atomic
26
+ * tmp+rename so the reader never sees a torn record.
27
+ */
28
+ export interface ServeProgressRecord {
29
+ /** Monotonic stamp (writer's monotonic clock) at the last served/enqueued update. */
30
+ serveProgressedMonoMs: number;
31
+ /** Writer process incarnation marker — the boot-epoch fence. */
32
+ bootId: string;
33
+ /** Writer pid (parity with pollIntent; diagnostics only). */
34
+ serverPid: number;
35
+ /** Wall-clock of the write (diagnostics; freshness uses the monotonic stamp). */
36
+ ts: number;
37
+ }
38
+ export declare function serveProgressPath(stateDir: string): string;
39
+ export declare function readServeProgress(stateDir: string): ServeProgressRecord | null;
40
+ /**
41
+ * Stamp serve progress. Monotonic-MAX: only ever advances — a write with a
42
+ * `monoMs` not greater than the current record's (SAME incarnation) is dropped, so
43
+ * concurrent dispatch-seam writers never regress the watermark. A record from a
44
+ * different `bootId` is always overwritten (a new incarnation starts its own clock
45
+ * domain; the prior stamp must not survive as fresh — the boot-epoch fence).
46
+ */
47
+ export declare function writeServeProgress(stateDir: string, args: {
48
+ bootId: string;
49
+ serverPid: number;
50
+ monoMs: number;
51
+ }): void;
52
+ /**
53
+ * Is serve progress FRESH (the relinquish evaluator's read)? Boot-epoch-fenced:
54
+ * a stamp from a different incarnation (`bootId` mismatch) is treated as "no
55
+ * progress yet" (false) — so a crash-stale on-disk stamp can never mask a
56
+ * non-serving new process. Within the current incarnation the monotonic compare is
57
+ * a valid same-clock-domain subtraction. `currentBootId` + `currentMonoMs` are
58
+ * injected (the reader's own incarnation + monotonic now) so this is pure + testable.
59
+ */
60
+ export declare function serveProgressFresh(stateDir: string, currentBootId: string, currentMonoMs: number, thresholdMs: number): boolean;
61
+ //# sourceMappingURL=serveProgress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serveProgress.d.ts","sourceRoot":"","sources":["../../src/core/serveProgress.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAOH,MAAM,WAAW,mBAAmB;IAClC,qFAAqF;IACrF,qBAAqB,EAAE,MAAM,CAAC;IAC9B,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,SAAS,EAAE,MAAM,CAAC;IAClB,iFAAiF;IACjF,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,mBAAmB,GAAG,IAAI,CAmB9E;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC1D,IAAI,CAcN;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,GAClB,OAAO,CAKT"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * MESH-SELF-HEAL G1 — the serve-progress watermark (MESH-SELF-HEAL-SPEC §3.1).
3
+ *
4
+ * `serveProgressedMonoMs` is the THIRD liveness signal — stamped when a fetched
5
+ * update is dispatched/served/durably-enqueued (proves end-to-end progress, closes
6
+ * the "fetched-and-dropped" gap, finding Adv-F4). It CANNOT share the lifeline's
7
+ * `lifeline-poll-active.json` (that record is the lifeline PROCESS's, atomically
8
+ * rewritten on every poll-state change with no serve field — a second-process write
9
+ * would clobber it). So it lives in its OWN single-writer record `state/serve-progress.json`,
10
+ * written by the dispatch seam and read cross-process by the relinquish evaluator
11
+ * (round-2 Int2-D / round-3 Les3-F1 — net-new, deliberately-acknowledged plumbing).
12
+ *
13
+ * THE LOAD-BEARING SAFETY: a **boot-epoch fence** (round-4 Adv4-B). Because this is a
14
+ * persisted file (one process can't read another's memory), a stamp written by a
15
+ * PRIOR incarnation must NEVER read as fresh after a crash/restart — else a
16
+ * crash-stale stamp would mask a non-serving new process (re-creating the zombie).
17
+ * The record carries a `bootId`; the reader discards any stamp whose `bootId` ≠ the
18
+ * current incarnation (a boot-epoch fence — NOT a raw monotonic compare, which
19
+ * across incarnations would be an invalid cross-domain subtraction). Within ONE
20
+ * incarnation the monotonic stamps share a clock domain, so the freshness compare is
21
+ * valid. The field is a single machine-global monotonic-MAX watermark (NOT per-topic
22
+ * state) — concurrent dispatch-seam writers are benign because it only ever advances
23
+ * (round-4 Adv4-A).
24
+ *
25
+ * Threat model + write posture mirror `pollIntent.ts`: local same-uid IPC, atomic
26
+ * tmp+rename so the reader never sees a torn record.
27
+ */
28
+ import { existsSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
29
+ import { join } from 'node:path';
30
+ const SERVE_PROGRESS_FILE = 'serve-progress.json';
31
+ export function serveProgressPath(stateDir) {
32
+ return join(stateDir, SERVE_PROGRESS_FILE);
33
+ }
34
+ export function readServeProgress(stateDir) {
35
+ const p = serveProgressPath(stateDir);
36
+ if (!existsSync(p))
37
+ return null;
38
+ try {
39
+ const rec = JSON.parse(readFileSync(p, 'utf8'));
40
+ if (typeof rec?.serveProgressedMonoMs !== 'number' ||
41
+ typeof rec?.bootId !== 'string' ||
42
+ typeof rec?.ts !== 'number')
43
+ return null;
44
+ return rec;
45
+ }
46
+ catch {
47
+ // @silent-fallback-ok — a corrupt/unreadable serve-progress record reads as
48
+ // "no progress yet" (null → serveProgressFresh false), the SAFE direction: a
49
+ // holder that cannot read its own serve watermark is treated as possibly-non-
50
+ // serving (a relinquish candidate), NEVER masked as healthy. A DegradationReporter
51
+ // event per failed read of a best-effort liveness file would be noise.
52
+ return null;
53
+ }
54
+ }
55
+ /**
56
+ * Stamp serve progress. Monotonic-MAX: only ever advances — a write with a
57
+ * `monoMs` not greater than the current record's (SAME incarnation) is dropped, so
58
+ * concurrent dispatch-seam writers never regress the watermark. A record from a
59
+ * different `bootId` is always overwritten (a new incarnation starts its own clock
60
+ * domain; the prior stamp must not survive as fresh — the boot-epoch fence).
61
+ */
62
+ export function writeServeProgress(stateDir, args) {
63
+ const { bootId, serverPid, monoMs } = args;
64
+ const existing = readServeProgress(stateDir);
65
+ if (existing && existing.bootId === bootId && existing.serveProgressedMonoMs >= monoMs) {
66
+ return; // monotonic-MAX within the same incarnation — never regress
67
+ }
68
+ const p = serveProgressPath(stateDir);
69
+ const tmp = `${p}.tmp.${process.pid}`;
70
+ writeFileSync(tmp, JSON.stringify({ serveProgressedMonoMs: monoMs, bootId, serverPid, ts: Date.now() }), 'utf8');
71
+ renameSync(tmp, p);
72
+ }
73
+ /**
74
+ * Is serve progress FRESH (the relinquish evaluator's read)? Boot-epoch-fenced:
75
+ * a stamp from a different incarnation (`bootId` mismatch) is treated as "no
76
+ * progress yet" (false) — so a crash-stale on-disk stamp can never mask a
77
+ * non-serving new process. Within the current incarnation the monotonic compare is
78
+ * a valid same-clock-domain subtraction. `currentBootId` + `currentMonoMs` are
79
+ * injected (the reader's own incarnation + monotonic now) so this is pure + testable.
80
+ */
81
+ export function serveProgressFresh(stateDir, currentBootId, currentMonoMs, thresholdMs) {
82
+ const rec = readServeProgress(stateDir);
83
+ if (!rec)
84
+ return false;
85
+ if (rec.bootId !== currentBootId)
86
+ return false; // boot-epoch fence
87
+ return currentMonoMs - rec.serveProgressedMonoMs < thresholdMs;
88
+ }
89
+ //# sourceMappingURL=serveProgress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serveProgress.js","sourceRoot":"","sources":["../../src/core/serveProgress.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC9E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,mBAAmB,GAAG,qBAAqB,CAAC;AAalD,MAAM,UAAU,iBAAiB,CAAC,QAAgB;IAChD,OAAO,IAAI,CAAC,QAAQ,EAAE,mBAAmB,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,QAAgB;IAChD,MAAM,CAAC,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IACtC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAChC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAwB,CAAC;QACvE,IACE,OAAO,GAAG,EAAE,qBAAqB,KAAK,QAAQ;YAC9C,OAAO,GAAG,EAAE,MAAM,KAAK,QAAQ;YAC/B,OAAO,GAAG,EAAE,EAAE,KAAK,QAAQ;YAC3B,OAAO,IAAI,CAAC;QACd,OAAO,GAAG,CAAC;IACb,CAAC;IAAC,MAAM,CAAC;QACP,4EAA4E;QAC5E,6EAA6E;QAC7E,8EAA8E;QAC9E,mFAAmF;QACnF,uEAAuE;QACvE,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAChC,QAAgB,EAChB,IAA2D;IAE3D,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAC3C,MAAM,QAAQ,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IAC7C,IAAI,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,MAAM,IAAI,QAAQ,CAAC,qBAAqB,IAAI,MAAM,EAAE,CAAC;QACvF,OAAO,CAAC,4DAA4D;IACtE,CAAC;IACD,MAAM,CAAC,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IACtC,MAAM,GAAG,GAAG,GAAG,CAAC,QAAQ,OAAO,CAAC,GAAG,EAAE,CAAC;IACtC,aAAa,CACX,GAAG,EACH,IAAI,CAAC,SAAS,CAAC,EAAE,qBAAqB,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAgC,CAAC,EAClH,MAAM,CACP,CAAC;IACF,UAAU,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;AACrB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAChC,QAAgB,EAChB,aAAqB,EACrB,aAAqB,EACrB,WAAmB;IAEnB,MAAM,GAAG,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IACxC,IAAI,CAAC,GAAG;QAAE,OAAO,KAAK,CAAC;IACvB,IAAI,GAAG,CAAC,MAAM,KAAK,aAAa;QAAE,OAAO,KAAK,CAAC,CAAC,mBAAmB;IACnE,OAAO,aAAa,GAAG,GAAG,CAAC,qBAAqB,GAAG,WAAW,CAAC;AACjE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "instar",
3
- "version": "1.3.693",
3
+ "version": "1.3.694",
4
4
  "description": "Coherence infrastructure for self-evolving AI agents — on the Claude Code or Codex subscription you already have.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "$schema": "./builtin-manifest.schema.json",
3
3
  "schemaVersion": 1,
4
- "generatedAt": "2026-06-28T10:28:11.496Z",
5
- "instarVersion": "1.3.693",
4
+ "generatedAt": "2026-06-28T10:37:09.930Z",
5
+ "instarVersion": "1.3.694",
6
6
  "entryCount": 202,
7
7
  "entries": {
8
8
  "hook:session-start": {
@@ -0,0 +1,24 @@
1
+ # Upgrade Guide — vNEXT
2
+
3
+ <!-- assembled-by: assemble-next-md -->
4
+ <!-- bump: patch -->
5
+
6
+ ## What Changed
7
+
8
+ Mesh Self-Heal **G1 — serve-progress watermark** (wiring increment A, MESH-SELF-HEAL-SPEC §3.1). Adds `src/core/serveProgress.ts`: the third liveness signal (`serveProgressedMonoMs` — proof a fetched update was actually served end-to-end, closing the "fetched-and-dropped" gap), in its own single-writer record `state/serve-progress.json`.
9
+
10
+ The load-bearing safety is a **boot-epoch fence**: a stamp left on disk by a crashed/prior process incarnation always reads as NOT fresh, so a crash-stale stamp can never mask a non-serving new process (which would re-create the zombie). Monotonic-MAX (only ever advances → concurrent writers benign), atomic tmp+rename, local same-uid IPC — mirrors `pollIntent.ts`.
11
+
12
+ Pure plumbing, NOT yet wired — zero runtime effect until increment B (the dispatch-seam write + the relinquish evaluator) consumes it. This watermark is also the prerequisite that lets the G2 take-over flip use a real serve/poll-health signal instead of a liveness approximation.
13
+
14
+ ## What to Tell Your User
15
+
16
+ Nothing changes yet — this is inert internal plumbing for the deepest multi-machine self-heal piece (detecting a machine that holds the "in charge" badge but has stopped actually serving). No action needed.
17
+
18
+ ## Summary of New Capabilities
19
+
20
+ - None user-facing. New internal record `state/serve-progress.json` + helpers (`src/core/serveProgress.ts`), consumed by a later wiring increment; no route, config, or runtime surface yet.
21
+
22
+ ## Evidence
23
+
24
+ - `tests/unit/serveProgress.test.ts` — 6 unit tests: write/read roundtrip; missing→null/not-fresh; monotonic-MAX no-regress; new-incarnation overwrite; freshness within/past threshold; and the BOOT-EPOCH FENCE (a prior-incarnation stamp reads not-fresh even when recent). Typecheck clean.
@@ -0,0 +1,32 @@
1
+ # Side-Effects Review — Mesh Self-Heal G1 (serve-progress watermark)
2
+
3
+ **Change:** The serve-progress watermark record (MESH-SELF-HEAL-SPEC §3.1) — `src/core/serveProgress.ts` (`writeServeProgress` / `readServeProgress` / `serveProgressFresh`) + 6 unit tests. The THIRD G1 liveness signal (`serveProgressedMonoMs` — end-to-end serve progress), in its OWN single-writer record `state/serve-progress.json` (it cannot share the lifeline's poll-active record without clobbering it). This is G1-wiring increment A: the watermark plumbing only. NOT YET CALLED by any writer or reader — ZERO runtime effect until increment B (the dispatch-seam write + the relinquish evaluator) consumes it. It is also the named **G2-enforce-enable prerequisite #1** (`localPollSucceededFresh` graduates from a liveness approximation to this real watermark).
4
+
5
+ **Decision point?** No — pure file I/O (a watermark record). Safety hinges on the boot-epoch fence (Q1/Q7).
6
+
7
+ ## 1. Over-block
8
+ N/A — no gating. `serveProgressFresh` biases SAFE: missing record → false; bootId mismatch → false; only a same-incarnation in-threshold stamp → true.
9
+
10
+ ## 2. Under-block
11
+ The boot-epoch fence is the guard against under-blocking (a crash-stale stamp masking a non-serving process): a prior incarnation's stamp (`bootId` mismatch) always reads NOT fresh. Tested.
12
+
13
+ ## 3. Level-of-abstraction fit
14
+ Mirrors `pollIntent.ts` exactly (atomic tmp+rename, local same-uid IPC, integrity fields). Correct layer — a cross-process record + a pure freshness reader; the dispatch-seam wiring + the evaluator are increment B.
15
+
16
+ ## 4. Signal vs authority compliance
17
+ COMPLIANT — pure I/O, no authority. It produces a freshness SIGNAL the relinquish decision will read; it never gates or actuates.
18
+
19
+ ## 5. Interactions
20
+ Single-writer, monotonic-MAX → concurrent dispatch-seam writers are benign (only advances). Distinct file from `lifeline-poll-active.json` → no clobber of the lifeline's record. No reader/writer yet.
21
+
22
+ ## 6. External surfaces
23
+ New file `state/serve-progress.json` (local, same-uid, like pollIntent). No route, no config. Written/read only once increment B wires it.
24
+
25
+ ## 7. Multi-machine posture (Cross-Machine Coherence)
26
+ Machine-local, never replicated (Sca-F1) — read only by the owning machine for its OWN relinquish decision. The boot-epoch fence makes it survive-restart-safe (a prior incarnation's stamp can't mask the new one). No cross-machine surface.
27
+
28
+ ## 8. Rollback cost
29
+ Trivial — revert the commit. Unreferenced; removing it cannot affect a running agent. The on-disk file (if ever written) is inert observability.
30
+
31
+ ## Second-pass review
32
+ Not triggered (pure file-I/O building block, no live decision-point/authority/session-lifecycle touch). The Phase-5 second-pass IS required for increment B (it wires the dispatch-seam write + the relinquish evaluator into the lease holder branch + the F3 actuation).