@intentic/constants 1.390.0 → 1.391.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/README.md CHANGED
@@ -31,10 +31,14 @@ flowchart LR
31
31
  on any Node an agent's project pins. A rule may also match the program's working directory (`cwd`), name its memory
32
32
  price (`size`), and be judged under a program that already holds a slot (`nests`): the editor's `vue-tsc` takes the
33
33
  `vue-typecheck` lane, one at a time, from under a `pnpm -r typecheck`. Only a pool no `nests` rule names may wait on
34
- one that does, so the waits cannot form a cycle.
34
+ one that does, so the waits cannot form a cycle. `cargoBuildArgs` translates supported `cargo run` options into
35
+ a build; `heavy-exec.cjs` queues that build in a child and starts the original run once its slot is released.
36
+ Unknown arguments retain the original invocation. The prebuild stays local even when ordinary Cargo builds
37
+ are offloaded, so its artifacts warm the original run.
35
38
  - `memory-room`'s `SIZE_BYTES` prices a toolchain command by its measured shape instead of its class: `targeted` (a test
36
39
  run aimed at named files), `editor-typecheck` (the editor's full `vue-tsc`, 7 GiB) and `scoped-typecheck` (`lsp diag`
37
- on a Vue package, 4 GiB).
40
+ on a Vue package, 4 GiB), and `cargo-build` (7 GiB per admission, based on Shinobi's 2026-11-02 Rust build peaks).
41
+ Two Cargo reservations fit an 18 GiB sandbox with headroom; the price does not cap compiler RSS.
38
42
  - `memory-room` is the one formula for whether the sandbox has room (limit, used, free, stall, and what each workload
39
43
  class costs). The daemon's resource budget judges by it, and it is also the `memory-room` command `queue-run` asks:
40
44
  it asks the daemon's room socket, and applies the formula itself where no daemon answers. (2026-11-02) A reading may
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intentic/constants",
3
- "version": "1.390.0",
3
+ "version": "1.391.0",
4
4
  "description": "Shared constants for the intentic packages, ports, paths, and image references the daemon, CLIs and desktop app all agree on",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -7,7 +7,10 @@
7
7
 
8
8
  const { accessSync, constants } = require("node:fs");
9
9
  const { delimiter, join, resolve } = require("node:path");
10
- const { takeTurn } = require("./heavy-turn.cjs");
10
+ const { spawnSync } = require("node:child_process");
11
+ const { constants: osConstants } = require("node:os");
12
+ const { takeTurn, pendingSpec } = require("./heavy-turn.cjs");
13
+ const { cargoBuildArgs, matchInvocation } = require("./heavy-rules.cjs");
11
14
 
12
15
  const [shims = "", program = "", ...args] = process.argv.slice(2);
13
16
 
@@ -30,8 +33,33 @@ if (real === undefined) {
30
33
  process.stderr.write(`${program}: command not found\n`);
31
34
  process.exit(127);
32
35
  }
36
+ // The child holds the slot only while compiling. The original run then starts with its untouched environment,
37
+ // so a server inherits neither the build's slot nor its toolchain priority. This build stays local to warm its artifacts.
38
+ let build;
39
+ let buildEnv = process.env;
40
+ try {
41
+ const spec = pendingSpec();
42
+ const translated = program === "cargo" ? cargoBuildArgs(args) : undefined;
43
+ if (spec !== undefined && translated !== undefined &&
44
+ matchInvocation([program, ...translated].join(" "), spec.rules, undefined, { cwd: process.cwd() })?.id === "cargo") {
45
+ build = translated;
46
+ const offload = { ...spec.offload };
47
+ delete offload.cargo;
48
+ buildEnv = { ...process.env, INTENTIC_HEAVY: JSON.stringify({ ...spec, offload }) };
49
+ }
50
+ } catch {
51
+ // allow(silent-catch): an unreadable table preserves the original invocation
52
+ }
53
+ if (build !== undefined) {
54
+ const compiled = spawnSync(process.execPath, [__filename, shims, program, ...build], { stdio: "inherit", env: buildEnv });
55
+ if (compiled.status !== 0) {
56
+ process.exit(compiled.status ?? (compiled.signal === null ? 1 : 128 + (osConstants.signals[compiled.signal] ?? 0)));
57
+ }
58
+ }
33
59
  try {
34
- takeTurn({ program, args, command: [real, ...args] });
60
+ if (build === undefined) {
61
+ takeTurn({ program, args, command: [real, ...args] });
62
+ }
35
63
  } catch {
36
64
  // allow(silent-catch): a table that does not parse runs the program as if unjudged
37
65
  }
@@ -39,6 +67,5 @@ try {
39
67
  if (typeof process.execve === "function") {
40
68
  process.execve(real, [program, ...args], process.env);
41
69
  }
42
- const { spawnSync } = require("node:child_process");
43
70
  const run = spawnSync(real, args, { stdio: "inherit", env: process.env, argv0: program });
44
71
  process.exit(run.status ?? 1);
@@ -113,13 +113,14 @@ const SHIPPED_HEAVY_COMMANDS = Object.freeze({
113
113
  { id: "typechecker", pattern: "(?<![-.])\\b(tsc|tsgo|vue-tsc)\\b(?![-.])" },
114
114
  { id: "turbo-fanout", pattern: "\\bturbo\\b.*\\brun\\b.*\\b(build|test|typecheck|check)\\b" },
115
115
  { id: "package-script", pattern: "\\b(pnpm|npm|yarn|bun)\\b.*\\b(test|typecheck|verify|check|build)\\b" },
116
- { id: "cargo", pattern: "^cargo\\s+(\\+\\S+\\s+)?(build|test|check|clippy|bench|doc)\\b" },
116
+ { id: "cargo", pattern: "^cargo\\s+(\\+\\S+\\s+)?(build|test|check|clippy|bench|doc)\\b", size: "cargo-build" },
117
117
  ]),
118
118
  });
