Match approvals and commands regardless of case and trailing punctuation
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m15s
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m15s
A phone keyboard's "Approve" did not match the approval pattern, so it counted as rejection feedback and threw the plan away; "Stop" did not reach the cancel flag; other capitalised commands got a hint instead of acting. gates.command_form() is how a message reads as a command: case, surrounding whitespace, inner runs of whitespace and a trailing '.' or '!' do not matter. The approval gate and every command match in the orchestrator (stop, status, abandon, use, start milestone, next milestone, project complete, the restart choices) use it. Only matching changes: the project name in 'use <name>' keeps its case, and feedback and answers are recorded and passed on as written. A stale revision is still refused, and approval still needs the whole message to be the command. Closes #64. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
This commit is contained in:
1 parent
b893fba342
commit
6afd0cc914
5 files changed
+76
-15
No files matched your search
@@ -5,6 +5,8 @@ import threading
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
import pytest
|
||||
|
||||
from nisse_dev.cancel import STOPPED_RESULT, Cancel
|
||||
from nisse_dev.canonical import AssistantText, ToolCall, ToolResult, UserMessage
|
||||
from nisse_dev.control import (
|
||||
@@ -207,7 +209,8 @@ class BlocksUntilStopped:
|
||||
return ExecutorOutcome("completed", "never stopped")
|
||||
|
||||
|
||||
def test_stop_reaches_work_running_on_the_worker(tmp_path: Path) -> None:
|
||||
@pytest.mark.parametrize("word", ["stop", "Stop!", " STOP "])
|
||||
def test_stop_reaches_work_running_on_the_worker(tmp_path: Path, word: str) -> None:
|
||||
# The bug this design fixes: the work used to run on the transport's own
|
||||
# thread, so no message, stop included, was read until it finished.
|
||||
worker = SerialWorker()
|
||||
@@ -231,7 +234,7 @@ def test_stop_reaches_work_running_on_the_worker(tmp_path: Path) -> None:
|
||||
assert executor.running.wait(5)
|
||||
|
||||
transport.receive("don", "status") # delivered while the milestone runs
|
||||
transport.receive("don", "stop")
|
||||
transport.receive("don", word) # a phone may capitalise it (#64)
|
||||
worker.call(lambda: None) # wait for the stop to be recorded
|
||||
|
||||
texts = [m.text for m in transport.outbound]
|
||||
|
||||
Reference in new issue
Block a user