@indigoai-us/hq-cli 5.345.65 → 5.345.67
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/CHANGELOG.md +10 -0
- package/dist/commands/lanes-session-start.js +72 -4
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [5.345.67] — 2026-10-09
|
|
6
|
+
|
|
7
|
+
- Persist the Codex SessionStart model and effort for conduct lanes, with safe fallback defaults.
|
|
8
|
+
|
|
9
|
+
- Native core families go back to their strict readers from 5.345.65. In 5.345.66, a process with no company context ignored the flag registry and ran every native family, so the registry kill switch could not turn a family off on most machines.
|
|
10
|
+
|
|
11
|
+
## [5.345.66] — 2026-10-09
|
|
12
|
+
- Native core families now run by default when the machine has no flag snapshot (including first-run and offline cases); explicit false in a fresh or stale snapshot remains the kill switch. Only the seven approved core-native families use default-on readers. Delegate and worker-skills keep strict default-off readers pending parity follow-ups, and other fast-route families such as hook-batch also remain on the strict reader.
|
|
13
|
+
- The Windows fast-route shell fallback now converts bundled script paths to Git Bash paths, so the family kill switch can reach its shell companion.
|
|
14
|
+
|
|
5
15
|
## [5.345.65] — 2026-10-09
|
|
6
16
|
- Reject unsafe lane and child ids before they reach inbox or state paths.
|
|
7
17
|
|
|
@@ -6,6 +6,74 @@ import { randomUUID } from "node:crypto";
|
|
|
6
6
|
import { resolveLanesHqRoot } from "../lib/lanes/hq-root.js";
|
|
7
7
|
import { readLanesRegistryFlagFailOpen } from "../lib/lanes/registry-flag.js";
|
|
8
8
|
import { LANE_CONDUCT_SESSION_START_FLAG } from "../lib/lanes/flag-keys.js";
|
|
9
|
+
const CODEX_DEFAULT_KEYS = ["conduct_engine", "conduct_child_model", "conduct_child_effort", "conduct_default_source"];
|
|
10
|
+
function readSessionMetaValue(text, key) {
|
|
11
|
+
const line = text.split(/\r?\n/).find((entry) => new RegExp(`^\\s*${key}:`).test(entry));
|
|
12
|
+
if (!line)
|
|
13
|
+
return "";
|
|
14
|
+
const value = line.replace(/^\s*[^:]+:\s*/, "");
|
|
15
|
+
return value.replace(/^"|"$/g, "");
|
|
16
|
+
}
|
|
17
|
+
function writeCodexSessionDefaults(root, env, payload, debug) {
|
|
18
|
+
if (env.HQ_HARNESS !== "codex")
|
|
19
|
+
return;
|
|
20
|
+
const sessionId = payload.session_id ?? payload.sessionId;
|
|
21
|
+
if (!sessionId || !/^[A-Za-z0-9._-]+$/.test(sessionId) || sessionId === "." || sessionId === "..")
|
|
22
|
+
return;
|
|
23
|
+
let model = typeof payload.model === "string" ? payload.model : "";
|
|
24
|
+
if (/\s/.test(model))
|
|
25
|
+
model = "";
|
|
26
|
+
let effort = payload.reasoning_effort ?? payload.reasoningEffort ?? payload.effort ?? "";
|
|
27
|
+
if (typeof effort !== "string" || !/^[a-z]+$/.test(effort))
|
|
28
|
+
effort = "";
|
|
29
|
+
try {
|
|
30
|
+
const sessionDir = path.join(root, "workspace", "sessions", sessionId);
|
|
31
|
+
const metaPath = path.join(sessionDir, "meta.yaml");
|
|
32
|
+
fs.mkdirSync(sessionDir, { recursive: true });
|
|
33
|
+
let text = "";
|
|
34
|
+
try {
|
|
35
|
+
text = fs.readFileSync(metaPath, "utf8");
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
if (error.code !== "ENOENT")
|
|
39
|
+
throw error;
|
|
40
|
+
}
|
|
41
|
+
if (CODEX_DEFAULT_KEYS.some((key) => readSessionMetaValue(text, key) !== ""))
|
|
42
|
+
return;
|
|
43
|
+
if (!text) {
|
|
44
|
+
text = `session_id: ${sessionId}\nstarted_at: "${new Date().toISOString().replace(/\.\d{3}Z$/, "Z")}"\nsenior: user\n`;
|
|
45
|
+
}
|
|
46
|
+
const defaults = {
|
|
47
|
+
conduct_engine: "codex",
|
|
48
|
+
conduct_child_model: model || undefined,
|
|
49
|
+
conduct_child_effort: effort || undefined,
|
|
50
|
+
conduct_default_source: model ? "codex-session" : "codex-fallback",
|
|
51
|
+
};
|
|
52
|
+
for (const key of CODEX_DEFAULT_KEYS) {
|
|
53
|
+
const value = defaults[key];
|
|
54
|
+
if (value === undefined)
|
|
55
|
+
continue;
|
|
56
|
+
const matcher = new RegExp(`^\\s*${key}:.*(?:\\r?\\n|$)`, "m");
|
|
57
|
+
const line = `${key}: ${value}\n`;
|
|
58
|
+
text = matcher.test(text) ? text.replace(matcher, line) : `${text}${text.endsWith("\n") || !text ? "" : "\n"}${line}`;
|
|
59
|
+
}
|
|
60
|
+
const tempPath = path.join(sessionDir, `.meta-${process.pid}-${randomUUID()}.tmp`);
|
|
61
|
+
try {
|
|
62
|
+
fs.writeFileSync(tempPath, text, { mode: 0o600 });
|
|
63
|
+
fs.renameSync(tempPath, metaPath);
|
|
64
|
+
}
|
|
65
|
+
finally {
|
|
66
|
+
try {
|
|
67
|
+
fs.rmSync(tempPath, { force: true });
|
|
68
|
+
}
|
|
69
|
+
catch { /* best-effort temp cleanup */ }
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
const kind = error instanceof Error ? error.name : "Error";
|
|
74
|
+
debug(`hq lanes session-start: Codex metadata bootstrap failed (${kind})`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
9
77
|
function enabledFromSettings(root) {
|
|
10
78
|
const personal = path.join(root, "personal", "settings", "orchestrator.yaml");
|
|
11
79
|
const settings = fs.existsSync(personal) ? personal : path.join(root, "core", "settings", "orchestrator.yaml");
|
|
@@ -155,11 +223,10 @@ export async function runLaneSessionStart(options = {}) {
|
|
|
155
223
|
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
156
224
|
const input = Buffer.concat(chunks).toString("utf8");
|
|
157
225
|
let source = "startup";
|
|
158
|
-
let
|
|
226
|
+
let payload = {};
|
|
159
227
|
try {
|
|
160
|
-
|
|
228
|
+
payload = JSON.parse(input);
|
|
161
229
|
source = payload.source || "startup";
|
|
162
|
-
payloadSessionId = payload.session_id;
|
|
163
230
|
}
|
|
164
231
|
catch { /* malformed hook input uses startup default */ }
|
|
165
232
|
if (source !== "startup")
|
|
@@ -179,7 +246,7 @@ export async function runLaneSessionStart(options = {}) {
|
|
|
179
246
|
if (!flagEnabled)
|
|
180
247
|
return;
|
|
181
248
|
(options.startSweep ?? ((r, e) => startSessionStartOrphanSweep(r, e, spawn)))(root, env);
|
|
182
|
-
if (sessionWasDisabled(root, env,
|
|
249
|
+
if (sessionWasDisabled(root, env, payload.session_id ?? payload.sessionId))
|
|
183
250
|
return;
|
|
184
251
|
const autoConduct = env.HQ_AUTO_CONDUCT ?? "";
|
|
185
252
|
const forceOn = /^(1|true|on|yes)$/i.test(autoConduct);
|
|
@@ -192,6 +259,7 @@ export async function runLaneSessionStart(options = {}) {
|
|
|
192
259
|
enabled = true;
|
|
193
260
|
if (!enabled)
|
|
194
261
|
return;
|
|
262
|
+
writeCodexSessionDefaults(root, env, payload, debug);
|
|
195
263
|
const core = path.join(root, ".claude", "skills", "conduct", "conductor-core.md");
|
|
196
264
|
if (!fs.existsSync(core))
|
|
197
265
|
return;
|