@intentic/constants 1.334.0 → 1.336.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/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/src/memory-room.d.mts +5 -0
- package/src/memory-room.mjs +40 -3
package/dist/index.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ export declare const PUBLIC_DIR = "public";
|
|
|
10
10
|
export declare const MEMORY_FILE = "AGENTS.md";
|
|
11
11
|
export declare const FIELD_NOTES_FILE = ".intentic/config/field-notes.toon";
|
|
12
12
|
export declare const HOST_STATE_ROOT = "/opt/intentic";
|
|
13
|
-
export declare const LEGAL_VERSION = "2026-10-
|
|
13
|
+
export declare const LEGAL_VERSION = "2026-10-13";
|
|
14
14
|
export declare const LEGAL_CONTACT_EMAIL = "contact@intentic.dev";
|
|
15
15
|
export declare const LEGAL_ENTITY_NAME = "Artur Kurowski, trading as radarsu";
|
|
16
16
|
export declare const LEGAL_ENTITY_COUNTRY = "Poland";
|
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ export const PUBLIC_DIR = "public";
|
|
|
10
10
|
export const MEMORY_FILE = "AGENTS.md";
|
|
11
11
|
export const FIELD_NOTES_FILE = ".intentic/config/field-notes.toon";
|
|
12
12
|
export const HOST_STATE_ROOT = "/opt/intentic";
|
|
13
|
-
export const LEGAL_VERSION = "2026-10-
|
|
13
|
+
export const LEGAL_VERSION = "2026-10-13";
|
|
14
14
|
export const LEGAL_CONTACT_EMAIL = "contact@intentic.dev";
|
|
15
15
|
export const LEGAL_ENTITY_NAME = "Artur Kurowski, trading as radarsu";
|
|
16
16
|
export const LEGAL_ENTITY_COUNTRY = "Poland";
|
package/package.json
CHANGED
package/src/memory-room.d.mts
CHANGED
|
@@ -9,6 +9,8 @@ export type RoomSize = "targeted";
|
|
|
9
9
|
export const TEST_PROCESS_BYTES: Readonly<{ fanOutWorker: number; standaloneWorker: number; typecheck: number; ceiling: number }>;
|
|
10
10
|
export const STALL_PERCENT: number;
|
|
11
11
|
export const STALL_SUSTAINED_PERCENT: number;
|
|
12
|
+
export const IO_STALL_PERCENT: number;
|
|
13
|
+
export const IO_STALL_SUSTAINED_PERCENT: number;
|
|
12
14
|
export const SWAP_FULL_SHARE: number;
|
|
13
15
|
export const RESERVATION_MS: number;
|
|
14
16
|
export const ROOM_SOCKET: string;
|
|
@@ -30,6 +32,9 @@ export interface MemoryReading {
|
|
|
30
32
|
readonly stallPercent: number;
|
|
31
33
|
// Memory PSI `full avg60`, in percent, from the same file; 0 when healthy or unreported.
|
|
32
34
|
readonly stallSustainedPercent?: number | undefined;
|
|
35
|
+
// IO PSI `full avg10` and `avg60`, in percent: the cgroup's, else the machine's; 0 when healthy or unreported.
|
|
36
|
+
readonly ioStallPercent?: number | undefined;
|
|
37
|
+
readonly ioStallSustainedPercent?: number | undefined;
|
|
33
38
|
// memory.events `oom_kill`, cumulative; undefined without a cgroup.
|
|
34
39
|
readonly oomKills: number | undefined;
|
|
35
40
|
}
|
package/src/memory-room.mjs
CHANGED
|
@@ -23,6 +23,12 @@
|
|
|
23
23
|
// stall memory PSI `full`: avg10, the share of the last ten seconds in which everything waited on memory, and avg60,
|
|
24
24
|
// the last minute's. A sandbox paging hard flickers around any avg10 threshold (19, 11, 15, 4, 18% in five
|
|
25
25
|
// minutes of the reading above, never 20), so a lower bar on the minute catches what the spikes miss.
|
|
26
|
+
// disk io PSI `full` the same way, for work nobody is waiting on only: swap paged in from disk and a build's writes
|
|
27
|
+
// stall everything on the disk, the daemon's own event loop included, before memory PSI says much. Measured
|
|
28
|
+
// 2026-10-10..13: of 29 daemon freezes of 5 s or more, 20 had disk `full` avg10 at 30% or past it, 18 had
|
|
29
|
+
// memory's at 20%, and the one that failed a turn's setup on 2026-10-13 had disk 42% and memory 7%. Disk
|
|
30
|
+
// reached 30% in 1.5% of the minute samples of those days, so holding background work then costs little. A
|
|
31
|
+
// person's turn is never refused for it: a busy disk slows a turn, it does not kill one.
|
|
26
32
|
import { spawnSync } from "node:child_process";
|
|
27
33
|
import { existsSync, readFileSync, realpathSync } from "node:fs";
|
|
28
34
|
import { request } from "node:http";
|
|
@@ -74,6 +80,9 @@ export const PERSON_RESERVE_BYTES = COST_BYTES.agentRuntime;
|
|
|
74
80
|
export const STALL_PERCENT = 20;
|
|
75
81
|
// Percent of full avg60 at which it does: lower than STALL_PERCENT, since a minute's average has smoothed the spikes.
|
|
76
82
|
export const STALL_SUSTAINED_PERCENT = 10;
|
|
83
|
+
// Percent of io `full` avg10, and of avg60, at which work nobody is waiting on waits for the disk (the `disk` clause).
|
|
84
|
+
export const IO_STALL_PERCENT = 30;
|
|
85
|
+
export const IO_STALL_SUSTAINED_PERCENT = 20;
|
|
77
86
|
// The share of its swap limit past which swap counts as full, and the swapped pages count as used.
|
|
78
87
|
export const SWAP_FULL_SHARE = 0.9;
|
|
79
88
|
export const RESERVATION_MS = 90_000;
|
|
@@ -91,8 +100,10 @@ export const READING_FILES = Object.freeze([
|
|
|
91
100
|
`${CGROUP}/memory.swap.max`,
|
|
92
101
|
`${CGROUP}/memory.pressure`,
|
|
93
102
|
`${CGROUP}/memory.events`,
|
|
103
|
+
`${CGROUP}/io.pressure`,
|
|
94
104
|
"/proc/meminfo",
|
|
95
105
|
"/proc/pressure/memory",
|
|
106
|
+
"/proc/pressure/io",
|
|
96
107
|
]);
|
|
97
108
|
|
|
98
109
|
const numeric = (text) => {
|
|
@@ -119,6 +130,13 @@ const fullAvg = (text, window) => {
|
|
|
119
130
|
|
|
120
131
|
const kib = (fields, key) => (fields[key] === undefined ? undefined : fields[key] * 1024);
|
|
121
132
|
|
|
133
|
+
// One resource's PSI `full` averages: the cgroup's where it keeps one, else the machine's, avg60 from the same file avg10
|
|
134
|
+
// came from; 0 where nothing reports it.
|
|
135
|
+
const stallOf = (read, resource) => {
|
|
136
|
+
const text = [read(`${CGROUP}/${resource}.pressure`), read(`/proc/pressure/${resource}`)].find((file) => fullAvg(file, "avg10") !== undefined);
|
|
137
|
+
return { recent: fullAvg(text, "avg10") ?? 0, sustained: fullAvg(text, "avg60") ?? 0 };
|
|
138
|
+
};
|
|
139
|
+
|
|
122
140
|
/** The reading, from a reader that answers each of READING_FILES with its text or undefined. */
|
|
123
141
|
export const readingFrom = (read) => {
|
|
124
142
|
const meminfo = keyed(read("/proc/meminfo"));
|
|
@@ -144,15 +162,18 @@ export const readingFrom = (read) => {
|
|
|
144
162
|
swapLimit = kib(meminfo, "SwapTotal") ?? Number.POSITIVE_INFINITY;
|
|
145
163
|
}
|
|
146
164
|
// The cgroup's pressure where it keeps one, else the machine's; avg60 from the same file avg10 came from.
|
|
147
|
-
const
|
|
165
|
+
const memory = stallOf(read, "memory");
|
|
166
|
+
const disk = stallOf(read, "io");
|
|
148
167
|
return {
|
|
149
168
|
limitBytes: Number.isFinite(bound) ? bound : undefined,
|
|
150
169
|
usedBytes,
|
|
151
170
|
swapBytes,
|
|
152
171
|
swapLimitBytes: Number.isFinite(swapLimit) ? swapLimit : undefined,
|
|
153
172
|
availableBytes: kib(meminfo, "MemAvailable"),
|
|
154
|
-
stallPercent:
|
|
155
|
-
stallSustainedPercent:
|
|
173
|
+
stallPercent: memory.recent,
|
|
174
|
+
stallSustainedPercent: memory.sustained,
|
|
175
|
+
ioStallPercent: disk.recent,
|
|
176
|
+
ioStallSustainedPercent: disk.sustained,
|
|
156
177
|
oomKills: keyed(read(`${CGROUP}/memory.events`)).oom_kill,
|
|
157
178
|
};
|
|
158
179
|
};
|
|
@@ -215,6 +236,10 @@ export const judge = (reading, { workload, attended, reservedBytes = 0, size })
|
|
|
215
236
|
if (stallSustainedPercent >= STALL_SUSTAINED_PERCENT) {
|
|
216
237
|
return shortOf(`The sandbox is short of memory: for ${Math.round(stallSustainedPercent)}% of the last minute, everything in it was waiting on memory`);
|
|
217
238
|
}
|
|
239
|
+
const disk = attended ? undefined : diskStalled(reading);
|
|
240
|
+
if (disk !== undefined) {
|
|
241
|
+
return shortOf(disk);
|
|
242
|
+
}
|
|
218
243
|
if (freeBytes >= need) {
|
|
219
244
|
return { verdict: "run", needBytes: need, freeBytes, reservedBytes };
|
|
220
245
|
}
|
|
@@ -235,6 +260,18 @@ export const judge = (reading, { workload, attended, reservedBytes = 0, size })
|
|
|
235
260
|
return shortOf(`Sandbox memory is low: ${used}${held}`, { limitBytes, residentBytes: usedBytes - swapBytes, swapBytes });
|
|
236
261
|
};
|
|
237
262
|
|
|
263
|
+
// Why work nobody is waiting on should wait for the disk, or undefined while it need not (the `disk` clause).
|
|
264
|
+
const diskStalled = (reading) => {
|
|
265
|
+
const recent = reading.ioStallPercent ?? 0;
|
|
266
|
+
const sustained = reading.ioStallSustainedPercent ?? 0;
|
|
267
|
+
if (recent >= IO_STALL_PERCENT) {
|
|
268
|
+
return `The sandbox's disk is saturated: for ${Math.round(recent)}% of the last ten seconds, everything in it was waiting on the disk`;
|
|
269
|
+
}
|
|
270
|
+
return sustained >= IO_STALL_SUSTAINED_PERCENT
|
|
271
|
+
? `The sandbox's disk is saturated: for ${Math.round(sustained)}% of the last minute, everything in it was waiting on the disk`
|
|
272
|
+
: undefined;
|
|
273
|
+
};
|
|
274
|
+
|
|
238
275
|
/**
|
|
239
276
|
* Free memory as the formula counts it (the limit less what counts against it: the resident part, and swap too once swap
|
|
240
277
|
* is full), or undefined where nothing bounds or measures it.
|