instar 1.3.1200 → 1.3.1201

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.
@@ -33,6 +33,23 @@
33
33
  */
34
34
  /** Pure FD1 classifier over the `df -P` device-source column. FAIL-CLOSED. */
35
35
  export declare function classifyDfSourceLocal(source: string): boolean;
36
+ /** Injectable reader for `/proc/self/mounts` (tests override; null when absent). */
37
+ export type ProcMountsReader = () => string | null;
38
+ /** Injectable `df -P <path>` runner (tests override; throws exactly as df failing does). */
39
+ export type DfRunner = (p: string, timeoutMs: number) => string;
40
+ /**
41
+ * Pure: given `/proc/self/mounts` content and an absolute path, return the
42
+ * fstype of the LONGEST mount-point prefix of that path, or null when nothing
43
+ * matches. Longest-prefix is required — `/` matches everything, so a shorter
44
+ * match would report the root filesystem for a path on a nested mount.
45
+ */
46
+ export declare function fstypeForPath(procMounts: string, absPath: string): string | null;
47
+ /**
48
+ * Pure: classify a path as host-local from `/proc/self/mounts` content.
49
+ * Returns null when the fstype is unknown to the allowlist — the caller then
50
+ * falls back to the df-source classifier rather than inventing a verdict.
51
+ */
52
+ export declare function classifyLinuxMountLocal(procMounts: string, absPath: string): boolean | null;
36
53
  /**
37
54
  * Detailed df probe. Distinguishes a POSITIVE not-local classification from a
38
55
  * FAILED probe ('unknown') — the distinction the 2026-07-01 §1.2 root-cause
@@ -40,9 +57,14 @@ export declare function classifyDfSourceLocal(source: string): boolean;
40
57
  * cached forever as "not local" and silently disables all reclaim for the
41
58
  * process lifetime. Consumers that cache MUST NOT cache an 'unknown' result.
42
59
  */
