Skip to content
Merged
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
33 changes: 30 additions & 3 deletions docs/reference/required-work-context.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,23 @@ narrative is never classified by headings or clipped to a size budget. Read all
delivered context and remaining reads before dependent work; changed sources need
a fresh guard. Enabled scoped acceptance does not replace original Goal intent.

Explicitly enabled native context delivery requests complete Goal material before
capture. For an unmarked or mixed Goal, the registered-source adapter supplies
the entire original UTF-8 text with its full-file revision and `full_source: true`.
The existing TypeScript interaction owner checks that digest before fulfilling
the read; `complete_goal_v1` acknowledges support so an older runtime cannot
silently retain a pending Goal read. Missing or invalid sources still reject.
Marked sources retain their generated-region lineage and canonical Todo authority.

Native delta delivery and source fulfillment share the same integrity predicate.
Only exact verified Goal text can be inherited from the retained baseline;
current source witnesses and unknown fields remain literal. Cold delivery and
context-loss recovery retain the complete original text, including arbitrary
sections, comments and final stops. This does not establish model retention,
execution authority, token savings or accepted outcome gains.

The Goal availability adapter still reads and UTF-8-validates the complete file
and hashes all bytes for its revision. For unmarked or mixed ownership, only its path and revision cross the
and hashes all bytes for its revision. With native context delivery off, only the path and revision of unmarked or mixed sources cross the
internal context-projection bridge, preserving the complete progressive read
without an unused body copy. Explicitly owned sources send the complete
non-generated narrative and region lineage to the typed consumer. Missing files
Expand Down Expand Up @@ -454,8 +469,20 @@ Todo 区域相交的区间均拒绝。
普通注释、代码块中的示例、损坏或未知回执、其他 Goal 的回执和附带其他文字的行均原样
保留。这样首轮全文读取不再携带累积的恢复日志;不改变回执重放校验,也不据此宣称
模型输入或 token 成本已经降低。
Goal adapter 仍完整读取文件、校验 UTF-8,并以全部字节计算修订摘要;未标记或混合归属
仅在内部桥接传路径与修订,避免未被消费的正文副本,Agent 仍须渐进式全文读取。显式
显式开启的 native context delivery 在捕获前请求完整 Goal。未标记或混合归属的来源
由原 registered-source adapter 提供全部原始 UTF-8 正文、完整修订与 `full_source: true`。
既有 TypeScript interaction owner 核对正文 digest 后才履行读取;`complete_goal_v1`
确认 runtime 支持,防止旧版静默保留未完成 Goal 读取。来源缺失或无效仍拒绝;已有标记
来源保留生成区域血缘和 canonical Todo 权限。

native 差分与来源履行共享同一完整性判断;只有精确核验的 Goal 正文可从保留的
baseline 继承,当前来源凭据和未知字段仍明文提供。冷态及上下文丢失恢复保留完整
原文,包括任意章节、注释和末尾停止条件。不据此证明模型保留、执行权限、token 节省
或已验收成果收益。

