@astrosheep/keiyaku 1.0.0 → 1.0.2

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.
Files changed (123) hide show
  1. package/README.md +73 -56
  2. package/build/.tsbuildinfo +1 -1
  3. package/build/agents/call-terms_v2.js +103 -0
  4. package/build/agents/harness/activity-values.js +54 -0
  5. package/build/agents/harness/event-channel.js +55 -20
  6. package/build/agents/harness/events.js +47 -1
  7. package/build/agents/harness/execution-handle.js +292 -61
  8. package/build/agents/harness/index.js +103 -121
  9. package/build/agents/harness/pump.js +36 -47
  10. package/build/agents/harness/runtime.js +3 -0
  11. package/build/agents/launch-snapshot_v2.js +348 -0
  12. package/build/agents/opencode-sdk.js +42 -169
  13. package/build/agents/providers/claude-agent-sdk.js +240 -79
  14. package/build/agents/providers/codex-app-server.js +280 -72
  15. package/build/agents/providers/codex-sdk.js +159 -41
  16. package/build/agents/providers/event-type-tail.js +16 -0
  17. package/build/agents/providers/opencode-sdk.js +165 -59
  18. package/build/agents/providers/pi.js +254 -42
  19. package/build/agents/selector_v2.js +122 -0
  20. package/build/cli/commands/akuma.js +120 -42
  21. package/build/cli/completion.js +6 -7
  22. package/build/cli/flags.js +36 -10
  23. package/build/cli/help.js +42 -26
  24. package/build/cli/index.js +225 -93
  25. package/build/cli/parse.js +194 -75
  26. package/build/cli/projection-address.js +11 -0
  27. package/build/cli/render/address.js +88 -0
  28. package/build/cli/render/arc.js +10 -10
  29. package/build/cli/render/call.js +59 -0
  30. package/build/cli/render/compact-text.js +3 -0
  31. package/build/cli/render/errors.js +4 -2
  32. package/build/cli/render/format.js +6 -0
  33. package/build/cli/render/line-width.js +70 -0
  34. package/build/cli/render/misc.js +7 -4
  35. package/build/cli/render/petition.js +4 -3
  36. package/build/cli/render/projection-activity.js +201 -0
  37. package/build/cli/render/shared.js +46 -12
  38. package/build/cli/render/status.js +59 -10
  39. package/build/cli/render/tool-ledger-rollup.js +74 -0
  40. package/build/cli/render/tool-presentation.js +97 -0
  41. package/build/cli/render/wait.js +229 -0
  42. package/build/cli/skills-install.js +42 -24
  43. package/build/cli/subagent-guard.js +1 -1
  44. package/build/config/akuma-loader_v2.js +222 -0
  45. package/build/config/env-keys.js +0 -4
  46. package/build/config/env.js +0 -6
  47. package/build/config/settings.js +325 -12
  48. package/build/core/addressing.js +224 -0
  49. package/build/core/amend.js +30 -47
  50. package/build/core/arc.js +68 -60
  51. package/build/core/bind.js +105 -25
  52. package/build/core/call-persist.js +69 -0
  53. package/build/core/call.js +658 -0
  54. package/build/core/claim.js +72 -44
  55. package/build/core/command-io.js +19 -19
  56. package/build/core/context.js +11 -36
  57. package/build/core/draft.js +2 -3
  58. package/build/core/entry.js +101 -6
  59. package/build/core/execution-coordinate.js +62 -0
  60. package/build/core/execution-pact.js +141 -0
  61. package/build/core/forfeit.js +2 -3
  62. package/build/core/hints.js +10 -10
  63. package/build/core/ids.js +6 -0
  64. package/build/core/ledger.js +16 -1
  65. package/build/core/petition-claim-gates.js +14 -12
  66. package/build/core/petition-claim.js +1 -0
  67. package/build/core/petition-run.js +6 -2
  68. package/build/core/petition.js +63 -21
  69. package/build/core/places.js +106 -13
  70. package/build/core/projection/generation.js +412 -0
  71. package/build/core/projection/heart.js +316 -0
  72. package/build/core/projection/identity.js +81 -0
  73. package/build/core/projection/leash.js +87 -0
  74. package/build/core/projection/mint.js +154 -0
  75. package/build/core/projection-activity.js +219 -0
  76. package/build/core/projection-coordinate.js +35 -0
  77. package/build/core/projection-core.js +69 -463
  78. package/build/core/projection-generation-continuation.js +31 -0
  79. package/build/core/projection-generation-execution.js +148 -0
  80. package/build/core/projection-generation-identity.js +17 -0
  81. package/build/core/projection-generation-launcher.js +90 -0
  82. package/build/core/projection-generation-process.js +43 -0
  83. package/build/core/projection-generation-runner.js +144 -0
  84. package/build/core/projection-generation-runtime.js +15 -0
  85. package/build/core/projection-generation-store.js +707 -0
  86. package/build/core/projection-identity.js +11 -0
  87. package/build/core/projection-life-observer.js +87 -0
  88. package/build/core/projection-life-protocol.js +95 -0
  89. package/build/core/projection-mint.js +96 -24
  90. package/build/core/projection-runner-lock.js +230 -0
  91. package/build/core/projection-status.js +207 -107
  92. package/build/core/projection-tells.js +401 -0
  93. package/build/core/projection-wait.js +155 -0
  94. package/build/core/projection-wake.js +109 -231
  95. package/build/core/queue_v2.js +342 -0
  96. package/build/core/registry.js +6 -3
  97. package/build/core/render.js +63 -1
  98. package/build/core/renew.js +80 -53
  99. package/build/core/scope.js +186 -137
  100. package/build/core/seal.js +16 -19
  101. package/build/core/status.js +88 -25
  102. package/build/core/stored-agent-event.js +101 -0
  103. package/build/core/transcripts.js +214 -228
  104. package/build/core/verdict.js +27 -15
  105. package/build/core/worktree-bootstrap.js +187 -0
  106. package/build/core/worktree-path.js +72 -18
  107. package/build/flow-error.js +4 -6
  108. package/build/generated/version.js +1 -1
  109. package/build/git/branches.js +6 -1
  110. package/build/index.js +8 -5
  111. package/build/keiyaku.js +1 -3
  112. package/package.json +6 -5
  113. package/skills/keiyaku/SKILL.md +6 -47
  114. package/skills/keiyaku-akuma/SKILL.md +75 -0
  115. package/build/agents/effective-policy.js +0 -32
  116. package/build/agents/index.js +0 -114
  117. package/build/agents/selector.js +0 -28
  118. package/build/cli/render/summon.js +0 -17
  119. package/build/cli/render/tell.js +0 -11
  120. package/build/config/akuma-loader.js +0 -268
  121. package/build/core/queue.js +0 -73
  122. package/build/core/summon-persist.js +0 -73
  123. package/build/core/summon.js +0 -377
