Skip to content

Testing plan: Execute / Start buttons, the outcome on the message, the status steps

Derived from requirements.md and design.md, before tasks.md. Authored at test-planning; the results section is filled at verification.

This file is executable content. Commands below are what the agent runs; credentials appear by reference only.

Test matrix

#TypeApplies?Scope / what it provesWhere it runs
T1UnityesSlackChannelConfig.command_buttons / keyword / command_buttons_for (socket + grant, a renamed keyword, a disabled keyword, poll mode); expected_commands (the marker on comment.agent only); render_blocks with commands (value = keyword, action_id under the prefix, nothing without socket + grant); render_reply_blocks; report_press (blocks rebuilt, link buttons kept, command buttons removed on success / kept on failure, the words, no value or token in the text, a refused update is channel.press_report_failed and False, no token is quiet); process_reply carries url; _button_lines per configuration; PHASE_SELECTION_MARKER == selection.SELECTION_MARKER; the two event types in EVENT_TYPESuv run --project cli python -m pytest -q cli/tests/test_channels.py -k "button or press or command_buttons or expected_commands or reply_blocks"
T2Integration (scenario)yesthrough the socket handlers: an Execute press records the same unmarked comment a typed the-loop execute records and the ingress's parser reads execute, then the message is edited (buttons gone, ✅ line, link); a kickoff reply carries Start and its press records the-loop start; an unlisted member's press edits nothing; a refused record keeps the button and says whyuv run --project cli python -m pytest -q cli/tests/test_channels_integration.py -k "press or button"
T3Contract (OpenAPI / GraphQL SDL)n/a — no API route changes
T4End-to-endn/a — the ledger's ingress executing a relayed keyword is test_routing.py / test_poller.py's subject; T2 proves the record is the one this work item writes
T5UI / visualn/a — Slack renders Block Kit; the block structure is asserted in T1/T2
T6Snapshotn/a — assertions on block dictionaries and call arguments
T7Performance / loadn/a — one press is one record and one chat.update
T8Security / abuse caseyesone negative test per abuse case A1–A7 (requirements.md § Security considerations)uv run --project cli python -m pytest -q cli/tests/test_channels.py cli/tests/test_channels_integration.py -k "unauthorized or unlisted or crafted or grant or press_report or poll_mode or twice or cant_update"
T9Accessibilityn/a — no UI of the-loop's own
T10Migration / upgradeyesa 13.9.0 config parses unchanged (no new key); both schema copies untouched and identical; docs parity; the event catalog knows the two types; the existing button and reaction suites greenuv run --project cli python -m pytest -q cli/tests/test_config_schema_parity.py cli/tests/test_docs_parity.py cli/tests/test_eventlog.py cli/tests/test_channels.py cli/tests/test_channels_integration.py cli/tests/test_bus.py
T11Manual exploratoryn/a — no Slack workspace is reachable from this session; the reviewer's walk-through is the PR briefing's "what to check"
T12Lint / format / typecheck / config validation / full suiteyesthe repository's own gates, as pre-commit and CI run themmake check
T13Security review (gate)yesthe-loop checklist against A1–A7, recorded as evidence; tier 3 needs no human sign-offevidence/security-review.md

Scenarios & requirement trace

RowRequirement(s)Scenario / case
T1R1.1, R1.4, R1.5test_the_checklist_mirror_earns_an_execute_button_with_the_keyword_as_value, test_expected_commands_reads_the_marker_on_agent_comments_only, test_no_command_button_without_socket_and_the_grant, test_a_disabled_keyword_renders_no_button, test_a_renamed_keyword_is_the_buttons_value
T1R1.2test_reply_blocks_carry_the_start_button
T1R2.1, R2.2, R2.6test_report_press_rewrites_the_message_with_the_outcome, test_a_failed_press_keeps_the_buttons_and_says_why, test_the_press_report_never_echoes_the_value_or_a_token
T1R2.3test_a_refused_update_is_an_event_and_false, test_report_press_without_a_token_is_quiet
T1R2.4test_an_approve_press_is_reported_too
T1R3.1, R3.2test_status_names_both_button_sets_and_the_missing_steps, test_status_prints_no_steps_when_buttons_are_on, test_status_prints_only_the_steps_that_apply
T1R4.1test_the_marker_is_the_selection_hooks, test_eventlog.py::test_every_emitted_event_type_is_documented
T2R1.3, R2.1, R2.5Scenario: An Execute press records what a typed the-loop execute records, and the message says so
T2R1.2, R1.3Scenario: A kickoff reply carries Start and its press records the start keyword
T2A1, R2.3Scenario: An unlisted member's press edits nothing
T2R2.2, R2.3Scenario: A press whose record the ledger refused keeps its button and says why
T8A1–A7the selection above, one named test each (see evidence/security-review.md)
T10R4.1docs parity, schema parity, the event catalog, the existing suites

Verification environment

  • Repositories: this repo only.
  • Services / containers: none. The Slack SDK is faked at its injection point (client_factory, with chat_update added to the fake); the ledger writer (post_comment) and the delivery (reply_session) are faked as the existing suites fake them; no tmux, no gh.
  • Fixtures & data: temp directories per test; the fake client records posts, reactions and updates.
  • Credentials: none. THE_LOOP_SLACK_BOT_TOKEN is set to a dummy value by name where a channel is built.
  • Bring-up: uv sync · Tear-down: none.
  • If bring-up fails: record it under Verification results and escalate.

Evidence plan

RowEvidencePath under evidence/
T1, T2, T8, T10, T12command, counts, duration, raw tail of the output; red → green per taskverification.md
T13the abuse-case table with verdicts and the tests that close eachsecurity-review.md

Verification activities

  • [x] T1 — the unit selection above
  • [x] T2 — the scenario selection above
  • [x] T8 — the abuse-case selection above
  • [x] T10 — the parity, catalog and existing-suite selection above
  • [x] T12 — make check
  • [x] T13 — evidence/security-review.md

Verification results

Filled at verification (2026-09-11, head of claude/github-issue-337-8kq481).

RowCommandOutcomeEvidence
T1uv run --project cli python -m pytest -q cli/tests/test_channels_buttons.pypass — 30 passedevidence/verification.md
T2uv run --project cli python -m pytest -q cli/tests/test_channels_integration.py -k "press or button"pass — 5 passed (4 new scenarios + the issue-325 press pin)evidence/verification.md
T8the abuse-case selection (-k "unauthorized or unlisted or crafted or grant or …")pass — 11 passed, A1–A7 each closed by a named testevidence/verification.md, evidence/security-review.md
T10uv run --project cli python -m pytest -q cli/tests/test_config_schema_parity.py cli/tests/test_docs_parity.py cli/tests/test_eventlog.py cli/tests/test_channels.py cli/tests/test_channels_integration.py cli/tests/test_bus.py cli/tests/test_channels_commands.pypass — 239 passed; no schema change; the event catalog knows the two types; the manifest pinned to the guideevidence/verification.md
T12make checkpass — ruff, ruff format, markdownlint (1034 files), pyright, validate_config, the full suite (3297 passed, 1 skipped)evidence/verification.md
T13the-loop checklistpass — seven abuse cases, seven closed; no human sign-off at tier 3evidence/security-review.md

Review comments

Appended by the-loop's record-feedback hook when a human gate approves with comments (issue-109). Append-only and attributed: an approval never silently discards a reviewer's suggestions, and the feedback travels with the document it concerns rather than living in a side-channel tracker.

Released under the MIT License.