Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions docs/reference/required-work-context.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,17 @@ object keys or exact array indices in the immutable base capture. This avoids
resending identical authoring and evidence records when task binding or source
ordering moves them to another field. The reference copies the complete exact
value, never a similar value or one from the current patch. A subtree containing
any field required as current input cannot use a whole-subtree reference. The
codec chooses a reference only when smaller than its literal or recursive edit.
any field required as current input cannot use a bare whole-subtree reference.
It may instead pair `from` with `edit`: copy the exact base value, then apply
the edit to that copy. Every current and unknown control still appears literally
in the edit. Nested `from` paths remain rooted in the original immutable base,
never the edited copy. This avoids repeating a long reference path for each
unchanged requirement when an admitted reader relocates a complete source.
The codec chooses this overlay only when smaller than the ordinary recursive
edit or complete current literal; its instructions appear only when used.
Readers validate the exact current change tree and complete reconstructed digest;
removing a required current override therefore recovers the current full capture.
Older readers recover the same full capture for an unsupported overlay.
Current and unknown controls remain inline. Older string-only readers recover
the current full capture for an unsupported structured reference. Missing,
malformed or incompatible references recover the same full current capture;
Expand Down
54 changes: 39 additions & 15 deletions loopx/control_plane/quota/context_delivery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ function splitContext(context: JsonObject): Split {
* Keep one exact codec for quota and Turn; source-only callers use the same codec. */
const SURFACES = ["work_context", "quota_packet", "turn_envelope"] as const;
type Surface = typeof SURFACES[number];
type Delta = {value: unknown} | {from: Path} | {changed?: Record<string, Delta>; values?: Record<string, unknown>; removed?: string[]}
type Delta = {value: unknown} | {from: Path; edit?: Delta} | {changed?: Record<string, Delta>; values?: Record<string, unknown>; removed?: string[]}
| {items: Record<string, Delta>; values?: Record<string, unknown>; length?: number};
const pathKey = (path: Path): string => JSON.stringify(path);

Expand Down Expand Up @@ -335,7 +335,7 @@ function changeTree(before: unknown, after: unknown, forced: Path[]): Delta | nu
for (const path of forced) for (let i = 0; i < path.length; i++) ancestors.add(pathKey(path.slice(0, i)));
// Binding or source reordering can relocate already-read authoring. Index
// exact strings and structured subtrees from the immutable base. A target
// containing any forced-current descendant cannot use a subtree reference.
// with current descendants needs literal overrides, never a bare reference.
const strings = new Map<string, {from: Path}>();
type Candidate = {reference: {from: Path}; value: unknown};
const subtrees = new Map<number, {candidates: Candidate[]; indexed?: Map<string, Candidate>}>();
Expand All @@ -356,16 +356,19 @@ function changeTree(before: unknown, after: unknown, forced: Path[]): Delta | nu
}
};
index(before, []);
const visit = (a: unknown, b: unknown, path: Path): Delta | null => {
const visit = (a: unknown, b: unknown, path: Path, relocate = true): Delta | null => {
const key = pathKey(path);
if (exact.has(key)) return {value: clone(b)};
if (!ancestors.has(key) && equal(a, b)) return null;
if (typeof b === "string" && strings.has(b)) return clone(strings.get(b)!);
let reference: {from: Path} | undefined;
if (!ancestors.has(key) && (Array.isArray(b) || jsonObject(b))) {
// Most current controls cannot reuse a subtree, and unchanged siblings
// already returned above. Hash only size buckets actually needed by a
// remaining candidate; avoid hashing the complete baseline eagerly.
let overlay: Delta | undefined;
if ((!ancestors.has(key) || relocate && a === undefined) && (Array.isArray(b) || jsonObject(b))) {
// Hash only size buckets needed by a relocated candidate. A complete
// exact base may carry the body while an edit repeats all current leaves.
// Current containers already present at this path use ordinary edits;
// repeatedly indexing their forced descendants adds work without moving
// a body. A newly inserted source is the actual relocation boundary.
const bucket = subtrees.get(size(b));
if (bucket && !bucket.indexed) {
bucket.indexed = new Map();
Expand All @@ -376,14 +379,23 @@ function changeTree(before: unknown, after: unknown, forced: Path[]): Delta | nu
}
const reusable = bucket?.indexed?.get(digest(b));
// Size and hash lookup are indices: exact equality remains the oracle.
if (reusable && equal(reusable.value, b)) reference = reusable.reference;
if (reusable && equal(reusable.value, b)) {
if (!ancestors.has(key)) reference = reusable.reference;
else if (relocate) {
// Compare against this exact body at its new location. Disabling
// relocation for this node avoids recursion; descendants still use
// the ordinary codec. Forced paths retain their CURRENT literals.
const edit = visit(b, b, path, false);
if (edit) overlay = {...reusable.reference, edit};
}
}
}
let delta: Delta;
if ((jsonObject(a) || a === undefined) && jsonObject(b)) {
const old = (a ?? {}) as JsonObject, next = b as JsonObject;
const changed: [string, Delta][] = [];
for (const [field, value] of Object.entries(next)) {
const child = visit(Object.hasOwn(old, field) ? old[field] : undefined, value, [...path, field]);
const child = visit(Object.hasOwn(old, field) ? old[field] : undefined, value, [...path, field], relocate && !overlay);
if (child) changed.push([field, child]);
}
const removed = Object.keys(old).filter(field => !Object.hasOwn(next, field));
Expand All @@ -392,15 +404,16 @@ function changeTree(before: unknown, after: unknown, forced: Path[]): Delta | nu
const old = a as unknown[] | undefined;
const items: [string, Delta][] = [];
b.forEach((value, i) => {
const child = visit(old?.[i], value, [...path, i]);
const child = visit(old?.[i], value, [...path, i], relocate && !overlay);
if (child) items.push([String(i), child]);
});
delta = groupCurrentValues({items: Object.fromEntries(items), ...(old?.length !== b.length ? {length: b.length} : {})}, size);
} else delta = {value: clone(b)};
// Sizing does not publish a value. Copy only a replacement that is chosen,
// rather than every unchanged subtree and every discarded ancestor value.
const result = size(delta) < size({value: b}) ? delta : {value: clone(b)};
return reference && size(reference) < size(result) ? clone(reference) : result;
let result = size(delta) < size({value: b}) ? delta : {value: clone(b)};
if (reference && size(reference) < size(result)) result = clone(reference);
return overlay && size(overlay) < size(result) ? overlay : result;
};
return visit(before, after, []);
}
Expand All @@ -413,7 +426,8 @@ function applyTree(before: unknown, delta: Delta | null, baseline: unknown = bef
if (delta === null) return clone(before);
if ("value" in delta) return clone(delta.value);
if ("from" in delta) {
if (Object.keys(delta).length !== 1 || !Array.isArray(delta.from)) throw new Error("invalid baseline reference");
if (Object.keys(delta).some(key => key !== "from" && key !== "edit")
|| !Array.isArray(delta.from)) throw new Error("invalid baseline reference");
let value = baseline;
for (const key of delta.from) {
if (!(typeof key === "string" || typeof key === "number" && Number.isSafeInteger(key) && key >= 0)
Expand All @@ -423,7 +437,9 @@ function applyTree(before: unknown, delta: Delta | null, baseline: unknown = bef
}
if (typeof value !== "string" && !Array.isArray(value) && !jsonObject(value))
throw new Error("reference has no exact baseline string or subtree");
return clone(value);
// Every nested reference still resolves against the immutable whole base,
// never the overlay or the partially reconstructed current projection.
return delta.edit === undefined ? clone(value) : applyTree(value, delta.edit, baseline);
}
if ("items" in delta) {
if (before !== undefined && !Array.isArray(before)) throw new Error("array baseline missing");
Expand All @@ -445,6 +461,12 @@ function applyTree(before: unknown, delta: Delta | null, baseline: unknown = bef
return result;
}

function hasOverlay(delta: Delta | null): boolean {
if (!delta || "value" in delta) return false;
if ("from" in delta) return delta.edit !== undefined;
return Object.values("items" in delta ? delta.items : delta.changed ?? {}).some(hasOverlay);
}

function targetBinding(request: JsonObject, context: JsonObject, surface: Surface): JsonObject {
const scope = requireJsonObject(request.scope, "context delivery scope");
const binding: JsonObject = {projection_version: VERSION, surface};
Expand Down Expand Up @@ -498,7 +520,9 @@ export function prepareContextDelivery(request: JsonObject, legacyQuotaFields: r
+ "Do not also fetch the full projection just to materialize JSON or replace missing Code Mode variables; "
+ "tool-process memory is separate from retained model context. If required baseline content is unavailable "
+ "or continuity is uncertain, recover this capture in full before dependent work. " : "")
+ "A value replaces its subtree; from copies the exact string, array or object at that path in the base capture, never in current changes. Values assigns complete fields (exact indices with items); changed/items recurse, removed deletes object keys, length sets array length. Lost context triggers automatic full recovery from this capture, never an owner question."};
+ "A value replaces its subtree; from copies the exact string, array or object at that path in the base capture, never in current changes. "
+ (hasOverlay(changes) ? "An optional edit then applies to that copied value, with all nested from paths still rooted in the immutable base. " : "")
+ "Values assigns complete fields (exact indices with items); changed/items recurse, removed deletes object keys, length sets array length. Lost context triggers automatic full recovery from this capture, never an owner question."};
if (bytes(delta) >= bytes(full("delta_not_smaller"))) return full("delta_not_smaller");
if (!equal(applyTree(prior, changes), context)) return full("reconstruction_failed");
// Native consumers page the wire before they can use its baseline. Deliver
Expand Down
35 changes: 35 additions & 0 deletions tests/control_plane/test_context_delivery_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,41 @@
)


def test_relocated_current_source_overlay_crosses_the_real_typed_codec(tmp_path, monkeypatch):
isolate_sqlite_runtime(tmp_path, monkeypatch)
scope = dict(goal_id="fixture", agent_id="reader", session_id="native", context_epoch="epoch")
acceptance = {"outcome_requirements": {"revision": 1, "outcomes": [{"id": "outcome",
"requirements": [{"id": f"r{i}", "description": "Preserve exact evidence and the original stop. " * 8,
"status": "unverified", "agent_review": {"conclusion": "uncertain", "basis_current": False,
"note": "An observation is not acceptance. " * 8}} for i in range(24)]}]}}
original = {"planning_horizon": {"core_goal": {"acceptance_contract": acceptance}}}
current = {"interaction_contract": {"agent_channel": {"work_context": {"complete": True,
"sources": [{"source": "goal_acceptance", "content": {
"provider_revision": "current", "goal_acceptance_contract": deepcopy(acceptance)}}]}}}}
args = dict(scope=scope, surface="quota_packet")
first = prepare_context_delivery(original, capture_id="before", **args)
full = prepare_context_delivery(current, capture_id="after", **args)
delta = prepare_context_delivery(current, capture_id="after", baseline=first,
retained={"complete": True, "target": first["target"]}, **args)
assert delta["mode"] == "delta"
overlays = []
def visit(node):
if not isinstance(node, dict) or "value" in node:
return
if "from" in node and "edit" in node:
overlays.append(node)
for child in node.get("changed", node.get("items", {})).values():
visit(child)
visit(delta["changes"])
assert overlays, "Real RPC must carry the registered overlay, not silently downgrade it"
assert restore_context_delivery(delta, baseline=first, current=full)["context"] == current
# The same original capture is the fallback for unsupported/damaged edits.
del overlays[0]["edit"]
restored = restore_context_delivery(delta, baseline=first, current=full)
assert restored["mode"] == "full" and restored["context"] == current
assert first["context"] == original


@pytest.mark.parametrize("body", ["plain text " * 900, '汉🙂"\\\t\n' * 700])
@pytest.mark.parametrize("limit", [1600, 7000])
def test_reader_bounds_actual_json_stdout_and_preserves_every_byte(tmp_path, monkeypatch, body, limit):
Expand Down
62 changes: 62 additions & 0 deletions tests/control_plane_ts/context_delivery.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ const recover = (delivery: JsonObject, baseline: JsonObject, value: JsonObject):
function inline(delivery: JsonObject, path: (string | number)[]): unknown {
let node = delivery.changes as JsonObject;
for (let i = 0; ; i++) {
// An overlay's inherited body is unavailable to this literal-only reader.
// Inspect only its current edit when checking fresh control delivery.
if (node?.from && node.edit) node = node.edit as JsonObject;
if (!node) return undefined;
if (Object.hasOwn(node, "value")) {
let value = node.value;
Expand Down Expand Up @@ -264,6 +267,65 @@ test("relocated immutable records reuse complete subtrees without hiding fresh d
current: prepareContextDelivery(request)}).context, request.context);
});

test("relocated evidence overlays keep current controls literal without repeating reference paths", () => {
const requirements = Array.from({length: 24}, (_, i) => ({id: `r${i}`,
description: `Requirement ${i}: ${long}`, status: "unverified", planning_satisfied: false,
unknown_control: {may_publish: false},
agent_review: {conclusion: "uncertain", basis_current: false,
independently_verified: false, note: `Evidence ${i}: ${long}`, evidence_refs: [`artifact:${i}`]}}));
const acceptance = {outcome_requirements: {revision: 1,
outcomes: [{id: "outcome", objective: long, requirements}]}};
const work = {complete: true, sources: [{source: "goal_acceptance", content: {
provider_revision: "current", goal_acceptance_contract: acceptance}}]};
// Actual callers relocate acceptance from planning into the admitted source.
const original = {planning_horizon: {core_goal: {objective: long, acceptance_contract: acceptance}}};
const current = {interaction_contract: {agent_channel: {work_context: work}}};
const initial = prepareContextDelivery({context: original, scope, capture_id: "a", surface: "quota_packet"});
const args = {context: current, scope, capture_id: "b", surface: "quota_packet"};
const delta = prepareContextDelivery({...args, baseline: initial, retained: {complete: true, target: initial.target}});
assert.equal(delta.mode, "delta");
const overlays: JsonObject[] = [];
const walk = (value: unknown) => {
if (!value || typeof value !== "object") return;
const item = value as JsonObject;
if (item.from && item.edit) overlays.push(item);
Object.values(item).forEach(walk);
};
walk(delta.changes);
assert.ok(overlays.length > 0, "relocated evidence should share a base with literal current overrides");
const path = ["interaction_contract", "agent_channel", "work_context", "sources", 0, "content",
"goal_acceptance_contract", "outcome_requirements"];
assert.equal(inline(delta, [...path, "revision"]), 1);
requirements.forEach((row, i) => {
const prefix = [...path, "outcomes", 0, "requirements", i];
assert.equal(inline(delta, [...prefix, "status"]), row.status);
assert.equal(inline(delta, [...prefix, "planning_satisfied"]), row.planning_satisfied);
assert.equal(inline(delta, [...prefix, "unknown_control", "may_publish"]), false);
for (const field of ["conclusion", "basis_current", "independently_verified"])
assert.equal(inline(delta, [...prefix, "agent_review", field]), (row.agent_review as JsonObject)[field]);
});
assert.deepEqual(restoreContextDelivery({delivery: delta, baseline: initial,
current: prepareContextDelivery(args)}).context, current);
assert.deepEqual(initial.context, original);
// Losing a current override, redirecting the base, or adding a patch-local
// reference must recover the current original, never revive inherited control.
for (const mutate of [(item: JsonObject) => { delete item.edit; },
(item: JsonObject) => { item.from = ["constructor", "prototype"]; },
(item: JsonObject) => { item.edit = {from: ["changes"]}; }]) {
const damaged = structuredClone(delta), found: JsonObject[] = [];
const find = (value: unknown) => {
if (!value || typeof value !== "object") return;
const item = value as JsonObject;
if (item.from && item.edit) found.push(item);
Object.values(item).forEach(find);
};
find(damaged.changes); mutate(found[0]);
const result = restoreContextDelivery({delivery: damaged, baseline: initial, current: prepareContextDelivery(args)});
assert.equal(result.mode, "full");
assert.deepEqual(result.context, current);
}
});

test("exact-base source and requirement reorders preserve current positions", () => {
const initial = context();
const outcomes = ((source(initial, 2).goal_acceptance_contract as JsonObject).outcome_requirements as JsonObject).outcomes as JsonObject[];
Expand Down
Loading