Match approvals and commands regardless of case and trailing punctuation #72

Merged
dongar merged 1 commits from case-insensitive-commands into main 2026-09-29 18:00:27 +00:00
Collaborator

Closes #64.

The problem: approvals and commands were exact, case-sensitive matches. A phone keyboard's Approve counted as rejection feedback and threw the plan away. Stop didn't reach the cancel flag while work ran. Other capitalised commands got a hint instead of acting.

Change: gates.command_form() defines how a message reads as a command. Case, surrounding whitespace, runs of inner whitespace and a trailing . or ! don't matter. It's used by:

  • the approval gate (approve, approve rev-N);
  • every command in the orchestrator: stop (checked on the transport thread), status, abandon, use, start milestone <n>, next milestone, project complete, and the restart choices (which already ignored case and now share the function).

Unchanged:

  • Only matching is affected: the project name in use <name> keeps its case (Use Demo. → Demo), and feedback and answers are recorded and passed on exactly as written.
  • A stale revision is still refused, e.g. Approve REV-1 at rev-2.
  • Approval still needs the whole message to be the command: "I approve of most of it" is feedback.
  • Sender checks are unchanged; they come from the event, not the text.

Tests: gate cases (Approve, APPROVE, Approve., approve!, Approve rev-2, a capitalised stale revision, a sentence containing "approve"); a full capitalised command flow through the orchestrator; and the stop-while-busy test parametrized over stop, Stop! and STOP. 9 new cases fail on main; the sentence case is a guard. 475 unit tests and the integration suite pass; lint and format clean.

🤖 Generated with Claude Code

https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE

Closes #64. **The problem:** approvals and commands were exact, case-sensitive matches. A phone keyboard's `Approve` counted as **rejection feedback** and threw the plan away. `Stop` didn't reach the cancel flag while work ran. Other capitalised commands got a hint instead of acting. **Change:** `gates.command_form()` defines how a message reads as a command. Case, surrounding whitespace, runs of inner whitespace and a trailing `.` or `!` don't matter. It's used by: - the approval gate (`approve`, `approve rev-N`); - every command in the orchestrator: `stop` (checked on the transport thread), `status`, `abandon`, `use`, `start milestone <n>`, `next milestone`, `project complete`, and the restart choices (which already ignored case and now share the function). **Unchanged:** - **Only matching is affected:** the project name in `use <name>` keeps its case (`Use Demo.` → `Demo`), and feedback and answers are recorded and passed on exactly as written. - **A stale revision is still refused**, e.g. `Approve REV-1` at rev-2. - **Approval still needs the whole message to be the command:** "I approve of most of it" is feedback. - **Sender checks are unchanged**; they come from the event, not the text. **Tests:** gate cases (`Approve`, `APPROVE`, `Approve.`, `approve!`, ` Approve rev-2 `, a capitalised stale revision, a sentence containing "approve"); a full capitalised command flow through the orchestrator; and the stop-while-busy test parametrized over `stop`, `Stop!` and ` STOP `. 9 new cases fail on `main`; the sentence case is a guard. 475 unit tests and the integration suite pass; lint and format clean. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
dev-agent added 1 commit 2026-09-29 17:57:35 +00:00
Match approvals and commands regardless of case and trailing punctuation
CI / checks (push) Skipped
CI / checks (pull_request) Successful in 1m15s
6afd0cc914
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
dongar approved these changes 2026-09-29 18:00:25 +00:00
dongar merged commit 26dabc3d54 into main 2026-09-29 18:00:27 +00:00
dongar deleted branch case-insensitive-commands 2026-09-29 18:00:28 +00:00
Sign in to join this conversation.
No Reviewers
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dev/nisse#72