@rightkit/release 0.2.156 → 0.2.158

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.
@@ -78,6 +78,8 @@ if (first === "--version" || first === "-v") {
78
78
  );
79
79
  } else if (first === "cache") {
80
80
  run("cache-command.mjs", args.slice(1));
81
+ } else if (first === "disk") {
82
+ run("disk-command.mjs", args.slice(1));
81
83
  } else if (first === "install-app") {
82
84
  run("install-app.mjs", args.slice(1));
83
85
  } else if (first === "dmg") {
@@ -242,6 +244,11 @@ Commands:
242
244
  cache prune [--dry-run|--apply] [--json] Plan or apply safe shared-target pruning
243
245
  cache migrate --config <file> [--dry-run|--apply] [--json]
244
246
  Move a same-volume legacy target without copying
247
+ disk check [--json] Per-writer sizes vs caps and free-space floor (exit 3 on warning)
248
+ disk sweep [--dry-run] [--days N] [--delete] [--json]
249
+ Move stale idle heavy data to the heavy volume (delete only with --delete)
250
+ disk run check, dry-run sweep, move sweep, warn (the scheduled job)
251
+ disk schedule install|uninstall|status Daily launchd job (Mac) / hidden Task Scheduler entry (Windows)
245
252
  deps --check|--audit|--update Shared dependency lane
246
253
  hardening <artifact...> Run the Right Suite hardening scan
247
254
  lsclean <AppName.app> Clear macOS LaunchServices duplicates
@@ -0,0 +1,204 @@
1
+ #!/usr/bin/env node
2
+ import { existsSync, mkdirSync, realpathSync, unlinkSync, writeFileSync } from "node:fs";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ import { fileURLToPath, pathToFileURL } from "node:url";
6
+ import { spawnSync } from "./background-process.mjs";
7
+ import {
8
+ DISK_EXIT_WARNING, applySweep, checkDisk, formatBytes, listOpenPaths, logEvent, planSweep, platformKey, readDiskPolicy,
9
+ } from "./disk-policy.mjs";
10
+
11
+ export const LAUNCHD_LABEL = "dev.rightkit.disk-hygiene";
12
+ export const WINDOWS_TASK = "RightKit Disk Hygiene";
13
+
14
+ export function renderCheck(result) {
15
+ const lines = [`${result.floor.label}: ${formatBytes(result.floor.freeBytes)} free of ${formatBytes(result.floor.totalBytes)} (floor ${formatBytes(result.floor.thresholdBytes)})${result.floor.warn ? " WARN" : ""}`];
16
+ for (const w of result.writers) {
17
+ const size = w.error ? `error: ${w.error}` : w.matches === 0 ? "absent" : `${formatBytes(w.bytes)} / cap ${formatBytes(w.capBytes)}`;
18
+ lines.push(` ${w.id.padEnd(28)} ${w.action.padEnd(6)} ${size}${w.over ? " OVER CAP" : ""}`);
19
+ }
20
+ for (const w of result.warnings) lines.push(`WARNING: ${w}`);
21
+ return lines.join("\n");
22
+ }
23
+
24
+ export function renderSweep(plan, applied) {
25
+ const lines = [`${applied ? "Swept" : "Dry run: would move"} ${plan.candidates.length} item(s), ${formatBytes(plan.totalBytes)} (stale > ${plan.staleDays} days)`];
26
+ const rows = applied ? applied.results : plan.candidates;
27
+ const byWriter = new Map();
28
+ for (const r of rows) byWriter.set(r.writer, [...(byWriter.get(r.writer) ?? []), r]);
29
+ for (const [writer, items] of byWriter) {
30
+ const total = items.reduce((s, r) => s + r.bytes, 0);
31
+ lines.push(` ${writer.padEnd(26)} ${String(items.length).padStart(4)} item(s) ${formatBytes(total).padStart(9)}`);
32
+ for (const r of [...items].sort((a, b) => b.bytes - a.bytes).slice(0, 5)) lines.push(` ${formatBytes(r.bytes).padStart(9)} ${r.path}${r.destination ? ` -> ${r.destination}` : ""}${r.ok === false ? ` FAILED: ${r.error}` : ""}`);
33
+ if (items.length > 5) lines.push(` ... ${items.length - 5} more`);
34
+ }
35
+ const counts = {};
36
+ for (const s of plan.skipped) counts[s.reason] = (counts[s.reason] ?? 0) + 1;
37
+ if (plan.skipped.length) lines.push(` skipped: ${Object.entries(counts).map(([k, v]) => `${v} ${k}`).join(", ")}`);
38
+ return lines.join("\n");
39
+ }
40
+
41
+ function parse(rest) {
42
+ const known = new Set(["--json", "--dry-run", "--delete", "--days", "--policy"]);
43
+ const opts = { json: false, dryRun: false, deleteMode: false, days: undefined, policy: undefined };
44
+ for (let i = 0; i < rest.length; i += 1) {
45
+ const a = rest[i];
46
+ if (!known.has(a)) throw new Error(`disk: unknown option ${a}`);
47
+ if (a === "--json") opts.json = true;
48
+ else if (a === "--dry-run") opts.dryRun = true;
49
+ else if (a === "--delete") opts.deleteMode = true;
50
+ else { const v = rest[++i]; if (!v) throw new Error(`disk: ${a} needs a value`); if (a === "--days") opts.days = Number(v); else opts.policy = v; }
51
+ }
52
+ if (opts.days !== undefined && !(opts.days >= 0)) throw new Error("disk: --days must be a non-negative number");
53
+ if (opts.dryRun && opts.deleteMode) throw new Error("disk sweep accepts either --dry-run or --delete");
54
+ return opts;
55
+ }
56
+
57
+ const CHECKOUT_FILE = fileURLToPath(import.meta.url);
58
+
59
+ // A path inside any git checkout (a `.git` entry on an ancestor) is development code, never an installed package.
60
+ export function insideGitCheckout(file, exists = existsSync) {
61
+ let dir = path.dirname(file);
62
+ for (;;) {
63
+ if (exists(path.join(dir, ".git"))) return true;
64
+ const up = path.dirname(dir);
65
+ if (up === dir) return false;
66
+ dir = up;
67
+ }
68
+ }
69
+
70
+ /** Installed @rightkit/release CLI for the Windows task: explicit --cli / RIGHT_RELEASE_INSTALLED_CLI, else the global
71
+ * node_modules (`npm root -g`, `pnpm root -g`). A checkout, including the one running install, is refused. */
72
+ export function resolveInstalledCli({ explicit, env = process.env, globalRoots = defaultGlobalRoots, exists = existsSync, checkoutFile = CHECKOUT_FILE } = {}) {
73
+ const rel = path.join("@rightkit", "release", "cli", "right-release.mjs");
74
+ const candidates = explicit || env.RIGHT_RELEASE_INSTALLED_CLI
75
+ ? [explicit || env.RIGHT_RELEASE_INSTALLED_CLI]
76
+ : globalRoots({ env }).map((root) => path.join(root, rel));
77
+ const checkoutCli = path.join(path.dirname(checkoutFile), "cli", "right-release.mjs");
78
+ for (const candidate of candidates) {
79
+ if (!exists(candidate)) continue;
80
+ let real = candidate;
81
+ try { real = realpathSync(candidate); } catch { /* keep lexical */ }
82
+ if (real === checkoutCli || insideGitCheckout(real, exists)) continue;
83
+ return candidate;
84
+ }
85
+ throw new Error("disk schedule install needs the installed @rightkit/release (not a checkout): install it globally or pass --cli <path to the installed cli/right-release.mjs>");
86
+ }
87
+
88
+ function defaultGlobalRoots() {
89
+ const roots = [];
90
+ for (const tool of ["npm", "pnpm"]) {
91
+ const r = spawnSync(tool, ["root", "-g"], { encoding: "utf8", shell: process.platform === "win32" });
92
+ const line = String(r.stdout ?? "").trim().split(/\r?\n/).pop();
93
+ if (r.status === 0 && line) roots.push(line);
94
+ }
95
+ return roots;
96
+ }
97
+
98
+ export function scheduleSpec({ platform = process.platform, nodePath = process.execPath, cli = path.join(path.dirname(fileURLToPath(import.meta.url)), "cli", "right-release.mjs"), home = os.homedir(), hour = 3, minute = 30 } = {}) {
99
+ if (platform === "darwin") {
100
+ const logDir = "/Volumes/D/claude/tmp/swept";
101
+ const file = path.join(home, "Library", "LaunchAgents", `${LAUNCHD_LABEL}.plist`);
102
+ const plist = `<?xml version="1.0" encoding="UTF-8"?>
103
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
104
+ <plist version="1.0"><dict>
105
+ <key>Label</key><string>${LAUNCHD_LABEL}</string>
106
+ <key>ProgramArguments</key><array><string>${nodePath}</string><string>${cli}</string><string>disk</string><string>run</string></array>
107
+ <key>StartCalendarInterval</key><dict><key>Hour</key><integer>${hour}</integer><key>Minute</key><integer>${minute}</integer></dict>
108
+ <key>StandardOutPath</key><string>${logDir}/launchd.out.log</string>
109
+ <key>StandardErrorPath</key><string>${logDir}/launchd.err.log</string>
110
+ <key>ProcessType</key><string>Background</string><key>LowPriorityIO</key><true/><key>Nice</key><integer>10</integer>
111
+ </dict></plist>
112
+ `;
113
+ return { platform: "mac", file, plist };
114
+ }
115
+ const script = `$a = New-ScheduledTaskAction -Execute '${nodePath}' -Argument '"${cli}" disk run'
116
+ $t = New-ScheduledTaskTrigger -Daily -At ${String(hour).padStart(2, "0")}:${String(minute).padStart(2, "0")}
117
+ $s = New-ScheduledTaskSettingsSet -Hidden -StartWhenAvailable -ExecutionTimeLimit (New-TimeSpan -Hours 2)
118
+ $p = New-ScheduledTaskPrincipal -UserId "$env:USERDOMAIN\\$env:USERNAME" -LogonType Interactive -RunLevel Limited
119
+ Register-ScheduledTask -TaskName '${WINDOWS_TASK}' -Action $a -Trigger $t -Settings $s -Principal $p -Force | Out-Null`;
120
+ return { platform: "win", script };
121
+ }
122
+
123
+ function schedule(sub, { stdout, cli }) {
124
+ const platform = process.platform;
125
+ const spec = scheduleSpec(platform === "darwin" || sub !== "install" ? { platform } : { platform, cli: resolveInstalledCli({ explicit: cli }) });
126
+ if (platform === "darwin") {
127
+ const uid = String(process.getuid());
128
+ if (sub === "install") {
129
+ mkdirSync(path.dirname(spec.file), { recursive: true });
130
+ mkdirSync("/Volumes/D/claude/tmp/swept", { recursive: true });
131
+ writeFileSync(spec.file, spec.plist);
132
+ spawnSync("launchctl", ["bootout", `gui/${uid}/${LAUNCHD_LABEL}`], { encoding: "utf8" });
133
+ const r = spawnSync("launchctl", ["bootstrap", `gui/${uid}`, spec.file], { encoding: "utf8" });
134
+ if (r.status !== 0) throw new Error(`launchctl bootstrap failed: ${r.stderr}`);
135
+ stdout(`installed ${spec.file} (daily 03:30)`);
136
+ } else if (sub === "uninstall") {
137
+ spawnSync("launchctl", ["bootout", `gui/${uid}/${LAUNCHD_LABEL}`], { encoding: "utf8" });
138
+ if (existsSync(spec.file)) unlinkSync(spec.file);
139
+ stdout("uninstalled");
140
+ } else if (sub === "status") {
141
+ const r = spawnSync("launchctl", ["print", `gui/${uid}/${LAUNCHD_LABEL}`], { encoding: "utf8" });
142
+ stdout(r.status === 0 ? `installed (${spec.file})` : "not installed");
143
+ } else throw new Error("disk schedule install|uninstall|status");
144
+ return;
145
+ }
146
+ if (sub === "install") {
147
+ const r = spawnSync("powershell.exe", ["-NoProfile", "-NonInteractive", "-WindowStyle", "Hidden", "-Command", spec.script], { encoding: "utf8" });
148
+ if (r.status !== 0) throw new Error(`Register-ScheduledTask failed: ${r.stderr || r.stdout}`);
149
+ stdout(`installed scheduled task "${WINDOWS_TASK}" (daily 03:30, hidden)`);
150
+ } else if (sub === "uninstall") {
151
+ spawnSync("powershell.exe", ["-NoProfile", "-NonInteractive", "-Command", `Unregister-ScheduledTask -TaskName '${WINDOWS_TASK}' -Confirm:$false`], { encoding: "utf8" });
152
+ stdout("uninstalled");
153
+ } else if (sub === "status") {
154
+ const r = spawnSync("powershell.exe", ["-NoProfile", "-NonInteractive", "-Command", `Get-ScheduledTask -TaskName '${WINDOWS_TASK}' | Select-Object -ExpandProperty State`], { encoding: "utf8" });
155
+ stdout(r.status === 0 ? `installed (${String(r.stdout).trim()})` : "not installed");
156
+ } else throw new Error("disk schedule install|uninstall|status");
157
+ }
158
+
159
+ export async function runDiskCommand(args = process.argv.slice(2), { env = process.env, stdout = console.log, platform = process.platform, deps = {} } = {}) {
160
+ const [command, ...rest] = args;
161
+ if (command === "schedule") {
162
+ const at = rest.indexOf("--cli");
163
+ schedule(rest[0], { stdout, cli: at === -1 ? undefined : rest[at + 1] });
164
+ return { exitCode: 0 };
165
+ }
166
+ const opts = parse(rest);
167
+ const policy = readDiskPolicy(opts.policy);
168
+ const key = platformKey(platform);
169
+ const logFile = path.join(policy.heavyVolume[key], "disk-hygiene.jsonl");
170
+ const out = (value, text) => stdout(opts.json ? JSON.stringify(value) : text);
171
+ const check = () => checkDisk({ policy, platform, env, ...deps.check });
172
+ const plan = () => planSweep({ policy, platform, env, staleDays: opts.days, openPaths: platform === "win32" ? null : (deps.openPaths ?? listOpenPaths({ platform })), ...deps.plan });
173
+
174
+ if (command === "check") {
175
+ const result = check();
176
+ out(result, renderCheck(result));
177
+ return { exitCode: result.warn ? DISK_EXIT_WARNING : 0, result };
178
+ }
179
+ if (command === "sweep") {
180
+ const p = plan();
181
+ if (opts.dryRun) { out(p, renderSweep(p)); return { exitCode: 0, plan: p }; }
182
+ const applied = applySweep({ plan: p, policy, platform, deleteMode: opts.deleteMode, ...deps.apply });
183
+ out({ ...p, applied }, renderSweep(p, applied));
184
+ return { exitCode: applied.results.some((r) => !r.ok) ? 1 : 0, plan: p, applied };
185
+ }
186
+ if (command === "run") {
187
+ const before = check();
188
+ stdout(renderCheck(before));
189
+ const p = plan();
190
+ stdout(renderSweep(p));
191
+ const applied = applySweep({ plan: p, policy, platform, ...deps.apply });
192
+ stdout(`moved ${formatBytes(applied.movedBytes)} (${applied.results.filter((r) => r.ok).length}/${applied.results.length})`);
193
+ const after = check();
194
+ const warn = after.warn;
195
+ logEvent(logFile, { event: warn ? "disk.floor.warn" : "disk.run.ok", warnings: after.warnings, freeBytes: after.floor.freeBytes, movedBytes: applied.movedBytes });
196
+ if (warn) stdout(`WARNING: ${after.warnings.join("; ")}`);
197
+ return { exitCode: warn ? DISK_EXIT_WARNING : 0, before, after, applied };
198
+ }
199
+ throw new Error("disk usage: check|sweep [--dry-run|--delete] [--days N]|run|schedule install|uninstall|status [--json]");
200
+ }
201
+
202
+ if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
203
+ runDiskCommand().then((r) => process.exit(r.exitCode)).catch((e) => { console.error(e.message); process.exit(2); });
204
+ }
@@ -0,0 +1,48 @@
1
+ {
2
+ "schema": 1,
3
+ "staleDays": 7,
4
+ "floors": {
5
+ "mac": {"path": "/System/Volumes/Data", "label": "Mac internal", "warnFreeBytes": 42949672960},
6
+ "win": {"path": "D:\\", "label": "Dell D:", "warnFreeBytes": 429496729600, "warnFreePercent": 10}
7
+ },
8
+ "heavyVolume": {
9
+ "mac": "/Volumes/D/claude/tmp/swept",
10
+ "win": "D:\\claude\\tmp\\swept"
11
+ },
12
+ "writers": [
13
+ {"id": "claude-session-dirs", "platform": "mac", "path": "/private/tmp/claude-501/*/*", "capBytes": 2147483648, "action": "sweep", "unit": "self"},
14
+ {"id": "rightkit-qa-tmp", "platform": "mac", "path": "/private/tmp/rightkit-qa", "capBytes": 2147483648, "action": "sweep", "unit": "children"},
15
+ {"id": "cache-e2e", "platform": "mac", "path": "~/Library/Caches/e2e_*", "capBytes": 1073741824, "action": "sweep", "unit": "self"},
16
+ {"id": "cache-parakeet", "platform": "mac", "path": "~/Library/Caches/parakeet_*", "capBytes": 1073741824, "action": "sweep", "unit": "self"},
17
+ {"id": "cache-swiftright-factory", "platform": "mac", "path": "~/Library/Caches/SwiftRightFactory", "capBytes": 10737418240, "action": "sweep", "unit": "children"},
18
+ {"id": "cache-cutright-engine", "platform": "mac", "path": "~/Library/Caches/cutright-engine", "capBytes": 2147483648, "action": "report"},
19
+ {"id": "cache-heardright-engine", "platform": "mac", "path": "~/Library/Caches/heardright-engine", "capBytes": 2147483648, "action": "report"},
20
+ {"id": "cache-pnpm", "platform": "mac", "path": "~/Library/Caches/pnpm", "capBytes": 3221225472, "action": "report"},
21
+ {"id": "cache-python", "platform": "mac", "path": "~/Library/Caches/python", "capBytes": 3221225472, "action": "report"},
22
+ {"id": "xcode-deriveddata", "platform": "mac", "path": "~/Library/Developer/Xcode/DerivedData", "capBytes": 10737418240, "action": "sweep", "unit": "children"},
23
+ {"id": "coresimulator", "platform": "mac", "path": "~/Library/Developer/CoreSimulator", "capBytes": 26843545600, "action": "report"},
24
+ {"id": "documents-scratch", "platform": "mac", "path": "~/Documents", "capBytes": 21474836480, "action": "report"},
25
+ {"id": "shared-models", "platform": "mac", "path": "/Volumes/D/Orthic Labs/shared/models", "capBytes": 107374182400, "action": "report"},
26
+ {"id": "stale-release-tarballs", "platform": "mac", "path": "/Volumes/D/claude/rightkit/packages/release/rightkit-release-*.tgz", "capBytes": 1073741824, "action": "sweep", "unit": "self"},
27
+ {"id": "win-temp", "platform": "win", "path": "${TEMP}", "capBytes": 10737418240, "action": "sweep", "unit": "children"},
28
+ {"id": "win-pnpm", "platform": "win", "path": "${LOCALAPPDATA}\\pnpm", "capBytes": 21474836480, "action": "report"},
29
+ {"id": "win-sccache", "platform": "win", "path": "D:\\.rightkit-managed\\rightkit-build-control\\global", "capBytes": 34359738368, "action": "report"},
30
+ {"id": "win-claude-workspace", "platform": "win", "path": "D:\\claude", "capBytes": 805306368000, "action": "report"},
31
+ {"id": "win-claude-tmp", "platform": "win", "path": "D:\\claude\\tmp", "capBytes": 107374182400, "action": "report"},
32
+ {"id": "win-shared-models", "platform": "win", "path": "${LOCALAPPDATA}\\Orthic Labs\\shared\\models", "capBytes": 107374182400, "action": "report"},
33
+ {"id": "stale-release-tarballs", "platform": "win", "path": "D:\\claude\\rightkit\\packages\\release\\rightkit-release-*.tgz", "capBytes": 1073741824, "action": "sweep", "unit": "self"},
34
+ {"id": "win-remote-inputs", "platform": "win", "path": "D:\\.rightkit-managed\\remote-inputs", "capBytes": 21474836480, "action": "report"},
35
+ {"id": "leftover-delete-me", "platform": "win", "path": "D:\\claude\\*-DELETE-ME", "capBytes": 1073741824, "action": "sweep", "unit": "self"},
36
+ {"id": "leftover-node-modules-medium-rightkit", "platform": "win", "path": "D:\\claude\\rightkit\\node_modules.medium-*", "capBytes": 1073741824, "action": "sweep", "unit": "self"},
37
+ {"id": "leftover-node-modules-medium-packages", "platform": "win", "path": "D:\\claude\\rightkit\\packages\\*\\node_modules.medium-*", "capBytes": 1073741824, "action": "sweep", "unit": "self"},
38
+ {"id": "leftover-legion-snap", "platform": "win", "path": "D:\\claude\\legion-snap-*", "capBytes": 1073741824, "action": "sweep", "unit": "self"},
39
+ {"id": "leftover-legion-final", "platform": "win", "path": "D:\\claude\\legion-final-*", "capBytes": 1073741824, "action": "sweep", "unit": "self"},
40
+ {"id": "leftover-delete-me", "platform": "mac", "path": "/Volumes/D/claude/*-DELETE-ME", "capBytes": 1073741824, "action": "sweep", "unit": "self"},
41
+ {"id": "leftover-node-modules-medium-rightkit", "platform": "mac", "path": "/Volumes/D/claude/rightkit/node_modules.medium-*", "capBytes": 1073741824, "action": "sweep", "unit": "self"},
42
+ {"id": "leftover-node-modules-medium-packages", "platform": "mac", "path": "/Volumes/D/claude/rightkit/packages/*/node_modules.medium-*", "capBytes": 1073741824, "action": "sweep", "unit": "self"},
43
+ {"id": "leftover-legion-snap", "platform": "mac", "path": "/Volumes/D/claude/legion-snap-*", "capBytes": 1073741824, "action": "sweep", "unit": "self"},
44
+ {"id": "leftover-legion-final", "platform": "mac", "path": "/Volumes/D/claude/legion-final-*", "capBytes": 1073741824, "action": "sweep", "unit": "self"},
45
+ {"id": "leftover-pulse-bak", "platform": "win", "path": "${LOCALAPPDATA}\\Programs\\Pulse.bak-*", "capBytes": 1073741824, "action": "sweep", "unit": "self"}
46
+ ],
47
+ "protectedSegments": ["Application Support", "Keychains", "Keychain", "HeardRightNext", "Credentials", ".ssh", ".rightkit-managed"]
48
+ }
@@ -0,0 +1,270 @@
1
+ import { closeSync, cpSync, existsSync, lstatSync, mkdirSync, opendirSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, statfsSync, appendFileSync } from "node:fs";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { spawnSync } from "./background-process.mjs";
6
+
7
+ export const DISK_EXIT_WARNING = 3;
8
+ export const DEFAULT_POLICY_FILE = path.join(path.dirname(fileURLToPath(import.meta.url)), "disk-policy.json");
9
+
10
+ export function readDiskPolicy(file = DEFAULT_POLICY_FILE) {
11
+ const policy = JSON.parse(readFileSync(file, "utf8"));
12
+ if (policy.schema !== 1 || !Array.isArray(policy.writers)) throw new Error("disk policy: unsupported schema");
13
+ return policy;
14
+ }
15
+
16
+ export function platformKey(platform = process.platform) {
17
+ return platform === "win32" || platform === "win" ? "win" : "mac";
18
+ }
19
+
20
+ export function expandPolicyPath(value, { env = process.env, home = os.homedir() } = {}) {
21
+ let out = value.replace(/^~(?=$|[\\/])/, home);
22
+ out = out.replace(/\$\{(\w+)\}/g, (_, name) => {
23
+ if (!env[name]) throw new Error(`disk policy: ${name} is not set`);
24
+ return env[name];
25
+ });
26
+ return out;
27
+ }
28
+
29
+ // Expand a policy path whose segments may contain `*` wildcards into existing paths.
30
+ export function expandGlob(pattern, sep = path.sep) {
31
+ const parts = pattern.split(/[\\/]/);
32
+ let bases = [parts[0] === "" ? sep : `${parts[0]}${sep}`];
33
+ for (const part of parts.slice(1)) {
34
+ if (part === "") continue;
35
+ const next = [];
36
+ for (const base of bases) {
37
+ if (!part.includes("*")) {
38
+ const candidate = path.join(base, part);
39
+ if (existsSync(candidate)) next.push(candidate);
40
+ continue;
41
+ }
42
+ const rx = new RegExp(`^${part.split("*").map((s) => s.replace(/[.+?^${}()|[\]\\]/g, "\\$&")).join(".*")}$`);
43
+ let names = [];
44
+ try { names = readdirSync(base); } catch { continue; }
45
+ for (const name of names) if (rx.test(name)) next.push(path.join(base, name));
46
+ }
47
+ bases = next;
48
+ }
49
+ return bases;
50
+ }
51
+
52
+ export function walkSize(root) {
53
+ let total = 0;
54
+ const stack = [root];
55
+ while (stack.length) {
56
+ const dir = stack.pop();
57
+ let st;
58
+ try { st = lstatSync(dir); } catch { continue; }
59
+ total += st.blocks !== undefined ? st.blocks * 512 : st.size;
60
+ if (!st.isDirectory()) continue;
61
+ let handle;
62
+ try { handle = opendirSync(dir); } catch { continue; }
63
+ try {
64
+ for (let e = handle.readSync(); e; e = handle.readSync()) stack.push(path.join(dir, e.name));
65
+ } finally { try { handle.closeSync(); } catch { /* ignore */ } }
66
+ }
67
+ return total;
68
+ }
69
+
70
+ export function pathSize(target, { platform = process.platform } = {}) {
71
+ if (platform === "darwin") {
72
+ const r = spawnSync("du", ["-sk", target], { encoding: "utf8" });
73
+ const kb = Number.parseInt(String(r.stdout).split(/\s+/)[0], 10);
74
+ if (Number.isFinite(kb)) return kb * 1024;
75
+ }
76
+ return walkSize(target);
77
+ }
78
+
79
+ export function freeSpace(volumePath) {
80
+ const s = statfsSync(volumePath);
81
+ return { freeBytes: Number(s.bavail) * Number(s.bsize), totalBytes: Number(s.blocks) * Number(s.bsize) };
82
+ }
83
+
84
+ export function floorThreshold(floor, totalBytes) {
85
+ const pct = floor.warnFreePercent ? Math.floor((totalBytes * floor.warnFreePercent) / 100) : 0;
86
+ return Math.max(floor.warnFreeBytes ?? 0, pct);
87
+ }
88
+
89
+ export function evaluateFloor(floor, space) {
90
+ const thresholdBytes = floorThreshold(floor, space.totalBytes);
91
+ return { label: floor.label, path: floor.path, ...space, thresholdBytes, warn: space.freeBytes < thresholdBytes };
92
+ }
93
+
94
+ // Literal directory prefix of a policy path: everything before the first wildcard segment
95
+ // (for a wildcard-free path, its parent). A sweep unit must resolve inside it.
96
+ export function literalRoot(expanded) {
97
+ const parts = expanded.split(/[\\/]/);
98
+ const firstWild = parts.findIndex((p) => p.includes("*"));
99
+ const keep = firstWild === -1 ? parts.slice(0, -1) : parts.slice(0, firstWild);
100
+ const joined = keep.join(path.sep);
101
+ return joined === "" || /^[A-Za-z]:$/.test(joined) ? `${joined}${path.sep}` : joined;
102
+ }
103
+
104
+ export function isInsideRoot(candidate, root) {
105
+ try {
106
+ const realRoot = realpathSync(root);
107
+ const realCandidate = realpathSync(candidate);
108
+ const prefix = realRoot.endsWith(path.sep) ? realRoot : realRoot + path.sep;
109
+ return realCandidate !== realRoot && realCandidate.startsWith(prefix);
110
+ } catch { return false; }
111
+ }
112
+
113
+ export function writerMatches(writer, ctx) {
114
+ const pattern = expandPolicyPath(writer.path, ctx);
115
+ return expandGlob(pattern);
116
+ }
117
+
118
+ export function checkDisk({ policy, platform = process.platform, env = process.env, home = os.homedir(), size = (p) => pathSize(p, { platform }), space = freeSpace } = {}) {
119
+ const key = platformKey(platform);
120
+ const floorPolicy = policy.floors[key];
121
+ const floor = evaluateFloor(floorPolicy, space(floorPolicy.path));
122
+ const writers = [];
123
+ for (const writer of policy.writers.filter((w) => w.platform === key)) {
124
+ let matches;
125
+ try { matches = writerMatches(writer, { env, home }); } catch (error) {
126
+ writers.push({ id: writer.id, action: writer.action, error: error.message, bytes: 0, capBytes: writer.capBytes, over: false, matches: 0 });
127
+ continue;
128
+ }
129
+ const bytes = matches.reduce((sum, m) => sum + size(m), 0);
130
+ writers.push({ id: writer.id, action: writer.action, path: writer.path, matches: matches.length, bytes, capBytes: writer.capBytes, over: bytes > writer.capBytes });
131
+ }
132
+ const warnings = [];
133
+ if (floor.warn) warnings.push(`${floor.label} free ${formatBytes(floor.freeBytes)} is below the ${formatBytes(floor.thresholdBytes)} floor`);
134
+ for (const w of writers) if (w.over) warnings.push(`${w.id} holds ${formatBytes(w.bytes)} over its ${formatBytes(w.capBytes)} cap`);
135
+ return { schema: 1, platform: key, floor, writers, warnings, warn: warnings.length > 0 };
136
+ }
137
+
138
+ export function formatBytes(n) {
139
+ if (n >= 1024 ** 3) return `${(n / 1024 ** 3).toFixed(1)} GB`;
140
+ if (n >= 1024 ** 2) return `${(n / 1024 ** 2).toFixed(1)} MB`;
141
+ return `${Math.round(n / 1024)} KB`;
142
+ }
143
+
144
+ // True when anything under `root` was modified after `cutoffMs` (early exit).
145
+ export function hasFreshContent(root, cutoffMs) {
146
+ const stack = [root];
147
+ while (stack.length) {
148
+ const entry = stack.pop();
149
+ let st;
150
+ try { st = lstatSync(entry); } catch { continue; }
151
+ if (st.mtimeMs > cutoffMs) return true;
152
+ if (!st.isDirectory()) continue;
153
+ let handle;
154
+ try { handle = opendirSync(entry); } catch { continue; }
155
+ try {
156
+ for (let e = handle.readSync(); e; e = handle.readSync()) stack.push(path.join(entry, e.name));
157
+ } finally { try { handle.closeSync(); } catch { /* ignore */ } }
158
+ }
159
+ return false;
160
+ }
161
+
162
+ export function isProtectedPath(candidate, policy) {
163
+ const segments = candidate.split(/[\\/]/);
164
+ return (policy.protectedSegments ?? []).some((p) => segments.includes(p));
165
+ }
166
+
167
+ // Open-file listing for the whole machine on macOS; paths a live process holds.
168
+ export function listOpenPaths({ platform = process.platform } = {}) {
169
+ if (platform === "win32") return null;
170
+ const r = spawnSync("lsof", ["-n", "-P", "-w", "-F", "n"], { encoding: "utf8", maxBuffer: 1 << 28 });
171
+ if (r.error || (r.status !== 0 && !r.stdout)) return undefined;
172
+ return String(r.stdout).split("\n").filter((l) => l.startsWith("n/")).map((l) => l.slice(1));
173
+ }
174
+
175
+ export function inUseByOpenPaths(candidate, openPaths) {
176
+ if (openPaths === undefined) return true; // cannot prove idle: treat as in use
177
+ if (openPaths === null) return false;
178
+ const prefix = candidate.endsWith(path.sep) ? candidate : candidate + path.sep;
179
+ return openPaths.some((p) => p === candidate || p.startsWith(prefix));
180
+ }
181
+
182
+ // Windows has no lsof; a locked directory cannot be renamed. Probe by renaming away and back.
183
+ export function windowsLockProbe(candidate) {
184
+ const probe = `${candidate}.rk-probe`;
185
+ try { renameSync(candidate, probe); } catch { return true; }
186
+ try { renameSync(probe, candidate); } catch { return true; }
187
+ return false;
188
+ }
189
+
190
+ export function planSweep({ policy, platform = process.platform, env = process.env, home = os.homedir(), now = Date.now(), staleDays = policy.staleDays, openPaths, inUse, size = (p) => pathSize(p, { platform }) } = {}) {
191
+ const key = platformKey(platform);
192
+ const cutoff = now - staleDays * 86400_000;
193
+ const candidates = [];
194
+ const skipped = [];
195
+ const seen = new Set();
196
+ const lockCheck = inUse ?? (key === "win" ? windowsLockProbe : (p) => inUseByOpenPaths(p, openPaths));
197
+ for (const writer of policy.writers.filter((w) => w.platform === key && w.action === "sweep")) {
198
+ let roots; let literal;
199
+ try { roots = writerMatches(writer, { env, home }); literal = literalRoot(expandPolicyPath(writer.path, { env, home })); } catch { continue; }
200
+ const units = [];
201
+ for (const r of roots) {
202
+ if (writer.unit !== "children") { units.push({ unit: r, root: literal }); continue; }
203
+ let rst;
204
+ try { rst = lstatSync(r); } catch { continue; }
205
+ if (rst.isSymbolicLink()) { skipped.push({ writer: writer.id, path: r, reason: "symlink-root" }); continue; }
206
+ let names = [];
207
+ try { names = readdirSync(r); } catch { continue; }
208
+ for (const n of names) units.push({ unit: path.join(r, n), root: r });
209
+ }
210
+ for (const { unit, root } of units) {
211
+ if (seen.has(unit)) continue;
212
+ seen.add(unit);
213
+ const base = { writer: writer.id, path: unit };
214
+ let st;
215
+ try { st = lstatSync(unit); } catch { continue; }
216
+ if (st.isSymbolicLink()) { skipped.push({ ...base, reason: "symlink" }); continue; }
217
+ if (!isInsideRoot(unit, root)) { skipped.push({ ...base, reason: "outside-root" }); continue; }
218
+ if (isProtectedPath(unit, policy)) { skipped.push({ ...base, reason: "protected" }); continue; }
219
+ if (hasFreshContent(unit, cutoff)) { skipped.push({ ...base, reason: "fresh" }); continue; }
220
+ if (lockCheck(unit)) { skipped.push({ ...base, reason: "in-use" }); continue; }
221
+ candidates.push({ ...base, root, bytes: size(unit), mtime: new Date(st.mtimeMs).toISOString() });
222
+ }
223
+ }
224
+ return { schema: 1, platform: key, staleDays, candidates, skipped, totalBytes: candidates.reduce((s, c) => s + c.bytes, 0) };
225
+ }
226
+
227
+ export function sweptDestination({ policy, platform = process.platform, date = new Date() }) {
228
+ const key = platformKey(platform);
229
+ return path.join(policy.heavyVolume[key], date.toISOString().slice(0, 10));
230
+ }
231
+
232
+ export function moveEntry(source, destination) {
233
+ mkdirSync(path.dirname(destination), { recursive: true });
234
+ try { renameSync(source, destination); return "rename"; } catch (error) {
235
+ if (error.code !== "EXDEV") throw error;
236
+ }
237
+ const before = walkSize(source);
238
+ cpSync(source, destination, { recursive: true, preserveTimestamps: true, verbatimSymlinks: true, errorOnExist: true, force: false });
239
+ if (walkSize(destination) < before) throw new Error(`copy verification failed for ${source}; source kept`);
240
+ rmSync(source, { recursive: true, force: true }); // completes the move after verified copy
241
+ return "copy-verify-remove";
242
+ }
243
+
244
+ export function logEvent(logFile, event) {
245
+ try {
246
+ mkdirSync(path.dirname(logFile), { recursive: true });
247
+ appendFileSync(logFile, `${JSON.stringify({ ts: new Date().toISOString(), ...event })}\n`);
248
+ } catch { /* logging must never fail the sweep */ }
249
+ }
250
+
251
+ export function applySweep({ plan, policy, platform = process.platform, deleteMode = false, date = new Date(), move = moveEntry, remove = (p) => rmSync(p, { recursive: true, force: true }) }) {
252
+ const destRoot = sweptDestination({ policy, platform, date });
253
+ const logFile = path.join(policy.heavyVolume[platformKey(platform)], "disk-hygiene.jsonl");
254
+ const results = [];
255
+ for (const c of plan.candidates) {
256
+ const rel = path.join(c.writer, path.basename(c.path));
257
+ let destination = path.join(destRoot, rel);
258
+ if (existsSync(destination)) destination = `${destination}.${date.getTime()}`;
259
+ try {
260
+ // Re-verify at apply time: still the planned unit, not a symlink, still inside its root.
261
+ if (!c.root || lstatSync(c.path).isSymbolicLink() || !isInsideRoot(c.path, c.root)) throw new Error("refused: path is not a sweepable unit inside its target root");
262
+ if (deleteMode) { remove(c.path); results.push({ ...c, action: "delete", ok: true }); logEvent(logFile, { event: "disk.sweep.delete", ...c }); }
263
+ else { const how = move(c.path, destination); results.push({ ...c, action: "move", destination, how, ok: true }); logEvent(logFile, { event: "disk.sweep.move", ...c, destination, how }); }
264
+ } catch (error) {
265
+ results.push({ ...c, action: deleteMode ? "delete" : "move", ok: false, error: error.message });
266
+ logEvent(logFile, { event: "disk.sweep.error", ...c, error: error.message });
267
+ }
268
+ }
269
+ return { logFile, results, movedBytes: results.filter((r) => r.ok).reduce((s, r) => s + r.bytes, 0) };
270
+ }
package/local-publish.mjs CHANGED
@@ -30,18 +30,20 @@ const refuse = (message) => { throw new LocalPublishError(message); };
30
30
 
