fix(tui/prompt): publish TASK_CANCEL when receive times out (proposal 003 PR-1) - #54
Merged
Merged
Conversation
Implements PR-1 of proposal 003 (ACC TUI usability hardening) in the operator's Obsidian vault. Also introduces CHANGELOG.md + bumps the project version to 0.2.0-dev to anchor the proposal 003 development cycle. ## Problem Operator tested TUI Prompt screen against a local llama backend. TUI showed "(timeout after 60s — no reply)" but `acc-deploy.sh logs acc-llm` confirmed vLLM kept generating long past the operator-visible timeout — the backend never received a cancel signal, finished its work, and the late TASK_COMPLETE landed on a screen the operator had moved past. Silent backend leak + abandoned work. `acc/tui/screens/prompt.py:_publish_cancel()` L417–461 already implements TASK_CANCEL publishing for the `/cancel` slash command at L376–390. The timeout handler at L602–615 just didn't call it. ## Fix 1. Timeout handler now calls `_publish_cancel(task_id=...)` before appending the system entry. Operator sees "(cancelled after Ns — no reply; TASK_CANCEL published)" instead of "(timeout after 60s — no reply)". 2. `_RECEIVE_TIMEOUT_S` default raised 60 → 180 s. Configurable via the `ACC_PROMPT_TIMEOUT_S` environment variable, read fresh per receive call via a new `_resolve_timeout()` helper. Malformed values fall back to the default + log a warning. 3. Cancelled-on-timeout task_ids recorded in a FIFO (`self._cancelled_task_ids`, capped at 256) for late- TASK_COMPLETE suppression via the new `_is_cancelled()` predicate — surface for future consumers. ## Repo hygiene (versioning) - Adds `CHANGELOG.md` in Keep-a-Changelog format. Tracking starts at proposal 003; earlier history reconstructable via `git log`. - Bumps `pyproject.toml` from 0.1.0 → 0.2.0-dev. Tags the v0.2.0 cut when proposal 003 closes (PRs 1–6 all landed). - Every subsequent proposal-003 PR adds entries to the `[Unreleased]` section. ## Tests Five new cases in `tests/test_prompt_screen_pilot.py`: - `test_timeout_publishes_task_cancel` — forces 50 ms timeout; asserts TASK_CANCEL appears with matching task_id. - `test_timeout_records_cancelled_task_id` — FIFO entry + `_is_cancelled()` true/false matrix. - `test_timeout_transcript_says_cancelled_not_timed_out` — operator-visible message reads "cancel" not "timed out". - `test_resolve_timeout_default` / `_reads_env` / `_ignores_garbage` / `_ignores_non_positive` — env-var override matrix. 22/22 green across prompt + channel + oversight TUI tests. ## Manual verification ``` ACC_PROMPT_TIMEOUT_S=10 acc-tui # Prompt screen → send → wait > 10s # acc-deploy.sh logs acc-llm shows cancel within 2s # Transcript shows "cancelled after 10s — no reply; TASK_CANCEL published" ``` Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
flg77
force-pushed
the
tui/prompt-timeout-cancel
branch
from
May 13, 2026 20:20
ab87a3a to
68e6ffc
Compare
flg77
added a commit
that referenced
this pull request
May 13, 2026
Implements PR-2 of proposal 003 (ACC TUI usability hardening).
Addresses operator review items 1, 2, 3 from `ACC TUI Review.md`:
1. Role detail box now shows the role's narrative `role.md`
content (was: only `role.yaml`).
2. Role overview is browsable — detail panel split into two
`Collapsible` widgets (role.md open by default; role.yaml
collapsed) inside the existing `ScrollableContainer`, so the
operator can scroll a long role.md without losing the yaml
surface.
3. Role table gains a filter `Input` above it. Typing narrows
to rows whose name / domain / persona contains the substring
(case-insensitive). Clearing restores the full list.
## Changes
### `acc/tui/screens/ecosystem.py`
* Compose:
- Added `Input(#role-filter)` above the role DataTable.
- Replaced the single `Static(#role-detail-panel)` with a
`Static(#role-detail-placeholder)` + two Collapsibles:
`#role-md-collapsible` (Markdown widget `#role-md-content`)
and `#role-yaml-collapsible` (Static `#role-yaml-content`).
* `_load_roles()` now caches the loaded row tuples in
`self._all_role_rows` and delegates the initial render to a
new `_apply_filter("")` so the filter handler can repopulate
without re-reading disk.
* `_apply_filter(query)` clears + repopulates the DataTable
keeping only rows whose name / domain / persona contain
the (case-insensitive) substring.
* `on_input_changed(event)` reacts to keystrokes in
`#role-filter`; other Inputs get a no-op.
* `_show_role_detail(role_name)` rewritten:
- Hides the "select a role" placeholder once a role is
chosen.
- Reads `roles/<name>/role.md` via the new module-level
`_read_role_md()` helper; renders it in the Markdown
widget. Missing file → friendly placeholder pointing
operators at the authoring convention (slot 006).
- role.yaml render unchanged in content, but lands on the
`#role-yaml-content` Static under its collapsible.
* New helper `_read_role_md(md_path, role_name)` — read-only
with safe fallbacks for missing / unreadable files.
### Tests
* `tests/test_ecosystem_screen_pilot.py`:
- `_capture_panel_updates()` updated to tap BOTH the Markdown
and the yaml Static so prior substring assertions
("test_role", "pilot fixture") keep passing.
- 5 new cases:
- `test_role_detail_renders_role_md_when_present`
- `test_role_detail_md_placeholder_when_absent`
- `test_role_filter_input_narrows_table`
- `test_role_filter_matches_persona_substring`
- `test_role_filter_no_match_empties_table`
* `tests/test_coding_agent_tui_pilot.py`:
- One-line update so the test reads from `#role-yaml-content`
instead of the now-removed `#role-detail-panel`.
25/25 green across `tests/test_ecosystem_screen_pilot.py` +
`tests/test_coding_agent_tui_pilot.py`.
## Note on CHANGELOG entry
This PR's `[Unreleased]` CHANGELOG entries will be added during
rebase once PR #54 (which introduces CHANGELOG.md) lands.
Skipping it here avoids a guaranteed merge conflict on a file
that doesn't yet exist on main.
## Manual verification
* Open Ecosystem screen → type substring in the filter →
only matching rows render. Clear → full list restored.
* Click any role row → role.md renders in the open
collapsible at the top. Roles without role.md show the
authoring-guidance placeholder.
* Click the `role.yaml (raw)` collapsible → raw yaml renders
identically to the pre-PR-2 single-pane view.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
flg77
added a commit
that referenced
this pull request
May 13, 2026
) Implements PR-2 of proposal 003 (ACC TUI usability hardening). Addresses operator review items 1, 2, 3 from `ACC TUI Review.md`: 1. Role detail box now shows the role's narrative `role.md` content (was: only `role.yaml`). 2. Role overview is browsable — detail panel split into two `Collapsible` widgets (role.md open by default; role.yaml collapsed) inside the existing `ScrollableContainer`, so the operator can scroll a long role.md without losing the yaml surface. 3. Role table gains a filter `Input` above it. Typing narrows to rows whose name / domain / persona contains the substring (case-insensitive). Clearing restores the full list. ## Changes ### `acc/tui/screens/ecosystem.py` * Compose: - Added `Input(#role-filter)` above the role DataTable. - Replaced the single `Static(#role-detail-panel)` with a `Static(#role-detail-placeholder)` + two Collapsibles: `#role-md-collapsible` (Markdown widget `#role-md-content`) and `#role-yaml-collapsible` (Static `#role-yaml-content`). * `_load_roles()` now caches the loaded row tuples in `self._all_role_rows` and delegates the initial render to a new `_apply_filter("")` so the filter handler can repopulate without re-reading disk. * `_apply_filter(query)` clears + repopulates the DataTable keeping only rows whose name / domain / persona contain the (case-insensitive) substring. * `on_input_changed(event)` reacts to keystrokes in `#role-filter`; other Inputs get a no-op. * `_show_role_detail(role_name)` rewritten: - Hides the "select a role" placeholder once a role is chosen. - Reads `roles/<name>/role.md` via the new module-level `_read_role_md()` helper; renders it in the Markdown widget. Missing file → friendly placeholder pointing operators at the authoring convention (slot 006). - role.yaml render unchanged in content, but lands on the `#role-yaml-content` Static under its collapsible. * New helper `_read_role_md(md_path, role_name)` — read-only with safe fallbacks for missing / unreadable files. ### Tests * `tests/test_ecosystem_screen_pilot.py`: - `_capture_panel_updates()` updated to tap BOTH the Markdown and the yaml Static so prior substring assertions ("test_role", "pilot fixture") keep passing. - 5 new cases: - `test_role_detail_renders_role_md_when_present` - `test_role_detail_md_placeholder_when_absent` - `test_role_filter_input_narrows_table` - `test_role_filter_matches_persona_substring` - `test_role_filter_no_match_empties_table` * `tests/test_coding_agent_tui_pilot.py`: - One-line update so the test reads from `#role-yaml-content` instead of the now-removed `#role-detail-panel`. 25/25 green across `tests/test_ecosystem_screen_pilot.py` + `tests/test_coding_agent_tui_pilot.py`. ## Note on CHANGELOG entry This PR's `[Unreleased]` CHANGELOG entries will be added during rebase once PR #54 (which introduces CHANGELOG.md) lands. Skipping it here avoids a guaranteed merge conflict on a file that doesn't yet exist on main. ## Manual verification * Open Ecosystem screen → type substring in the filter → only matching rows render. Clear → full list restored. * Click any role row → role.md renders in the open collapsible at the top. Roles without role.md show the authoring-guidance placeholder. * Click the `role.yaml (raw)` collapsible → raw yaml renders identically to the pre-PR-2 single-pane view. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced May 13, 2026
flg77
added a commit
that referenced
this pull request
May 13, 2026
All six PRs of proposal 003 (ACC TUI usability hardening) are on main: * #54 (PR-1) — Prompt cancel-on-timeout + CHANGELOG/version bump * #55 (PR-2) — Ecosystem role.md detail + searchable filter * #56 (PR-3) — Ecosystem roles/ watcher + selection lock * #57 (PR-4) — Configuration pane (pane 8) * #58 (PR-5) — Performance + Soma cluster/governance context * #59 (PR-6) — CLI/TUI infuse parity + subrole sibling listing pyproject.toml: 0.2.0-dev → 0.2.0 CHANGELOG.md: [Unreleased] section closed off as [0.2.0] (dated 2026-05-14) with a fresh [Unreleased] header ready for the next cycle. Tag v0.2.0 follows this merge. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
flg77
pushed a commit
that referenced
this pull request
Jun 11, 2026
Bumps [github.com/moby/spdystream](https://github.com/moby/spdystream) from 0.4.0 to 0.5.1. - [Release notes](https://github.com/moby/spdystream/releases) - [Commits](moby/spdystream@v0.4.0...v0.5.1) --- updated-dependencies: - dependency-name: github.com/moby/spdystream dependency-version: 0.5.1 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
PR-1 of proposal 003 (ACC TUI usability hardening) in the operator's Obsidian vault. Hotfix priority — the operator confirmed vLLM keeps generating after the TUI shows a timeout. Silent backend leak.
This PR also introduces repo-level versioning hygiene (
CHANGELOG.md+ version bump to0.2.0-dev) so the proposal-003 series has somewhere to record per-PR entries.What changed — fix
acc/tui/screens/prompt.pytimeout handler now calls_publish_cancel(task_id)before appending the system entry to the transcript. Operator sees "(cancelled after Ns — no reply; TASK_CANCEL published)" instead of "(timeout after 60s — no reply)".ACC_PROMPT_TIMEOUT_Senvironment variable; read fresh per receive call via a new_resolve_timeout()helper. Malformed values fall back to default + log a warning.self._cancelled_task_ids) so lateTASK_COMPLETEreplies can be suppressed downstream via the new_is_cancelled(task_id)predicate.What changed — repo hygiene (versioning)
CHANGELOG.mdintroduced in Keep-a-Changelog format. Tracking starts at proposal 003; earlier history reconstructable viagit log(not back-filled).[Unreleased]section now carries the PR-1 entries; subsequent PR-2..PR-6 of proposal 003 add their own entries here.pyproject.tomlversion bumped0.1.0→0.2.0-dev. We tagv0.2.0when proposal 003 closes (all six PRs merged).Tests
Five new pilot tests in
tests/test_prompt_screen_pilot.py:test_timeout_publishes_task_cancelacc.{cid}.task.cancelwith matching task_idtest_timeout_records_cancelled_task_id_is_cancelled()true/false correcttest_timeout_transcript_says_cancelled_not_timed_outtest_resolve_timeout_default/_reads_env/_ignores_garbage/_ignores_non_positive22/22 tests green across
tests/test_prompt_screen_pilot.py+tests/test_prompt_channel.py+tests/test_oversight_tui_diagnose.py.Manual verification
Reference
Proposal 003 —
C:\Users\micro\Documents\Notes\Notes\Development\AgenticCellCorpus\ACC Implementation\003 - ACC TUI usability hardening.md(operator vault).🤖 Generated with Claude Code