Goal adapter 仍完整读取文件、校验 UTF-8,并以全部字节计算修订摘要;关闭 native
context delivery 时,未标记或混合归属仅在内部桥接传路径与修订,避免未被消费的正文
副本,Agent 仍须渐进式全文读取。显式
归属的来源才向 typed owner 传完整非生成正文和区域血缘。字节减少不能证明模型费用、
延迟或任务效果改善。
已附带的内容不要求重复读取;未提供的 provider 内容继续保留精确命令与顺序。
Expand Down
4 changes: 2 additions & 2 deletions loopx/cli_commands/quota.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from .quota_capture import (
bind_capture_selection_transport, capture_decision, handoff_decision,
handle_native_context_command, handle_replan_view, prepare_quota_capture, native_context_capture_view,
native_context_activation,
)
from ..control_plane.turn_driver.decision_capture import (
context_capture_read_command,
Expand Down Expand Up @@ -374,8 +375,6 @@ def _emit_quota_result(
turn_id=_effective_spend_turn_instance_id(payload, heartbeat_turn_id=heartbeat_turn_id),
started_at=usage_quota_started,
)
from .quota_capture import native_context_activation

context_delivery_enabled = payload.get("ok") is True and native_context_activation(args)["enabled"]
bind_capture_selection_transport(payload, args)
delivery_request = None
Expand Down Expand Up @@ -610,6 +609,7 @@ def handle_quota_command(
status_payload,
goal_id=args.goal_id,
agent_id=args.agent_id,
inline_goal_source=native_context_activation(args)["enabled"],
available_capabilities=args.available_capabilities,
include_scheduler_detail="scheduler" in detail_sections,
include_agent_todo_detail=(
Expand Down
4 changes: 3 additions & 1 deletion loopx/control_plane/quota/context_delivery.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {completeGoalNarrative} from "../work_items/goal_context_source.ts";
/** Presentation of immutable quota, Turn and work-context captures. No admission or state writes.
* Confirmed final input and explicit native-hook continuity assumptions remain
* distinct; successful capture handoff alone is never retained-input proof. */
Expand Down Expand Up @@ -84,7 +85,8 @@ function splitContext(context: JsonObject, binding: JsonObject): Split {
&& readModel.contract_fields.every(field => typeof field === "string"))
add(`todo_contract_fields:${i}`, [...prefix, "authority_read", "todo_read_model", "contract_fields"], true);
if (kind === "goal_state" && typeof content.state_file === "string"
&& typeof content.text === "string" && Array.isArray(content.excluded_todo_regions)) {
&& typeof content.text === "string" && (Array.isArray(content.excluded_todo_regions)
|| content.full_source === true && completeGoalNarrative(content))) {
const id = JSON.stringify([kind, content.state_file]);
if (sourceIds.has(id)) { valid = false; continue; }
sourceIds.add(id);
Expand Down
3 changes: 2 additions & 1 deletion loopx/control_plane/quota/live_decision.py
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,7 @@ def build_live_quota_should_run_decision(
turn_start_hook_dispatch: Mapping[str, Any] | None = None,
workspace_path: Path | None = None,
goal_ref: Mapping[str, object] | None = None,
inline_goal_source: bool = False,
) -> dict[str, Any]:
"""Build one live CLI decision while keeping host observation injectable."""
resolved_context = resolve_scheduler_execution_context(scheduler_execution_context)
Expand Down Expand Up @@ -824,5 +825,5 @@ def build_live_quota_should_run_decision(
from ..work_items.context_readback import attach_work_context

attach_work_context(payload, registry_path=registry_path, runtime_root=runtime_root,
hook_dispatch=turn_start_hook_dispatch)
hook_dispatch=turn_start_hook_dispatch, inline_goal_source=inline_goal_source)
return payload
20 changes: 15 additions & 5 deletions loopx/control_plane/work_items/context_readback.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
from ..todos.summary_item import todo_text_content_revision


def _source_content(read, *, registry_path, runtime_root, goal_id, todo_id):
def _source_content(read, *, registry_path, runtime_root, goal_id, todo_id,
inline_goal_source=False):
source = read.get("source")
if source == "goal_state":
_goal, _project, state_file = resolve_goal_state(
Expand All @@ -32,8 +33,8 @@ def _source_content(read, *, registry_path, runtime_root, goal_id, todo_id):
"revision": "sha256:" + sha256(source_bytes).hexdigest()}
# Only the writer's explicitly marked regions have generated ownership.
# Retain every other byte, except identity-bound historical Monitor
# receipt lines owned by their codec. Legacy/unmarked input stays a full
# progressive read; malformed ownership fails rather than hiding text.
# receipt lines owned by their codec. Progressive callers keep legacy
# reads; native delivery retains the entire unmarked source.
lines = text.splitlines(keepends=True)
visible = visible_markdown_lines(lines)
regions = find_todo_regions(lines, visible=visible)
Expand Down Expand Up @@ -63,6 +64,8 @@ def _source_content(read, *, registry_path, runtime_root, goal_id, todo_id):
# grows the current prompt without adding recovery information.
content["excluded_monitor_receipts"] = {"count": receipt_count,
"line_ranges": receipt_ranges}
if inline_goal_source and "text" not in content:
content.update(text=text, full_source=True)
return content
if source == "goal_acceptance":
# The typed acceptance owner scopes task-binding observations while
Expand Down Expand Up @@ -127,7 +130,8 @@ def _user_context(*, registry_path, runtime_root, goal_id, agent_id):


def attach_work_context(payload: dict[str, Any], *, registry_path: Path,
runtime_root: Path, hook_dispatch: dict[str, Any] | None) -> None:
runtime_root: Path, hook_dispatch: dict[str, Any] | None,
inline_goal_source: bool = False) -> None:
packet_selected = payload.get("selected_todo")
selected_text_snapshot = None
if isinstance(packet_selected, dict):
Expand All @@ -152,7 +156,8 @@ def attach_work_context(payload: dict[str, Any], *, registry_path: Path,
result = {"command": read["command"]}
try:
result["content"] = _source_content(read, registry_path=registry_path,
runtime_root=runtime_root, goal_id=goal_id, todo_id=plan.get("todo_id"))
runtime_root=runtime_root, goal_id=goal_id, todo_id=plan.get("todo_id"),
inline_goal_source=inline_goal_source)
except (OSError, ValueError, RuntimeError):
result["error_code"] = "context_source_unavailable"
results.append(result)
Expand All @@ -167,7 +172,12 @@ def attach_work_context(payload: dict[str, Any], *, registry_path: Path,
"required_reads": reads, "source_results": results,
"selected_todo": plan.get("selected_todo"), "user_todos": users,
"hook_dispatch": hook_dispatch,
**({"require_full_goal_source": True} if inline_goal_source else {}),
}, large_local_snapshot=True)
# An older runtime must not silently ignore the requested delivery profile.
profile = projected.pop("source_delivery_profile", None)
if inline_goal_source and profile != "complete_goal_v1":
raise RuntimeError("Complete Goal source delivery is unsupported by this runtime")
channel.update(projected)
selected_todo = payload.get("selected_todo")
if isinstance(selected_todo, dict):
Expand Down
67 changes: 67 additions & 0 deletions loopx/control_plane/work_items/goal_context_source.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/** Integrity of registered Goal source observations, shared by delivery and exact reuse. */
import {createHash} from "node:crypto";
import type {JsonObject} from "../effect_program.ts";
import {jsonObject} from "../runtime_decode.ts";
import {ENVELOPED_SHA256_PATTERN} from "../content_digest.ts";

/** The registered file adapter reuses the writer's strict region parser.
* No heading/prose classification here: its exact complement is Goal context,
* and canonical Todo readers retain task authority. A complete original file
* needs no exclusions; metadata alone retains the progressive read. */
export function completeGoalNarrative(content: JsonObject): boolean {
if (Object.hasOwn(content, "read_complete") && content.read_complete !== true) return false;
if (Object.hasOwn(content, "full_source")) {
return content.full_source === true && typeof content.text === "string"
&& typeof content.state_file === "string" && content.state_file.length > 0
&& content.revision === `sha256:${createHash("sha256").update(content.text, "utf8").digest("hex")}`
&& !Object.hasOwn(content, "excluded_todo_regions")
&& !Object.hasOwn(content, "excluded_monitor_receipts");
}
if (!Array.isArray(content.excluded_todo_regions) || !content.excluded_todo_regions.length
|| typeof content.text !== "string" || typeof content.state_file !== "string" || !content.state_file
|| typeof content.revision !== "string" || !ENVELOPED_SHA256_PATTERN.test(content.revision)) return false;
let end = 0;
if (!content.excluded_todo_regions.every(value => {
const region = jsonObject(value);
if (!region || !["user", "agent", "archive"].includes(String(region.role))
|| !Number.isSafeInteger(region.start_line) || !Number.isSafeInteger(region.end_line)
|| Number(region.start_line) <= end || Number(region.end_line) < Number(region.start_line)
|| typeof region.revision !== "string" || !ENVELOPED_SHA256_PATTERN.test(region.revision)) return false;
end = Number(region.end_line);
return true;
})) return false;
if (!Object.hasOwn(content, "excluded_monitor_receipts")) return true;
const receipts = content.excluded_monitor_receipts;
const compact = jsonObject(receipts);
let ranges: unknown[];
let expectedCount: number;
if (compact) {
if (Object.keys(compact).some(key => !["count", "line_ranges"].includes(key))
|| !Number.isSafeInteger(compact.count) || Number(compact.count) <= 0
|| !Array.isArray(compact.line_ranges)) return false;
ranges = compact.line_ranges;
expectedCount = Number(compact.count);
} else {
// Already captured source observations retain their original readback.
if (!Array.isArray(receipts) || !receipts.length) return false;
ranges = [];
for (const value of receipts) {
const region = jsonObject(value);
if (!region || region.start_line !== region.end_line || typeof region.revision !== "string"
|| !ENVELOPED_SHA256_PATTERN.test(region.revision)) return false;
ranges.push([region.start_line, region.end_line]);
}
expectedCount = receipts.length;
}
end = 0;
let count = 0;
return ranges.length > 0 && ranges.every(range => {
if (!Array.isArray(range) || range.length !== 2 || !range.every(Number.isSafeInteger)
|| range[0] <= end || range[1] < range[0]
|| (content.excluded_todo_regions as JsonObject[]).some(todo =>
range[0] <= Number(todo.end_line) && range[1] >= Number(todo.start_line))) return false;
end = range[1];
count += range[1] - range[0] + 1;
return true;
}) && Number.isSafeInteger(count) && count === expectedCount;
}
Loading
Loading