43
- export declare function probeDfHostLocalDetailed(p: string, timeoutMs?: number): {
60
+ export declare function probeDfHostLocalDetailed(p: string, timeoutMs?: number, deps?: {
61
+ platform?: NodeJS.Platform;
62
+ readProcMounts?: ProcMountsReader;
63
+ runDf?: DfRunner;
64
+ }): {
44
65
  status: 'local' | 'not-local' | 'unknown';
45
66
  source?: string;
67
+ fstype?: string;
46
68
  };
47
69
  /**
48
70
  * Boolean df probe (the spawn lane's historical shape). FAIL-CLOSED: anything
@@ -1 +1 @@
1
- {"version":3,"file":"hostSemaphoreCore.d.ts","sourceRoot":"","sources":["../../src/core/hostSemaphoreCore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AASH,8EAA8E;AAC9E,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAM7D;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,CAAC,EAAE,MAAM,EACT,SAAS,SAAO,GACf;IAAE,MAAM,EAAE,OAAO,GAAG,WAAW,GAAG,SAAS,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAiBhE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,SAAO,GAAG,OAAO,CAErE;AAID;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACzC,IAAI,CAeN;AAID,MAAM,MAAM,cAAc,GACtB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GACxB;IACE,EAAE,EAAE,KAAK,CAAC;IACV,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;IACzB;;;;;;;;;OASG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEN;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,cAAc,CAkBhF;AAED,6EAA6E;AAC7E,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAaxF;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,GACjC,OAAO,CAwBT;AAID,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IACnC,wEAAwE;IACxE,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC;AAElF;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAC9B,IAAI,EAAE,OAAO,EAAE,EACf,YAAY,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,CAAC,IAAI,GAAG,EACtC,MAAM,EAAE,mBAAmB,CAAC,GAAG,CAAC,EAChC,GAAG,EAAE,cAAc,GAClB,GAAG,EAAE,CAQP"}
1
+ {"version":3,"file":"hostSemaphoreCore.d.ts","sourceRoot":"","sources":["../../src/core/hostSemaphoreCore.ts"],"names":[],"mappings":"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"}
@@ -32,6 +32,7 @@
32
32
  * singleton) — each lane keeps its own thin configure/get/reset trio.
33
33
  */
34
34
  import fs from 'node:fs';
35
+ import path from 'node:path';
35
36
  import { execFileSync } from 'node:child_process';
36
37
  import { SafeFsExecutor } from './SafeFsExecutor.js';
37
38
  // ── df -P host-local determination (fail-closed) ─────────────────────────
@@ -47,6 +48,101 @@ export function classifyDfSourceLocal(source) {
47
48
  return true; // a real block device → local
48
49
  return false; // map/tmpfs/anything unrecognized → fail-closed
49
50
  }
51
+ /**
52
+ * Linux fstype allowlist — filesystems that are HOST-LOCAL *and* support the
53
+ * exclusive-create + atomic-rename semantics the holder lock is built on.
54
+ *
55
+ * WHY THIS EXISTS (2026-08-25, first non-CI Linux host — WSL2/Ubuntu 26.04).
56
+ * `classifyDfSourceLocal` reads the `df -P` *device-source* column, which only
57
+ * recognises a filesystem as local when it looks like a block device
58
+ * (`/dev/...`). Several perfectly ordinary local Linux filesystems do not name
59
+ * a device there, so they were classified as "possibly a shared network
60
+ * volume" and the two host semaphores degraded silently in OPPOSITE
61
+ * directions: the test-runner lane FAILS OPEN (admits the run unslotted — the
62
+ * bound reports itself present while guarding nothing), and the spawn lane
63
+ * FAILS CLOSED (stops reclaiming dead holders, so the cap slowly clogs until
64
+ * it blocks legitimate work). Neither announces itself.
65
+ *
66
+ * Misclassified before this fix, all commonplace:
67
+ * tmpfs — RAM-backed; Ubuntu's default /tmp. Cannot be shared by
68
+ * construction.
69
+ * overlay — every Docker container's root filesystem. This one means any
70
+ * containerised instar was in the misjudged set.
71
+ * devtmpfs — the kernel's own /dev.
72
+ * zfs — ZFS names a POOL (`rpool/ROOT/x`), never a device. Note the
73
+ * pool-name SHAPE is deliberately NOT pattern-matched: FUSE
74
+ * cloud mounts (gcsfuse/s3fs bucket names) share that shape and
75
+ * are genuinely remote. Only the fstype settles it.
76
+ *
77
+ * DELIBERATELY ABSENT (these are correct rejections, not oversights):
78
+ * 9p / drvfs — WSL's translation layer onto the Windows drive. Same physical
79
+ * machine, but exclusive-create and rename semantics are not
80
+ * dependable across it, so it must not hold the lock.
81
+ * virtiofs — host-shared directory; may be mounted by sibling guests.
82
+ * nfs/cifs/smb/fuse.sshfs/ceph/glusterfs/lustre/afs — network by definition.
83
+ *
84
+ * Anything not on this list keeps the pre-existing fail-closed behaviour.
85
+ */
86
+ const LINUX_HOST_LOCAL_FSTYPES = new Set([
87
+ // on-disk local filesystems
88
+ 'ext2', 'ext3', 'ext4', 'btrfs', 'xfs', 'zfs', 'f2fs', 'jfs', 'reiserfs',
89
+ 'bcachefs', 'nilfs2', 'squashfs', 'erofs', 'vfat', 'exfat', 'msdos',
90
+ // in-memory local filesystems
91
+ 'tmpfs', 'ramfs', 'devtmpfs',
92
+ // container/union local filesystems
93
+ 'overlay', 'overlayfs', 'aufs',
94
+ ]);
95
+ const defaultProcMountsReader = () => {
96
+ try {
97
+ return fs.readFileSync('/proc/self/mounts', 'utf-8');
98
+ }
99
+ catch {
100
+ // @silent-fallback-ok: no procfs (non-Linux, or a jail without it) — the
101
+ // caller falls back to the df-source classifier, which is fail-closed.
102
+ return null;
103
+ }
104
+ };
105
+ /**
106
+ * Pure: given `/proc/self/mounts` content and an absolute path, return the
107
+ * fstype of the LONGEST mount-point prefix of that path, or null when nothing
108
+ * matches. Longest-prefix is required — `/` matches everything, so a shorter
109
+ * match would report the root filesystem for a path on a nested mount.
110
+ */
111
+ export function fstypeForPath(procMounts, absPath) {
112
+ let bestPoint = '';
113
+ let bestType = null;
114
+ for (const line of procMounts.split('\n')) {
115
+ if (!line)
116
+ continue;
117
+ const parts = line.split(/\s+/);
118
+ if (parts.length < 3)
119
+ continue;
120
+ // /proc/self/mounts octal-escapes spaces and friends in the mount point.
121
+ const point = parts[1].replace(/\\(\d{3})/g, (_m, o) => String.fromCharCode(parseInt(o, 8)));
122
+ const type = parts[2];
123
+ if (!point || !type)
124
+ continue;
125
+ const isPrefix = absPath === point || point === '/' || absPath.startsWith(point.endsWith('/') ? point : `${point}/`);
126
+ if (!isPrefix)
127
+ continue;
128
+ if (point.length >= bestPoint.length) {
129
+ bestPoint = point;
130
+ bestType = type;
131
+ }
132
+ }
133
+ return bestType;
134
+ }
135
+ /**
136
+ * Pure: classify a path as host-local from `/proc/self/mounts` content.
137
+ * Returns null when the fstype is unknown to the allowlist — the caller then
138
+ * falls back to the df-source classifier rather than inventing a verdict.
139
+ */
140
+ export function classifyLinuxMountLocal(procMounts, absPath) {
141
+ const type = fstypeForPath(procMounts, absPath);
142
+ if (!type)
143
+ return null;
144
+ return LINUX_HOST_LOCAL_FSTYPES.has(type) ? true : null;
145
+ }
50
146
  /**
51
147
  * Detailed df probe. Distinguishes a POSITIVE not-local classification from a
52
148
  * FAILED probe ('unknown') — the distinction the 2026-07-01 §1.2 root-cause
@@ -54,13 +150,15 @@ export function classifyDfSourceLocal(source) {
54
150
  * cached forever as "not local" and silently disables all reclaim for the
55
151
  * process lifetime. Consumers that cache MUST NOT cache an 'unknown' result.
56
152
  */
57
- export function probeDfHostLocalDetailed(p, timeoutMs = 3000) {
153
+ export function probeDfHostLocalDetailed(p, timeoutMs = 3000, deps = {}) {
58
154
  let out;
59
155
  try {
60
156
  // lint-allow-sync-spawn: a bounded (3s) one-shot host-FS classification,
61
157
  // run once per cold start and cached by callers on SUCCESS only — never on
62
158
  // the hot acquire path.
63
- out = execFileSync('df', ['-P', p], { timeout: timeoutMs, encoding: 'utf-8' });
159
+ out = deps.runDf
160
+ ? deps.runDf(p, timeoutMs)
161
+ : execFileSync('df', ['-P', p], { timeout: timeoutMs, encoding: 'utf-8' });
64
162
  }
65
163
  catch {
66
164
  // @silent-fallback-ok: df unavailable/timed out ⇒ we could not PROBE — the
@@ -72,7 +170,25 @@ export function probeDfHostLocalDetailed(p, timeoutMs = 3000) {
72
170
  if (lines.length < 2)
73
171
  return { status: 'unknown' }; // unparseable → unknown
74
172
  const source = lines[1]?.trim().split(/\s+/)[0] ?? '';
75
- return { status: classifyDfSourceLocal(source) ? 'local' : 'not-local', source };
173
+ if (classifyDfSourceLocal(source))
174
+ return { status: 'local', source };
175
+ // Linux second opinion. The df-source column cannot see tmpfs / overlay /
176
+ // devtmpfs / zfs as local because none of them names a block device, so the
177
+ // fstype is consulted before settling on 'not-local'. This can only ever
178
+ // UPGRADE not-local → local for an explicitly allowlisted fstype; it never
179
+ // downgrades a positive, and an unknown fstype leaves the fail-closed
180
+ // verdict exactly as it was.
181
+ const platform = deps.platform ?? process.platform;
182
+ if (platform === 'linux') {
183
+ const procMounts = (deps.readProcMounts ?? defaultProcMountsReader)();
184
+ if (procMounts) {
185
+ const abs = path.resolve(p);
186
+ if (classifyLinuxMountLocal(procMounts, abs) === true) {
187
+ return { status: 'local', source, fstype: fstypeForPath(procMounts, abs) ?? undefined };
188
+ }
189
+ }
190
+ }
191
+ return { status: 'not-local', source };
76
192
  }
77
193
  /**
78
194
  * Boolean df probe (the spawn lane's historical shape). FAIL-CLOSED: anything
@@ -1 +1 @@
1
- {"version":3,"file":"hostSemaphoreCore.js","sourceRoot":"","sources":["../../src/core/hostSemaphoreCore.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hostSemaphoreCore.js","sourceRoot":"","sources":["../../src/core/hostSemaphoreCore.ts"],"names":[],"mappings":"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"}
@@ -2,7 +2,7 @@
2
2
  "schemaVersion": 1,
3
3
  "generatedFrom": "source-tree",
4
4
  "registrySha256": "8e6606a6722433c5ffc15b3870402283c5406083a14cdbd0e18e735731e2aae2",
5
- "packageVersion": "1.3.1200",
5
+ "packageVersion": "1.3.1201",
6
6
  "guards": [
7
7
  {
8
8
  "ref": "docs/audits/phase-b/f10-triage.md",
@@ -1,5 +1,5 @@
1
1
  {
2
- "sha256": "d48c07b7869e4f91502569dbf3890619ed60ed4e62972b092197e2cb1d1c1fab",
2
+ "sha256": "7cc7eace9958f0daae3b9c37eadf2541b2b5a6bd3b16bf0f7f1cf281a86dadca",
3
3
  "registrySha256": "8e6606a6722433c5ffc15b3870402283c5406083a14cdbd0e18e735731e2aae2",
4
- "packageVersion": "1.3.1200"
4
+ "packageVersion": "1.3.1201"
5
5
  }
@@ -2,5 +2,5 @@
2
2
  "sha256": "8e6606a6722433c5ffc15b3870402283c5406083a14cdbd0e18e735731e2aae2",
3
3
  "articleCount": 90,
4
4
  "generatedFrom": "docs/STANDARDS-REGISTRY.md",
5
- "packageVersion": "1.3.1200"
5
+ "packageVersion": "1.3.1201"
6
6
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "instar",
3
- "version": "1.3.1200",
3
+ "version": "1.3.1201",
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-08-25T03:17:54.252Z",
5
- "instarVersion": "1.3.1200",
4
+ "generatedAt": "2026-08-25T23:10:03.683Z",
5
+ "instarVersion": "1.3.1201",
6
6
  "entryCount": 202,
7
7
  "entries": {
8
8
  "hook:session-start": {
@@ -2,7 +2,7 @@
2
2
  "schemaVersion": 1,
3
3
  "generatedFrom": "source-tree",
4
4
  "registrySha256": "8e6606a6722433c5ffc15b3870402283c5406083a14cdbd0e18e735731e2aae2",
5
- "packageVersion": "1.3.1200",
5
+ "packageVersion": "1.3.1201",
6
6
  "guards": [
7
7
  {
8
8
  "ref": "docs/audits/phase-b/f10-triage.md",
@@ -1,5 +1,5 @@
1
1
  {
2
- "sha256": "d48c07b7869e4f91502569dbf3890619ed60ed4e62972b092197e2cb1d1c1fab",
2
+ "sha256": "7cc7eace9958f0daae3b9c37eadf2541b2b5a6bd3b16bf0f7f1cf281a86dadca",
3
3
  "registrySha256": "8e6606a6722433c5ffc15b3870402283c5406083a14cdbd0e18e735731e2aae2",
4
- "packageVersion": "1.3.1200"
4
+ "packageVersion": "1.3.1201"
5
5
  }
@@ -2,5 +2,5 @@
2
2
  "sha256": "8e6606a6722433c5ffc15b3870402283c5406083a14cdbd0e18e735731e2aae2",
3
3
  "articleCount": 90,
4
4
  "generatedFrom": "docs/STANDARDS-REGISTRY.md",
5
- "packageVersion": "1.3.1200"
5
+ "packageVersion": "1.3.1201"
6
6
  }
@@ -0,0 +1,72 @@
1
+ # Upgrade Guide — vNEXT
2
+
3
+ <!-- assembled-by: assemble-next-md -->
4
+ <!-- bump: patch -->
5
+
6
+ ## What Changed
7
+
8
+ The two host-level safety limits — the concurrent-test-suite bound and the concurrent-LLM-spawn cap
9
+ — trust their shared holders file only after establishing that the file lives on a host-local
10
+ filesystem. That question was answered solely from the `df -P` device-source column, which
11
+ recognises a filesystem as local only when it names a block device.
12
+
13
+ Four commonplace **local** Linux filesystems do not name one: `tmpfs` (Ubuntu's default `/tmp`),
14
+ `overlay` (every Docker container's root filesystem), `devtmpfs`, and `zfs` (which names a pool,
15
+ never a device). All four read as "possibly a shared network volume", and the two lanes then
16
+ degraded silently in **opposite directions**: the test-runner lane **fails open** — it admits the run
17
+ without a slot, so the bound reports itself present while guarding nothing — and the spawn lane
18
+ **fails closed** — it stops reclaiming dead holders, so the cap slowly clogs until it blocks
19
+ legitimate work. Neither announces itself.
20
+
21
+ `probeDfHostLocalDetailed` now takes a Linux-only second opinion: when the source column has not
22
+ already settled the question as local, the fstype for the path is resolved from `/proc/self/mounts`
23
+ and checked against an explicit allowlist. The new path can only ever **upgrade** `not-local` →
24
+ `local`, only for an allowlisted fstype, and only on Linux — macOS never reaches it, and an
25
+ unrecognised fstype keeps the existing fail-closed verdict untouched.
26
+
27
+ The pool-name *shape* is deliberately not pattern-matched. A ZFS pool (`rpool/ROOT/x`) and a FUSE
28
+ cloud bucket (`my-bucket`) are shape-identical and one of them is genuinely remote; only the fstype
29
+ separates them, which is the argument for fixing this at the fstype layer rather than with a broader
30
+ regex. `9p`/`drvfs` (WSL's mount of the Windows drive) and `virtiofs` remain rejected **on purpose**
31
+ — same physical machine, but the exclusive-create and rename semantics these limits depend on are
32
+ not dependable across them. Previously they were rejected for the wrong reason; now they are absent
33
+ from the allowlist with that reason written down.
34
+
35
+ ## What to Tell Your User
36
+
37
+ If you run instar on Linux — including inside Docker — two of its safety limits have not been working
38
+ the way they report. The one that stops several test suites colliding has been quietly letting runs
39
+ through unbounded, and the one that stops runaway model-process storms has been unable to clean up
40
+ after itself, which makes it slowly fill up and eventually block work that should be allowed. Both
41
+ are fixed. On macOS nothing changes.
42
+
43
+ ## Summary of New Capabilities
44
+
45
+ No new capabilities. Two existing safety limits now work correctly on Linux and in containers.
46
+
47
+ ## Evidence
48
+
49
+ Found on the first non-CI Linux host — WSL2 / Ubuntu 26.04, where `/tmp` is `tmpfs`. The live
50
+ signature is the limiter announcing its own disarmament: `[test-runner-bound] WARN: admitted WITHOUT
51
+ a slot (fail-open: df-not-local)`. Before the change that host failed 30 tests across three limiter
52
+ files (`host-test-runner-semaphore` 13, `test-runner-bound-meta` 14, `test-runner-limiter-route` 3);
53
+ after it, all three pass — 132 unit and 29 integration tests green on that host.
54
+
55
+ GitHub's Ubuntu runners mount `/tmp` on the ordinary root disk, so `df` reports a `/dev`-backed
56
+ source there and the check passes by accident. CI has been green on Linux for as long as it has run
57
+ on Linux and has never once exercised this path — which is why the defect needed a real Linux
58
+ machine to surface.
59
+
60
+ Nine unit tests over the new code. Longest-prefix mount resolution (`/` matches everything, so a
61
+ shorter match must never win); a same-prefix sibling directory (`/tmp` must not match `/tmpfoo`);
62
+ octal-escaped mount points; the four newly-correct local verdicts driven end-to-end through the real
63
+ probe with `df` output injected, so the wiring is covered rather than only the pure classifier
64
+ beneath it; and the rejections that must **stay** rejections — `fuse.gcsfuse` (the shape-identical
65
+ twin of a ZFS pool), `9p`/`drvfs`, `virtiofs`, and an unknown fstype. Two control tests assert macOS
66
+ never reads procfs and that a `/dev`-backed source still short-circuits before procfs is consulted —
67
+ both by making the procfs reader *throw* if it is reached.
68
+
69
+ Falsification check: emptying the allowlist makes exactly the two rescue tests fail and leaves the
70
+ rest green, confirming the tests detect the defect rather than passing regardless of it. The fix was
71
+ authored on macOS and verified on the Linux host that exposed it, so the proof does not come from the
72
+ machine it was written on.
@@ -0,0 +1,47 @@
1
+ # Two safety limits misjudge ordinary Linux disks — Plain-English Overview
2
+
3
+ > The one-line version: on Linux, four perfectly normal local filesystems look like network drives to instar's safety limits, so one limit quietly stops guarding and the other slowly clogs — this teaches them to ask the operating system what the filesystem actually is instead of guessing from its name.
4
+
5
+ ## The problem in one breath
6
+
7
+ Instar has two limits that stop a machine tearing itself apart: one caps how many test suites run at once, and one caps how many model processes can be spawned at once. Both coordinate through a shared file, and before trusting that file each one asks "is this disk actually mine, or could another machine be writing to it too?" On Linux it asks that question in a way that gets the wrong answer for several completely ordinary disks — and when it does, the two limits break in opposite directions without saying a word.
8
+
9
+ ## What already exists
10
+
11
+ - **The test-runner limit** — stops several test suites running at once and starving the machine. Born from a day when 29 test runs collided and healthy servers got killed.
12
+ - **The spawn limit** — caps how many model processes can run at once across everything instar is doing on the machine. Born from a fork-bomb that ate roughly 100GB of memory.
13
+ - **The shared "who's holding a slot" file** — how both limits coordinate between separate processes on the same machine.
14
+ - **The "is this disk mine?" check** — the piece being fixed. It exists because if the coordination file were on a drive shared with another computer, two machines could each think they held the same slot.
15
+
16
+ ## What this adds
17
+
18
+ The check currently decides by looking at the disk's *name*: if the name looks like a traditional hard disk it is trusted, and otherwise it isn't. That worked on Macs, where disks always look like that. On Linux, several everyday local filesystems don't have a name of that shape at all — RAM-backed temporary space (which is the standard setup on Ubuntu), the layered filesystem every Docker container runs on, the kernel's own device area, and ZFS, which names a storage pool rather than a disk. All four are unmistakably local. All four were being treated as "might be a network drive."
19
+
20
+ This change gives the check a second, better question on Linux: instead of guessing from the name, ask the operating system what type of filesystem it actually is, and compare that against an explicit list of types known to be local *and* known to support the kind of file locking these limits depend on.
21
+
22
+ - It only runs on Linux. Macs never reach the new code and behave exactly as before.
23
+ - It can only ever change a "not mine" answer into "mine" — never the reverse.
24
+ - Anything not on the list keeps today's cautious answer, unchanged.
25
+
26
+ ## The new pieces
27
+
28
+ - **A filesystem-type lookup** — reads the list of mounted filesystems the Linux kernel already publishes, and works out which one a given file sits on. It picks the most specific match, because otherwise everything would match the root filesystem.
29
+ - **An explicit list of trusted filesystem types** — a closed, named list, not a pattern or a guess. Adding to it is a deliberate act.
30
+
31
+ ## The safeguards
32
+
33
+ **It cannot make anything less safe.** The new code only runs after the existing check has already declined to say "local", and the only outcome it can produce is "local". There is no input anywhere for which this change produces a stricter answer than today's code. Reverting it restores exactly the behaviour every Linux agent is running right now.
34
+
35
+ **It refuses the tempting shortcut.** The obvious fix is to widen the name-matching to accept these filesystems. That cannot be made safe: a ZFS pool name and a cloud-storage bucket name are indistinguishable by shape, and one of those is genuinely remote. Only the filesystem type tells them apart — which is the argument for fixing it at this level rather than with a cleverer pattern.
36
+
37
+ **It keeps the right things rejected, on purpose.** WSL's view of the Windows C: drive is on the same physical machine, but the file-locking behaviour these limits rely on isn't dependable across it, so it stays untrusted — now deliberately, with the reason written down, rather than by accident. Shared-with-other-guests filesystems stay untrusted too. Genuine network drives were already rejected correctly and still are.
38
+
39
+ **It doesn't hide a broken probe.** If the underlying disk query fails outright, the answer stays "I couldn't tell" rather than becoming a confident verdict — the distinction that a previous incident turned on.
40
+
41
+ ## What ships when
42
+
43
+ One change, one PR: the filesystem-type lookup, the trusted-types list, and nine tests covering both the newly-correct answers and the rejections that must remain rejections. Nothing is staged or behind a flag, because there is no rollout risk to stage — the change cannot produce a stricter answer than the code it replaces.
44
+
45
+ ## What you actually need to decide
46
+
47
+ Whether to accept a change that makes two existing safety limits work correctly on Linux and containers, given that it can only ever loosen a verdict in the direction of "this disk is mine" and only for an explicit list of filesystem types — yes or no.
@@ -0,0 +1,158 @@
1
+ # Side-Effects Review — Linux fstype second opinion for host-local classification
2
+
3
+ **Version / slug:** `linux-fstype-host-local-classification`
4
+ **Date:** `2026-08-25`
5
+ **Author:** `Echo`
6
+ **Second-pass reviewer:** `not run — see the Second-pass section for why, and the gap it leaves`
7
+
8
+ ## Summary of the change
9
+
10
+ Two host-level safety semaphores — `HostTestRunnerSemaphore` (concurrent test suites) and `HostSpawnSemaphore` (concurrent LLM subprocesses, the fork-bomb floor) — coordinate through a holders file and must first establish that the file lives on a HOST-LOCAL filesystem. That question was answered solely by `classifyDfSourceLocal`, which reads the `df -P` *device-source* column and only recognises a filesystem as local when it names a block device (`/dev/...`).
11
+
12
+ Several ordinary LOCAL Linux filesystems do not name a device in that column — `tmpfs` (Ubuntu's default `/tmp`), `overlay` (every Docker container's root), `devtmpfs`, and `zfs` (which names a pool, never a device). All four were therefore classified "possibly a shared network volume", and the two semaphores degraded silently in OPPOSITE directions (see §5).
13
+
14
+ This change adds a Linux-only **second opinion**: when the df-source column does not already settle the question as local, the fstype for the path is resolved from `/proc/self/mounts` and checked against an explicit allowlist. It can only ever UPGRADE `not-local → local`, only for an allowlisted fstype, and only on Linux. macOS never reaches the new code path.
15
+
16
+ Files touched: `src/core/hostSemaphoreCore.ts` (new `fstypeForPath`, `classifyLinuxMountLocal`, `LINUX_HOST_LOCAL_FSTYPES`, injectable `ProcMountsReader` + `DfRunner`; `probeDfHostLocalDetailed` consults them), `tests/unit/host-semaphore-core.test.ts` (+9 tests).
17
+
18
+ ## Decision-point inventory
19
+
20
+ - `probeDfHostLocalDetailed` (`src/core/hostSemaphoreCore.ts`) — **modify** — the host-local verdict that gates holder-file trust for both semaphores. The verdict domain is unchanged (`local` / `not-local` / `unknown`); only its accuracy on Linux changes.
21
+ - `classifyDfSourceLocal` — **pass-through** — byte-identical. It remains the first and only test on macOS, and still the fallback on Linux.
22
+ - `HostTestRunnerSemaphore` admission / `HostSpawnSemaphore` reclaim — **pass-through** — both consume the verdict unchanged; neither is edited.
23
+
24
+ ---
25
+
26
+ ## 1. Over-block
27
+
28
+ **What legitimate inputs does this change reject that it shouldn't?**
29
+
30
+ None — the change cannot reject anything it did not already reject. The new code path is reachable only after `classifyDfSourceLocal(source)` has returned false, and its only possible effect is to return `local` instead of `not-local`. There is no input for which this change produces a *more* restrictive verdict than the current code.
31
+
32
+ ---
33
+
34
+ ## 2. Under-block
35
+
36
+ **What failure modes does this still miss?**
37
+
38
+ Concrete cases that remain classified not-local, all deliberately:
39
+
40
+ - **`9p` / `drvfs`** (WSL's mount of the Windows drive, verified live on this host as fstype `9p` with `aname=drvfs`). Same physical machine, but exclusive-create and rename semantics are not dependable across the translation layer, so it must not hold the lock. Rejecting it is correct; before this change it was rejected for the wrong reason (no `/dev/` prefix) and now it is rejected deliberately (absent from the allowlist).
41
+ - **`virtiofs`** — a host-shared directory that sibling guests may also mount. Genuinely ambiguous; fail-closed is right.
42
+ - **An unlisted local fstype** (e.g. a new filesystem, or `fuseblk` NTFS) still reads not-local. The failure mode is the pre-existing one, unchanged.
43
+ - **A bind-mount whose underlying device is remote** is classified by the *mount's* fstype. `/proc/self/mounts` reports the real fstype for bind mounts, so an NFS bind still reports `nfs4` and stays rejected.
44
+ - **The `unknown` status is untouched.** A `df` timeout still yields `unknown`, never a positive verdict — the 2026-07-01 §1.2 distinction is preserved.
45
+
46
+ ---
47
+
48
+ ## 3. Level-of-abstraction fit
49
+
50
+ This is a **detector accuracy** fix at exactly the layer that already owns the question. `hostSemaphoreCore` is the extracted shared primitive both lanes already call; the change adds no new layer and no new caller.
51
+
52
+ The deeper point the review surfaced: the existing check asks *"does this look like a block device?"* as a proxy for the real question, which is *"is this filesystem mine, and does exclusive locking work on it?"*. The proxy is what fails. On Linux the real question has a direct answer (the fstype), so the fix consults it rather than improving the proxy. Notably, the ZFS case **cannot** be fixed at the proxy layer at all: a ZFS pool name (`rpool/ROOT/x`) is shape-identical to a FUSE cloud-bucket source (`my-bucket`), which is genuinely remote. Only the fstype separates them — which is the argument for this layer rather than a better regex.
53
+
54
+ ---
55
+
56
+ ## 4. Signal vs authority compliance
57
+
58
+ **Required reference:** [docs/signal-vs-authority.md](../../docs/signal-vs-authority.md)
59
+
60
+ - [x] No — this change produces a signal consumed by an existing gate.
61
+
62
+ The verdict is a **signal** consumed by the two semaphores, which hold the authority. This change does not move authority, does not add a decision point, and does not change what either semaphore does with a given verdict. It makes an existing brittle detector *less* brittle on one platform while leaving its fail-closed default intact for everything it does not positively recognise. The allowlist is a closed, enumerated set — not a heuristic.
63
+
64
+ ---
65
+
66
+ ## 4b. Judgment-point check (Judgment Within Floors standard)
67
+
68
+ No new static heuristic at a competing-signals decision point. The domain here is **enumerable by construction**: a filesystem type is a finite, named kind, and the invariant ("this fstype supports exclusive-create + atomic-rename and cannot be mounted by another host") is a property of the kind, not a weighing of live signals. There are no competing signals to arbitrate — one path, one fstype, one answer. The allowlist is the enumeration; anything outside it falls to the pre-existing fail-closed floor.
69
+
70
+ ---
71
+
72
+ ## 5. Interactions
73
+
74
+ - **Shadowing:** the new path runs strictly AFTER `classifyDfSourceLocal` and only when that returned false. It cannot shadow the source classifier; the `/dev/`-backed short-circuit is covered by a test that makes procfs *throw* if consulted.
75
+ - **Double-fire:** none. The probe is a pure read; both callers already memoize it (spawn lane on success only). No new writes, no new spawns — the new path reads one file and does no I/O beyond it.
76
+ - **Races:** none introduced. `/proc/self/mounts` is a kernel-synthesised read; a mount changing mid-read yields a stale-but-consistent line, and the worst outcome is one probe returning the pre-existing verdict.
77
+ - **Feedback loops:** none. The verdict does not feed anything that changes mounts.
78
+ - **The interaction that motivated the fix** is the pre-existing one this repairs: the same misclassification degraded the two lanes in OPPOSITE directions — the test-runner lane **fails open** (admits the run unslotted; the bound reports itself present while guarding nothing — observed as `admitted WITHOUT a slot (fail-open: df-not-local)` on this host, producing 30 test failures across 3 files), and the spawn lane **fails closed** (stops reclaiming dead holders, so the cap clogs until it blocks legitimate work). Restoring an accurate verdict repairs both without touching either lane's logic.
79
+
80
+ ---
81
+
82
+ ## 6. External surfaces
83
+
84
+ - **Other agents on the same machine:** yes, beneficially — the host spawn cap is host-wide across every compliant instar process. On a Linux host whose `~/.instar` sits on an allowlisted-but-previously-misjudged filesystem, dead-holder reclaim starts working again for all of them.
85
+ - **Install base:** any Linux or containerised install. `overlay` means **every Docker-hosted instar** was in the misjudged set.
86
+ - **External systems:** none.
87
+ - **Persistent state:** none added. The probe writes nothing.
88
+ - **Return shape:** `probeDfHostLocalDetailed` gains an OPTIONAL `fstype` field. Additive — no existing caller reads it, and `probeDfHostLocal` (the boolean wrapper) is unchanged.
89
+ - **New optional `deps` third parameter:** default `{}`, so every existing two-argument call is untouched.
90
+ - **Timing:** one extra `readFileSync('/proc/self/mounts')` on the cold path only (after df has already run, and only when df did not settle it). Not on the hot acquire path.
91
+ - **Operator surface:** no operator-facing actions added or touched — not applicable.
92
+
93
+ ---
94
+
95
+ ## 6b. Operator-surface quality (Operator-Surface Quality standard)
96
+
97
+ No operator surface — not applicable. No dashboard renderer, approval page, or grant/revoke/secret-drop form is touched.
98
+
99
+ ---
100
+
101
+ ## 7. Multi-machine posture (Cross-Machine Coherence)
102
+
103
+ **Machine-local BY DESIGN**, and the reason is the feature's whole point: the holders file is a *host-local* coordination file, and this verdict exists precisely to establish that a given filesystem belongs to exactly one machine. Replicating it would be a category error — the correct answer genuinely differs per machine (a Mac reports `/dev/disk3s5`, a WSL2 host reports `ext4`, a container reports `overlay`), and a peer's verdict about its own disk carries no information about mine.
104
+
105
+ - **User-facing notices:** none — the change emits nothing. One-voice gating not applicable.
106
+ - **Durable state:** none held, so nothing strands on topic transfer.
107
+ - **Generated URLs:** none.
108
+ - **Pool-wide read:** the existing `GET /spawn-limiter` and `GET /test-runner-limiter` already report per-machine state, and those surfaces are unchanged.
109
+
110
+ ---
111
+
112
+ ## 8. Rollback cost
113
+
114
+ - **Hot-fix release:** revert the code change, ship as next patch. Pure code, no schema.
115
+ - **Data migration:** none — no persistent state is written or read beyond `/proc/self/mounts`.
116
+ - **Agent state repair:** none. Reverting restores the previous (fail-open on the test lane, no-reclaim on the spawn lane) behaviour, which is the status quo every Linux agent is running today.
117
+ - **User visibility:** none during the rollback window. The verdict is internal; no user-facing surface renders it.
118
+
119
+ ---
120
+
121
+ ## Conclusion
122
+
123
+ This review produced one design change and one correction to my own initial finding.
124
+
125
+ The **design change**: my first instinct was to widen the source-column pattern to accept `tmpfs`/`overlay`/pool-shaped names. Working through §3 showed that cannot be made safe — a ZFS pool name and a FUSE cloud-bucket name are shape-identical, so any regex broad enough to admit ZFS admits genuinely-remote mounts too. Consulting the fstype is not merely tidier; it is the only formulation that separates them.
126
+
127
+ The **correction**: I initially reported `drvfs` as a fifth false rejection. It is not. Verified live on this host, `/mnt/c` is fstype `9p`, and exclusive-locking semantics across it are not dependable — so the rejection is correct and is now deliberate (documented absence from the allowlist) rather than accidental.
128
+
129
+ The change is bounded in the safe direction by construction: Linux-only, upgrade-only, allowlist-only. Clear to ship pending second-pass review.
130
+
131
+ ---
132
+
133
+ ## Second-pass review (if required)
134
+
135
+ **Reviewer:** none — not spawned.
136
+ **Independent read of the artifact: NOT PERFORMED.**
137
+
138
+ Stating the gap plainly rather than papering over it. This change is adjacent to the Phase-5 trigger list without landing squarely on it: it touches no messaging block/allow decision, no session lifecycle, no coherence/idempotency/trust surface, and the module is not a sentinel, guard, gate, or watchdog by name. It *is* the accuracy of a signal two safety limiters consume, which is the spirit of the rule even if not its letter.
139
+
140
+ A dedicated reviewer subagent was not spawned because a standing operator instruction in this session forbids delegating to subagents unless explicitly asked. I did not want to record a concurrence that never happened, so this section says so. The PR is therefore the review surface, and the strongest independent evidence available is empirical rather than a second opinion: the tests were falsified against a deliberately-broken fix, and verification ran on the Linux host that exposed the defect rather than the macOS host it was authored on.
141
+
142
+ If an independent read is wanted before merge, say so and I will run one.
143
+
144
+ ---
145
+
146
+ ## Evidence pointers
147
+
148
+ - Live reproduction (WSL2 / Ubuntu 26.04, `/tmp` on `tmpfs`): `[test-runner-bound] WARN: admitted WITHOUT a slot (fail-open: df-not-local) — posture: dry-run.`
149
+ - Before: 30 failures across `tests/unit/host-test-runner-semaphore.test.ts` (13), `tests/integration/test-runner-bound-meta.test.ts` (14), `tests/integration/test-runner-limiter-route.test.ts` (3).
150
+ - After, same host: all three files pass — 132 unit + 29 integration tests green.
151
+ - Falsification check: emptying `LINUX_HOST_LOCAL_FSTYPES` makes exactly the two new rescue tests fail, confirming the tests detect the defect rather than passing regardless.
152
+ - Cross-platform: the fix was authored on macOS and verified on the Linux host that exposed the defect, so the proof does not come from the machine it was written on.
153
+
154
+ ---
155
+
156
+ ## Class-Closure Declaration (display-only mirror)
157
+
158
+ No agent-authored-artifact defect — not applicable. This fixes a hand-written classifier in TypeScript source, not an LLM prompt, hook, config, skill, or standards text; and it adds no self-triggered controller (no loop, monitor, sentinel, reaper, scheduler, or recovery path — the change is a pure read consulted by two existing semaphores whose control logic is untouched).