Skip to content
Merged
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
2 changes: 1 addition & 1 deletion .agents/evidence/composer.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ resolves every one against the source, so a renamed or deleted test fails the bu
| COM-2 | `backspace_removes_a_whole_grapheme_cluster`, `deleting_an_empty_draft_changes_nothing`, `editing_happens_at_the_caret_rather_than_at_the_end`, `motion_steps_over_whole_clusters_and_stops_at_the_ends`, `word_deletion_takes_the_trailing_space_and_the_word`, `killing_binds_to_the_logical_line_the_caret_is_on`, `the_visible_window_follows_the_caret_above_the_tail`, `a_draft_grows_to_a_third_of_the_column_then_its_window_follows_the_caret` with the `composer-grown-*` and `composer-windowed-*` frames, `the_wheel_over_the_composer_walks_the_draft_one_row_per_notch` |
| COM-3 | `a_refused_dispatch_returns_the_draft_and_opens_one_notice`, `a_refused_dispatch_is_one_bounded_notice_and_not_an_exit`, `ctrl_j_breaks_the_conversation_draft_but_not_the_drawer_filter`, `enter_submits_and_modified_enter_or_ctrl_j_breaks_the_line`, `a_blank_draft_submits_nothing_and_is_left_alone`, `taking_the_draft_returns_it_exactly_and_clears_it`, `returned_text_lands_after_the_existing_draft`, `a_typed_message_reaches_the_transcript_by_way_of_the_runtime`, `a_submitted_message_is_a_finished_user_item`, `a_live_dispatch_restores_undelivered_user_text`, `persistence_failure_restores_the_draft_and_opens_one_notice` |
| COM-4 | `the_composer_names_the_model_while_another_agent_is_selected`, `the_user_controlled_child_input_submits_a_message_when_finished`, `ccv_2_user_child_input_uses_its_lifecycle_without_primary_commands`, `production_mapping_preserves_message_steering_interrupt_and_approval`, `production_handoff_routes_child_input_and_retains_the_locked_draft`; `scripts/smoke-delegate.py`; CCV-2/CCV-4 |
| COM-5 | `current_work_priority_is_derived_from_semantic_facts`, `parallel_running_tools_use_stable_first_appearance_order`, `the_activity_line_names_each_current_work_state_and_the_rule_carries_none`, `current_work_does_not_move_input_and_repeated_facts_cost_no_frame`, `the_current_work_frames_match_their_fixtures` with the `current-work-*` frames |
| COM-5 | `current_work_priority_is_derived_from_semantic_facts`, `parallel_running_tools_use_stable_first_appearance_order`, `the_activity_line_names_each_current_work_state_and_the_rule_carries_none`, `current_work_does_not_move_input_and_repeated_facts_cost_no_frame`, `the_activity_line_takes_rows_only_while_there_is_work_or_a_request`, `the_activity_line_reads_elapsed_effort_and_quiet_and_drops_them_in_order`, `the_turn_is_counted_from_its_start_and_forgotten_when_it_ends`, `the_count_carries_through_the_gap_between_steps`, `the_count_stops_while_the_turn_waits_on_the_user`, `a_child_streaming_does_not_break_the_primary_quiet`, `the_current_work_frames_match_their_fixtures` with the `current-work-*` frames |
| COM-6 | `pointer_clicks_place_the_caret_in_each_input`, `edits_that_join_clusters_restore_the_grapheme_boundary`, `a_full_input_row_never_places_the_caret_on_the_border`, `terminal_paste_edits_the_focused_input_without_submitting`; `scripts/smoke-tui.py` drives Chinese paste, pointer insertion, selection replacement and source copying |
4 changes: 2 additions & 2 deletions .agents/evidence/motion.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ resolves every one against the source, so a renamed or deleted test fails the bu

