@spexcode/spec-cli 0.7.0-next.4 → 0.7.0-next.5
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.
|
@@ -46,6 +46,10 @@ export declare function prepareCodexGenerationClose(root: string, sessionId: str
|
|
|
46
46
|
export declare function repinCodexGeneration(root: string, sessionId: string, threadId: string, generationId: string): void;
|
|
47
47
|
export declare function resolveCodexGenerationForResume(root: string, sessionId: string, threadId: string, start: (endpoint: CodexGenerationEndpoint) => Promise<void>): Promise<CodexGenerationEndpoint | null>;
|
|
48
48
|
export declare function resolveCodexGenerationForSession(root: string, sessionId: string, threadId: string): CodexGenerationEndpoint | null;
|
|
49
|
+
export declare function resolveCodexGenerationForClose(root: string, sessionId: string, threadId: string): {
|
|
50
|
+
endpoint: CodexGenerationEndpoint;
|
|
51
|
+
gone: boolean;
|
|
52
|
+
} | null;
|
|
49
53
|
export declare function codexGenerationBindingForSession(root: string, sessionId: string): CodexGenerationBinding | null;
|
|
50
54
|
export declare function currentCodexGeneration(root: string): CodexGenerationEndpoint | null;
|
|
51
55
|
export declare function codexGenerationEndpoints(root: string): CodexGenerationEndpoint[];
|
|
@@ -765,6 +765,18 @@ export function resolveCodexGenerationForSession(root, sessionId, threadId) {
|
|
|
765
765
|
const generation = ledger.generations[binding.generationId];
|
|
766
766
|
return generation && generation.state !== 'reclaimed' ? generation.endpoint : null;
|
|
767
767
|
}
|
|
768
|
+
// Close still needs the immutable endpoint record to recognize a positively retired generation. The
|
|
769
|
+
// endpoint is never used for native I/O in this state; it only identifies the empty control plane.
|
|
770
|
+
export function resolveCodexGenerationForClose(root, sessionId, threadId) {
|
|
771
|
+
const ledger = readCodexGenerationLedger(root);
|
|
772
|
+
const binding = ledger.bindings[sessionId];
|
|
773
|
+
if (!binding || binding.threadId !== threadId)
|
|
774
|
+
return null;
|
|
775
|
+
const generation = ledger.generations[binding.generationId];
|
|
776
|
+
if (!generation)
|
|
777
|
+
return null;
|
|
778
|
+
return { endpoint: generation.endpoint, gone: generation.state === 'reclaimed' };
|
|
779
|
+
}
|
|
768
780
|
export function codexGenerationBindingForSession(root, sessionId) {
|
|
769
781
|
return readCodexGenerationLedger(root).bindings[sessionId] ?? null;
|
|
770
782
|
}
|
package/dist/harness.js
CHANGED
|
@@ -18,7 +18,7 @@ import { runtimeRoot, mainCheckout, readConfig, sessionArtifactPath, spexcodeHom
|
|
|
18
18
|
import { git } from '@spexcode/spec-core';
|
|
19
19
|
import { shQuote } from './sh.js';
|
|
20
20
|
import { detachedRuntimeGenerationToken, migrateLegacyDetachedRuntimeReceipt, processStartToken, verifyDetachedRuntime } from '@spexcode/spec-core';
|
|
21
|
-
import { codexGenerationEndpoints, codexGenerationSocketPath, currentCodexGeneration, legacyCodexGenerationEndpoint, readCodexGenerationLedger, resolveCodexGenerationForSession } from './codex-runtime-generations.js';
|
|
21
|
+
import { codexGenerationEndpoints, codexGenerationSocketPath, currentCodexGeneration, legacyCodexGenerationEndpoint, readCodexGenerationLedger, prepareCodexGenerationClose, resolveCodexGenerationForClose, resolveCodexGenerationForSession } from './codex-runtime-generations.js';
|
|
22
22
|
import { writeFileIfChanged } from './file-write.js';
|
|
23
23
|
import { claudeTranscript, codexRolloutPath, codexTranscript, opencodeTranscript, piTranscript, unsupportedTranscript } from '@spexcode/transcript';
|
|
24
24
|
import { harnessIdentity, HARNESS_IDENTITIES } from '@spexcode/spec-core';
|
|
@@ -220,12 +220,14 @@ function codexMutationGeneration(dir = runtimeRoot(), endpoint = legacyCodexGene
|
|
|
220
220
|
return codexRuntimeGeneration(dir, endpoint);
|
|
221
221
|
}
|
|
222
222
|
const codexDescriptorKey = (endpoint) => endpoint.id === 'legacy' ? 'codex-app-server' : `codex-app-server:${endpoint.id}`;
|
|
223
|
-
function codexEndpointForRecord(rec, dir = runtimeRoot()) {
|
|
223
|
+
function codexEndpointForRecord(rec, dir = runtimeRoot(), includeGone = false) {
|
|
224
224
|
if (!rec.harnessSessionId)
|
|
225
225
|
return null;
|
|
226
226
|
const ledger = readCodexGenerationLedger(dir);
|
|
227
227
|
if (ledger.revision === 0 && !ledger.current && !Object.keys(ledger.generations).length)
|
|
228
228
|
return legacyCodexGenerationEndpoint(dir);
|
|
229
|
+
if (includeGone)
|
|
230
|
+
return resolveCodexGenerationForClose(dir, rec.session, rec.harnessSessionId)?.endpoint ?? null;
|
|
229
231
|
return resolveCodexGenerationForSession(dir, rec.session, rec.harnessSessionId);
|
|
230
232
|
}
|
|
231
233
|
// the spex launcher (bin/spex.mjs), baked into the codex launch script (mirrors materialize.ts's SPEX) so
|
|
@@ -3028,7 +3030,7 @@ export const codexHarness = {
|
|
|
3028
3030
|
interrupt: interruptCodexTurn,
|
|
3029
3031
|
cleanupRuntime: async () => { },
|
|
3030
3032
|
targetDescriptorKey: (rec) => {
|
|
3031
|
-
const endpoint = codexEndpointForRecord(rec);
|
|
3033
|
+
const endpoint = codexEndpointForRecord(rec, runtimeRoot(), true);
|
|
3032
3034
|
return endpoint ? codexDescriptorKey(endpoint) : null;
|
|
3033
3035
|
},
|
|
3034
3036
|
coldRetirementPreflight: async (rec) => {
|
|
@@ -3052,8 +3054,13 @@ export const codexHarness = {
|
|
|
3052
3054
|
coldPreflight: async (rec) => {
|
|
3053
3055
|
if (!rec.harnessSessionId)
|
|
3054
3056
|
return { ok: false, reason: 'no exact Codex thread identity is registered' };
|
|
3055
|
-
const
|
|
3056
|
-
|
|
3057
|
+
const dir = runtimeRoot();
|
|
3058
|
+
const binding = resolveCodexGenerationForClose(dir, rec.session, rec.harnessSessionId);
|
|
3059
|
+
if (binding?.gone) {
|
|
3060
|
+
return { ok: true, alreadyCold: true };
|
|
3061
|
+
}
|
|
3062
|
+
const endpoint = binding?.endpoint ?? codexEndpointForRecord(rec, dir);
|
|
3063
|
+
return endpoint ? codexColdPreflight(rec.harnessSessionId, dir, undefined, endpoint)
|
|
3057
3064
|
: { ok: false, reason: 'no exact Codex generation binding is registered for this target' };
|
|
3058
3065
|
},
|
|
3059
3066
|
coldRuntime: async (rec, suppliedReceipt) => {
|
|
@@ -3061,7 +3068,12 @@ export const codexHarness = {
|
|
|
3061
3068
|
return { ok: false, reason: 'no exact Codex thread identity is registered' };
|
|
3062
3069
|
const threadId = rec.harnessSessionId;
|
|
3063
3070
|
const dir = runtimeRoot();
|
|
3064
|
-
const
|
|
3071
|
+
const binding = resolveCodexGenerationForClose(dir, rec.session, threadId);
|
|
3072
|
+
if (binding?.gone) {
|
|
3073
|
+
prepareCodexGenerationClose(dir, rec.session, threadId);
|
|
3074
|
+
return { ok: true };
|
|
3075
|
+
}
|
|
3076
|
+
const endpoint = binding?.endpoint ?? codexEndpointForRecord(rec, dir);
|
|
3065
3077
|
if (!endpoint)
|
|
3066
3078
|
return { ok: false, reason: 'no exact Codex generation binding is registered for this target' };
|
|
3067
3079
|
const sock = endpoint.socketPath;
|
package/dist/host-resources.js
CHANGED
|
@@ -471,6 +471,17 @@ const sessionStopBlocker = async (id, harnessId, recs = rawRecords(), knownProbe
|
|
|
471
471
|
const entryTargetThread = entry.recs.find((rec) => rec.session_id === id)?.harness_session_id;
|
|
472
472
|
if (entryTargetThread && ownerCounts.get(entryTargetThread) !== 1)
|
|
473
473
|
return `${descriptor.label} target thread ${entryTargetThread} has no one exact governed session owner`;
|
|
474
|
+
// A retired shared generation is positive death, not an unknown control plane. Its residency census is
|
|
475
|
+
// the only proof needed here; there is no native target left to signal or unload.
|
|
476
|
+
if (descriptor.residency && entryTargetThread) {
|
|
477
|
+
let residency = null;
|
|
478
|
+
try {
|
|
479
|
+
residency = await descriptor.residency();
|
|
480
|
+
}
|
|
481
|
+
catch { /* retain the normal fail-closed path */ }
|
|
482
|
+
if (residency?.healthy && residency.rootAbsent === true && residency.referenceIds.length === 0)
|
|
483
|
+
continue;
|
|
484
|
+
}
|
|
474
485
|
if (!knownProbes && descriptor.mutationGuard) {
|
|
475
486
|
if (!targetThread)
|
|
476
487
|
return `${descriptor.label} target has no exact governed thread identity`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spexcode/spec-cli",
|
|
3
|
-
"version": "0.7.0-next.
|
|
3
|
+
"version": "0.7.0-next.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "SpexCode CLI + server. The root spexcode package delegates to this compiled package; dashboard assets live in @spexcode/spec-dashboard.",
|
|
6
6
|
"bin": {
|
|
@@ -35,12 +35,12 @@
|
|
|
35
35
|
"test": "tsx --import ../scripts/test-home.mjs --test src/*.test.ts"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@spexcode/session-application": "0.7.0-next.
|
|
39
|
-
"@spexcode/session-selflaunch": "0.7.0-next.
|
|
40
|
-
"@spexcode/spec-core": "0.7.0-next.
|
|
41
|
-
"@spexcode/spec-eval": "0.7.0-next.
|
|
42
|
-
"@spexcode/spec-forge": "0.7.0-next.
|
|
43
|
-
"@spexcode/transcript": "0.7.0-next.
|
|
38
|
+
"@spexcode/session-application": "0.7.0-next.5",
|
|
39
|
+
"@spexcode/session-selflaunch": "0.7.0-next.5",
|
|
40
|
+
"@spexcode/spec-core": "0.7.0-next.5",
|
|
41
|
+
"@spexcode/spec-eval": "0.7.0-next.5",
|
|
42
|
+
"@spexcode/spec-forge": "0.7.0-next.5",
|
|
43
|
+
"@spexcode/transcript": "0.7.0-next.5",
|
|
44
44
|
"smol-toml": "^1.8.0"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|