119
119
 
120
120
  // Every rule an earlier release shipped, as it shipped it (matched against the agent's shell line then). A stored rule
121
121
  // equal to one of these was seeded, not chosen, so converting a stored file drops it and the current rule takes over.
122
122
  const EARLIER_SHIPPED_RULES = Object.freeze([
123
+ { id: "cargo", pattern: "^cargo\\s+(\\+\\S+\\s+)?(build|test|check|clippy|bench|doc)\\b" },
123
124
  {
124
125
  id: "read-only",
125
126
  pattern: "^\\s*(grep|rg|iq|ag|cat|bat|head|tail|less|ls|find|fd|wc|which|echo|git\\s+(log|status|diff|show|blame))\\b",
@@ -342,6 +343,44 @@ const sizeArgs = (match, invocation) => {
342
343
  return ["vitest", "package-script"].includes(match.id) && targetedRun(invocation) ? ["--size", "targeted"] : [];
343
344
  };
344
345
 
346
+ // Translate only known Cargo options. Unknown flags, aliases and help requests keep the original invocation.
347
+ // Runtime arguments after `--` belong only to `run`; a toolchain selector belongs before either verb.
348
+ const cargoBuildArgs = (args) => {
349
+ const prefix = args[0]?.startsWith("+") ? [args[0]] : [];
350
+ if (args[prefix.length] !== "run") {
351
+ return undefined;
352
+ }
353
+ const build = [...prefix, "build"];
354
+ const values = new Set([
355
+ "--package", "--bin", "--example", "--features", "--profile", "--target", "--target-dir", "--manifest-path",
356
+ "--jobs", "--color", "--message-format", "--config", "--lockfile-path", "-p", "-F", "-j", "-Z",
357
+ ]);
358
+ const switches = new Set([
359
+ "--release", "-r", "--all-features", "--no-default-features", "--locked", "--offline", "--frozen",
360
+ "--verbose", "--quiet", "-q", "--timings", "--future-incompat-report", "--ignore-rust-version", "--keep-going",
361
+ ]);
362
+ for (let i = prefix.length + 1; i < args.length; i++) {
363
+ const arg = args[i];
364
+ if (arg === "--") {
365
+ break;
366
+ }
367
+ if (switches.has(arg) || /^-v+$/u.test(arg) || /^-(p|F|j|Z).+/u.test(arg)) {
368
+ build.push(arg);
369
+ } else if (values.has(arg)) {
370
+ const value = args[++i];
371
+ if (value === undefined || value === "--" || (value.startsWith("-") && !(arg === "-j" || arg === "--jobs"))) {
372
+ return undefined;
373
+ }
374
+ build.push(arg, value);
375
+ } else if (arg.includes("=") && (values.has(arg.split("=")[0]) || arg.startsWith("--timings="))) {
376
+ build.push(arg);
377
+ } else {
378
+ return undefined;
379
+ }
380
+ }
381
+ return build;
382
+ };
383
+
345
384
  // When a slot held this long is worth a line in the log: half of what its own rule lets it hold, never for a rule that
346
385
  // lets it hold forever.
347
386
  const holdWarnSeconds = (maxHold) => (maxHold > 0 ? maxHold / 2 : undefined);
@@ -363,4 +402,5 @@ module.exports = {
363
402
  holdWarnSeconds,
364
403
  ruleById,
365
404
  heldPoolsOf,
405
+ cargoBuildArgs,
366
406
  };
@@ -95,3 +95,6 @@ export function holdWarnSeconds(maxHold: number): number | undefined;
95
95
  export function ruleById(config: HeavyCommands, id: string): HeavyCommandRule | undefined;
96
96
  // The pools the programs above one already hold slots of, from INTENTIC_HEAVY_HELD and INTENTIC_QUEUE_SLOT.
97
97
  export function heldPoolsOf(env: Readonly<Record<string, string | undefined>>, config: HeavyCommands): string[];
98
+
99
+ // The build before a cargo run, or undefined when its arguments cannot be translated safely.
100
+ export function cargoBuildArgs(args: readonly string[]): string[] | undefined;
@@ -5,8 +5,8 @@ export const COST_BYTES: Readonly<Record<RoomWorkload, number>>;
5
5
  export const PERSON_RESERVE_BYTES: number;
6
6
  export const TARGETED_RUN_BYTES: number;
7
7
  // A toolchain command priced by its named shape instead of its class's cost (SIZE_BYTES): one aimed at named files,
8
- // the editor's full typecheck, a changed-files Vue typecheck.
9
- export type RoomSize = "targeted" | "editor-typecheck" | "scoped-typecheck";
8
+ // the editor's full typecheck, a changed-files Vue typecheck, a Cargo build.
9
+ export type RoomSize = "targeted" | "editor-typecheck" | "scoped-typecheck" | "cargo-build";
10
10
  export const SIZE_BYTES: Readonly<Record<RoomSize, number>>;
11
11
  export function isRoomSize(size: string): size is RoomSize;
12
12
  export const TEST_PROCESS_BYTES: Readonly<{ fanOutWorker: number; standaloneWorker: number; typecheck: number; ceiling: number }>;
@@ -34,6 +34,10 @@ export const TARGETED_RUN_BYTES = 512 * MIB;
34
34
  // `size`, which queue-run passes as `--size <name>`). One name per measured shape:
35
35
  export const SIZE_BYTES = Object.freeze({
36
36
  targeted: TARGETED_RUN_BYTES,
37
+ // Shinobi resource-metrics.jsonl, 2026-11-02: `other` RSS peaked at 12.70 GiB at 19:25 with one cargo slot held,
38
+ // and 13.88 GiB at 23:14 with two. Rust was unclassified then, so this includes other work and unqueued runs.
39
+ // Admission estimate per slot: two fit the 18 GiB sandbox with headroom. Cargo's jobs still bound its fan-out.
40
+ "cargo-build": 7 * GIB,
37
41
  // The editor's full typecheck, `vue-tsc` over `_editor/web`, or `_site/demo`'s, which compiles the same source:
38
42
  // 6.8 GiB at its peak (measured 2026-10-26, cold and warm alike), under the 8 GiB heap its script gives it.
39
43
  "editor-typecheck": 7 * GIB,