| Invariant | Proven by |
| --- | --- |
| MOT-1 | `mot_1_one_deadline_serves_every_mover_and_late_wakes_coalesce`, `effort_xhigh_labels_remain_static_without_an_animation_deadline`, `effort_animation_changes_only_visible_max_cells_and_stops_when_hidden` |
| MOT-2 | Unproven beyond `effort_animation_changes_only_visible_max_cells_and_stops_when_hidden`, which checks the effort markers' width |
| MOT-1 | `mot_1_one_deadline_serves_every_mover_and_late_wakes_coalesce`, `the_mark_cycle_divides_the_clock_cycle`, `effort_xhigh_labels_remain_static_without_an_animation_deadline`, `effort_animation_changes_only_visible_max_cells_and_stops_when_hidden` |
| MOT-2 | `mot_2_every_activity_mark_frame_is_one_cell`, `effort_animation_changes_only_visible_max_cells_and_stops_when_hidden` |
| MOT-3 | `effort_animation_changes_only_visible_max_cells_and_stops_when_hidden` |
2 changes: 1 addition & 1 deletion .agents/phases/phase-04-product-polish.md
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ Visual changes are reviewed against real frames before the contract adopts them.
queues above the composer. `Alt-↑` restores the newest message and its explicit skill only
into an empty primary draft; an occupied draft preserves both messages and advertises the
precondition. Completed skill preparation wakes the projection without requiring provider
output or another key. The activity row meets the waiting rule without an extra blank row.
output or another key. The waiting rule follows the activity line's own blank row.
The user delegated completion on 2026-09-12; the agent reviewed the existing design and these
fixes, and [ui-ux](../ui-ux.md) adopts the resulting input/state grammar. Reviewed frames at
[wide](../../crates/plexmaton-tui/frames/input-queue-wide.txt),
Expand Down
27 changes: 16 additions & 11 deletions .agents/plans/phase-04-stage-34-conversation-chrome.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
| Phase | [Phase 04](../phases/phase-04-product-polish.md) stage 34 |
| Contract | [ui-ux](../ui-ux.md) §transcript grammar and its activity-line rule; EFF-4 in [reasoning-effort](../specs/reasoning-effort.md); FR-1 in [frame-loop](../specs/frame-loop.md); TR-6 in [transcript-layout](../specs/transcript-layout.md); SEL-1 and SEL-2 in [selection-and-copy](../specs/selection-and-copy.md) |
| Evidence | [Conversation chrome spike](../spikes/conversation-chrome/README.md): the rendered candidates the user chose from and the survey of three other CLIs |
| Status | Slices 1–3 of 5 implemented and locally verified |
| Status | Slices 1–4 of 5 implemented and locally verified |

## Outcome

The user's turn is told by its surface rather than by a shout, and a working agent is told by a
row that moves and says only what is known: how long the step has run, at what effort, and how long
row that moves and says only what is known: how long the turn has run, at what effort, and how long
the route has been quiet. Both are presentation. Removing either changes no journal entry, no
request and no replay.

Expand Down Expand Up @@ -38,15 +38,20 @@ MOT-1 to MOT-3 live in [motion](../specs/motion.md), promoted when the motion ow
of view state where every renderer reads it. The effort rail is its first user with no change in
behaviour. Closed by the effort tests passing unchanged and
`mot_1_one_deadline_serves_every_mover_and_late_wakes_coalesce`.
4. **Activity line.** The row opens with the mark's core moving, then the label, then muted `· 11s ·
high effort`, and after five seconds without a model event `· quiet for 31s`. Elapsed reads
`11s`, `2m 11s`, `1h 2m`. The mark wears blue, the server-tool colour while a provider-run search
is the work, and stands still in the action-required colour while approval is required. The
core's cycle is the outline morph the user chose in the spike; whether Unicode geometric shapes
or the Nerd Font's Material Design outlines draw it, and at what length, is the user's call once
their terminal font settles, recorded there. Closes with frames for thinking, responding, running
tool, running search, approval, compacting and quiet at three widths; MOT-2 for the cycle; MOT-3
as a test that a tick advances no semantic revision.
4. **Activity line — implemented.** The row opens with the mark, then the label, then muted
readings: elapsed across the turn, stopped while an approval or a question waits on the user, the
effort, and after five seconds with nothing from the primary's own route `quiet for`, which a
child's stream does not interrupt. Elapsed reads `11s`, `2m 11s`, `1h 2m`; a short row drops
effort, then quiet, then elapsed. The mark is the Nerd Font's circle, rounded square and square,
outline then filled, eight frames at 200 ms, which the user chose in their own terminal over the
Unicode cycles that shook. It wears blue, the server-tool colour while a hosted search runs, and
stands still in the action-required colour during approval. The readings are presentation: events
are dated as they are applied and the motion clock supplies the instant a frame is drawn for.
After the user's first look in kitty the row gained a blank row beneath it and gives up its rows
when idle with nothing waiting; a selection note never opens them, and rides the status row while
they are closed. Closed by refreshed current-work frames, the readings, turn-count, child-quiet
and footer-rows tests, the selection drags that no longer move, MOT-2 for the mark, and the
activity smokes.
5. **Documents.** Evidence tables current; SVG review of the frames attached; this plan deleted;
the phase row says done.

Expand Down
19 changes: 12 additions & 7 deletions .agents/specs/composer.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,17 @@ production snapshot delivery and focused child routing are accepted by `scripts/
The product retains an addressed child submission before cold activation or journal work and
returns any later refusal to that same worker composer.