31
31
  export function parseLocalPublishArgs(kind, argv, cwd = process.cwd()) {
32
32
  const flag = kind === "npm" ? "--package" : "--crate";
33
- let unit; let workspace; let local = false;
33
+ let unit; let workspace; let local = false; let allowIgnored = false;
34
34
  for (let i = 0; i < argv.length; i += 1) {
35
35
  const arg = argv[i];
36
36
  if (arg === "--local") local = true;
37
37
  else if (arg === flag) unit = argv[++i];
38
38
  else if (arg === "--workspace") workspace = argv[++i];
39
- else refuse(`unknown publish ${kind} --local option: ${arg} (accepted: ${flag} <name>, --workspace <dir>, --local)`);
39
+ // Same meaning as publish.yml's allow_ignored: this unit may have ignored tests; the count is recorded.
40
+ else if (arg === "--allow-ignored") allowIgnored = true;
41
+ else refuse(`unknown publish ${kind} --local option: ${arg} (accepted: ${flag} <name>, --workspace <dir>, --allow-ignored, --local)`);
40
42
  }
41
43
  if (!local) refuse("--local is required");
42
44
  if (kind === "npm" && !/^@rightkit\/[a-z0-9-]+$/.test(unit ?? "")) refuse("publish npm --local requires --package @rightkit/<name>");
43
45
  if (kind === "cargo" && !/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(unit ?? "")) refuse("publish cargo --local requires --crate <name>");
44
- return { kind, unit, workspaceRoot: path.resolve(workspace ?? cwd) };
46
+ return { kind, unit, allowIgnored, workspaceRoot: path.resolve(workspace ?? cwd) };
45
47
  }
