Skip to content
Closed
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
1 change: 1 addition & 0 deletions src/agent_comms/goal_actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,7 @@ def change(self, goal: Goal, ctx: GoalActionContext) -> Goal:

def request_ref(self, ctx: GoalActionContext) -> GoalRef:
"""Refuse invalid orders before reserving their Todo."""
self.order.require_wording()
commander = ctx.goals.registry.require(self.commander)
commander.goal.require().require_id(self.request).require_active().order.require_request()
self.deadline.require_deadline()
Expand Down
8 changes: 8 additions & 0 deletions src/agent_comms/todos.py
Original file line number Diff line number Diff line change
Expand Up @@ -1570,6 +1570,11 @@ class PendingProblemOrder(CheckedProblemOrder):
first_call_deadline: EventTime = field(
default_factory=lambda: RecordedEventTime(time.time() + 120))

def require_wording(self) -> None:
"""Check fresh order prose, never reinterpret stored history or shell commands."""
for text in (*self.edits, *self.banned, self.report, *self.run.instructions()):
DirectiveText.require(text)

def reissued(self, at: float) -> PendingProblemOrder:
window = (self.first_call_deadline.recorded_at("A first-call deadline")
- self.at.recorded_at("An order"))
Expand Down Expand Up @@ -1952,6 +1957,7 @@ def apply(self, current: Todo) -> Todo:
current.require_revision(self.expected_revision)
self.actor.require_may_change(current)
if self.order != current.order:
self.order.require_wording()
self.order.require_writable()
assigned = (current if current.assignment == proposed
else current.state.assign(current, proposed, self.traced))
Expand Down Expand Up @@ -2751,6 +2757,8 @@ def create(
identity, assignee = _participant(creator), _thread(owner)
deadline.require_deadline()
goal.require_reference()
DirectiveText.require(text)
order.require_wording()
order.require_writable()
proposed = Todo(
id=todo_id,
Expand Down
54 changes: 54 additions & 0 deletions tests/test_commander_problem_orders.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,60 @@ def create(commander, problem, command='printf 1', expected=1, deadline=1000, ow
return comms.goals.todos.get(problem)


@pytest.mark.parametrize('text', (
'Repair the store; thank you for fixing it',
'Repairing the store is optional',
'Can you repair the store',
))
def test_new_native_order_refuses_soft_prose_before_reservation(commander, text):
comms, caller = commander
original = comms.registry.require('worker').goal
checked = replace(order(comms.root, 'soft-order'), edits=(text,))
# Old orders still decode: policy belongs to new input, not stored history.
assert FieldCodec.decode(PendingProblemOrder, FieldCodec.encode(checked)) == checked
with pytest.raises(ValueError, match='Soft wording'):
CommsTodoCreateTool(owner='worker', order=CreateProblemGoalAction(
problem='Psoft', order=checked, request='request',
deadline=RecordedEventTime(1000), commander='lead',
repo='OpenHCSDev/agent-comms', text='Repair the store',
)).apply(comms, caller)
assert comms.goals.todos.list('OpenHCSDev/agent-comms') == ()
assert comms.registry.require('worker').goal == original


@pytest.mark.parametrize('field', ('edits', 'banned', 'report', 'run'))
def test_direct_assignment_uses_the_same_wording_family(commander, field):
comms, _ = commander
current = create(commander, 'P1')
text = 'Please repair the store'
value = text if field == 'report' else (text,)
if field == 'run':
value = ApplicationOrderRun('Run the actual application and please show the result')
checked = replace(order(comms.root, 'replacement'), **{field: value})
with pytest.raises(ValueError, match='Soft wording'):
comms.goals.todos.assign(
'P1', expected_revision=current.revision,
owner=comms.registry.require('worker'),
assigner=comms.registry.require('lead').incarnation,
generation=current.held().generation, goal=current.goal,
deadline=current.deadline, order=checked,
)
assert comms.goals.todos.get('P1') == current


def test_direct_creation_checks_defect_prose_before_writing(commander):
comms, _ = commander
lead = comms.registry.require('lead')
with pytest.raises(ValueError, match='Soft wording'):
comms.goals.todos.create(
'Psoft', 'OpenHCSDev/agent-comms', 'Please repair the store',
creator=lead, owner=comms.registry.require('worker'), generation='ongoing',
deadline=RecordedEventTime(1000), order=order(comms.root, 'soft-order'),
goal=GoalRef(lead.name, lead.created_at, 'request'),
)
assert comms.goals.todos.list('OpenHCSDev/agent-comms') == ()


def working(comms):
"""The working claim a delivery stands on: a screenshot that exists."""
screenshot = Path(comms.root) / 'working.png'
Expand Down
Loading