**COM-5 — Current work is derived and static.** The conversation's activity line, its last row
above the composer's top rule, shows at most one label: `Approval required` outranks
`Running <tool>`, then `Responding`, then `Thinking`; idle shows none. The label is derived from
the semantic projection and owns no timer; the composer's rules never carry it. The same row's
right end holds the selection note (SEL-5) and the attention pill (ATT-1), which no longer have a
border to ride (ui-ux §input).
**COM-5 — Current work is derived; its readings are presentation.** The conversation's activity
line, over one blank row above the composer's top rule, shows at most one label: `Approval
required` outranks `Running <tool>`, then `Responding`, then `Thinking`; idle with nothing waiting
takes no rows. The label is derived from the semantic projection; the composer's rules never carry
it. The readings are dated as the workspace applies events and drawn for the motion clock's
instant, so they never move the semantic revision. Elapsed counts the primary's turn, from when it
opens until it ends: it carries through the gaps between steps and stops while an approval or a
question holds the turn on the user. Quiet hears only the primary's own events, never a child's,
and says nothing while the turn waits on the user. The row's right end holds the selection note
(SEL-2) and the attention pill (ATT-1); while its rows are closed the selection note rides the
status row instead (ui-ux §input).

**COM-6 — Input selection names editable source.** A click places the caret; dragging retains a
grapheme-boundary anchor, paints the source range, and release copies it through SEL-4. Typing or
Expand Down Expand Up @@ -91,7 +96,7 @@ Ctrl-C ──▶ non-empty draft ──▶ clear
| --- | --- |
| Place | Directly under the primary conversation, between two rules (ui-ux §input): the top rule carries the title and the resolved model's reasoning effort, then the lines, then the bottom rule. The columns a box's sides would spend stay blank, so the caret and the pointer keep a box's geometry |
| Height | One row per wrapped line, at the width of the conversation column it actually occupies, up to a third of the terminal's height and never fewer than three; a taller draft shows the window containing the caret, which is its newest lines until `↑`/`↓` or the wheel over the composer walk the caret out of them |
| Current work | One semantic suffix in the existing divider; action required uses its role and other work is ambient |
| Current work | Never on the composer's rules: the conversation's activity line names it (COM-5) |
| On a short terminal | Served before the notice strip and the agent list: a workspace that cannot be typed into is not a supported shape |
| While a sub-agent's input holds the cursor | One row over the bottom rule, `Message Agent A · ⇥ to return`: no top rule, no title, still a focus stop and a pointer target. `Tab` from that input lands on it, because the composer follows the second window in the focus ring |

Expand Down
4 changes: 2 additions & 2 deletions .agents/specs/input-queue.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ every entry it did not list.

Cut below what it asked for, it lists fewer entries rather than losing the rows off its bottom, and
the count grows to cover them; below its floor — its rule, one heading, one entry, that count and
the way back — it takes no rows at all. Its top rule meets the activity row without an extra
bottom border or blank row. It is chrome, so a row past its rectangle is a row with no
the way back — it takes no rows at all. Its top rule follows the blank row the activity line keeps
beneath itself, with no bottom border or blank row of its own. It is chrome, so a row past its rectangle is a row with no
way to reach it: what it cannot show it must count, and the way back is the last row it gives up.
Rejected: letting the rows it was granted simply clip its content, which drops the key in IQU-3
first and leaves the title counting messages the band has stopped showing.
Expand Down
10 changes: 5 additions & 5 deletions .agents/specs/motion.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

| Field | Value |
| --- | --- |
| Status | MOT-1 and MOT-3 implemented for the effort rail; MOT-2 unproven until the activity line moves |
| Status | Implemented for the effort rail and the activity line's mark |
| Owns | When anything in the workspace moves, what a moving frame may change, and the one clock it runs on |
| Depends on | FR-1 and FR-3 in [frame-loop](./frame-loop.md); EFF-4 in [reasoning-effort](./reasoning-effort.md) as the first thing that moves |
| Proven by | `plexmaton-tui::workspace` effort tests below |
| Proven by | `plexmaton-tui::workspace` effort tests and `plexmaton-tui::render` activity-mark tests |

## Invariants

Expand All @@ -17,8 +17,7 @@ phase and counts the next tick from itself, queuing no missed frames. Rejected:
thing, which is how the effort rail began and would have given the activity line a second one.

**MOT-2 — A motion frame is one cell.** Every glyph in a motion sequence has display width one, and
a test proves it for each sequence, so a frame can never widen or reflow a row. Unproven: the
effort markers are checked; no other sequence exists yet.
a test proves it for each sequence, so a frame can never widen or reflow a row.

**MOT-3 — Motion changes presentation only.** A phase change invalidates the painted frame and never
the semantic revision or layout (FR-1), so replaying a journal reproduces the same rows whatever the
Expand All @@ -27,4 +26,5 @@ clock was doing.
## Grammar

The phase is a count, not a time: renderers derive their frame from it, so two moving things on
screen stay in step. The effort rail's marker completes a cycle every 1.6 s (EFF-4).
screen stay in step. The effort rail's marker and the activity line's mark each complete a cycle every
1.6 s, the mark at three phases a frame over eight frames.
8 changes: 6 additions & 2 deletions .agents/specs/selection-and-copy.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ capability/failure labels are not copied. Clipping and source fallback preserve
Maps and prepared rows share MD-4's bounded cache; cache hits borrow mapping data, and highlighting
copies only the rows it paints. Copying reads only the selected entries, not the whole history;
PRE-4 prepares missing maps through the owned worker rather than reparsing on release. Pending,
changed-source and failure feedback appears on the selected conversation's activity line, not as a delivery acknowledgement.
changed-source and failure feedback appears on the selected conversation's activity line, or, for
the primary while that line's rows are closed, at the status row's right end; never as a delivery
acknowledgement.

**SEL-3 — One selection, in one surface, for one agent.** A selection carries the surface and the
agent it indexes. Extending in a different surface replaces it, and a selection whose surface stops
Expand All @@ -62,7 +64,9 @@ successful terminal write has no acknowledgement; helper success proves only tha
accepted the request. Native helper failure is returned without a silent route change. The CLI publishes `✓ Copied` only
for native acceptance, or `Copy sent` for terminal/tmux send. A two-second receipt overlays the
bottom-right status cells without layout or focus changes; quit has priority without extending
its window. New admitted copies withdraw old receipts; cancellation, replacement and delivery
its window. While the primary's activity line is closed those cells otherwise carry its selection
note (SEL-2), which a receipt replaces for its two seconds. New admitted copies withdraw old
receipts; cancellation, replacement and delivery
failure produce none. The two tmux legs remain independent: a successful terminal send can report
`Copy sent` even when the helper rejects; this does not claim clipboard acceptance. All helper
operations bound both stdin writes and exit waits to 500 ms, kill and reap on failure, timeout or
Expand Down
2 changes: 1 addition & 1 deletion .agents/spikes/conversation-chrome/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ generators are in [`mockups/`](./mockups/); each writes one HTML page to
| Surface | Chosen | Rejected on sight |
| --- | --- | --- |
| Activity line composition | mark, label, muted `· 32s · high effort`, `· quiet for 31s` once nothing has arrived; no token count | a red stall tell; estimated tokens |
| Activity mark | the outline morph: ring grows, rounds into the frame, frame sharpens (`◦ ○ ◯ ▢ □ ◻`). Drawn with Unicode geometric shapes (C2′, 12 frames; C2″, 8) or the Nerd Font's Material Design outlines (N2): the user decides once their terminal font settles | filled squares, which the font draws as rectangles; braille; quarter circles; Claude Code's star |
| Activity mark | N2, the Nerd Font's circle, rounded square and square, outline then filled: chosen 2026-09-22 in a kitty window beside the Unicode cycles; the user asked for the filled half to keep it simple yet ever changing | C2′ and C2″, which shook in the user's terminal because mixed-size Unicode shapes centre differently; filled squares; braille; quarter circles; Claude Code's star |
| User message | band of lifted ground with a blue `›`, continuation indented | the accent bar; a bare prefix; a hairline bar; a band alone |
| Mark placement | centred in the empty conversation, name beneath, gone with the first message | a header or drawer slot, not yet asked for |
| Mark motion | K4 as the base: frame breathes between weights and drifts between palette slots; centre morphs circle, ring, rounded square, square, solid and outline | K1 to K3 as they stood |
Expand Down
Loading
Loading