@@ -1,158 +1,259 @@
1
1
  import * as fs from "node:fs";
2
2
  import * as path from "node:path";
3
3
  import { isErrnoException } from "../errno.js";
4
- import { deriveProjectionPhase, projectionRoot } from "./projection-core.js";
5
- const HEARTBEAT_STALE_MS = 15_000;
6
- const TELL_LAYERS = ["inbox", "inflight", "submitted", "consumed"];
7
- function statOrNull(filePath) {
8
- try {
9
- return fs.statSync(filePath);
10
- }
11
- catch (error) {
12
- if (isErrnoException(error) && error.code === "ENOENT")
13
- return null;
14
- throw error;
4
+ import { executionEventsPath, projectionRoot, } from "./projection-core.js";
5
+ import { ProjectionStateError } from "./atomic-publish.js";
6
+ import { foldAgentActivity, } from "./projection-activity.js";
7
+ import { readProjectionIdentity } from "./projection-identity.js";
8
+ import { readProjectionTellCounts, } from "./projection-tells.js";
9
+ import { ProjectionGenerationStoreError } from "./projection-generation-store.js";
10
+ import { PROJECTION_ADOPTION_TIMEOUT_MS } from "./projection-generation-launcher.js";
11
+ import { observeProjectionLifeSnapshot } from "./projection-life-observer.js";
12
+ import { selectCurrentGeneration } from "./projection-life-protocol.js";
13
+ import { invalidActivityEventDiagnostic, selectValidStoredAgentEvents } from "./stored-agent-event.js";
14
+ const MAX_STATUS_FILE_BYTES = 256 * 1024;
15
+ class ProjectionStatusFileError extends Error {
16
+ diagnostic;
17
+ constructor(kind, filePath) {
18
+ const label = path.basename(filePath);
19
+ const detail = kind === "non-regular-projection-file"
20
+ ? `${label} is not a regular file`
21
+ : `${label} exceeds status read limit`;
22
+ super(detail);
23
+ this.name = "ProjectionStatusFileError";
24
+ this.diagnostic = { kind, detail };
15
25
  }
16
26
  }
17
- function readJsonFile(filePath) {
18
- return JSON.parse(fs.readFileSync(filePath, "utf8"));
27
+ function recordProjectionStatusFileError(error, diagnostics) {
28
+ if (!(error instanceof ProjectionStatusFileError))
29
+ return false;
30
+ diagnostics.push(error.diagnostic);
31
+ return true;
19
32
  }
20
- function countTellLayer(projectionDir, layer, diagnostics) {
21
- const layerDir = path.join(projectionDir, layer);
22
- let entries;
33
+ function readBoundedRegularFile(filePath) {
34
+ const before = fs.lstatSync(filePath);
35
+ if (!before.isFile())
36
+ throw new ProjectionStatusFileError("non-regular-projection-file", filePath);
37
+ if (before.size > MAX_STATUS_FILE_BYTES) {
38
+ throw new ProjectionStatusFileError("oversized-projection-file", filePath);
39
+ }
40
+ let fd;
23
41
  try {
24
- entries = fs.readdirSync(layerDir);
42
+ fd = fs.openSync(filePath, fs.constants.O_RDONLY | fs.constants.O_NONBLOCK | fs.constants.O_NOFOLLOW);
25
43
  }
26
44
  catch (error) {
27
- if (isErrnoException(error) && error.code === "ENOENT") {
28
- diagnostics.push({ kind: "missing-layer", detail: `${layer}/ missing` });
29
- return 0;
45
+ if (isErrnoException(error) && error.code === "ELOOP") {
46
+ throw new ProjectionStatusFileError("non-regular-projection-file", filePath);
30
47
  }
31
- diagnostics.push({ kind: "unreadable-layer", detail: `${layer}/ unreadable: ${String(error)}` });
32
- return 0;
48
+ throw error;
33
49
  }
34
- let count = 0;
35
- for (const entry of entries) {
36
- if (entry.startsWith("."))
37
- continue;
38
- try {
39
- if (fs.statSync(path.join(layerDir, entry)).isFile())
40
- count += 1;
50
+ try {
51
+ const opened = fs.fstatSync(fd);
52
+ if (!opened.isFile())
53
+ throw new ProjectionStatusFileError("non-regular-projection-file", filePath);
54
+ if (opened.size > MAX_STATUS_FILE_BYTES) {
55
+ throw new ProjectionStatusFileError("oversized-projection-file", filePath);
56
+ }
57
+ const chunks = [];
58
+ let total = 0;
59
+ while (total <= MAX_STATUS_FILE_BYTES) {
60
+ const chunk = Buffer.allocUnsafe(Math.min(64 * 1024, MAX_STATUS_FILE_BYTES + 1 - total));
61
+ const bytesRead = fs.readSync(fd, chunk, 0, chunk.length, null);
62
+ if (bytesRead === 0)
63
+ break;
64
+ chunks.push(chunk.subarray(0, bytesRead));
65
+ total += bytesRead;
41
66
  }
42
- catch (error) {
43
- diagnostics.push({ kind: "layer-entry", detail: `${layer}/${entry} unreadable: ${String(error)}` });
67
+ if (total > MAX_STATUS_FILE_BYTES) {
68
+ throw new ProjectionStatusFileError("oversized-projection-file", filePath);
44
69
  }
70
+ return Buffer.concat(chunks, total).toString("utf8");
71
+ }
72
+ finally {
73
+ fs.closeSync(fd);
45
74
  }
46
- return count;
47
75
  }
48
- function readTellCounts(projectionDir, diagnostics) {
76
+ function displayedTellCounts(counts) {
49
77
  return {
50
- inbox: countTellLayer(projectionDir, "inbox", diagnostics),
51
- inflight: countTellLayer(projectionDir, "inflight", diagnostics),
52
- submitted: countTellLayer(projectionDir, "submitted", diagnostics),
53
- consumed: countTellLayer(projectionDir, "consumed", diagnostics),
78
+ inbox: counts.inbox,
79
+ inflight: counts.inflight,
80
+ submitted: counts.submitted,
81
+ consumed: counts.consumed,
54
82
  };
55
83
  }
56
- function readPactFacts(projectionDir, diagnostics) {
57
- const pactPath = path.join(projectionDir, "pact.json");
58
- const pactStat = statOrNull(pactPath);
59
- if (!pactStat) {
60
- diagnostics.push({ kind: "missing-pact", detail: "pact.json missing" });
61
- return { pact: null, pid: undefined, akuma: undefined, provider: undefined, mintedAt: undefined };
62
- }
84
+ function emptyTellCounts() {
85
+ return { inbox: 0, inflight: 0, submitted: 0, consumed: 0 };
86
+ }
87
+ function readIdentityFacts(projectionDir, diagnostics) {
63
88
  try {
64
- const pact = readJsonFile(pactPath);
65
- const pid = Number.isInteger(pact.pid) && pact.pid >= 0 ? pact.pid : undefined;
66
- if (pid === undefined) {
67
- diagnostics.push({ kind: "invalid-pact", detail: "pact.json pid invalid" });
68
- }
69
- if (typeof pact.akuma !== "string" || pact.akuma.trim() === "") {
70
- diagnostics.push({ kind: "invalid-pact", detail: "pact.json akuma invalid" });
89
+ const identity = readProjectionIdentity(projectionDir);
90
+ return {
91
+ identity,
92
+ pid: identity.pid,
93
+ akuma: identity.akuma,
94
+ provider: identity.provider,
95
+ mintedAt: identity.mintedAt,
96
+ workspaceRoot: identity.workspaceRoot,
97
+ };
98
+ }
99
+ catch (error) {
100
+ if (isErrnoException(error) && error.code === "ENOENT") {
101
+ diagnostics.push({ kind: "missing-identity", detail: "heart identity missing" });
102
+ return { identity: null, pid: undefined, akuma: undefined, provider: undefined, mintedAt: undefined, workspaceRoot: undefined };
71
103
  }
72
- if (typeof pact.provider !== "string" || pact.provider.trim() === "") {
73
- diagnostics.push({ kind: "invalid-pact", detail: "pact.json provider invalid" });
104
+ if (error instanceof ProjectionGenerationStoreError) {
105
+ diagnostics.push({ kind: "invalid-identity", detail: error.message });
106
+ return { identity: null, pid: undefined, akuma: undefined, provider: undefined, mintedAt: undefined, workspaceRoot: undefined };
74
107
  }
75
- if (typeof pact.mintedAt !== "string" || pact.mintedAt.trim() === "") {
76
- diagnostics.push({ kind: "invalid-pact", detail: "pact.json mintedAt invalid" });
108
+ if (error instanceof ProjectionStateError) {
109
+ diagnostics.push({ kind: "invalid-identity", detail: error.message });
110
+ return { identity: null, pid: undefined, akuma: undefined, provider: undefined, mintedAt: undefined, workspaceRoot: undefined };
77
111
  }
78
- return {
79
- pact,
80
- pid,
81
- akuma: typeof pact.akuma === "string" && pact.akuma.trim() ? pact.akuma : undefined,
82
- provider: typeof pact.provider === "string" && pact.provider.trim() ? pact.provider : undefined,
83
- mintedAt: typeof pact.mintedAt === "string" && pact.mintedAt.trim() ? pact.mintedAt : undefined,
84
- };
112
+ diagnostics.push({ kind: "unreadable-identity", detail: `heart identity unreadable: ${String(error)}` });
113
+ return { identity: null, pid: undefined, akuma: undefined, provider: undefined, mintedAt: undefined, workspaceRoot: undefined };
114
+ }
115
+ }
116
+ function readHeartTellCounts(projectionDir, diagnostics) {
117
+ try {
118
+ return displayedTellCounts(readProjectionTellCounts(projectionDir));
85
119
  }
86
120
  catch (error) {
87
- diagnostics.push({ kind: "unreadable-pact", detail: `pact.json unreadable: ${String(error)}` });
88
- return { pact: null, pid: undefined, akuma: undefined, provider: undefined, mintedAt: undefined };
121
+ if (error instanceof ProjectionGenerationStoreError || error instanceof ProjectionStateError) {
122
+ diagnostics.push({ kind: "unreadable-tells", detail: error.message });
123
+ return emptyTellCounts();
124
+ }
125
+ diagnostics.push({ kind: "unreadable-tells", detail: `heart tells unreadable: ${String(error)}` });
126
+ return emptyTellCounts();
89
127
  }
90
128
  }
91
- function readVerdictState(projectionDir, diagnostics) {
92
- const verdictPath = path.join(projectionDir, "verdict.json");
93
- if (!statOrNull(verdictPath))
94
- return null;
129
+ function readStoredEvents(projectionDir, executionId, diagnostics) {
130
+ let content;
95
131
  try {
96
- const verdict = readJsonFile(verdictPath);
97
- if (verdict.state === "done" || verdict.state === "dismissed" || verdict.state === "failed")
98
- return verdict.state;
99
- diagnostics.push({ kind: "invalid-verdict", detail: "verdict.json state invalid" });
100
- return null;
132
+ content = readBoundedRegularFile(executionEventsPath(projectionDir, executionId));
101
133
  }
102
134
  catch (error) {
103
- diagnostics.push({ kind: "unreadable-verdict", detail: `verdict.json unreadable: ${String(error)}` });
104
- return null;
135
+ if (isErrnoException(error) && error.code === "ENOENT")
136
+ return [];
137
+ if (recordProjectionStatusFileError(error, diagnostics))
138
+ return [];
139
+ diagnostics.push({ kind: "unreadable-activity", detail: `activity ledger unreadable: ${String(error)}` });
140
+ return [];
141
+ }
142
+ const lines = content.split("\n");
143
+ const terminated = content.endsWith("\n");
144
+ const values = [];
145
+ let malformed = 0;
146
+ for (const line of lines.slice(0, -1)) {
147
+ try {
148
+ values.push(JSON.parse(line));
149
+ }
150
+ catch {
151
+ malformed += 1;
152
+ }
153
+ }
154
+ const finalLine = lines.at(-1);
155
+ if (!terminated && finalLine) {
156
+ try {
157
+ values.push(JSON.parse(finalLine));
158
+ }
159
+ catch {
160
+ // A concurrent append can leave only this final record incomplete.
161
+ }
162
+ }
163
+ if (malformed > 0) {
164
+ diagnostics.push({
165
+ kind: "invalid-activity-event",
166
+ detail: `${malformed} persisted activity event${malformed === 1 ? "" : "s"} malformed`,
167
+ });
105
168
  }
169
+ return values;
106
170
  }
107
- function readHeartbeatFacts(projectionDir, nowMs, diagnostics) {
108
- const heartbeatPath = path.join(projectionDir, "heartbeat");
109
- const heartbeat = statOrNull(heartbeatPath);
110
- if (!heartbeat) {
111
- diagnostics.push({ kind: "missing-heartbeat", detail: "heartbeat missing" });
112
- return {};
171
+ function latestValidEventAtMs(events) {
172
+ let latest;
173
+ for (const event of events) {
174
+ const atMs = Date.parse(event.at);
175
+ if (!Number.isFinite(atMs))
176
+ continue;
177
+ if (latest === undefined || atMs > latest)
178
+ latest = atMs;
113
179
  }
180
+ return latest;
181
+ }
182
+ function readActivityFacts(projectionDir, executionId, nowMs, diagnostics, fallbackAtMs) {
183
+ if (!executionId)
184
+ return {};
185
+ const stored = readStoredEvents(projectionDir, executionId, diagnostics);
186
+ const { events, malformed } = selectValidStoredAgentEvents(stored);
187
+ const invalidActivity = invalidActivityEventDiagnostic(malformed);
188
+ if (invalidActivity)
189
+ diagnostics.push(invalidActivity);
190
+ const activityAtMs = latestValidEventAtMs(events) ?? fallbackAtMs;
114
191
  return {
115
- heartbeatMtimeMs: heartbeat.mtimeMs,
116
- heartbeatAgeMs: Math.max(0, nowMs - heartbeat.mtimeMs),
192
+ ...(events.length > 0 ? { activity: foldAgentActivity(events) } : {}),
193
+ ...(activityAtMs !== undefined
194
+ ? {
195
+ activityAtMs,
196
+ activityAgeMs: Math.max(0, nowMs - activityAtMs),
197
+ }
198
+ : {}),
117
199
  };
118
200
  }
119
- function readProjectionRow(projectionDir, id, nowMs, probePid) {
201
+ function readProjectionRow(projectionDir, id, nowMs) {
120
202
  const diagnostics = [];
121
- const tellCounts = readTellCounts(projectionDir, diagnostics);
122
- const ready = statOrNull(path.join(projectionDir, "ready"));
123
- const pactFacts = readPactFacts(projectionDir, diagnostics);
124
- if (!ready) {
203
+ const identityFacts = readIdentityFacts(projectionDir, diagnostics);
204
+ const tellCounts = identityFacts.identity
205
+ ? readHeartTellCounts(projectionDir, diagnostics)
206
+ : emptyTellCounts();
207
+ if (!identityFacts.identity) {
125
208
  return {
126
209
  id,
127
- state: "minting",
128
- akuma: pactFacts.akuma,
129
- provider: pactFacts.provider,
130
- pid: pactFacts.pid,
131
- mintedAt: pactFacts.mintedAt,
210
+ state: "unknown",
132
211
  tellCounts,
133
212
  diagnostics,
134
213
  };
135
214
  }
136
- const heartbeatFacts = readHeartbeatFacts(projectionDir, nowMs, diagnostics);
137
- // Keep malformed verdict evidence visible without using this adapter as a
138
- // second phase authority.
139
- readVerdictState(projectionDir, diagnostics);
140
- const phase = deriveProjectionPhase(projectionDir, nowMs, probePid);
215
+ const observation = observeProjectionLifeSnapshot(projectionDir, {
216
+ nowMs,
217
+ startupTimeoutMs: PROJECTION_ADOPTION_TIMEOUT_MS,
218
+ });
219
+ const life = observation.life;
220
+ const current = observation.records
221
+ ? selectCurrentGeneration(observation.records)
222
+ : null;
223
+ const adoptedAt = current?.adoption?.facts.adoptedAt;
224
+ const adoptedAtMs = typeof adoptedAt === "string"
225
+ ? Date.parse(adoptedAt)
226
+ : Number.NaN;
227
+ const activityFacts = readActivityFacts(projectionDir, life.executionId, nowMs, diagnostics, Number.isFinite(adoptedAtMs) ? adoptedAtMs : undefined);
228
+ if (life.phase === "unknown" && life.diagnostic) {
229
+ diagnostics.push({ kind: "unknown-lifecycle", detail: life.diagnostic });
230
+ }
231
+ const phase = life.phase;
141
232
  const state = phase === "active" || phase === "quiescent" ? "out" : phase;
142
233
  return {
143
234
  id,
144
235
  state,
145
- akuma: pactFacts.akuma,
146
- provider: pactFacts.provider,
147
- pid: pactFacts.pid,
148
- mintedAt: pactFacts.mintedAt,
236
+ akuma: identityFacts.akuma,
237
+ provider: identityFacts.provider,
238
+ pid: identityFacts.pid,
239
+ mintedAt: identityFacts.mintedAt,
240
+ ...(identityFacts.workspaceRoot ? { workspaceRoot: identityFacts.workspaceRoot } : {}),
241
+ ...activityFacts,
149
242
  tellCounts,
150
243
  diagnostics,
151
- ...heartbeatFacts,
152
244
  };
153
245
  }
154
- export function readProjectionStatusBoard(cwd, nowMs, options = {}) {
246
+ export function readProjectionStatusBoard(cwd, nowMs) {
155
247
  const root = projectionRoot(cwd);
248
+ try {
249
+ if (!fs.lstatSync(root).isDirectory())
250
+ return null;
251
+ }
252
+ catch (error) {
253
+ if (isErrnoException(error) && error.code === "ENOENT")
254
+ return null;
255
+ throw error;
256
+ }
156
257
  let entries;
157
258
  try {
158
259
  entries = fs.readdirSync(root);
@@ -162,18 +263,17 @@ export function readProjectionStatusBoard(cwd, nowMs, options = {}) {
162
263
  return null;
163
264
  throw error;
164
265
  }
165
- const probePid = options.probePid ?? ((pid) => process.kill(pid, 0));
166
266
  const rows = entries
167
267
  .filter((entry) => !entry.startsWith("."))
168
268
  .filter((entry) => {
169
269
  try {
170
- return fs.statSync(path.join(root, entry)).isDirectory();
270
+ return fs.lstatSync(path.join(root, entry)).isDirectory();
171
271
  }
172
272
  catch {
173
273
  return false;
174
274
  }
175
275
  })
176
276
  .sort()
177
- .map((id) => readProjectionRow(path.join(root, id), id, nowMs, probePid));
277
+ .map((id) => readProjectionRow(path.join(root, id), id, nowMs));
178
278
  return rows.length > 0 ? { rows } : null;
179
279
  }