From 9ae4066ca7f8862534d1b8d7f40e4dc88f38c984 Mon Sep 17 00:00:00 2001 From: Tristan Simas Date: Mon, 19 Oct 2026 00:08:12 -0400 Subject: [PATCH 1/8] P197: a done report's measure is its order's Check MeasuredClaim joins the ProgressClaim family: what a report ran and the count it printed. CommsOrderDoneTool compares every claim against the order's declared Check, so a report quoting another command or count is refused with both shown. Src-Budget: 31 Co-Authored-By: Claude Opus 5.5 --- src/agent_comms/progress_claims.py | 32 +++++++++++++++++++++++++- src/agent_comms/tools.py | 3 ++- tests/test_commander_problem_orders.py | 15 +++++++++++- 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/src/agent_comms/progress_claims.py b/src/agent_comms/progress_claims.py index fe93a849b4..2c662b1f0a 100644 --- a/src/agent_comms/progress_claims.py +++ b/src/agent_comms/progress_claims.py @@ -2,7 +2,8 @@ A claim is a typed record, never a word in free text: merged names a commit that resolves on origin, installed names the order whose check result is recorded, working names a screenshot -that exists. A claim whose artifact does not verify is refused with that artifact named. +that exists, measured quotes the command a report ran and the count it printed. A claim whose +artifact does not verify is refused with that artifact named. """ from __future__ import annotations @@ -14,6 +15,7 @@ from typing import TYPE_CHECKING, ClassVar from .declared_family import DeclaredFamily +from .goals import CountCheckResult, OrderCheck if TYPE_CHECKING: from .comms import Comms @@ -25,11 +27,20 @@ class ProgressClaim(DeclaredFamily, affix="Claim"): def verify(self, comms: Comms, worktree: Path) -> None: """Raise ValueError naming the missing artifact unless it verifies.""" + def measures(self, check: OrderCheck) -> None: + """Raise ValueError unless this claim measured what the order's Check declares.""" + @classmethod def require_all(cls, claims: tuple[ProgressClaim, ...], comms: Comms, worktree: Path) -> None: for claim in claims: claim.verify(comms, worktree) + @classmethod + def require_measured(cls, claims: tuple[ProgressClaim, ...], check: OrderCheck) -> None: + """A done report's measure is its order's Check, never one the report chose.""" + for claim in claims: + claim.measures(check) + @classmethod def require_claimed(cls, claims: tuple[ProgressClaim, ...], report: str) -> None: """A done or delivered report stands only on an attached claim, never on its prose.""" @@ -75,6 +86,25 @@ def verify(self, comms: Comms, worktree: Path) -> None: comms.goals.todos.get(self.problem).order.require_checked(self.problem) +@dataclass(frozen=True) +class MeasuredClaim(ProgressClaim): + """What a report ran and the count it printed; the order's Check stays the measure.""" + + command: str + count: int + + def verify(self, comms: Comms, worktree: Path) -> None: + """Its artifact is the order's Check result, which the delivery records.""" + + def measures(self, check: OrderCheck) -> None: + if (self.command, CountCheckResult(self.count)) != (check.command, check.result): + raise ValueError( + f"The report measured {self.command!r} -> {self.count}; the order's Check is " + f"{check.command!r} -> {check.result}. Report the Check's result at the " + "delivered head." + ) + + @dataclass(frozen=True) class WorkingClaim(ProgressClaim): screenshot: str diff --git a/src/agent_comms/tools.py b/src/agent_comms/tools.py index cb985fbbdc..36056d8eea 100644 --- a/src/agent_comms/tools.py +++ b/src/agent_comms/tools.py @@ -891,12 +891,13 @@ class CommsOrderDoneTool(ThreadToolRequest): delivery: OrderDelivery = tool_field("A clean commit delivery or an operation verified by the order's check") claims: tuple[ProgressClaim, ...] = tool_field( "Merged, installed or working claims, each with the artifact Core verifies in the order's " - "checkout; at least one") + "checkout; at least one. A measured claim must quote the order's own Check") def apply(self, comms: Comms, caller: ThreadCaller) -> GoalRead: ProgressClaim.require_claimed(self.claims, "delivered") todo = comms.goals.todos.get(self.problem) ProgressClaim.require_all(self.claims, comms, Path(todo.order.check.directory)) + ProgressClaim.require_measured(self.claims, todo.order.check) todo.require_commander(comms.registry.require(caller.name).incarnation) assignment = todo.assignment goal = comms.goals.update_goal(assignment.owner, DeliveredOrderGoalAction( diff --git a/tests/test_commander_problem_orders.py b/tests/test_commander_problem_orders.py index ab2521cb90..a241bf7cac 100644 --- a/tests/test_commander_problem_orders.py +++ b/tests/test_commander_problem_orders.py @@ -27,7 +27,7 @@ from agent_comms.goal_actions import BlockedGoalAction, CreateProblemGoalAction, ModelInvocable, OrderGoalAction, SetGoalAction from agent_comms.goal_states import CompletedGoal from agent_comms.goals import CountCheckResult, OrderCheck, ProblemGoalOrder -from agent_comms.progress_claims import WorkingClaim +from agent_comms.progress_claims import MeasuredClaim, WorkingClaim from agent_comms.recorded_time import RecordedEventTime, UnrecordedEventTime from agent_comms.threads import Thread from agent_comms.tool_caller import ThreadCaller @@ -176,6 +176,19 @@ def test_failed_check_keeps_problem_pending(commander): assert comms.registry.require('worker').goal.state.active +def test_done_report_of_a_wrong_measure_is_refused_and_the_declared_check_passes(commander): + comms, caller = commander + original = create(commander, 'P1') + for command, count in (('grep -c x tests', 1), ('printf 1', 2)): + with pytest.raises(ValueError, match=f"measured '{command}' -> {count}; the order's Check is 'printf 1'"): + CommsOrderDoneTool(problem='P1', delivery=OperationDelivery(), + claims=(*working(comms), MeasuredClaim(command, count))).apply(comms, caller) + assert comms.goals.todos.get('P1') == original + CommsOrderDoneTool(problem='P1', delivery=OperationDelivery(), + claims=(*working(comms), MeasuredClaim('printf 1', 1))).apply(comms, caller) + assert not comms.goals.todos.get('P1').pending + + def test_close_records_evidence_once_and_does_not_depend_on_artifact_lifetime(commander): comms, caller = commander create(commander, 'P1') From bc507582dd76d0599c470b742b252e14a8dd8b7b Mon Sep 17 00:00:00 2001 From: Tristan Simas Date: Mon, 19 Oct 2026 00:29:58 -0400 Subject: [PATCH 2/8] P197: done carries no measure; the board shows the Check result Core recorded Revert MeasuredClaim: it restated the order's Check only to compare it. OrderDelivery.verified now records what the order's Check printed when Core verified the delivery, and a delivered order's board line shows it. Co-Authored-By: Claude Opus 5.5 --- src/agent_comms/progress_claims.py | 32 +------------------------- src/agent_comms/todos.py | 23 +++++++++++++----- src/agent_comms/tools.py | 3 +-- tests/test_commander_problem_orders.py | 28 +++++++++++----------- 4 files changed, 33 insertions(+), 53 deletions(-) diff --git a/src/agent_comms/progress_claims.py b/src/agent_comms/progress_claims.py index 2c662b1f0a..fe93a849b4 100644 --- a/src/agent_comms/progress_claims.py +++ b/src/agent_comms/progress_claims.py @@ -2,8 +2,7 @@ A claim is a typed record, never a word in free text: merged names a commit that resolves on origin, installed names the order whose check result is recorded, working names a screenshot -that exists, measured quotes the command a report ran and the count it printed. A claim whose -artifact does not verify is refused with that artifact named. +that exists. A claim whose artifact does not verify is refused with that artifact named. """ from __future__ import annotations @@ -15,7 +14,6 @@ from typing import TYPE_CHECKING, ClassVar from .declared_family import DeclaredFamily -from .goals import CountCheckResult, OrderCheck if TYPE_CHECKING: from .comms import Comms @@ -27,20 +25,11 @@ class ProgressClaim(DeclaredFamily, affix="Claim"): def verify(self, comms: Comms, worktree: Path) -> None: """Raise ValueError naming the missing artifact unless it verifies.""" - def measures(self, check: OrderCheck) -> None: - """Raise ValueError unless this claim measured what the order's Check declares.""" - @classmethod def require_all(cls, claims: tuple[ProgressClaim, ...], comms: Comms, worktree: Path) -> None: for claim in claims: claim.verify(comms, worktree) - @classmethod - def require_measured(cls, claims: tuple[ProgressClaim, ...], check: OrderCheck) -> None: - """A done report's measure is its order's Check, never one the report chose.""" - for claim in claims: - claim.measures(check) - @classmethod def require_claimed(cls, claims: tuple[ProgressClaim, ...], report: str) -> None: """A done or delivered report stands only on an attached claim, never on its prose.""" @@ -86,25 +75,6 @@ def verify(self, comms: Comms, worktree: Path) -> None: comms.goals.todos.get(self.problem).order.require_checked(self.problem) -@dataclass(frozen=True) -class MeasuredClaim(ProgressClaim): - """What a report ran and the count it printed; the order's Check stays the measure.""" - - command: str - count: int - - def verify(self, comms: Comms, worktree: Path) -> None: - """Its artifact is the order's Check result, which the delivery records.""" - - def measures(self, check: OrderCheck) -> None: - if (self.command, CountCheckResult(self.count)) != (check.command, check.result): - raise ValueError( - f"The report measured {self.command!r} -> {self.count}; the order's Check is " - f"{check.command!r} -> {check.result}. Report the Check's result at the " - "delivered head." - ) - - @dataclass(frozen=True) class WorkingClaim(ProgressClaim): screenshot: str diff --git a/src/agent_comms/todos.py b/src/agent_comms/todos.py index 662d1e03d0..51bf96a759 100644 --- a/src/agent_comms/todos.py +++ b/src/agent_comms/todos.py @@ -45,6 +45,7 @@ @dataclass(frozen=True, kw_only=True) class OrderDelivery(DeclaredFamily, affix="Delivery"): at: EventTime = field(default_factory=UnrecordedEventTime) + printed: str = "" # what the order's Check printed when Core verified this delivery @property def work(self) -> str: @@ -56,12 +57,19 @@ async def run(self, check, *command): raise ValueError(result.stderr.decode(errors="replace") or "Delivery source check failed.") return result.stdout.decode(errors="replace") + async def passed(self, check: OrderCheck) -> str: + await self.require_source(check) + result = await self.checked(check) + check.result.require(result) + return result.stdout.decode(errors="replace").strip() + async def verified(self, check: OrderCheck, deletes: OrderDeletion) -> OrderDelivery: - """The order's check and every count its deletion declares run on the delivered source.""" - for each in (check, *deletes.checks): - await self.require_source(each) - each.result.require(await self.checked(each)) - return replace(self, at=await self.delivery_time(check)) + """The order's check and every count its deletion declares run on the delivered source; + the delivery records what the order's check printed, never what a report says.""" + printed = await self.passed(check) + for each in deletes.checks: + await self.passed(each) + return replace(self, at=await self.delivery_time(check), printed=printed) @abstractmethod async def require_source(self, check): ... @@ -1013,7 +1021,10 @@ def withdrawn(self, previous: Assignment, why: str, superseded_by: str | None) - class DeliveredProblemOrder(ProblemOrder): delivery: OrderDelivery pending: ClassVar[bool] = False - line: ClassVar[str] = "Delivered, waiting on install" + + @property + def line(self) -> str: + return f"Delivered, waiting on install · Check printed {self.delivery.printed!r}" def require_transfer(self, todo: Todo) -> None: owner = (todo.assignment or todo.released[-1].previous).owner diff --git a/src/agent_comms/tools.py b/src/agent_comms/tools.py index 36056d8eea..cb985fbbdc 100644 --- a/src/agent_comms/tools.py +++ b/src/agent_comms/tools.py @@ -891,13 +891,12 @@ class CommsOrderDoneTool(ThreadToolRequest): delivery: OrderDelivery = tool_field("A clean commit delivery or an operation verified by the order's check") claims: tuple[ProgressClaim, ...] = tool_field( "Merged, installed or working claims, each with the artifact Core verifies in the order's " - "checkout; at least one. A measured claim must quote the order's own Check") + "checkout; at least one") def apply(self, comms: Comms, caller: ThreadCaller) -> GoalRead: ProgressClaim.require_claimed(self.claims, "delivered") todo = comms.goals.todos.get(self.problem) ProgressClaim.require_all(self.claims, comms, Path(todo.order.check.directory)) - ProgressClaim.require_measured(self.claims, todo.order.check) todo.require_commander(comms.registry.require(caller.name).incarnation) assignment = todo.assignment goal = comms.goals.update_goal(assignment.owner, DeliveredOrderGoalAction( diff --git a/tests/test_commander_problem_orders.py b/tests/test_commander_problem_orders.py index a241bf7cac..cc389a72d3 100644 --- a/tests/test_commander_problem_orders.py +++ b/tests/test_commander_problem_orders.py @@ -14,7 +14,7 @@ import pytest from contextlib import closing -from dataclasses import replace +from dataclasses import fields, replace from cutover.carry import CarryChain @@ -27,12 +27,13 @@ from agent_comms.goal_actions import BlockedGoalAction, CreateProblemGoalAction, ModelInvocable, OrderGoalAction, SetGoalAction from agent_comms.goal_states import CompletedGoal from agent_comms.goals import CountCheckResult, OrderCheck, ProblemGoalOrder -from agent_comms.progress_claims import MeasuredClaim, WorkingClaim +from agent_comms.progress_claims import WorkingClaim from agent_comms.recorded_time import RecordedEventTime, UnrecordedEventTime from agent_comms.threads import Thread from agent_comms.tool_caller import ThreadCaller from agent_comms.tools import (CommsCorrectWordingTool, CommsSendTool, CommsFireTool, CommsOrderCheckTool, CommsOrderDoneTool, CommsOrderTool, - CommsOrderWorkTool, CommsProblemCloseTool, CommsTodoCreateTool, CommsTodoListTool, CommsTodoTool, CommsVerdictTool) + CommsOrderWorkTool, CommsProblemCloseTool, CommsTodoCreateTool, CommsTodoListTool, CommsTodoTool, CommsVerdictTool, + ThreadToolRequest) from agent_comms.todos import (AwaitingFirstCall, VerdictAudience, OrderMessage, OrderDeletion, GoalRef, CleanHunt, CommitDelivery, FirstCall, Hunt, OrderDelivery, ApplicationOrderRun, RecordedCommitDelivery, MechanicalOrderRun, TodoStore, LateObservedFirstCall, OperationDelivery, OrderedHunt, @@ -176,17 +177,16 @@ def test_failed_check_keeps_problem_pending(commander): assert comms.registry.require('worker').goal.state.active -def test_done_report_of_a_wrong_measure_is_refused_and_the_declared_check_passes(commander): +def test_done_declares_no_wrong_measure_and_the_board_shows_the_recorded_check_result(commander): comms, caller = commander - original = create(commander, 'P1') - for command, count in (('grep -c x tests', 1), ('printf 1', 2)): - with pytest.raises(ValueError, match=f"measured '{command}' -> {count}; the order's Check is 'printf 1'"): - CommsOrderDoneTool(problem='P1', delivery=OperationDelivery(), - claims=(*working(comms), MeasuredClaim(command, count))).apply(comms, caller) - assert comms.goals.todos.get('P1') == original - CommsOrderDoneTool(problem='P1', delivery=OperationDelivery(), - claims=(*working(comms), MeasuredClaim('printf 1', 1))).apply(comms, caller) - assert not comms.goals.todos.get('P1').pending + create(commander, 'P1') + reported = {f.name for f in fields(CommsOrderDoneTool)} - {f.name for f in fields(ThreadToolRequest)} + assert reported == {'problem', 'delivery', 'claims'} + CommsOrderDoneTool(problem='P1', delivery=OperationDelivery(), claims=working(comms)).apply(comms, caller) + assert comms.goals.todos.get('P1').order.delivery.printed == '1' + worker = comms.registry.require('worker') + progress = GoalSegment.capture(worker, worker.goal, comms.goals).progress + assert progress == "P1: Delivered, waiting on install · Check printed '1'" def test_close_records_evidence_once_and_does_not_depend_on_artifact_lifetime(commander): @@ -1202,7 +1202,7 @@ def test_a_problem_goal_shows_only_its_live_orders_through_convert_deliver_send_ todo.assignment, 'toolu_3', reason=StrikeReason(why))).apply(comms, caller) worker = comms.registry.require('worker') progress = GoalSegment.capture(worker, worker.goal, comms.goals).progress - assert progress.splitlines() == ['P1: Delivered, waiting on install', f'P2: Open · Sent back: {why}'] + assert progress.splitlines() == ["P1: Delivered, waiting on install · Check printed '1'", f'P2: Open · Sent back: {why}'] assert (worker.goal.text, worker.goal.progress) == (ProblemGoalOrder.text, '') with pytest.raises(ValueError, match='block the problem.s Todo, or standby with wait_for'): comms.goals.update_goal('worker', BlockedGoalAction(block_reason='Waiting on lead.'), actor=ModelInvocable) From ec42bf412f73833552b0170e7677c66a761a4eac Mon Sep 17 00:00:00 2001 From: Tristan Simas Date: Mon, 19 Oct 2026 00:36:58 -0400 Subject: [PATCH 3/8] P197: the delivered order records what its Check printed The delivery stays as recorded, so a record from before the split still round-trips; DeliverTodo carries the printed result to the delivered order whose board line shows it. Co-Authored-By: Claude Opus 5.5 --- src/agent_comms/todos.py | 23 ++++++++++++----------- tests/test_commander_problem_orders.py | 2 +- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/agent_comms/todos.py b/src/agent_comms/todos.py index 51bf96a759..e95a67cd9a 100644 --- a/src/agent_comms/todos.py +++ b/src/agent_comms/todos.py @@ -45,7 +45,6 @@ @dataclass(frozen=True, kw_only=True) class OrderDelivery(DeclaredFamily, affix="Delivery"): at: EventTime = field(default_factory=UnrecordedEventTime) - printed: str = "" # what the order's Check printed when Core verified this delivery @property def work(self) -> str: @@ -63,13 +62,13 @@ async def passed(self, check: OrderCheck) -> str: check.result.require(result) return result.stdout.decode(errors="replace").strip() - async def verified(self, check: OrderCheck, deletes: OrderDeletion) -> OrderDelivery: + async def verified(self, check: OrderCheck, deletes: OrderDeletion) -> tuple[OrderDelivery, str]: """The order's check and every count its deletion declares run on the delivered source; - the delivery records what the order's check printed, never what a report says.""" + with the delivery comes what the order's check printed, never what a report says.""" printed = await self.passed(check) for each in deletes.checks: await self.passed(each) - return replace(self, at=await self.delivery_time(check), printed=printed) + return replace(self, at=await self.delivery_time(check)), printed @abstractmethod async def require_source(self, check): ... @@ -960,9 +959,9 @@ def instructions(self, todo): *(f"{n}. {edit}" for n, edit in enumerate(self.edits, 1)), "Banned: " + "; ".join(self.banned), "Report: " + self.report)) - def delivered(self, delivery): + def delivered(self, delivery, printed): delivery.at.require_delivery() - return self.copy_as(DeliveredProblemOrder, delivery=delivery) + return self.copy_as(DeliveredProblemOrder, delivery=delivery, printed=printed) def corrected(self, correction: CorrectCheckTodo) -> ProblemOrder: if correction.previous != self.check: @@ -1020,17 +1019,18 @@ def withdrawn(self, previous: Assignment, why: str, superseded_by: str | None) - @dataclass(frozen=True, kw_only=True) class DeliveredProblemOrder(ProblemOrder): delivery: OrderDelivery + printed: str = "" # what the order's Check printed when Core verified the delivery pending: ClassVar[bool] = False @property def line(self) -> str: - return f"Delivered, waiting on install · Check printed {self.delivery.printed!r}" + return f"Delivered, waiting on install · Check printed {self.printed!r}" def require_transfer(self, todo: Todo) -> None: owner = (todo.assignment or todo.released[-1].previous).owner raise ValueError(f"{owner} already has {self.delivery.work}; {owner} merges it.") - def delivered(self, delivery): + def delivered(self, delivery, printed): if delivery != self.delivery: raise ValueError("The order already records a different delivery.") return self @@ -1545,17 +1545,18 @@ def apply(self, current): class DeliverTodo(TodoOperation): actor: ThreadIncarnation delivery: OrderDelivery + printed: str = "" def prepare(self, goals, current): current.require_revision(self.expected_revision) current.require_commander(self.actor) - verified = self.delivery.verified(current.order.check, current.order.deletes) - return replace(self, delivery=asyncio.run(verified)) + delivery, printed = asyncio.run(self.delivery.verified(current.order.check, current.order.deletes)) + return replace(self, delivery=delivery, printed=printed) def apply(self, current): current.require_revision(self.expected_revision) current.require_commander(self.actor) - return replace(current, order=current.order.delivered(self.delivery), revision=current.revision + 1) + return replace(current, order=current.order.delivered(self.delivery, self.printed), revision=current.revision + 1) @dataclass(frozen=True) diff --git a/tests/test_commander_problem_orders.py b/tests/test_commander_problem_orders.py index cc389a72d3..096b69b293 100644 --- a/tests/test_commander_problem_orders.py +++ b/tests/test_commander_problem_orders.py @@ -183,7 +183,7 @@ def test_done_declares_no_wrong_measure_and_the_board_shows_the_recorded_check_r reported = {f.name for f in fields(CommsOrderDoneTool)} - {f.name for f in fields(ThreadToolRequest)} assert reported == {'problem', 'delivery', 'claims'} CommsOrderDoneTool(problem='P1', delivery=OperationDelivery(), claims=working(comms)).apply(comms, caller) - assert comms.goals.todos.get('P1').order.delivery.printed == '1' + assert comms.goals.todos.get('P1').order.printed == '1' worker = comms.registry.require('worker') progress = GoalSegment.capture(worker, worker.goal, comms.goals).progress assert progress == "P1: Delivered, waiting on install · Check printed '1'" From e498b82595a05b4bf3fdb72345001a1e88e8d31c Mon Sep 17 00:00:00 2001 From: Tristan Simas Date: Mon, 19 Oct 2026 00:38:25 -0400 Subject: [PATCH 4/8] P197: wrap the verified delivery lines Co-Authored-By: Claude Opus 5.5 --- src/agent_comms/todos.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/agent_comms/todos.py b/src/agent_comms/todos.py index e95a67cd9a..eb8343589a 100644 --- a/src/agent_comms/todos.py +++ b/src/agent_comms/todos.py @@ -62,7 +62,8 @@ async def passed(self, check: OrderCheck) -> str: check.result.require(result) return result.stdout.decode(errors="replace").strip() - async def verified(self, check: OrderCheck, deletes: OrderDeletion) -> tuple[OrderDelivery, str]: + async def verified(self, check: OrderCheck, + deletes: OrderDeletion) -> tuple[OrderDelivery, str]: """The order's check and every count its deletion declares run on the delivered source; with the delivery comes what the order's check printed, never what a report says.""" printed = await self.passed(check) @@ -1550,7 +1551,8 @@ class DeliverTodo(TodoOperation): def prepare(self, goals, current): current.require_revision(self.expected_revision) current.require_commander(self.actor) - delivery, printed = asyncio.run(self.delivery.verified(current.order.check, current.order.deletes)) + verified = self.delivery.verified(current.order.check, current.order.deletes) + delivery, printed = asyncio.run(verified) return replace(self, delivery=delivery, printed=printed) def apply(self, current): From 03920675d563b1f5091322e3fd886624b20a0459 Mon Sep 17 00:00:00 2001 From: Tristan Simas Date: Mon, 19 Oct 2026 00:40:21 -0400 Subject: [PATCH 5/8] P197: the board reads each order's progress line Co-Authored-By: Claude Opus 5.5 --- src/agent_comms/goals.py | 2 +- src/agent_comms/todos.py | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/agent_comms/goals.py b/src/agent_comms/goals.py index 2dd354a8f7..e22882e8d5 100644 --- a/src/agent_comms/goals.py +++ b/src/agent_comms/goals.py @@ -577,7 +577,7 @@ def goal_text(self, goal: Goal) -> str: def progress(self, goal: Goal, todos: Sequence[Todo]) -> str: """Each problem's order state and latest verdict, as Core records them on its Todo.""" - return "\n".join(" · ".join((f"{todo.id}: {todo.order.line}", + return "\n".join(" · ".join((f"{todo.id}: {todo.order.progress_line()}", *(verdict.line for verdict in todo.verdicts[-1:]))) for todo in todos) diff --git a/src/agent_comms/todos.py b/src/agent_comms/todos.py index eb8343589a..e2c64f79b0 100644 --- a/src/agent_comms/todos.py +++ b/src/agent_comms/todos.py @@ -897,6 +897,10 @@ def __post_init__(self): pending: ClassVar[bool] line: ClassVar[str] + + def progress_line(self) -> str: + """This order's state on the board.""" + return self.line NAMED_FILE: ClassVar[re.Pattern] = re.compile(r"([\w./-]+\.\w+):\d+") def require_transfer(self, todo: Todo) -> None: @@ -1022,10 +1026,10 @@ class DeliveredProblemOrder(ProblemOrder): delivery: OrderDelivery printed: str = "" # what the order's Check printed when Core verified the delivery pending: ClassVar[bool] = False + line: ClassVar[str] = "Delivered, waiting on install" - @property - def line(self) -> str: - return f"Delivered, waiting on install · Check printed {self.printed!r}" + def progress_line(self) -> str: + return f"{self.line} · Check printed {self.printed!r}" def require_transfer(self, todo: Todo) -> None: owner = (todo.assignment or todo.released[-1].previous).owner From 2d8dae4ec86026749e1c69ed566d2051efd8bd7e Mon Sep 17 00:00:00 2001 From: Tristan Simas Date: Mon, 19 Oct 2026 00:56:44 -0400 Subject: [PATCH 6/8] P197: the verified delivery member records what the order's Check printed DeliverTodo's verified delivery is now CheckedCommitDelivery or CheckedOperationDelivery, carrying printed as its own field; saved deliveries without a print decode as their declared member and the board says no print was recorded. No tuple and no empty-string defaults. Co-Authored-By: Claude Opus 5.5 --- src/agent_comms/todos.py | 54 +++++++++++++++++++------- tests/test_commander_problem_orders.py | 5 ++- 2 files changed, 44 insertions(+), 15 deletions(-) diff --git a/src/agent_comms/todos.py b/src/agent_comms/todos.py index e2c64f79b0..9022420106 100644 --- a/src/agent_comms/todos.py +++ b/src/agent_comms/todos.py @@ -45,11 +45,17 @@ @dataclass(frozen=True, kw_only=True) class OrderDelivery(DeclaredFamily, affix="Delivery"): at: EventTime = field(default_factory=UnrecordedEventTime) + checked_kind: ClassVar[type[OrderDelivery]] @property def work(self) -> str: return "delivered work" + @property + def check_line(self) -> str: + """A delivery saved before Core recorded the Check's print says so.""" + return "no print recorded" + async def run(self, check, *command): result = await BoundedRun.run(tuple(command), cwd=check.directory, timeout=120) if result.outcome != ExitedOutcome(0): @@ -62,14 +68,15 @@ async def passed(self, check: OrderCheck) -> str: check.result.require(result) return result.stdout.decode(errors="replace").strip() - async def verified(self, check: OrderCheck, - deletes: OrderDeletion) -> tuple[OrderDelivery, str]: + async def verified(self, check: OrderCheck, deletes: OrderDeletion) -> OrderDelivery: """The order's check and every count its deletion declares run on the delivered source; - with the delivery comes what the order's check printed, never what a report says.""" + the checked member records what the order's check printed, never what a report says.""" printed = await self.passed(check) for each in deletes.checks: await self.passed(each) - return replace(self, at=await self.delivery_time(check)), printed + carried = {item.name: getattr(self, item.name) for item in fields(self)} + return self.checked_kind( + **carried | {"at": await self.delivery_time(check), "printed": printed}) @abstractmethod async def require_source(self, check): ... @@ -138,6 +145,16 @@ async def require_source(self, check: OrderCheck) -> None: f"Delivered commit {self.delivered} is on no origin branch; push it first.") +@dataclass(frozen=True, kw_only=True) +class CheckedCommitDelivery(CommitDelivery, declared_name="checked_commit"): + """A commit delivery Core verified, with what the order's Check printed on it.""" + printed: str + + @property + def check_line(self) -> str: + return f"Check printed {self.printed!r}" + + @dataclass(frozen=True, kw_only=True) class OperationDelivery(OrderDelivery): async def require_source(self, check): @@ -150,6 +167,20 @@ async def delivery_time(self, check): return EventTime.capture(time.time()) +@dataclass(frozen=True, kw_only=True) +class CheckedOperationDelivery(OperationDelivery, declared_name="checked_operation"): + """An operation delivery Core verified, with what the order's Check printed.""" + printed: str + + @property + def check_line(self) -> str: + return f"Check printed {self.printed!r}" + + +CommitDelivery.checked_kind = CheckedCommitDelivery +OperationDelivery.checked_kind = CheckedOperationDelivery + + @dataclass(frozen=True) class PullRequest: number: int @@ -964,9 +995,9 @@ def instructions(self, todo): *(f"{n}. {edit}" for n, edit in enumerate(self.edits, 1)), "Banned: " + "; ".join(self.banned), "Report: " + self.report)) - def delivered(self, delivery, printed): + def delivered(self, delivery): delivery.at.require_delivery() - return self.copy_as(DeliveredProblemOrder, delivery=delivery, printed=printed) + return self.copy_as(DeliveredProblemOrder, delivery=delivery) def corrected(self, correction: CorrectCheckTodo) -> ProblemOrder: if correction.previous != self.check: @@ -1024,18 +1055,17 @@ def withdrawn(self, previous: Assignment, why: str, superseded_by: str | None) - @dataclass(frozen=True, kw_only=True) class DeliveredProblemOrder(ProblemOrder): delivery: OrderDelivery - printed: str = "" # what the order's Check printed when Core verified the delivery pending: ClassVar[bool] = False line: ClassVar[str] = "Delivered, waiting on install" def progress_line(self) -> str: - return f"{self.line} · Check printed {self.printed!r}" + return f"{self.line} · {self.delivery.check_line}" def require_transfer(self, todo: Todo) -> None: owner = (todo.assignment or todo.released[-1].previous).owner raise ValueError(f"{owner} already has {self.delivery.work}; {owner} merges it.") - def delivered(self, delivery, printed): + def delivered(self, delivery): if delivery != self.delivery: raise ValueError("The order already records a different delivery.") return self @@ -1550,19 +1580,17 @@ def apply(self, current): class DeliverTodo(TodoOperation): actor: ThreadIncarnation delivery: OrderDelivery - printed: str = "" def prepare(self, goals, current): current.require_revision(self.expected_revision) current.require_commander(self.actor) verified = self.delivery.verified(current.order.check, current.order.deletes) - delivery, printed = asyncio.run(verified) - return replace(self, delivery=delivery, printed=printed) + return replace(self, delivery=asyncio.run(verified)) def apply(self, current): current.require_revision(self.expected_revision) current.require_commander(self.actor) - return replace(current, order=current.order.delivered(self.delivery, self.printed), revision=current.revision + 1) + return replace(current, order=current.order.delivered(self.delivery), revision=current.revision + 1) @dataclass(frozen=True) diff --git a/tests/test_commander_problem_orders.py b/tests/test_commander_problem_orders.py index 096b69b293..c297937e66 100644 --- a/tests/test_commander_problem_orders.py +++ b/tests/test_commander_problem_orders.py @@ -183,7 +183,8 @@ def test_done_declares_no_wrong_measure_and_the_board_shows_the_recorded_check_r reported = {f.name for f in fields(CommsOrderDoneTool)} - {f.name for f in fields(ThreadToolRequest)} assert reported == {'problem', 'delivery', 'claims'} CommsOrderDoneTool(problem='P1', delivery=OperationDelivery(), claims=working(comms)).apply(comms, caller) - assert comms.goals.todos.get('P1').order.printed == '1' + delivery = comms.goals.todos.get('P1').order.delivery + assert delivery.printed == '1' and FieldCodec.decode(OrderDelivery, FieldCodec.encode(delivery)) == delivery worker = comms.registry.require('worker') progress = GoalSegment.capture(worker, worker.goal, comms.goals).progress assert progress == "P1: Delivered, waiting on install · Check printed '1'" @@ -371,7 +372,7 @@ def test_a_done_record_from_before_the_split_reads_its_one_commit_as_both(): old = {'kind': 'commit', 'commit': 'd012d23b4', 'at': FieldCodec.encode(RecordedEventTime(1000))} recorded = FieldCodec.decode(OrderDelivery, old) assert type(recorded) is RecordedCommitDelivery and recorded.delivered == recorded.commit == 'd012d23b4' - assert FieldCodec.encode(recorded) == old + assert FieldCodec.encode(recorded) == old and recorded.check_line == 'no print recorded' def test_delivery_time_has_its_own_named_requirement(): From 980dd48c0ae9d5a88ca380424b945ea8f3bf3767 Mon Sep 17 00:00:00 2001 From: Tristan Simas Date: Mon, 19 Oct 2026 00:58:42 -0400 Subject: [PATCH 7/8] P197: source budget for the two checked delivery members Src-Budget: 15 Co-Authored-By: Claude Opus 5.5 From daac0e95ebe7de255ac1c0894e505a0c7610a418 Mon Sep 17 00:00:00 2001 From: Tristan Simas Date: Mon, 19 Oct 2026 01:02:09 -0400 Subject: [PATCH 8/8] P197: source budget covering the checked delivery members (52 added, 6 removed) Src-Budget: 46 Co-Authored-By: Claude Opus 5.5