@jentrix/runner 0.5.20 → 0.5.22
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 +2 -2
- package/dist/chunk-2YTE5PGH.js +7 -0
- package/dist/{chunk-FWAHAHAM.js.map → chunk-2YTE5PGH.js.map} +1 -1
- package/dist/runner-cli.js +2 -2
- package/dist/{session-host-P6W3PH3S.js → session-host-6WPHLGSS.js} +259 -48
- package/dist/session-host-6WPHLGSS.js.map +7 -0
- package/dist/workflow-runner.js +3 -3
- package/package.json +1 -1
- package/dist/chunk-FWAHAHAM.js +0 -7
- package/dist/session-host-P6W3PH3S.js.map +0 -7
package/README.md
CHANGED
|
@@ -132,10 +132,10 @@ Setup:
|
|
|
132
132
|
|
|
133
133
|
| Context loaded up front | Bytes | ≈ Tokens |
|
|
134
134
|
| --- | --- | --- |
|
|
135
|
-
| MCP agent — all 242 tool definitions |
|
|
135
|
+
| MCP agent — all 242 tool definitions | 375 KB | ~101k |
|
|
136
136
|
| CLI agent — `CLI_STANDUP_SYSTEM_PROMPT` only | 2 KB | ~510 |
|
|
137
137
|
|
|
138
|
-
That is a **~
|
|
138
|
+
That is a **~199× smaller** Jentrix-specific up-front context.
|
|
139
139
|
<!-- END GENERATED: mcp-tool-count:agent-token-cost -->
|
|
140
140
|
|
|
141
141
|
Reproduce the two numbers directly:
|
package/dist/runner-cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
RUNNER_VERSION
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-2YTE5PGH.js";
|
|
5
5
|
|
|
6
6
|
// runner-cli.ts
|
|
7
7
|
import { fileURLToPath } from "node:url";
|
|
@@ -219,7 +219,7 @@ async function main(args = process.argv.slice(2)) {
|
|
|
219
219
|
return runConfiguredRunner(args.includes("--once"));
|
|
220
220
|
}
|
|
221
221
|
if (command === "session-run" && (args.includes("--plan-stdin") || args.includes("--plan-file"))) {
|
|
222
|
-
const { runSessionHost } = await import("./session-host-
|
|
222
|
+
const { runSessionHost } = await import("./session-host-6WPHLGSS.js");
|
|
223
223
|
let raw;
|
|
224
224
|
const planFile = valueAfter(args, "--plan-file");
|
|
225
225
|
if (planFile) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
RUNNER_VERSION
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-2YTE5PGH.js";
|
|
4
4
|
import {
|
|
5
5
|
appendHookEvent,
|
|
6
6
|
readHookLines,
|
|
@@ -180,6 +180,126 @@ function serializeSessionEvent(event) {
|
|
|
180
180
|
`;
|
|
181
181
|
}
|
|
182
182
|
|
|
183
|
+
// lib/session-skeleton.ts
|
|
184
|
+
var SKELETON_VERSION = 1;
|
|
185
|
+
var MAX_SKELETON_BYTES = 32 * 1024;
|
|
186
|
+
var MAX_DISTINCT_TOOLS = 100;
|
|
187
|
+
var MAX_TRACKED_FILES = 300;
|
|
188
|
+
var MAX_HOURLY_BUCKETS = 500;
|
|
189
|
+
var MAX_PATH_CHARS = 300;
|
|
190
|
+
var PATH_KEYS = ["file_path", "path", "notebook_path", "filePath"];
|
|
191
|
+
function pathOf(value) {
|
|
192
|
+
if (typeof value !== "string") return null;
|
|
193
|
+
const trimmed = value.trim();
|
|
194
|
+
if (!trimmed || /^[a-z][a-z0-9+.-]*:\/\//i.test(trimmed)) return null;
|
|
195
|
+
return trimmed.slice(0, MAX_PATH_CHARS);
|
|
196
|
+
}
|
|
197
|
+
var SessionSkeleton = class {
|
|
198
|
+
constructor(provider) {
|
|
199
|
+
this.provider = provider;
|
|
200
|
+
}
|
|
201
|
+
provider;
|
|
202
|
+
turns = 0;
|
|
203
|
+
firstEventAt = null;
|
|
204
|
+
lastEventAt = null;
|
|
205
|
+
eventCounts = /* @__PURE__ */ new Map();
|
|
206
|
+
toolCounts = /* @__PURE__ */ new Map();
|
|
207
|
+
files = /* @__PURE__ */ new Set();
|
|
208
|
+
filesOverflow = 0;
|
|
209
|
+
hourly = /* @__PURE__ */ new Map();
|
|
210
|
+
coalesced = false;
|
|
211
|
+
get observedAnything() {
|
|
212
|
+
return this.firstEventAt !== null;
|
|
213
|
+
}
|
|
214
|
+
/** Feed one REDACTED observed event. Pure accumulation, never throws. */
|
|
215
|
+
observe(event) {
|
|
216
|
+
this.eventCounts.set(
|
|
217
|
+
event.kind,
|
|
218
|
+
(this.eventCounts.get(event.kind) ?? 0) + 1
|
|
219
|
+
);
|
|
220
|
+
if (event.kind === "user_message") this.turns += 1;
|
|
221
|
+
if (this.firstEventAt === null) this.firstEventAt = event.at;
|
|
222
|
+
this.lastEventAt = event.at;
|
|
223
|
+
const hour = event.at.slice(0, 13);
|
|
224
|
+
if (this.hourly.has(hour) || this.hourly.size < MAX_HOURLY_BUCKETS) {
|
|
225
|
+
this.hourly.set(hour, (this.hourly.get(hour) ?? 0) + 1);
|
|
226
|
+
} else {
|
|
227
|
+
this.coalesced = true;
|
|
228
|
+
}
|
|
229
|
+
const payload = event.payload ?? {};
|
|
230
|
+
if (event.kind === "tool_call") {
|
|
231
|
+
const name = typeof payload.name === "string" && payload.name.trim() ? payload.name.trim().slice(0, 120) : "(unnamed)";
|
|
232
|
+
if (this.toolCounts.has(name) || this.toolCounts.size < MAX_DISTINCT_TOOLS) {
|
|
233
|
+
this.toolCounts.set(name, (this.toolCounts.get(name) ?? 0) + 1);
|
|
234
|
+
} else {
|
|
235
|
+
this.coalesced = true;
|
|
236
|
+
this.toolCounts.set(
|
|
237
|
+
"(other)",
|
|
238
|
+
(this.toolCounts.get("(other)") ?? 0) + 1
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
const input = payload.input;
|
|
242
|
+
if (input && typeof input === "object" && !Array.isArray(input)) {
|
|
243
|
+
for (const key of PATH_KEYS) {
|
|
244
|
+
const path = pathOf(input[key]);
|
|
245
|
+
if (path) this.touch(path);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
if (event.kind === "file_change") {
|
|
250
|
+
const changes = payload.changes;
|
|
251
|
+
if (Array.isArray(changes)) {
|
|
252
|
+
for (const change of changes) {
|
|
253
|
+
const path = pathOf(change?.path);
|
|
254
|
+
if (path) this.touch(path);
|
|
255
|
+
}
|
|
256
|
+
} else if (changes && typeof changes === "object") {
|
|
257
|
+
for (const key of Object.keys(changes)) {
|
|
258
|
+
const path = pathOf(key);
|
|
259
|
+
if (path) this.touch(path);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
touch(path) {
|
|
265
|
+
if (this.files.has(path)) return;
|
|
266
|
+
if (this.files.size >= MAX_TRACKED_FILES) {
|
|
267
|
+
this.filesOverflow += 1;
|
|
268
|
+
this.coalesced = true;
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
this.files.add(path);
|
|
272
|
+
}
|
|
273
|
+
/** The bounded v1 JSON. ≤ 32 KB serialized — file-list tail drops first. */
|
|
274
|
+
snapshot() {
|
|
275
|
+
const build = (paths2, listTruncated2) => ({
|
|
276
|
+
version: SKELETON_VERSION,
|
|
277
|
+
provider: this.provider,
|
|
278
|
+
turns: this.turns,
|
|
279
|
+
firstEventAt: this.firstEventAt,
|
|
280
|
+
lastEventAt: this.lastEventAt,
|
|
281
|
+
eventCounts: Object.fromEntries(this.eventCounts),
|
|
282
|
+
toolCounts: Object.fromEntries(this.toolCounts),
|
|
283
|
+
filesTouched: {
|
|
284
|
+
total: this.files.size + this.filesOverflow,
|
|
285
|
+
paths: paths2,
|
|
286
|
+
...listTruncated2 ? { listTruncated: true } : {}
|
|
287
|
+
},
|
|
288
|
+
hourlyBuckets: Object.fromEntries(this.hourly),
|
|
289
|
+
...this.coalesced || listTruncated2 ? { truncated: true } : {}
|
|
290
|
+
});
|
|
291
|
+
let paths = [...this.files];
|
|
292
|
+
let listTruncated = this.filesOverflow > 0;
|
|
293
|
+
let skeleton = build(paths, listTruncated);
|
|
294
|
+
while (Buffer.byteLength(JSON.stringify(skeleton), "utf8") > MAX_SKELETON_BYTES && paths.length > 0) {
|
|
295
|
+
paths = paths.slice(0, Math.max(0, Math.floor(paths.length / 2)));
|
|
296
|
+
listTruncated = true;
|
|
297
|
+
skeleton = build(paths, listTruncated);
|
|
298
|
+
}
|
|
299
|
+
return skeleton;
|
|
300
|
+
}
|
|
301
|
+
};
|
|
302
|
+
|
|
183
303
|
// lib/session-usage.ts
|
|
184
304
|
function insideOneRange(ranges, from, to) {
|
|
185
305
|
return ranges.some((r) => r.from <= from && to <= r.to);
|
|
@@ -362,6 +482,7 @@ var HEARTBEAT_MIN_INTERVAL_MS = 3e4;
|
|
|
362
482
|
var SessionBridge = class {
|
|
363
483
|
constructor(deps) {
|
|
364
484
|
this.deps = deps;
|
|
485
|
+
this.skeleton = deps.collectSkeleton === false ? null : new SessionSkeleton(deps.provider);
|
|
365
486
|
}
|
|
366
487
|
deps;
|
|
367
488
|
sequence = 0;
|
|
@@ -393,6 +514,13 @@ var SessionBridge = class {
|
|
|
393
514
|
* session keeps its telemetry and loses what it actually concluded).
|
|
394
515
|
*/
|
|
395
516
|
lastAssistantMessage = null;
|
|
517
|
+
/**
|
|
518
|
+
* Session evidence floor (PRD §4): the v1 activity skeleton, accumulated
|
|
519
|
+
* from every REDACTED event this bridge records — capture-off included —
|
|
520
|
+
* and submitted on the existing heartbeats plus the forced beat at close.
|
|
521
|
+
* Null when the operator opted out at align (D3).
|
|
522
|
+
*/
|
|
523
|
+
skeleton;
|
|
396
524
|
/**
|
|
397
525
|
* True after a heartbeat came back 409 SESSION_NOT_ACTIVE — the session is
|
|
398
526
|
* terminal server-side. The watch host uses this as its end signal when no
|
|
@@ -463,6 +591,7 @@ var SessionBridge = class {
|
|
|
463
591
|
this.deps.redactor.text(serializeSessionEvent(full))
|
|
464
592
|
);
|
|
465
593
|
}
|
|
594
|
+
this.skeleton?.observe(full);
|
|
466
595
|
if (full.kind === "assistant_message") {
|
|
467
596
|
const text2 = full.payload?.text;
|
|
468
597
|
if (typeof text2 === "string" && text2.trim().length > 0) {
|
|
@@ -601,7 +730,12 @@ var SessionBridge = class {
|
|
|
601
730
|
// Sent only once a receipt has actually been observed — an empty
|
|
602
731
|
// rollup would overwrite the session's totals with nulls and
|
|
603
732
|
// report UNAVAILABLE for a session that had already reported.
|
|
604
|
-
...this.receipts.length > 0 ? { usage: this.usageRollup() } : {}
|
|
733
|
+
...this.receipts.length > 0 ? { usage: this.usageRollup() } : {},
|
|
734
|
+
// Evidence floor (PRD §4/D2): the bounded activity skeleton rides
|
|
735
|
+
// the same beat (tolerant server parse — an old server strips the
|
|
736
|
+
// unknown key). Sent only once something was observed: null column
|
|
737
|
+
// means "never observed", never an empty object.
|
|
738
|
+
...this.skeleton?.observedAnything ? { activitySkeleton: this.skeleton.snapshot() } : {}
|
|
605
739
|
})
|
|
606
740
|
}
|
|
607
741
|
);
|
|
@@ -801,6 +935,7 @@ var SessionBridge = class {
|
|
|
801
935
|
*/
|
|
802
936
|
async complete(opts) {
|
|
803
937
|
const { pending } = await this.flushParts();
|
|
938
|
+
await this.flushUsageNow().catch(() => false);
|
|
804
939
|
const finalResponseArtifactId = await this.pushFinalResponse();
|
|
805
940
|
const rollup = this.usageRollup();
|
|
806
941
|
const current = await this.deps.callTool("get_agent_session", {
|
|
@@ -818,6 +953,8 @@ var SessionBridge = class {
|
|
|
818
953
|
endHead: opts.end.head,
|
|
819
954
|
endDirty: opts.end.dirty,
|
|
820
955
|
captureError,
|
|
956
|
+
...opts.acknowledgeEvidenceGaps ? { acknowledgeEvidenceGaps: true } : {},
|
|
957
|
+
...typeof opts.commitCount === "number" ? { commitCount: opts.commitCount } : {},
|
|
821
958
|
...manifest ? { manifest } : {},
|
|
822
959
|
usage: {
|
|
823
960
|
inputTokens: rollup.inputTokens,
|
|
@@ -1230,6 +1367,13 @@ function mapCodexRolloutLine(rawLine) {
|
|
|
1230
1367
|
return { event: null, modelId: null, turn: null };
|
|
1231
1368
|
}
|
|
1232
1369
|
}
|
|
1370
|
+
function lastCodexRolloutModelOf(rollout) {
|
|
1371
|
+
let modelId = null;
|
|
1372
|
+
for (const rawLine of rollout.split("\n")) {
|
|
1373
|
+
modelId = mapCodexRolloutLine(rawLine).modelId ?? modelId;
|
|
1374
|
+
}
|
|
1375
|
+
return modelId;
|
|
1376
|
+
}
|
|
1233
1377
|
|
|
1234
1378
|
// lib/session-codex-hooks.ts
|
|
1235
1379
|
function text(value) {
|
|
@@ -1595,6 +1739,22 @@ function sessionCallTool(mcpUrl, bearerSource, sessionId) {
|
|
|
1595
1739
|
}
|
|
1596
1740
|
};
|
|
1597
1741
|
}
|
|
1742
|
+
function evidenceFloorRefusalOf(error) {
|
|
1743
|
+
const raw = error instanceof Error ? error.message : String(error ?? "");
|
|
1744
|
+
if (!raw.includes("EVIDENCE_FLOOR")) return null;
|
|
1745
|
+
const start = raw.indexOf("{");
|
|
1746
|
+
if (start >= 0) {
|
|
1747
|
+
try {
|
|
1748
|
+
const envelope = JSON.parse(raw.slice(start));
|
|
1749
|
+
const message = envelope.error?.message;
|
|
1750
|
+
if (typeof message === "string" && message.includes("EVIDENCE_FLOOR")) {
|
|
1751
|
+
return message;
|
|
1752
|
+
}
|
|
1753
|
+
} catch {
|
|
1754
|
+
}
|
|
1755
|
+
}
|
|
1756
|
+
return raw;
|
|
1757
|
+
}
|
|
1598
1758
|
function claudeHookSettings(runnerBin, sessionDir) {
|
|
1599
1759
|
const hook = (event) => [
|
|
1600
1760
|
{
|
|
@@ -1664,6 +1824,7 @@ async function runClaudeSessionHost(plan, deps = {}) {
|
|
|
1664
1824
|
callTool: deps.callTool ?? sessionCallTool(plan.mcpUrl, bearerSource, plan.sessionId),
|
|
1665
1825
|
fetchImpl: deps.fetchImpl,
|
|
1666
1826
|
traceCapture,
|
|
1827
|
+
collectSkeleton: plan.collectSkeleton !== false,
|
|
1667
1828
|
log
|
|
1668
1829
|
});
|
|
1669
1830
|
bridge.recordCapabilities(
|
|
@@ -1724,6 +1885,9 @@ async function runClaudeSessionHost(plan, deps = {}) {
|
|
|
1724
1885
|
}
|
|
1725
1886
|
let transcriptPath = watch ? plan.transcriptPath ?? null : null;
|
|
1726
1887
|
let transcriptOffset = 0;
|
|
1888
|
+
let codexTurnId = null;
|
|
1889
|
+
let codexModelId = null;
|
|
1890
|
+
const codexRolloutTurnStarts = /* @__PURE__ */ new Map();
|
|
1727
1891
|
const timing = new ClaudeTimingTracker();
|
|
1728
1892
|
let transcriptSeen = false;
|
|
1729
1893
|
let transcriptWarned = false;
|
|
@@ -1734,18 +1898,29 @@ async function runClaudeSessionHost(plan, deps = {}) {
|
|
|
1734
1898
|
markHostTranscript(sessionDir, true, transcriptPath ?? void 0);
|
|
1735
1899
|
}
|
|
1736
1900
|
};
|
|
1901
|
+
const observePriorCodexModel = (path) => {
|
|
1902
|
+
if (plan.provider !== "codex" || plan.importHistory) return;
|
|
1903
|
+
try {
|
|
1904
|
+
const modelId = lastCodexRolloutModelOf(readFileSync3(path, "utf8"));
|
|
1905
|
+
if (modelId) {
|
|
1906
|
+
codexModelId = modelId;
|
|
1907
|
+
bridge.observeModel(modelId);
|
|
1908
|
+
}
|
|
1909
|
+
} catch {
|
|
1910
|
+
}
|
|
1911
|
+
};
|
|
1737
1912
|
if (watch && transcriptPath && !plan.importHistory) {
|
|
1738
1913
|
try {
|
|
1739
1914
|
transcriptOffset = statSync2(transcriptPath).size;
|
|
1915
|
+
observePriorCodexModel(transcriptPath);
|
|
1740
1916
|
noteTranscriptSeen();
|
|
1741
1917
|
} catch {
|
|
1742
1918
|
}
|
|
1743
1919
|
}
|
|
1744
1920
|
let bound = watch;
|
|
1745
|
-
let codexTurnId = null;
|
|
1746
|
-
let codexModelId = null;
|
|
1747
|
-
const codexRolloutTurnStarts = /* @__PURE__ */ new Map();
|
|
1748
1921
|
let sessionEnded = false;
|
|
1922
|
+
let endAcknowledgeGaps = false;
|
|
1923
|
+
let endCommitCount = null;
|
|
1749
1924
|
let lastPeriodicFlushAt = 0;
|
|
1750
1925
|
let lastPromptAttemptAt = 0;
|
|
1751
1926
|
const promptRedactor = createSessionRedactor({ homedir: homedir() });
|
|
@@ -1823,6 +1998,14 @@ async function runClaudeSessionHost(plan, deps = {}) {
|
|
|
1823
1998
|
const poll = async () => {
|
|
1824
1999
|
const endRequestPath = join3(sessionDir, "end-request.json");
|
|
1825
2000
|
if (!sessionEnded && existsSync(endRequestPath)) {
|
|
2001
|
+
try {
|
|
2002
|
+
const request = JSON.parse(readFileSync3(endRequestPath, "utf8"));
|
|
2003
|
+
endAcknowledgeGaps = request.acknowledgeEvidenceGaps === true;
|
|
2004
|
+
endCommitCount = typeof request.commitCount === "number" ? request.commitCount : null;
|
|
2005
|
+
} catch {
|
|
2006
|
+
endAcknowledgeGaps = false;
|
|
2007
|
+
endCommitCount = null;
|
|
2008
|
+
}
|
|
1826
2009
|
try {
|
|
1827
2010
|
unlinkSync3(endRequestPath);
|
|
1828
2011
|
} catch {
|
|
@@ -1841,6 +2024,7 @@ async function runClaudeSessionHost(plan, deps = {}) {
|
|
|
1841
2024
|
transcriptPath = hookTranscript;
|
|
1842
2025
|
try {
|
|
1843
2026
|
transcriptOffset = plan.importHistory ? 0 : statSync2(transcriptPath).size;
|
|
2027
|
+
observePriorCodexModel(transcriptPath);
|
|
1844
2028
|
noteTranscriptSeen();
|
|
1845
2029
|
} catch {
|
|
1846
2030
|
transcriptOffset = 0;
|
|
@@ -1988,52 +2172,77 @@ async function runClaudeSessionHost(plan, deps = {}) {
|
|
|
1988
2172
|
}
|
|
1989
2173
|
await bridge.maybeHeartbeat();
|
|
1990
2174
|
};
|
|
1991
|
-
|
|
2175
|
+
let timer = setInterval(() => {
|
|
1992
2176
|
void poll();
|
|
1993
2177
|
}, 2e3);
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
(
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2178
|
+
let exitCode = 0;
|
|
2179
|
+
let result = null;
|
|
2180
|
+
for (; ; ) {
|
|
2181
|
+
exitCode = await (watch ? (
|
|
2182
|
+
// Watch mode: live capture beside the operator's own provider process.
|
|
2183
|
+
// End signals: the SessionEnd lifecycle hook, an end request from
|
|
2184
|
+
// `jentrix session end`, or a heartbeat 409 (session terminal
|
|
2185
|
+
// server-side — the out-of-band case the hooks can never deliver).
|
|
2186
|
+
new Promise((resolve) => {
|
|
2187
|
+
const check = setInterval(() => {
|
|
2188
|
+
if (sessionEnded || bridge.sessionInactive) {
|
|
2189
|
+
clearInterval(check);
|
|
2190
|
+
resolve(0);
|
|
2191
|
+
}
|
|
2192
|
+
}, 1e3);
|
|
2193
|
+
})
|
|
2194
|
+
) : new Promise((resolve) => {
|
|
2195
|
+
child.once("error", () => resolve(1));
|
|
2196
|
+
child.once(
|
|
2197
|
+
"exit",
|
|
2198
|
+
(code, signal) => resolve(code ?? (signal ? 130 : 0))
|
|
2199
|
+
);
|
|
2200
|
+
}));
|
|
2201
|
+
clearInterval(timer);
|
|
2202
|
+
await poll().catch(() => void 0);
|
|
2203
|
+
await bridge.flushParts().catch(() => void 0);
|
|
2204
|
+
for (const id of timing.unclosedToolIds()) {
|
|
2205
|
+
bridge.recordUnclosedInterval("tool", id);
|
|
2206
|
+
}
|
|
2207
|
+
for (const id of codexRolloutTurnStarts.keys()) {
|
|
2208
|
+
bridge.recordUnclosedInterval("turn", id);
|
|
2209
|
+
}
|
|
2210
|
+
const end = await endRepoState(plan.repoRoot);
|
|
2211
|
+
let failure = null;
|
|
2212
|
+
result = await bridge.complete({
|
|
2213
|
+
outcome: exitCode === 0 ? "COMPLETED" : "INTERRUPTED",
|
|
2214
|
+
end,
|
|
2215
|
+
acknowledgeEvidenceGaps: endAcknowledgeGaps,
|
|
2216
|
+
commitCount: endCommitCount
|
|
2217
|
+
}).catch((error) => {
|
|
2218
|
+
failure = error;
|
|
2219
|
+
return null;
|
|
2220
|
+
});
|
|
2221
|
+
if (result) break;
|
|
2222
|
+
const refusal = watch ? evidenceFloorRefusalOf(failure) : null;
|
|
2223
|
+
if (refusal) {
|
|
2224
|
+
writeFileSync4(
|
|
2225
|
+
join3(sessionDir, "end-refusal.json"),
|
|
2226
|
+
JSON.stringify({
|
|
2227
|
+
refusedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2228
|
+
message: refusal
|
|
2229
|
+
}),
|
|
2230
|
+
{ mode: 384 }
|
|
2231
|
+
);
|
|
2232
|
+
log(
|
|
2233
|
+
`capture: the close was refused by the evidence floor \u2014 this host (pid ${process.pid}) stays up; push the named evidence and re-run \`jentrix session end ${plan.sessionId}\``
|
|
2234
|
+
);
|
|
2235
|
+
sessionEnded = false;
|
|
2236
|
+
endAcknowledgeGaps = false;
|
|
2237
|
+
endCommitCount = null;
|
|
2238
|
+
timer = setInterval(() => {
|
|
2239
|
+
void poll();
|
|
2240
|
+
}, 2e3);
|
|
2241
|
+
continue;
|
|
2242
|
+
}
|
|
2031
2243
|
log(
|
|
2032
|
-
`capture: completion failed (${
|
|
2244
|
+
`capture: completion failed (${failure instanceof Error ? failure.message : "unknown"}) \u2014 spool retained for retry`
|
|
2033
2245
|
);
|
|
2034
|
-
return null;
|
|
2035
|
-
});
|
|
2036
|
-
if (!result) {
|
|
2037
2246
|
markHostExited(sessionDir, 1);
|
|
2038
2247
|
return 1;
|
|
2039
2248
|
}
|
|
@@ -2066,6 +2275,7 @@ async function runCodexSessionHost(plan, deps = {}) {
|
|
|
2066
2275
|
redactor: createSessionRedactor({ homedir: homedir() }),
|
|
2067
2276
|
callTool: sessionCallTool(plan.mcpUrl, codexBearerSource, plan.sessionId),
|
|
2068
2277
|
fetchImpl: deps.fetchImpl,
|
|
2278
|
+
collectSkeleton: plan.collectSkeleton !== false,
|
|
2069
2279
|
log
|
|
2070
2280
|
});
|
|
2071
2281
|
bridge.recordCapabilities({
|
|
@@ -2196,6 +2406,7 @@ export {
|
|
|
2196
2406
|
appendHookEvent,
|
|
2197
2407
|
claudeHookSettings,
|
|
2198
2408
|
defaultSpoolRoot,
|
|
2409
|
+
evidenceFloorRefusalOf,
|
|
2199
2410
|
readHookLines,
|
|
2200
2411
|
readTranscriptTail,
|
|
2201
2412
|
runClaudeSessionHost,
|
|
@@ -2204,4 +2415,4 @@ export {
|
|
|
2204
2415
|
safeParse,
|
|
2205
2416
|
sessionCallTool
|
|
2206
2417
|
};
|
|
2207
|
-
//# sourceMappingURL=session-host-
|
|
2418
|
+
//# sourceMappingURL=session-host-6WPHLGSS.js.map
|