@claudexor/orchestrator 2.1.2 → 3.0.0
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/dist/attemptTelemetry.d.ts +9 -0
- package/dist/attemptTelemetry.d.ts.map +1 -1
- package/dist/attemptTelemetry.js +25 -0
- package/dist/attemptTelemetry.js.map +1 -1
- package/dist/attemptUsage.d.ts +19 -0
- package/dist/attemptUsage.d.ts.map +1 -0
- package/dist/attemptUsage.js +29 -0
- package/dist/attemptUsage.js.map +1 -0
- package/dist/candidateEvidence.d.ts +22 -0
- package/dist/candidateEvidence.d.ts.map +1 -0
- package/dist/candidateEvidence.js +40 -0
- package/dist/candidateEvidence.js.map +1 -0
- package/dist/candidateOutputs.d.ts +56 -0
- package/dist/candidateOutputs.d.ts.map +1 -0
- package/dist/candidateOutputs.js +209 -0
- package/dist/candidateOutputs.js.map +1 -0
- package/dist/continuity-facts.d.ts +37 -0
- package/dist/continuity-facts.d.ts.map +1 -0
- package/dist/continuity-facts.js +100 -0
- package/dist/continuity-facts.js.map +1 -0
- package/dist/continuity-summary.d.ts +45 -0
- package/dist/continuity-summary.d.ts.map +1 -0
- package/dist/continuity-summary.js +113 -0
- package/dist/continuity-summary.js.map +1 -0
- package/dist/continuity.d.ts +119 -0
- package/dist/continuity.d.ts.map +1 -0
- package/dist/continuity.js +220 -0
- package/dist/continuity.js.map +1 -0
- package/dist/contract-gates.d.ts +2 -3
- package/dist/contract-gates.d.ts.map +1 -1
- package/dist/contract-gates.js +2 -3
- package/dist/contract-gates.js.map +1 -1
- package/dist/council.d.ts +57 -0
- package/dist/council.d.ts.map +1 -0
- package/dist/council.js +98 -0
- package/dist/council.js.map +1 -0
- package/dist/credential-profiles.d.ts +37 -1
- package/dist/credential-profiles.d.ts.map +1 -1
- package/dist/credential-profiles.js +111 -3
- package/dist/credential-profiles.js.map +1 -1
- package/dist/diffReview.d.ts +3 -0
- package/dist/diffReview.d.ts.map +1 -1
- package/dist/diffReview.js +3 -0
- package/dist/diffReview.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/orchestrator.d.ts +218 -62
- package/dist/orchestrator.d.ts.map +1 -1
- package/dist/orchestrator.js +1078 -1236
- package/dist/orchestrator.js.map +1 -1
- package/dist/planQuestions.d.ts +11 -0
- package/dist/planQuestions.d.ts.map +1 -0
- package/dist/planQuestions.js +119 -0
- package/dist/planQuestions.js.map +1 -0
- package/dist/planRun.d.ts +114 -0
- package/dist/planRun.d.ts.map +1 -0
- package/dist/planRun.js +346 -0
- package/dist/planRun.js.map +1 -0
- package/dist/runSupport.d.ts +31 -80
- package/dist/runSupport.d.ts.map +1 -1
- package/dist/runSupport.js +33 -106
- package/dist/runSupport.js.map +1 -1
- package/dist/runTerminals.d.ts.map +1 -1
- package/dist/runTerminals.js +18 -7
- package/dist/runTerminals.js.map +1 -1
- package/package.json +18 -19
- package/dist/orchestrateExecutor.d.ts +0 -43
- package/dist/orchestrateExecutor.d.ts.map +0 -1
- package/dist/orchestrateExecutor.js +0 -207
- package/dist/orchestrateExecutor.js.map +0 -1
- package/dist/orchestratePlanner.d.ts +0 -12
- package/dist/orchestratePlanner.d.ts.map +0 -1
- package/dist/orchestratePlanner.js +0 -91
- package/dist/orchestratePlanner.js.map +0 -1
- package/dist/outcomeReducer.d.ts +0 -25
- package/dist/outcomeReducer.d.ts.map +0 -1
- package/dist/outcomeReducer.js +0 -121
- package/dist/outcomeReducer.js.map +0 -1
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Continuity FACTS (INV-137): the I/O-bearing helpers that feed the pure packet
|
|
3
|
+
* builder (`continuity.ts`) — the active-plan pointer, the git workspace anchor,
|
|
4
|
+
* and the cached-or-fresh LLM summary resolution. Split out of the orchestrator
|
|
5
|
+
* so the engine's chat surface stays under the readability ratchet; each is a
|
|
6
|
+
* free function taking explicit, already-resolved inputs (no orchestrator
|
|
7
|
+
* `this`), so they are directly unit-testable.
|
|
8
|
+
*/
|
|
9
|
+
import { join } from "node:path";
|
|
10
|
+
import { PlanQuestionsArtifact, derivePlanReadiness, } from "@claudexor/schema";
|
|
11
|
+
import { readTextSafe } from "@claudexor/util";
|
|
12
|
+
import { readThreadSummary, revParse, statusPorcelain, writeThreadSummary, } from "@claudexor/workspace";
|
|
13
|
+
import { planContinuation, } from "./continuity.js";
|
|
14
|
+
import { summarizeThreadPrefix } from "./continuity-summary.js";
|
|
15
|
+
/** The thread's most recent readable plan pointer (INV-137 packet section). */
|
|
16
|
+
export function activePlanPointer(priorTurns, store) {
|
|
17
|
+
for (let i = priorTurns.length - 1; i >= 0; i -= 1) {
|
|
18
|
+
const runId = priorTurns[i].runId;
|
|
19
|
+
if (!runId)
|
|
20
|
+
continue;
|
|
21
|
+
const finalDir = store.runPaths(runId).finalDir;
|
|
22
|
+
const planText = readTextSafe(join(finalDir, "plan.md"));
|
|
23
|
+
if (!planText || !planText.trim())
|
|
24
|
+
continue;
|
|
25
|
+
const questions = readTextSafe(join(finalDir, "questions.json"));
|
|
26
|
+
let readiness = "unverified";
|
|
27
|
+
if (questions) {
|
|
28
|
+
try {
|
|
29
|
+
readiness = derivePlanReadiness(PlanQuestionsArtifact.parse(JSON.parse(questions))).state;
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
readiness = "unverified";
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return { path: join(finalDir, "plan.md"), readiness, planRunId: runId };
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
/** HEAD sha + dirty file count for the packet's workspace anchor. Best-effort:
|
|
40
|
+
* a non-git or unborn tree yields a null sha / zero dirty count, never a throw. */
|
|
41
|
+
export async function workspaceAnchor(repoRoot) {
|
|
42
|
+
let headSha = null;
|
|
43
|
+
try {
|
|
44
|
+
headSha = await revParse(repoRoot, "HEAD");
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
headSha = null;
|
|
48
|
+
}
|
|
49
|
+
let dirtyCount = 0;
|
|
50
|
+
try {
|
|
51
|
+
dirtyCount = (await statusPorcelain(repoRoot)).split("\n").filter((l) => l.trim()).length;
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
dirtyCount = 0;
|
|
55
|
+
}
|
|
56
|
+
return { headSha, dirtyCount };
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Resolve the cached-or-fresh LLM summary for a packet's collapsed prefix
|
|
60
|
+
* (INV-137, V9c). Returns the summary to inject, or null when the packet does
|
|
61
|
+
* not collapse, no adapter is available, or summarization fails/times out — in
|
|
62
|
+
* every null case the caller keeps the mechanical one-liner collapse. Owns its
|
|
63
|
+
* OWN try/catch: a summary failure must never drop the whole packet.
|
|
64
|
+
*/
|
|
65
|
+
export async function resolveContinuitySummary(inputs) {
|
|
66
|
+
if (!inputs.threadId)
|
|
67
|
+
return null;
|
|
68
|
+
try {
|
|
69
|
+
const plan = planContinuation(inputs.req);
|
|
70
|
+
// Only a budget-forced collapse needs a summary; nothing to collapse → skip.
|
|
71
|
+
if (plan.kind !== "packet" || !plan.summaryUpToTurnId)
|
|
72
|
+
return null;
|
|
73
|
+
const { threadId, projectRoot } = inputs;
|
|
74
|
+
const upToTurnId = plan.summaryUpToTurnId;
|
|
75
|
+
// Cache hit: reuse until the collapse boundary (upToTurnId) advances.
|
|
76
|
+
const cached = readThreadSummary(projectRoot, threadId, upToTurnId);
|
|
77
|
+
if (cached)
|
|
78
|
+
return { upToTurnId, text: cached };
|
|
79
|
+
if (!inputs.adapter)
|
|
80
|
+
return null;
|
|
81
|
+
const text = await summarizeThreadPrefix({
|
|
82
|
+
adapter: inputs.adapter,
|
|
83
|
+
turns: plan.collapsedPrefix,
|
|
84
|
+
cwd: inputs.cwd,
|
|
85
|
+
env: inputs.laneEnv,
|
|
86
|
+
credentialProfile: inputs.credentialProfile,
|
|
87
|
+
authPreference: inputs.authPreference,
|
|
88
|
+
envInheritance: inputs.envInheritance,
|
|
89
|
+
signal: inputs.signal,
|
|
90
|
+
});
|
|
91
|
+
if (!text)
|
|
92
|
+
return null;
|
|
93
|
+
writeThreadSummary(projectRoot, threadId, upToTurnId, text);
|
|
94
|
+
return { upToTurnId, text };
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=continuity-facts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"continuity-facts.js","sourceRoot":"","sources":["../src/continuity-facts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bounded inline continuation summariser (INV-137, V9c).
|
|
3
|
+
*
|
|
4
|
+
* When a continuation packet must collapse an older prefix and no fresh cached
|
|
5
|
+
* summary covers it, the orchestrator runs ONE bounded read-only summarisation
|
|
6
|
+
* pass over the collapsed turns — ask-mode intent, the thread's primary harness,
|
|
7
|
+
* the lane's own credential route + scoped home, a hard timeout, and a single
|
|
8
|
+
* turn. Success replaces the mechanical one-liner collapse with real prose;
|
|
9
|
+
* failure/timeout/unavailable falls back to the one-liners (which always work).
|
|
10
|
+
*
|
|
11
|
+
* This is deliberately NOT a run: it opens no run dir, records no native
|
|
12
|
+
* session, and emits no run events — it must never masquerade as a user turn.
|
|
13
|
+
* It reuses the same credential-profile + scoped-home + env-inheritance route a
|
|
14
|
+
* real read-only thread turn uses, so it authenticates identically and consumes
|
|
15
|
+
* quota honestly (the disclosure's `summarized` flag already tells the user the
|
|
16
|
+
* prefix was condensed).
|
|
17
|
+
*/
|
|
18
|
+
import { type CredentialProfile } from "@claudexor/schema";
|
|
19
|
+
import { type HarnessAdapter } from "@claudexor/core";
|
|
20
|
+
import type { ContinuityTurn } from "./continuity.js";
|
|
21
|
+
/** Default wall-clock ceiling for one inline summary pass. */
|
|
22
|
+
export declare const SUMMARY_TIMEOUT_MS = 60000;
|
|
23
|
+
export interface SummaryRunParams {
|
|
24
|
+
adapter: HarnessAdapter;
|
|
25
|
+
/** The collapsed older-prefix turns to summarise (oldest → newest). */
|
|
26
|
+
turns: ContinuityTurn[];
|
|
27
|
+
/** Read-only working directory (the thread's execution root). */
|
|
28
|
+
cwd: string;
|
|
29
|
+
/** Scoped lane-home env so the pass authenticates on the lane's own account. */
|
|
30
|
+
env: Record<string, string>;
|
|
31
|
+
/** Resolved credential profile for the lane (null = engine default ladder). */
|
|
32
|
+
credentialProfile: CredentialProfile | null;
|
|
33
|
+
authPreference: "subscription" | "api_key" | "auto";
|
|
34
|
+
envInheritance: "mirror_native" | "clean";
|
|
35
|
+
/** Upper bound on the pass; the caller's run signal aborts it too. */
|
|
36
|
+
timeoutMs?: number;
|
|
37
|
+
signal?: AbortSignal;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Run one bounded summary pass. Returns the summary text, or null on any
|
|
41
|
+
* failure/timeout/empty answer (the caller then keeps the mechanical collapse).
|
|
42
|
+
* Never throws.
|
|
43
|
+
*/
|
|
44
|
+
export declare function summarizeThreadPrefix(params: SummaryRunParams): Promise<string | null>;
|
|
45
|
+
//# sourceMappingURL=continuity-summary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"continuity-summary.d.ts","sourceRoot":"","sources":["../src/continuity-summary.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAEL,KAAK,iBAAiB,EAEvB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAkB,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEtD,8DAA8D;AAC9D,eAAO,MAAM,kBAAkB,QAAS,CAAC;AAMzC,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,cAAc,CAAC;IACxB,uEAAuE;IACvE,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,iEAAiE;IACjE,GAAG,EAAE,MAAM,CAAC;IACZ,gFAAgF;IAChF,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,+EAA+E;IAC/E,iBAAiB,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC5C,cAAc,EAAE,cAAc,GAAG,SAAS,GAAG,MAAM,CAAC;IACpD,cAAc,EAAE,eAAe,GAAG,OAAO,CAAC;IAC1C,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AA2BD;;;;GAIG;AACH,wBAAsB,qBAAqB,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAmD5F"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bounded inline continuation summariser (INV-137, V9c).
|
|
3
|
+
*
|
|
4
|
+
* When a continuation packet must collapse an older prefix and no fresh cached
|
|
5
|
+
* summary covers it, the orchestrator runs ONE bounded read-only summarisation
|
|
6
|
+
* pass over the collapsed turns — ask-mode intent, the thread's primary harness,
|
|
7
|
+
* the lane's own credential route + scoped home, a hard timeout, and a single
|
|
8
|
+
* turn. Success replaces the mechanical one-liner collapse with real prose;
|
|
9
|
+
* failure/timeout/unavailable falls back to the one-liners (which always work).
|
|
10
|
+
*
|
|
11
|
+
* This is deliberately NOT a run: it opens no run dir, records no native
|
|
12
|
+
* session, and emits no run events — it must never masquerade as a user turn.
|
|
13
|
+
* It reuses the same credential-profile + scoped-home + env-inheritance route a
|
|
14
|
+
* real read-only thread turn uses, so it authenticates identically and consumes
|
|
15
|
+
* quota honestly (the disclosure's `summarized` flag already tells the user the
|
|
16
|
+
* prefix was condensed).
|
|
17
|
+
*/
|
|
18
|
+
import { HarnessRunSpec, } from "@claudexor/schema";
|
|
19
|
+
import { AnswerAssembly } from "@claudexor/core";
|
|
20
|
+
/** Default wall-clock ceiling for one inline summary pass. */
|
|
21
|
+
export const SUMMARY_TIMEOUT_MS = 60_000;
|
|
22
|
+
/** Bytes of each collapsed turn fed to the summariser (prompt + output halves). */
|
|
23
|
+
const PER_TURN_INPUT_BYTES = 4 * 1024;
|
|
24
|
+
/** Bytes retained from the summary answer. */
|
|
25
|
+
const MAX_SUMMARY_BYTES = 8 * 1024;
|
|
26
|
+
function boundBytes(text, maxBytes) {
|
|
27
|
+
const buf = Buffer.from(text, "utf8");
|
|
28
|
+
if (buf.length <= maxBytes)
|
|
29
|
+
return text;
|
|
30
|
+
return `${buf.subarray(0, maxBytes).toString("utf8")}…`;
|
|
31
|
+
}
|
|
32
|
+
/** Render the collapsed prefix as the summariser's input transcript. */
|
|
33
|
+
function transcript(turns) {
|
|
34
|
+
return turns
|
|
35
|
+
.map((t, i) => {
|
|
36
|
+
const prompt = boundBytes(t.prompt.trim(), PER_TURN_INPUT_BYTES / 2);
|
|
37
|
+
const output = t.outputText.trim()
|
|
38
|
+
? boundBytes(t.outputText.trim(), PER_TURN_INPUT_BYTES / 2)
|
|
39
|
+
: "(no recorded answer)";
|
|
40
|
+
return `Turn ${i + 1}\nUser: ${prompt}\nAssistant: ${output}`;
|
|
41
|
+
})
|
|
42
|
+
.join("\n\n");
|
|
43
|
+
}
|
|
44
|
+
const SUMMARY_INSTRUCTION = "You are handing this conversation off to a successor agent that has NOT seen it. " +
|
|
45
|
+
"Summarize the earlier turns below for that agent: the decisions reached, the current " +
|
|
46
|
+
"state of the work, and the open items still to do. Be concise and factual — no preamble, " +
|
|
47
|
+
"no questions, no tool calls. Output only the summary.";
|
|
48
|
+
/**
|
|
49
|
+
* Run one bounded summary pass. Returns the summary text, or null on any
|
|
50
|
+
* failure/timeout/empty answer (the caller then keeps the mechanical collapse).
|
|
51
|
+
* Never throws.
|
|
52
|
+
*/
|
|
53
|
+
export async function summarizeThreadPrefix(params) {
|
|
54
|
+
if (params.turns.length === 0)
|
|
55
|
+
return null;
|
|
56
|
+
const timeoutMs = params.timeoutMs ?? SUMMARY_TIMEOUT_MS;
|
|
57
|
+
const abort = new AbortController();
|
|
58
|
+
const onOuterAbort = () => abort.abort();
|
|
59
|
+
if (params.signal) {
|
|
60
|
+
if (params.signal.aborted)
|
|
61
|
+
return null;
|
|
62
|
+
params.signal.addEventListener("abort", onOuterAbort, { once: true });
|
|
63
|
+
}
|
|
64
|
+
const timer = setTimeout(() => abort.abort(), timeoutMs);
|
|
65
|
+
timer.unref?.();
|
|
66
|
+
const answer = new AnswerAssembly();
|
|
67
|
+
try {
|
|
68
|
+
const spec = HarnessRunSpec.parse({
|
|
69
|
+
session_id: `continuity-summary-${Date.now()}`,
|
|
70
|
+
intent: "explain",
|
|
71
|
+
prompt: `${SUMMARY_INSTRUCTION}\n\n---\n\n${transcript(params.turns)}`,
|
|
72
|
+
cwd: params.cwd,
|
|
73
|
+
access: "readonly",
|
|
74
|
+
external_context_policy: "off",
|
|
75
|
+
tool_permission_policy: { web: "off", allow: [], deny: [] },
|
|
76
|
+
model_hint: null,
|
|
77
|
+
effort_hint: null,
|
|
78
|
+
max_turns: 1,
|
|
79
|
+
auth_preference: params.authPreference === "auto" ? undefined : params.authPreference,
|
|
80
|
+
credential_profile: params.credentialProfile,
|
|
81
|
+
// A fresh pass: never resume — this is a side computation, not a lane turn.
|
|
82
|
+
resume_session_id: null,
|
|
83
|
+
env_inheritance: params.envInheritance,
|
|
84
|
+
evidence_policy: "stream_only",
|
|
85
|
+
env: params.env,
|
|
86
|
+
attachments: [],
|
|
87
|
+
browser: null,
|
|
88
|
+
stream_deltas: false,
|
|
89
|
+
extra: { abortSignal: abort.signal },
|
|
90
|
+
});
|
|
91
|
+
for await (const raw of params.adapter.run(spec)) {
|
|
92
|
+
if (abort.signal.aborted)
|
|
93
|
+
return null;
|
|
94
|
+
const event = raw;
|
|
95
|
+
if (event.type === "error")
|
|
96
|
+
return null;
|
|
97
|
+
if (event.type === "message")
|
|
98
|
+
answer.observe(event);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
finally {
|
|
105
|
+
clearTimeout(timer);
|
|
106
|
+
params.signal?.removeEventListener("abort", onOuterAbort);
|
|
107
|
+
}
|
|
108
|
+
if (abort.signal.aborted)
|
|
109
|
+
return null;
|
|
110
|
+
const text = answer.text().trim();
|
|
111
|
+
return text ? boundBytes(text, MAX_SUMMARY_BYTES) : null;
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=continuity-summary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"continuity-summary.js","sourceRoot":"","sources":["../src/continuity-summary.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Continuation-packet builder (INV-137, V9b) — PURE.
|
|
3
|
+
*
|
|
4
|
+
* A lane is a (thread, harness, profile) triple. When a turn runs on a lane
|
|
5
|
+
* whose checkpoint lags the thread head — a lane switch (A→B→A) or a gap — the
|
|
6
|
+
* new lane has no native memory of the missed turns, so the engine hydrates it
|
|
7
|
+
* with a bounded MECHANICAL continuation packet: recent delta turns verbatim,
|
|
8
|
+
* older ones collapsed to one-line entries when the budget is exceeded, plus
|
|
9
|
+
* the active plan pointer and a workspace anchor.
|
|
10
|
+
*
|
|
11
|
+
* When the budget forces a collapse, a cached LLM summary (V9c) can REPLACE the
|
|
12
|
+
* collapsed one-liners with real prose: the caller runs `planContinuation` to
|
|
13
|
+
* learn which older turns would collapse (and their boundary turn id — the
|
|
14
|
+
* summary cache key), resolves a summary for that prefix (cache hit or a bounded
|
|
15
|
+
* inline summarization pass), and passes it back as `cachedSummary`. The
|
|
16
|
+
* mechanical one-liner collapse is ALWAYS the fallback, so a missing/failed
|
|
17
|
+
* summary never loses information. Either way `summarized` stays true (the
|
|
18
|
+
* verbatim prefix was condensed); the packet text itself discloses which form
|
|
19
|
+
* was used.
|
|
20
|
+
*
|
|
21
|
+
* This module takes fully-resolved structured data (the daemon supplies thread
|
|
22
|
+
* facts; the orchestrator reads prior outputs + git anchor) and returns the
|
|
23
|
+
* disclosure + the packet body. No I/O, no clock — trivially unit-testable.
|
|
24
|
+
*/
|
|
25
|
+
/** Per delta turn: verbatim budget (user prompt + primary output). */
|
|
26
|
+
export declare const PER_TURN_BUDGET_BYTES: number;
|
|
27
|
+
/** Whole-packet verbatim budget; older turns collapse past this. */
|
|
28
|
+
export declare const TOTAL_BUDGET_BYTES: number;
|
|
29
|
+
/** One-line collapsed entry keeps this many chars of each field. */
|
|
30
|
+
export declare const COLLAPSE_PREFIX_CHARS = 200;
|
|
31
|
+
export interface ContinuityTurn {
|
|
32
|
+
/** Turn id (checkpoint math keys off this). */
|
|
33
|
+
id: string;
|
|
34
|
+
/** The user's message for the turn (already redacted). */
|
|
35
|
+
prompt: string;
|
|
36
|
+
/** The turn's primary output text (final/answer.md), "" when none. */
|
|
37
|
+
outputText: string;
|
|
38
|
+
}
|
|
39
|
+
export interface ContinuityLane {
|
|
40
|
+
harness: string;
|
|
41
|
+
profileId: string | null;
|
|
42
|
+
}
|
|
43
|
+
export interface ContinuityPlanPointer {
|
|
44
|
+
/** Absolute path to the approved plan.md the packet points at. */
|
|
45
|
+
path: string;
|
|
46
|
+
/** derivePlanReadiness state: ready | needs_answers | unverified. */
|
|
47
|
+
readiness: string;
|
|
48
|
+
planRunId: string;
|
|
49
|
+
}
|
|
50
|
+
export interface ContinuityAnchor {
|
|
51
|
+
headSha: string | null;
|
|
52
|
+
dirtyCount: number;
|
|
53
|
+
}
|
|
54
|
+
export interface ContinuityRequest {
|
|
55
|
+
/** This turn's resolved lane. */
|
|
56
|
+
lane: ContinuityLane;
|
|
57
|
+
/** All prior turns of the thread, in order (EXCLUDES the current turn). */
|
|
58
|
+
priorTurns: ContinuityTurn[];
|
|
59
|
+
/** The last turn id this lane has seen, or null when the lane never ran. */
|
|
60
|
+
laneCheckpointTurnId: string | null;
|
|
61
|
+
/** True when the lane can resume its OWN native vendor session in place. */
|
|
62
|
+
nativeResumeAvailable: boolean;
|
|
63
|
+
/** The lane that produced the prior head turn, when known (for laneSwitchedFrom). */
|
|
64
|
+
priorHeadLane: ContinuityLane | null;
|
|
65
|
+
/** Active plan pointer to append, when any. */
|
|
66
|
+
activePlan: ContinuityPlanPointer | null;
|
|
67
|
+
/** Workspace anchor to append, when available. */
|
|
68
|
+
anchor: ContinuityAnchor | null;
|
|
69
|
+
/**
|
|
70
|
+
* A resolved LLM summary of the collapsed older prefix (V9c). Applied ONLY
|
|
71
|
+
* when the packet actually collapses AND `upToTurnId` equals the plan's
|
|
72
|
+
* `summaryUpToTurnId` (the collapse boundary) — otherwise ignored and the
|
|
73
|
+
* mechanical one-liner collapse renders. Absent = mechanical fallback.
|
|
74
|
+
*/
|
|
75
|
+
cachedSummary?: ResolvedSummary | null;
|
|
76
|
+
}
|
|
77
|
+
/** A summary of the collapsed older prefix, keyed by its boundary turn id. */
|
|
78
|
+
export interface ResolvedSummary {
|
|
79
|
+
/** The id of the LAST turn the summary covers (the collapse boundary). */
|
|
80
|
+
upToTurnId: string;
|
|
81
|
+
/** The summary prose to render in place of the collapsed one-liners. */
|
|
82
|
+
text: string;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* The mechanical collapse plan for a request — WHICH delta turns are carried and
|
|
86
|
+
* which would collapse under the budget — computed WITHOUT rendering so the
|
|
87
|
+
* caller can resolve a summary for the collapsed prefix before building the
|
|
88
|
+
* packet. Pure and cheap (the same math `buildContinuation` uses internally).
|
|
89
|
+
*/
|
|
90
|
+
export interface ContinuityPlan {
|
|
91
|
+
kind: "native_resume" | "packet" | "fresh";
|
|
92
|
+
/** All delta turns this lane must be told about (after its checkpoint). */
|
|
93
|
+
delta: ContinuityTurn[];
|
|
94
|
+
/** The oldest delta turns that collapse under the budget (empty = none). */
|
|
95
|
+
collapsedPrefix: ContinuityTurn[];
|
|
96
|
+
/** Boundary turn id — the summary cache key; null when nothing collapses. */
|
|
97
|
+
summaryUpToTurnId: string | null;
|
|
98
|
+
}
|
|
99
|
+
export interface ContinuityDisclosureResult {
|
|
100
|
+
kind: "native_resume" | "packet" | "fresh";
|
|
101
|
+
packetTurns: number;
|
|
102
|
+
summarized: boolean;
|
|
103
|
+
laneSwitchedFrom: ContinuityLane | null;
|
|
104
|
+
}
|
|
105
|
+
export interface ContinuityResult {
|
|
106
|
+
disclosure: ContinuityDisclosureResult;
|
|
107
|
+
/** The THREAD.md packet body, or null when no packet is delivered. */
|
|
108
|
+
packetMarkdown: string | null;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Compute the mechanical collapse plan for a lane WITHOUT rendering: the caller
|
|
112
|
+
* uses `summaryUpToTurnId` to look up / generate a summary for the collapsed
|
|
113
|
+
* prefix, then feeds it back via `req.cachedSummary` to `buildContinuation`.
|
|
114
|
+
* Pure; matches `buildContinuation`'s own collapse math exactly.
|
|
115
|
+
*/
|
|
116
|
+
export declare function planContinuation(req: ContinuityRequest): ContinuityPlan;
|
|
117
|
+
/** Compute the continuity disclosure + packet body for a resolved lane. */
|
|
118
|
+
export declare function buildContinuation(req: ContinuityRequest): ContinuityResult;
|
|
119
|
+
//# sourceMappingURL=continuity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"continuity.d.ts","sourceRoot":"","sources":["../src/continuity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,sEAAsE;AACtE,eAAO,MAAM,qBAAqB,QAAW,CAAC;AAC9C,oEAAoE;AACpE,eAAO,MAAM,kBAAkB,QAAY,CAAC;AAC5C,oEAAoE;AACpE,eAAO,MAAM,qBAAqB,MAAM,CAAC;AAEzC,MAAM,WAAW,cAAc;IAC7B,+CAA+C;IAC/C,EAAE,EAAE,MAAM,CAAC;IACX,0DAA0D;IAC1D,MAAM,EAAE,MAAM,CAAC;IACf,sEAAsE;IACtE,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,qBAAqB;IACpC,kEAAkE;IAClE,IAAI,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,iCAAiC;IACjC,IAAI,EAAE,cAAc,CAAC;IACrB,2EAA2E;IAC3E,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B,4EAA4E;IAC5E,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,4EAA4E;IAC5E,qBAAqB,EAAE,OAAO,CAAC;IAC/B,qFAAqF;IACrF,aAAa,EAAE,cAAc,GAAG,IAAI,CAAC;IACrC,+CAA+C;IAC/C,UAAU,EAAE,qBAAqB,GAAG,IAAI,CAAC;IACzC,kDAAkD;IAClD,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAChC;;;;;OAKG;IACH,aAAa,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;CACxC;AAED,8EAA8E;AAC9E,MAAM,WAAW,eAAe;IAC9B,0EAA0E;IAC1E,UAAU,EAAE,MAAM,CAAC;IACnB,wEAAwE;IACxE,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,eAAe,GAAG,QAAQ,GAAG,OAAO,CAAC;IAC3C,2EAA2E;IAC3E,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,4EAA4E;IAC5E,eAAe,EAAE,cAAc,EAAE,CAAC;IAClC,6EAA6E;IAC7E,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE,eAAe,GAAG,QAAQ,GAAG,OAAO,CAAC;IAC3C,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,gBAAgB,EAAE,cAAc,GAAG,IAAI,CAAC;CACzC;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,0BAA0B,CAAC;IACvC,sEAAsE;IACtE,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAmKD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,iBAAiB,GAAG,cAAc,CAgBvE;AAED,2EAA2E;AAC3E,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,iBAAiB,GAAG,gBAAgB,CA6C1E"}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Continuation-packet builder (INV-137, V9b) — PURE.
|
|
3
|
+
*
|
|
4
|
+
* A lane is a (thread, harness, profile) triple. When a turn runs on a lane
|
|
5
|
+
* whose checkpoint lags the thread head — a lane switch (A→B→A) or a gap — the
|
|
6
|
+
* new lane has no native memory of the missed turns, so the engine hydrates it
|
|
7
|
+
* with a bounded MECHANICAL continuation packet: recent delta turns verbatim,
|
|
8
|
+
* older ones collapsed to one-line entries when the budget is exceeded, plus
|
|
9
|
+
* the active plan pointer and a workspace anchor.
|
|
10
|
+
*
|
|
11
|
+
* When the budget forces a collapse, a cached LLM summary (V9c) can REPLACE the
|
|
12
|
+
* collapsed one-liners with real prose: the caller runs `planContinuation` to
|
|
13
|
+
* learn which older turns would collapse (and their boundary turn id — the
|
|
14
|
+
* summary cache key), resolves a summary for that prefix (cache hit or a bounded
|
|
15
|
+
* inline summarization pass), and passes it back as `cachedSummary`. The
|
|
16
|
+
* mechanical one-liner collapse is ALWAYS the fallback, so a missing/failed
|
|
17
|
+
* summary never loses information. Either way `summarized` stays true (the
|
|
18
|
+
* verbatim prefix was condensed); the packet text itself discloses which form
|
|
19
|
+
* was used.
|
|
20
|
+
*
|
|
21
|
+
* This module takes fully-resolved structured data (the daemon supplies thread
|
|
22
|
+
* facts; the orchestrator reads prior outputs + git anchor) and returns the
|
|
23
|
+
* disclosure + the packet body. No I/O, no clock — trivially unit-testable.
|
|
24
|
+
*/
|
|
25
|
+
/** Per delta turn: verbatim budget (user prompt + primary output). */
|
|
26
|
+
export const PER_TURN_BUDGET_BYTES = 8 * 1024;
|
|
27
|
+
/** Whole-packet verbatim budget; older turns collapse past this. */
|
|
28
|
+
export const TOTAL_BUDGET_BYTES = 24 * 1024;
|
|
29
|
+
/** One-line collapsed entry keeps this many chars of each field. */
|
|
30
|
+
export const COLLAPSE_PREFIX_CHARS = 200;
|
|
31
|
+
function bytes(text) {
|
|
32
|
+
return Buffer.byteLength(text, "utf8");
|
|
33
|
+
}
|
|
34
|
+
/** Truncate to at most `maxBytes` UTF-8 bytes on a safe char boundary. */
|
|
35
|
+
function boundBytes(text, maxBytes) {
|
|
36
|
+
if (bytes(text) <= maxBytes)
|
|
37
|
+
return text;
|
|
38
|
+
// Buffer slice can split a multi-byte scalar; back off a few bytes until valid.
|
|
39
|
+
const buf = Buffer.from(text, "utf8").subarray(0, maxBytes);
|
|
40
|
+
for (let trim = 0; trim <= 3 && trim <= buf.length; trim += 1) {
|
|
41
|
+
try {
|
|
42
|
+
const decoded = new TextDecoder("utf-8", { fatal: true }).decode(trim === 0 ? buf : buf.subarray(0, buf.length - trim));
|
|
43
|
+
return `${decoded}\n…[truncated]`;
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
/* prefix ended inside a scalar; back off */
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return `${buf.toString("utf8")}\n…[truncated]`;
|
|
50
|
+
}
|
|
51
|
+
function oneLine(text) {
|
|
52
|
+
const flat = text.replace(/\s+/g, " ").trim();
|
|
53
|
+
return flat.length > COLLAPSE_PREFIX_CHARS ? `${flat.slice(0, COLLAPSE_PREFIX_CHARS)}…` : flat;
|
|
54
|
+
}
|
|
55
|
+
/** Delta turns for this lane: everything AFTER the checkpoint (all prior when
|
|
56
|
+
* the lane never ran / has no reachable native session to trust). */
|
|
57
|
+
function deltaTurns(req) {
|
|
58
|
+
// Without a reachable native session the lane starts blank — carry the whole
|
|
59
|
+
// prior conversation regardless of any stale checkpoint.
|
|
60
|
+
if (!req.nativeResumeAvailable)
|
|
61
|
+
return req.priorTurns;
|
|
62
|
+
if (!req.laneCheckpointTurnId)
|
|
63
|
+
return req.priorTurns;
|
|
64
|
+
const idx = req.priorTurns.findIndex((t) => t.id === req.laneCheckpointTurnId);
|
|
65
|
+
// Checkpoint not among the retained prior turns → carry everything (safe).
|
|
66
|
+
return idx < 0 ? req.priorTurns : req.priorTurns.slice(idx + 1);
|
|
67
|
+
}
|
|
68
|
+
function verbatimEntry(turn, index) {
|
|
69
|
+
const prompt = boundBytes(turn.prompt.trim(), PER_TURN_BUDGET_BYTES / 2);
|
|
70
|
+
const output = turn.outputText.trim()
|
|
71
|
+
? boundBytes(turn.outputText.trim(), PER_TURN_BUDGET_BYTES / 2)
|
|
72
|
+
: "_(no recorded output)_";
|
|
73
|
+
return `### Turn ${index + 1}\n\n**User asked:**\n\n${prompt}\n\n**The assistant answered:**\n\n${output}\n`;
|
|
74
|
+
}
|
|
75
|
+
function collapsedEntry(turn, index) {
|
|
76
|
+
const prompt = oneLine(turn.prompt) || "(empty)";
|
|
77
|
+
const output = turn.outputText.trim() ? oneLine(turn.outputText) : "(no recorded output)";
|
|
78
|
+
return `- Turn ${index + 1} — user: ${prompt} · assistant: ${output}`;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* How many of the OLDEST delta turns collapse to one-liners: grow the collapsed
|
|
82
|
+
* prefix from the oldest until the verbatim total fits the budget. Pure — the
|
|
83
|
+
* single owner of the collapse decision (both `planContinuation` and
|
|
84
|
+
* `renderPacket` read it, so the boundary the caller summarizes is exactly the
|
|
85
|
+
* boundary the packet renders).
|
|
86
|
+
*/
|
|
87
|
+
function collapseCount(delta) {
|
|
88
|
+
const verbatim = delta.map((t, i) => verbatimEntry(t, i));
|
|
89
|
+
let collapsed = 0;
|
|
90
|
+
const totalBytes = () => delta.reduce((sum, t, i) => sum + bytes(i < collapsed ? collapsedEntry(t, i) : verbatim[i]), 0);
|
|
91
|
+
while (collapsed < delta.length && totalBytes() > TOTAL_BUDGET_BYTES) {
|
|
92
|
+
collapsed += 1;
|
|
93
|
+
}
|
|
94
|
+
return collapsed;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Assemble the packet body from delta turns, collapsing the OLDEST turns while
|
|
98
|
+
* the verbatim total exceeds the budget. When a `summary` covering the collapse
|
|
99
|
+
* boundary is supplied it REPLACES the one-liners with real prose; otherwise the
|
|
100
|
+
* mechanical one-liner collapse renders (always works). Returns the body and
|
|
101
|
+
* whether any collapse happened (`summarized`).
|
|
102
|
+
*/
|
|
103
|
+
function renderPacket(delta, activePlan, anchor, summary) {
|
|
104
|
+
const collapsedCount = collapseCount(delta);
|
|
105
|
+
const summarized = collapsedCount > 0;
|
|
106
|
+
const boundaryTurnId = collapsedCount > 0 ? delta[collapsedCount - 1].id : null;
|
|
107
|
+
// A summary applies only when it covers the EXACT collapse boundary — a stale
|
|
108
|
+
// summary (boundary moved since it was cached) falls back to one-liners.
|
|
109
|
+
const usableSummary = summary && boundaryTurnId && summary.upToTurnId === boundaryTurnId ? summary : null;
|
|
110
|
+
const parts = [
|
|
111
|
+
"# Thread continuation packet",
|
|
112
|
+
"",
|
|
113
|
+
"You are continuing an existing Claudexor conversation on a new lane. The earlier turns below did not run on this lane's native session — read them before answering the new prompt at the end of your instructions.",
|
|
114
|
+
"",
|
|
115
|
+
];
|
|
116
|
+
if (summarized) {
|
|
117
|
+
parts.push(usableSummary
|
|
118
|
+
? "> The oldest turns are condensed into the cached conversation summary below; the most recent turns are verbatim."
|
|
119
|
+
: "> The older turns are condensed to one-line entries below (a cached conversation summary was unavailable for this turn). The most recent turns are verbatim.", "");
|
|
120
|
+
}
|
|
121
|
+
if (usableSummary) {
|
|
122
|
+
parts.push("## Earlier conversation (summary)", "", usableSummary.text.trim(), "", "## Recent turns", "");
|
|
123
|
+
for (let i = collapsedCount; i < delta.length; i += 1) {
|
|
124
|
+
parts.push(verbatimEntry(delta[i], i));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
parts.push("## Earlier turns", "");
|
|
129
|
+
const collapsedLines = [];
|
|
130
|
+
for (let i = 0; i < delta.length; i += 1) {
|
|
131
|
+
if (i < collapsedCount) {
|
|
132
|
+
collapsedLines.push(collapsedEntry(delta[i], i));
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
if (collapsedLines.length > 0) {
|
|
136
|
+
parts.push(...collapsedLines, "");
|
|
137
|
+
collapsedLines.length = 0;
|
|
138
|
+
}
|
|
139
|
+
parts.push(verbatimEntry(delta[i], i));
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
if (collapsedLines.length > 0)
|
|
143
|
+
parts.push(...collapsedLines, "");
|
|
144
|
+
}
|
|
145
|
+
if (activePlan) {
|
|
146
|
+
parts.push("## Active plan", "", `The thread's approved plan is at: ${activePlan.path} (readiness: ${activePlan.readiness}). Re-read it as needed.`, "");
|
|
147
|
+
}
|
|
148
|
+
if (anchor) {
|
|
149
|
+
parts.push("## Workspace anchor", "", `HEAD ${anchor.headSha ?? "(unborn)"} · ${anchor.dirtyCount} file(s) with uncommitted changes at the start of this turn.`, "");
|
|
150
|
+
}
|
|
151
|
+
return {
|
|
152
|
+
body: parts
|
|
153
|
+
.join("\n")
|
|
154
|
+
.replace(/\n{3,}/g, "\n\n")
|
|
155
|
+
.trimEnd() + "\n",
|
|
156
|
+
summarized,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Compute the mechanical collapse plan for a lane WITHOUT rendering: the caller
|
|
161
|
+
* uses `summaryUpToTurnId` to look up / generate a summary for the collapsed
|
|
162
|
+
* prefix, then feeds it back via `req.cachedSummary` to `buildContinuation`.
|
|
163
|
+
* Pure; matches `buildContinuation`'s own collapse math exactly.
|
|
164
|
+
*/
|
|
165
|
+
export function planContinuation(req) {
|
|
166
|
+
if (req.priorTurns.length === 0) {
|
|
167
|
+
return { kind: "fresh", delta: [], collapsedPrefix: [], summaryUpToTurnId: null };
|
|
168
|
+
}
|
|
169
|
+
const delta = deltaTurns(req);
|
|
170
|
+
if (delta.length === 0) {
|
|
171
|
+
return { kind: "native_resume", delta: [], collapsedPrefix: [], summaryUpToTurnId: null };
|
|
172
|
+
}
|
|
173
|
+
const collapsed = collapseCount(delta);
|
|
174
|
+
const collapsedPrefix = delta.slice(0, collapsed);
|
|
175
|
+
return {
|
|
176
|
+
kind: "packet",
|
|
177
|
+
delta,
|
|
178
|
+
collapsedPrefix,
|
|
179
|
+
summaryUpToTurnId: collapsed > 0 ? delta[collapsed - 1].id : null,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
/** Compute the continuity disclosure + packet body for a resolved lane. */
|
|
183
|
+
export function buildContinuation(req) {
|
|
184
|
+
const laneSwitchedFrom = req.priorHeadLane &&
|
|
185
|
+
(req.priorHeadLane.harness !== req.lane.harness ||
|
|
186
|
+
(req.priorHeadLane.profileId ?? null) !== (req.lane.profileId ?? null))
|
|
187
|
+
? req.priorHeadLane
|
|
188
|
+
: null;
|
|
189
|
+
// Nothing before this turn → the thread's first move on any lane.
|
|
190
|
+
if (req.priorTurns.length === 0) {
|
|
191
|
+
return {
|
|
192
|
+
disclosure: { kind: "fresh", packetTurns: 0, summarized: false, laneSwitchedFrom: null },
|
|
193
|
+
packetMarkdown: null,
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
const delta = deltaTurns(req);
|
|
197
|
+
if (delta.length === 0) {
|
|
198
|
+
// The lane's own native session already holds everything up to the head.
|
|
199
|
+
return {
|
|
200
|
+
disclosure: {
|
|
201
|
+
kind: "native_resume",
|
|
202
|
+
packetTurns: 0,
|
|
203
|
+
summarized: false,
|
|
204
|
+
laneSwitchedFrom: null,
|
|
205
|
+
},
|
|
206
|
+
packetMarkdown: null,
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
const { body, summarized } = renderPacket(delta, req.activePlan, req.anchor, req.cachedSummary ?? null);
|
|
210
|
+
return {
|
|
211
|
+
disclosure: {
|
|
212
|
+
kind: "packet",
|
|
213
|
+
packetTurns: delta.length,
|
|
214
|
+
summarized,
|
|
215
|
+
laneSwitchedFrom,
|
|
216
|
+
},
|
|
217
|
+
packetMarkdown: body,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
//# sourceMappingURL=continuity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"continuity.js","sourceRoot":"","sources":["../src/continuity.ts"],"names":[],"mappings":"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"}
|
package/dist/contract-gates.d.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import type { AccessProfile, GateResult, ProjectConfig, TaskContract, TestCommandGrant, TestCommandInvocation } from "@claudexor/schema";
|
|
2
2
|
import type { GateSpec } from "@claudexor/review";
|
|
3
3
|
type GateCommands = TaskContract["tests"]["commands"];
|
|
4
|
-
/** Merge the
|
|
5
|
-
* to versioned project commands.
|
|
4
|
+
/** Merge the command authorities once and attach external grants only
|
|
5
|
+
* to versioned project commands. Operator commands are explicit input. */
|
|
6
6
|
export declare function resolveContractGates(input: {
|
|
7
7
|
repoRoot: string;
|
|
8
8
|
effectiveAccess: AccessProfile;
|
|
9
9
|
config: ProjectConfig;
|
|
10
10
|
trustGrants: TestCommandGrant[];
|
|
11
|
-
specCommands: TestCommandInvocation[];
|
|
12
11
|
operatorCommands: TestCommandInvocation[];
|
|
13
12
|
projectCommands: TestCommandInvocation[];
|
|
14
13
|
}): {
|