46
48
 
47
49
  function defaultGit(args, cwd) {
@@ -107,7 +109,7 @@ const tail = (text, lines = 40) => String(text ?? "").split(/\r?\n/).slice(-line
107
109
 
108
110
  export async function runLocalPublish(kind, argv, deps = {}) {
109
111
  const log = deps.log ?? ((line) => process.stdout.write(`${line}\n`));
110
- const { unit, workspaceRoot } = parseLocalPublishArgs(kind, argv, deps.cwd);
112
+ const { unit, allowIgnored, workspaceRoot } = parseLocalPublishArgs(kind, argv, deps.cwd);
111
113
  const platform = deps.platform ?? process.platform;
112
114
  const git = deps.git ?? defaultGit;
113
115
  const readJson = deps.readJson ?? defaultReadJson;
@@ -170,7 +172,7 @@ export async function runLocalPublish(kind, argv, deps = {}) {
170
172
  }
171
173
  steps.push(row);
172
174
  }
173
- const verdict = judgeUnit({ name: unit, steps: steps.map((s) => ({ ...s, unit: plan.id })), allowIgnored: [], allowMissingAssets: isAssetGated ? [unit] : [] });
175
+ const verdict = judgeUnit({ name: unit, steps: steps.map((s) => ({ ...s, unit: plan.id })), allowIgnored: allowIgnored ? [unit] : [], allowMissingAssets: isAssetGated ? [unit] : [] });
174
176
  if (verdict.status === "fail" || steps.some((s) => s.failed > 0)) refuse(`${plan.id} not qualified: ${verdict.problems.join("; ") || "failed tests reported"}`);
175
177
  if (!(verdict.executed > 0)) refuse(`${plan.id} executed no test`);
176
178
  log(`[right-release] ${plan.id}: ${verdict.executed} passed, 0 failed, ${verdict.skipped} skipped, ${verdict.ignored} ignored${isAssetGated ? " (asset-gated: RIGHTKIT_REQUIRE_ASSETS=0, skips recorded)" : ""}`);
@@ -212,7 +214,7 @@ export async function runLocalPublish(kind, argv, deps = {}) {
212
214
  runs: [{
213
215
  host: { os: "darwin", arch: deps.arch ?? process.arch }, commit: head, features: plan.featureLabels, artifactSha256,
214
216
  command: commands.join(" && "), operator: LOCAL_OPERATOR, timestamp,
215
- passed: verdict.executed, failed: 0, skipped: verdict.skipped, ignored: verdict.ignored,
217
+ passed: verdict.executed, failed: 0, skipped: verdict.skipped, ignored: verdict.ignored, allowIgnored,
216
218
  requireAssets: env.RIGHTKIT_REQUIRE_ASSETS, assetGated: isAssetGated,
217
219
  steps: steps.map(({ command, ok, executed, failed, ignored, skipped, binaries }) => ({ command, ok, ...(executed === undefined ? {} : { executed, failed, ignored, skipped, binaries }) })),
218
220
  }],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rightkit/release",
3
- "version": "0.2.156",
3
+ "version": "0.2.158",
4
4
  "description": "Portable release CLI/SDK with fail-closed public GitHub Releases and private R2 + RightApps distribution.",
5
5
  "license": "MIT OR Apache-2.0",
6
6
  "type": "module",
package/publish-cargo.mjs CHANGED
@@ -42,6 +42,17 @@ export function parseCargoPublishArgs(argv, cwd = process.cwd()) {
42
42
  };
43
43
  }
44
44
 
45
+ // A committed ci/runtime-budget-deferred.json names crates whose runtime-budget refusal is deferred by an
46
+ // explicit decision (who, when, why). The refusal is still printed; a listed crate publishes with the
47
+ // deferral logged. Returns the logged reason, or null when the crate is not listed.
48
+ export function runtimeBudgetDeferral(crateDir, crate) {
49
+ const file = path.join(crateDir, "..", "..", "ci", "runtime-budget-deferred.json");
50
+ let data;
51
+ try { data = JSON.parse(fs.readFileSync(file, "utf8")); } catch { return null; }
52
+ if (!data?.crates?.includes?.(crate) || !data.approvedBy || !data.approved || !data.reason) return null;
53
+ return `${data.reason} (${data.approvedBy}, ${data.approved}; ci/runtime-budget-deferred.json)`;
54
+ }
55
+
45
56
  export function buildCargoPublishPlan({ crate, crateDir, dryRun, allowDirty = false }) {
46
57
  const dryRunArgs = ["publish", "--dry-run", "-p", crate];
47
58
  const packageArgs = ["package", "--list", "-p", crate];
@@ -123,6 +134,11 @@ export async function runCargoPublish(options, execute = (_command, args, settin
123
134
  if (step.internal === "runtime-budget") {
124
135
  const check = runtimeBudgetCheck({ crate: options.crate, crateDir, version: cargoVersion, evidence: gate.evidence ?? undefined });
125
136
  if (check) process.stdout.write(`${formatPreflight([check])}\n`);
137
+ const deferral = check?.status === PREFLIGHT_FAIL ? runtimeBudgetDeferral(crateDir, options.crate) : null;
138
+ if (deferral) {
139
+ process.stdout.write(`[right-release] runtime budget DEFERRED for ${options.crate}: ${deferral}\n`);
140
+ continue;
141
+ }
126
142
  if (check?.status === PREFLIGHT_FAIL && !options.dryRun) {
127
143
  const error = new Error(`runtime budget refused: ${check.detail}. Fix: ${check.fix}`);
128
144
  error.code = RUNTIME_BUDGET_CODE;
@@ -13,23 +13,28 @@
13
13
  "@rightkit/updates": "0.2.3"
14
14
  },
15
15
  "stagedNpm": {
16
- "@rightkit/ax": "0.2.4",
16
+ "@rightkit/app-update": "0.2.5",
17
+ "@rightkit/ax": "0.3.2",
18
+ "@rightkit/ci": "0.2.43",
17
19
  "@rightkit/doc-render": "0.1.6",
18
20
  "@rightkit/hooks": "0.1.2",
19
21
  "@rightkit/i18n": "0.1.0",
20
22
  "@rightkit/legal": "0.3.1",
21
23
  "@rightkit/legal-ui": "0.2.2",
22
- "@rightkit/license": "0.1.8",
24
+ "@rightkit/license": "0.2.0",
23
25
  "@rightkit/logs": "0.1.4",
24
26
  "@rightkit/media-ui": "0.3.4",
25
27
  "@rightkit/onboarding": "0.3.3",
28
+ "@rightkit/outdated": "0.2.0",
26
29
  "@rightkit/pdf-ui": "0.1.6",
27
- "@rightkit/platform-ui": "0.2.7",
28
- "@rightkit/qa": "0.4.7",
29
- "@rightkit/qa-chrome": "0.1.5",
30
- "@rightkit/release": "0.2.156",
31
- "@rightkit/settings-ui": "0.4.3",
32
- "@rightkit/tauri": "0.2.0",
30
+ "@rightkit/platform-ui": "0.2.8",
31
+ "@rightkit/qa": "0.4.8",
32
+ "@rightkit/qa-chrome": "0.1.6",
33
+ "@rightkit/react-shell": "0.6.4",
34
+ "@rightkit/release": "0.2.158",
35
+ "@rightkit/settings-ui": "0.4.4",
36
+ "@rightkit/tauri": "0.2.1",
37
+ "@rightkit/tauri-shell": "0.1.1",
33
38
  "@rightkit/theme": "0.2.3"
34
39
  },
35
40
  "legacyNpm": {
@@ -37,7 +42,8 @@
37
42
  "0.2.0",
38
43
  "0.2.1",
39
44
  "0.2.2",
40
- "0.2.3"
45
+ "0.2.3",
46
+ "0.2.4"
41
47
  ],
42
48
  "@rightkit/git": [
43
49
  "0.2.1",
@@ -97,7 +103,8 @@
97
103
  ],
98
104
  "@rightkit/license": [
99
105
  "0.1.6",
100
- "0.1.7"
106
+ "0.1.7",
107
+ "0.1.8"
101
108
  ],
102
109
  "@rightkit/release": [
103
110
  "0.2.22",
@@ -191,7 +198,8 @@
191
198
  "0.2.149",
192
199
  "0.2.150",
193
200
  "0.2.151",
194
- "0.2.155"
201
+ "0.2.155",
202
+ "0.2.156"
195
203
  ],
196
204
  "@rightkit/qa": [
197
205
  "0.1.0",
@@ -209,7 +217,8 @@
209
217
  "0.4.3",
210
218
  "0.4.4",
211
219
  "0.4.5",
212
- "0.4.6"
220
+ "0.4.6",
221
+ "0.4.7"
213
222
  ],
214
223
  "@rightkit/app-shell": [
215
224
  "0.1.0",
@@ -259,7 +268,8 @@
259
268
  "0.3.4",
260
269
  "0.4.0",
261
270
  "0.4.1",
262
- "0.4.2"
271
+ "0.4.2",
272
+ "0.4.3"
263
273
  ],
264
274
  "@rightkit/onboarding": [
265
275
  "0.1.0",
@@ -288,7 +298,8 @@
288
298
  "0.2.3",
289
299
  "0.2.4",
290
300
  "0.2.5",
291
- "0.2.6"
301
+ "0.2.6",
302
+ "0.2.7"
292
303
  ],
293
304
  "@rightkit/pdf-ui": [
294
305
  "0.1.0",
@@ -303,13 +314,15 @@
303
314
  "0.1.1",
304
315
  "0.1.2",
305
316
  "0.1.3",
306
- "0.1.4"
317
+ "0.1.4",
318
+ "0.1.5"
307
319
  ],
308
320
  "@rightkit/updates": [
309
321
  "0.2.4"
310
322
  ],
311
323
  "@rightkit/tauri": [
312
- "0.1.1"
324
+ "0.1.1",
325
+ "0.2.0"
313
326
  ],
314
327
  "@rightkit/shell": [
315
328
  "0.1.0"
@@ -334,40 +347,58 @@
334
347
  },
335
348
  "stagedCargo": {
336
349
  "rightkit-agent-tools": "0.1.2",
337
- "rightkit-asr": "0.1.0",
338
- "rightkit-audio": "0.2.1",
350
+ "rightkit-agents": "0.1.0",
351
+ "rightkit-app-settings": "0.2.0",
352
+ "rightkit-asr": "0.2.1",
353
+ "rightkit-audio": "0.2.3",
339
354
  "rightkit-automation": "0.3.0",
340
- "rightkit-browser": "0.2.4",
341
- "rightkit-cache": "0.1.0",
342
- "rightkit-contracts": "0.1.2",
343
- "rightkit-crash": "0.2.1",
344
- "rightkit-db": "0.3.2",
345
- "rightkit-embed": "0.3.2",
346
- "rightkit-fs": "0.3.3",
347
- "rightkit-fsindex": "0.1.1",
355
+ "rightkit-browser": "0.3.1",
356
+ "rightkit-cache": "0.2.0",
357
+ "rightkit-channel-memory": "0.1.0",
358
+ "rightkit-child-process": "0.4.0",
359
+ "rightkit-compose": "0.1.0",
360
+ "rightkit-contracts": "0.1.5",
361
+ "rightkit-crash": "0.3.0",
362
+ "rightkit-credentials": "0.2.0",
363
+ "rightkit-daemon": "0.2.2",
364
+ "rightkit-db": "0.4.0",
365
+ "rightkit-device": "0.1.3",
366
+ "rightkit-embed": "0.4.0",
367
+ "rightkit-ffmpeg": "0.2.6",
368
+ "rightkit-file-watch": "0.4.0",
369
+ "rightkit-fs": "0.4.0",
370
+ "rightkit-fsindex": "0.2.1",
348
371
  "rightkit-hotkeys": "0.1.0",
349
- "rightkit-http": "0.2.5",
350
- "rightkit-license": "0.1.3",
351
- "rightkit-llm": "0.2.0",
352
- "rightkit-logs": "0.2.1",
372
+ "rightkit-http": "0.3.0",
373
+ "rightkit-job-queue": "0.3.1",
374
+ "rightkit-license": "0.2.0",
375
+ "rightkit-llm": "0.2.1",
376
+ "rightkit-logs": "0.3.0",
353
377
  "rightkit-mcp": "0.5.3",
354
- "rightkit-models": "0.2.8",
355
- "rightkit-oauth": "0.3.1",
356
- "rightkit-ocr": "0.2.0",
378
+ "rightkit-models": "0.3.1",
379
+ "rightkit-oauth": "0.5.0",
380
+ "rightkit-ocr": "0.2.2",
381
+ "rightkit-onnx": "0.2.3",
357
382
  "rightkit-overlay": "0.1.1",
358
383
  "rightkit-ownership": "0.2.1",
359
- "rightkit-pdf": "0.2.0",
360
- "rightkit-playback": "0.1.2",
361
- "rightkit-qa": "0.2.15",
362
- "rightkit-review": "0.1.0",
363
- "rightkit-sandbox": "0.3.4",
364
- "rightkit-search": "0.2.0",
384
+ "rightkit-pdf": "0.3.0",
385
+ "rightkit-playback": "0.2.1",
386
+ "rightkit-qa": "0.3.0",
387
+ "rightkit-qa-driver": "0.3.1",
388
+ "rightkit-review": "0.2.0",
389
+ "rightkit-sandbox": "0.4.0",
390
+ "rightkit-search": "0.2.1",
365
391
  "rightkit-send": "0.1.0",
366
- "rightkit-speech-client": "0.3.3",
367
- "rightkit-sync": "0.1.0",
368
- "rightkit-transcript": "0.2.0",
369
- "rightkit-tts": "0.1.1",
370
- "rightkit-vad": "0.0.3"
392
+ "rightkit-sidecar": "0.2.0",
393
+ "rightkit-speech-client": "0.3.5",
394
+ "rightkit-sync": "0.1.1",
395
+ "rightkit-tauri-shell": "0.3.0",
396
+ "rightkit-transcript": "0.3.0",
397
+ "rightkit-tts": "0.2.1",
398
+ "rightkit-tts-qwen": "0.2.6",
399
+ "rightkit-tts-qwen-sys": "0.1.2",
400
+ "rightkit-vad": "0.1.1",
401
+ "rightkit-workflow": "0.1.0"
371
402
  },
372
403
  "swift": {
373
404
  "rightkit-swift": {
@@ -384,70 +415,101 @@
384
415
  },
385
416
  "registry": {
386
417
  "cargo": {
387
- "rightkit-asr": "0.1.0",
388
- "rightkit-audio": "0.2.1",
389
- "rightkit-browser": "0.2.4",
390
- "rightkit-cache": "0.1.0",
391
- "rightkit-control": "0.1.11",
392
- "rightkit-crash": "0.2.1",
393
- "rightkit-db": "0.3.2",
394
- "rightkit-embed": "0.3.2",
395
- "rightkit-framed-sidecar": "0.1.0",
396
- "rightkit-fs": "0.3.3",
397
- "rightkit-fsindex": "0.1.1",
398
- "rightkit-http": "0.2.5",
399
- "rightkit-jobs": "0.2.7",
400
- "rightkit-license": "0.1.3",
401
- "rightkit-llm": "0.1.0",
402
- "rightkit-logs": "0.2.1",
418
+ "rightkit-agent-tools": "0.1.2",
419
+ "rightkit-agents": "0.1.0",
420
+ "rightkit-app-settings": "0.2.0",
421
+ "rightkit-asr": "0.2.1",
422
+ "rightkit-audio": "0.2.3",
423
+ "rightkit-automation": "0.3.0",
424
+ "rightkit-browser": "0.3.1",
425
+ "rightkit-cache": "0.2.0",
426
+ "rightkit-channel-memory": "0.1.0",
427
+ "rightkit-child-process": "0.4.0",
428
+ "rightkit-compose": "0.1.0",
429
+ "rightkit-contracts": "0.1.5",
430
+ "rightkit-control": "0.3.0",
431
+ "rightkit-crash": "0.3.0",
432
+ "rightkit-credentials": "0.2.0",
433
+ "rightkit-daemon": "0.2.2",
434
+ "rightkit-db": "0.4.0",
435
+ "rightkit-device": "0.1.3",
436
+ "rightkit-embed": "0.4.0",
437
+ "rightkit-ffmpeg": "0.2.6",
438
+ "rightkit-file-watch": "0.4.0",
439
+ "rightkit-framed-sidecar": "0.2.0",
440
+ "rightkit-fs": "0.4.0",
441
+ "rightkit-fsindex": "0.2.1",
442
+ "rightkit-hotkeys": "0.1.0",
443
+ "rightkit-http": "0.3.0",
444
+ "rightkit-job-queue": "0.3.1",
445
+ "rightkit-jobs": "0.3.0",
446
+ "rightkit-license": "0.2.0",
447
+ "rightkit-llm": "0.2.1",
448
+ "rightkit-logs": "0.3.0",
403
449
  "rightkit-mcp": "0.5.3",
404
- "rightkit-media": "0.2.5",
405
- "rightkit-models": "0.2.8",
406
- "rightkit-oauth": "0.3.1",
407
- "rightkit-ocr": "0.2.0",
408
- "rightkit-ort": "0.2.2",
450
+ "rightkit-media": "0.2.6",
451
+ "rightkit-models": "0.3.1",
452
+ "rightkit-oauth": "0.5.0",
453
+ "rightkit-ocr": "0.2.2",
454
+ "rightkit-onnx": "0.2.3",
455
+ "rightkit-ort": "0.2.3",
456
+ "rightkit-overlay": "0.1.1",
409
457
  "rightkit-ownership": "0.2.1",
410
- "rightkit-pdf": "0.2.0",
411
- "rightkit-playback": "0.1.1",
412
- "rightkit-process": "0.3.3",
413
- "rightkit-qa": "0.2.14",
414
- "rightkit-qts": "0.2.5",
458
+ "rightkit-pdf": "0.3.0",
459
+ "rightkit-playback": "0.2.1",
460
+ "rightkit-process": "0.4.0",
461
+ "rightkit-qa": "0.3.0",
462
+ "rightkit-qa-driver": "0.3.1",
463
+ "rightkit-qts": "0.2.6",
415
464
  "rightkit-qts-ggml": "0.1.2",
416
465
  "rightkit-qts-ggml-sys": "0.1.2",
417
- "rightkit-sandbox": "0.3.4",
418
- "rightkit-search": "0.2.0",
419
- "rightkit-secrets": "0.1.3",
466
+ "rightkit-review": "0.2.0",
467
+ "rightkit-sandbox": "0.4.0",
468
+ "rightkit-search": "0.2.1",
469
+ "rightkit-secrets": "0.2.0",
470
+ "rightkit-send": "0.1.0",
420
471
  "rightkit-service": "0.1.4",
421
- "rightkit-settings": "0.1.1",
422
- "rightkit-shell": "0.2.0",
423
- "rightkit-speech-client": "0.3.3",
424
- "rightkit-tauri": "0.1.2",
425
- "rightkit-transcript": "0.2.0",
426
- "rightkit-tts": "0.1.1",
427
- "rightkit-vad": "0.0.3",
428
- "rightkit-watch": "0.3.1"
472
+ "rightkit-settings": "0.2.0",
473
+ "rightkit-shell": "0.3.0",
474
+ "rightkit-sidecar": "0.2.0",
475
+ "rightkit-speech-client": "0.3.5",
476
+ "rightkit-sync": "0.1.1",
477
+ "rightkit-tauri": "0.1.3",
478
+ "rightkit-tauri-shell": "0.3.0",
479
+ "rightkit-transcript": "0.3.0",
480
+ "rightkit-tts": "0.2.1",
481
+ "rightkit-tts-qwen": "0.2.6",
482
+ "rightkit-tts-qwen-sys": "0.1.2",
483
+ "rightkit-vad": "0.1.1",
484
+ "rightkit-watch": "0.4.0",
485
+ "rightkit-workflow": "0.1.0"
429
486
  },
430
487
  "npm": {
431
488
  "@rightkit/app-shell": "0.6.2",
432
- "@rightkit/ax": "0.2.4",
489
+ "@rightkit/app-update": "0.2.5",
490
+ "@rightkit/ax": "0.3.2",
491
+ "@rightkit/ci": "0.2.43",
433
492
  "@rightkit/doc-render": "0.1.6",
434
493
  "@rightkit/git": "0.2.42",
435
494
  "@rightkit/hooks": "0.1.2",
436
495
  "@rightkit/i18n": "0.1.0",
437
496
  "@rightkit/legal": "0.3.1",
438
497
  "@rightkit/legal-ui": "0.2.2",
439
- "@rightkit/license": "0.1.8",
498
+ "@rightkit/license": "0.2.0",
440
499
  "@rightkit/logs": "0.1.4",
441
500
  "@rightkit/media-ui": "0.3.4",
442
- "@rightkit/onboarding": "0.3.2",
501
+ "@rightkit/onboarding": "0.3.3",
502
+ "@rightkit/outdated": "0.2.0",
443
503
  "@rightkit/pdf-ui": "0.1.6",
444
- "@rightkit/platform-ui": "0.2.7",
445
- "@rightkit/qa": "0.4.7",
446
- "@rightkit/qa-chrome": "0.1.5",
447
- "@rightkit/release": "0.2.155",
448
- "@rightkit/settings-ui": "0.4.3",
504
+ "@rightkit/platform-ui": "0.2.8",
505
+ "@rightkit/qa": "0.4.8",
506
+ "@rightkit/qa-chrome": "0.1.6",
507
+ "@rightkit/react-shell": "0.6.4",
508
+ "@rightkit/release": "0.2.156",
509
+ "@rightkit/settings-ui": "0.4.4",
449
510
  "@rightkit/shell": "0.1.1",
450
- "@rightkit/tauri": "0.2.0",
511
+ "@rightkit/tauri": "0.2.1",
512
+ "@rightkit/tauri-shell": "0.1.1",
451
513
  "@rightkit/theme": "0.2.3",
452
514
  "@rightkit/updates": "0.2.5"
453
515
  }
@@ -459,7 +521,8 @@
459
521
  "rightkit-browser": [
460
522
  "0.2.0",
461
523
  "0.2.1",
462
- "0.2.2"
524
+ "0.2.2",
525
+ "0.3.0"
463
526
  ],
464
527
  "rightkit-models": [
465
528
  "0.2.1",
@@ -468,12 +531,14 @@
468
531
  "0.2.4",
469
532
  "0.2.5",
470
533
  "0.2.6",
471
- "0.2.7"
534
+ "0.2.7",
535
+ "0.3.0"
472
536
  ],
473
537
  "rightkit-audio": [
474
538
  "0.1.0",
475
539
  "0.1.1",
476
- "0.2.0"
540
+ "0.2.0",
541
+ "0.2.2"
477
542
  ],
478
543
  "rightkit-db": [
479
544
  "0.2.1",
@@ -484,7 +549,8 @@
484
549
  "0.2.1",
485
550
  "0.2.2",
486
551
  "0.3.0",
487
- "0.3.1"
552
+ "0.3.1",
553
+ "0.3.2"
488
554
  ],
489
555
  "rightkit-jobs": [
490
556
  "0.2.1",
@@ -512,7 +578,8 @@
512
578
  "rightkit-oauth": [
513
579
  "0.2.0",
514
580
  "0.2.1",
515
- "0.3.0"
581
+ "0.3.0",
582
+ "0.4.0"
516
583
  ],
517
584
  "rightkit-ort": [
518
585
  "0.1.4",
@@ -521,7 +588,8 @@
521
588
  ],
522
589
  "rightkit-playback": [
523
590
  "0.1.0",
524
- "0.1.1"
591
+ "0.1.1",
592
+ "0.2.0"
525
593
  ],
526
594
  "rightkit-process": [
527
595
  "0.2.1",
@@ -536,7 +604,8 @@
536
604
  "0.2.10",
537
605
  "0.2.11",
538
606
  "0.2.12",
539
- "0.2.14"
607
+ "0.2.14",
608
+ "0.2.16"
540
609
  ],
541
610
  "rightkit-sandbox": [
542
611
  "0.1.0",
@@ -548,7 +617,8 @@
548
617
  "0.3.0",
549
618
  "0.3.1",
550
619
  "0.3.2",
551
- "0.3.3"
620
+ "0.3.3",
621
+ "0.3.5"
552
622
  ],
553
623
  "rightkit-shell": [
554
624
  "0.1.0",
@@ -620,27 +690,33 @@
620
690
  "rightkit-speech-client": [
621
691
  "0.3.0",
622
692
  "0.3.1",
623
- "0.3.2"
693
+ "0.3.2",
694
+ "0.3.4"
624
695
  ],
625
696
  "rightkit-crash": [
626
697
  "0.1.0",
627
- "0.2.0"
698
+ "0.2.0",
699
+ "0.2.2"
628
700
  ],
629
701
  "rightkit-qts-ggml-sys": [
630
702
  "0.1.0",
631
703
  "0.1.1"
632
704
  ],
633
705
  "rightkit-fsindex": [
634
- "0.1.0"
706
+ "0.1.0",
707
+ "0.2.0"
635
708
  ],
636
709
  "rightkit-asr": [
637
- "0.0.2"
710
+ "0.0.2",
711
+ "0.2.0"
638
712
  ],
639
713
  "rightkit-logs": [
640
- "0.2.0"
714
+ "0.2.0",
715
+ "0.2.2"
641
716
  ],
642
717
  "rightkit-ocr": [
643
- "0.1.2"
718
+ "0.1.2",
719
+ "0.2.1"
644
720
  ],
645
721
  "rightkit-settings": [
646
722
  "0.1.0"
@@ -649,13 +725,26 @@
649
725
  "0.1.0"
650
726
  ],
651
727
  "rightkit-vad": [
652
- "0.0.2"
728
+ "0.0.2",
729
+ "0.1.0"
653
730
  ],
654
731
  "rightkit-tts": [
655
- "0.1.0"
732
+ "0.1.0",
733
+ "0.2.0"
656
734
  ],
657
735
  "rightkit-llm": [
658
- "0.1.0"
736
+ "0.1.0",
737
+ "0.2.0"
738
+ ],
739
+ "rightkit-daemon": [
740
+ "0.2.0",
741
+ "0.2.1"
742
+ ],
743
+ "rightkit-job-queue": [
744
+ "0.3.0"
745
+ ],
746
+ "rightkit-qa-driver": [
747
+ "0.3.0"
659
748
  ]
660
749
  }
661
750
  }
@@ -1,4 +1,33 @@
1
1
  {
2
2
  "schema": 1,
3
- "heldResource": {}
3
+ "heldResource": {
4
+ "rightkit-asr": {
5
+ "ceilings": null,
6
+ "requiredScale": null
7
+ },
8
+ "rightkit-audio": {
9
+ "ceilings": null,
10
+ "requiredScale": null
11
+ },
12
+ "rightkit-browser": {
13
+ "ceilings": null,
14
+ "requiredScale": null
15
+ },
16
+ "rightkit-embed": {
17
+ "ceilings": null,
18
+ "requiredScale": null
19
+ },
20
+ "rightkit-ocr": {
21
+ "ceilings": null,
22
+ "requiredScale": null
23
+ },
24
+ "rightkit-sandbox": {
25
+ "ceilings": null,
26
+ "requiredScale": null
27
+ },
28
+ "rightkit-vad": {
29
+ "ceilings": null,
30
+ "requiredScale": null
31
+ }
32
+ }
4
33
  }