@optimuslabs/harness-map-staging 1.5.39 → 1.5.40
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.
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
* Paths and JSON persistence for ~/.optimuslabs/management:
|
|
3
3
|
* - remediation_instructions.json (remediations[])
|
|
4
4
|
*/
|
|
5
|
-
import {
|
|
5
|
+
import { randomBytes } from 'node:crypto';
|
|
6
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, statSync, writeFileSync } from 'node:fs';
|
|
6
7
|
import { dirname, join } from 'node:path';
|
|
7
8
|
import { homedir } from 'node:os';
|
|
8
9
|
import { OPTIMUSLABS_MANAGEMENT_REL, OPTIMUSLABS_LOGS_REL } from '../../bootstrap_constants.js';
|
|
@@ -123,13 +124,23 @@ export function writeFileCollectionVscdbContract(contract) {
|
|
|
123
124
|
return;
|
|
124
125
|
atomicWriteJson(getFileCollectionVscdbContractPath(), sanitized);
|
|
125
126
|
}
|
|
127
|
+
/**
|
|
128
|
+
* Write `data` as JSON to `filePath` in one step: to a temporary file of this write's own, then a
|
|
129
|
+
* rename. Two hooks writing at once (two Claude Code windows, the gate and the compliance runner)
|
|
130
|
+
* each use their own temporary file, so neither can rename the other's half-written one into place.
|
|
131
|
+
*/
|
|
126
132
|
export function atomicWriteJson(filePath, data) {
|
|
127
133
|
const dir = dirname(filePath);
|
|
128
134
|
if (!existsSync(dir))
|
|
129
135
|
mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
130
|
-
const tmp = `${filePath}.tmp`;
|
|
131
|
-
|
|
132
|
-
|
|
136
|
+
const tmp = `${filePath}.${process.pid}.${randomBytes(4).toString('hex')}.tmp`;
|
|
137
|
+
try {
|
|
138
|
+
writeFileSync(tmp, JSON.stringify(data, null, 2), 'utf8');
|
|
139
|
+
renameSync(tmp, filePath);
|
|
140
|
+
}
|
|
141
|
+
finally {
|
|
142
|
+
rmSync(tmp, { force: true });
|
|
143
|
+
}
|
|
133
144
|
}
|
|
134
145
|
function parseInstructionsRaw(raw) {
|
|
135
146
|
try {
|
|
@@ -16,11 +16,16 @@ import { basename } from 'node:path';
|
|
|
16
16
|
import { atomicWriteJson, getSkillBlockProcessesPath, readRemediationInstructionsFile, } from './management_storage.js';
|
|
17
17
|
import { launchAgentAccessWindow } from '../../agent_access/window_runner.js';
|
|
18
18
|
import { quarantinedAt } from './skill_block.js';
|
|
19
|
-
/**
|
|
20
|
-
|
|
19
|
+
/**
|
|
20
|
+
* A process's parent, start time and command name, from `ps`; null when it cannot be read. `ps`
|
|
21
|
+
* writes the start time in the user's language ("Do. 5 Nov." in German), which the pattern below
|
|
22
|
+
* cannot read, so it runs in the C locale.
|
|
23
|
+
*/
|
|
24
|
+
export function processRow(pid) {
|
|
21
25
|
try {
|
|
26
|
+
const options = { encoding: 'utf8', env: { ...process.env, LC_ALL: 'C' } };
|
|
22
27
|
// A fixed command, no shell, and a process id that is always a number.
|
|
23
|
-
const out = execFileSync('ps', ['-o', 'ppid=,lstart=,comm=', '-p', String(pid)],
|
|
28
|
+
const out = execFileSync('ps', ['-o', 'ppid=,lstart=,comm=', '-p', String(pid)], options).trim(); // nosafe: SAFE801
|
|
24
29
|
const row = out.match(/^(\d+)\s+(\S+\s+\S+\s+\d+\s+[\d:]+\s+\d+)\s+(.*)$/);
|
|
25
30
|
return row ? { parent: Number(row[1]), startedAt: Date.parse(row[2]), name: basename(row[3]).toLowerCase() } : null;
|
|
26
31
|
}
|