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
6 changes: 5 additions & 1 deletion .commitrail/initiatives/WS-CLI-001/OVERVIEW.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ workbench: exact-grant projects, one-page Ready/active Mine/own Submissions,
fresh details and explicit Mine context/intake reads.
[WS-CLI-001-49](WS-CLI-001-49.md) adds exact-Submission findings pages and
ordered locked-guide selection with explicit verified single-document download.
[WS-CLI-001-50](WS-CLI-001-50.md) replaces their contributor presentation with
visible collections/sections, readable instructions and truthful page/evidence
states; it changes no public operation or lifecycle authority.
Contribution evidence remains an inert CLI handoff. Product mutations, management
screens and operation-specific recovery remain separate TUI boundaries; this
interface does not depend on first binary publication or system-wide discovery.
Expand Down Expand Up @@ -426,7 +429,8 @@ CLIs. Keep the package independent of backend and MCP runtime dependencies.
Hosted and human-review journey proof remain separate.
Unfinished human review/revision is not current CLI implementation scope.
26. **Optional TUI:** -48 supplies contributor navigation through existing typed
reads; -49 adds findings pages and confirmed verified guide downloads.
reads; -49 adds findings pages and confirmed verified guide downloads; -50
redraws this same contributor boundary for readable work and evidence states.
In-TUI Evidence, product writes and management remain
separate boundaries; Evidence first needs a shared typed single-page client
port without changing complete CLI exports. Never require a TUI for agents
Expand Down
132 changes: 132 additions & 0 deletions .commitrail/initiatives/WS-CLI-001/WS-CLI-001-50.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# WS-CLI-001-50 — Readable contributor terminal workbench

- Initiative: `WS-CLI-001`
- Durable disposition: `Planned`
- Intended merge outcome: Replace the contributor TUI presentation in place with visible navigation, readable work content and truthful evidence states.

## Intent

The human's 26 October design brief targets main `fcd32057`, which still matches
the inspected implementation. Existing contributor reads and verified downloads
work, but hidden tabs and flat metadata streams make instructions hard to find.
This is a presentation redesign, not the separate fixture prototype or a new
product capability. No overlapping production TUI PR was found during discovery.

## Bounded change

Allowed: `cli/internal/tui/`, focused existing `cli/tests/integration/test_tui*`
and native terminal observer support, `cli/README.md`,
`docs/design/cli-terminal-experience.md`, affected `docs/roadmap_status.md` claims,
and this initiative's records. Command terminal-capability plumbing may change
only if necessary for existing Bubble Tea background detection; no new config.

Replace view composition with a measured shell, visible collection/section labels,
contextual footer, loaded-page observation line, and two panes only at >=100x24.
The right viewport owns scrolling while the retained left list preserves exact
selection. Plain mode stays single-column. A small style owner supplies semantic
slate/cyan/peach and readable light-terminal equivalents without dependencies.
Group existing detail values by the brief's reading order, retaining all exact
IDs, hashes and decimal strings. Uninspected previews use only loaded row facts.

Keep the existing model, typed requests, generation/cancellation and staged
download owners. Reflow changes no selection and dispatches no request. A narrow
prose sanitizer may preserve LF paragraph boundaries after bearer suppression,
while escaping all other controls and keeping labels/IDs on the existing strict
sanitizer. Long confirmation content must remain scrollable without changing
the explicit destination -> Enter -> y publication decision.
Entering confirmation resets its viewport to the target heading. Existing scroll
keys can inspect its remaining fields; below 40x10, `y` cannot stage files or
dispatch a download while only resize guidance is visible. The retained worklist
is composed outside the scrolling detail viewport.

Prohibited: backend/API/client changes, new product mutations, polling, stale
caches, manager/review workspaces, credentials, shell execution, automatic viewers,
clipboard, new dependencies, release/CI weakening, compatibility implementations.
The existing design document becomes the single current presentation contract.

## Acceptance criteria

- Mine Overview at 120x40 and 80x24 prioritizes complete instructions and criteria;
terms remain potential, exact and separate for submission/review contributions.
- Collection and applicable section labels stay visible with one active label.
Resize and Unicode wrapping remain cell-bounded at 40x10 and above; below that
retain resize/quit guidance. Plain/no-color and light terminals remain readable.
- Row movement makes no requests; Enter performs the existing exact fresh read.
Findings/list continuations remain distinct one-page requests. Late responses,
denial and unavailable sessions cannot restore protected content.
- Guide metadata is not called verified until a successful verified download.
Confirmation includes exact target/destination/bytes/hash and explicit y;
cancellation, no-overwrite and cleanup behavior are unchanged.
A confirmation resized below minimum cannot dispatch or stage on `y`; restoring
size preserves its exact target and still requires deliberate confirmation.
- Stored outcomes are distinguished from findings; no inferred payment, authority,
acceptance or progress. Inert CLI arguments and explicit CLI contracts remain.
- Representative fixture terminal renders cover picker, lists, task/intake/guide,
submission/findings, empty/filter miss/denial/help at desktop, compact and plain
sizes. Render evidence is not live-backend evidence.

## Risk and review routing

L1: presentation of untrusted terminal text and exact download confirmations.
Plan review before implementation; final focused security, QA/test-delta,
architecture/reuse and documentation review on a clean pinned candidate.
Native proof-observer changes also receive CI-integrity review so a corrected
terminal fixture cannot silently weaken the platform evidence.
No authorization policy or custody operation changes are authorized.

The cohesive diff exceeds the preferred small-change line budget: the existing
detail renderer moves out of view.go while being regrouped, the obsolete mixed
current/future design document is replaced, and presentation/terminal regressions
cover the shared shell across existing screens. Splitting would leave competing
renderers or inconsistent navigation. Requests, API, download custody, dependencies
and workflows are unchanged; focused reviewers inspect these separate risks.

## Verification

Retain existing model/request/guide/hostile-text tests and real HTTP/PTY/public-API
journeys. Add focused layout/focus/multiline/ANSI/light/minimum-size regressions.
Use `go test ./...`, `go vet ./...`, focused race tests, and the existing isolated
runner for `test_tui_http.py`, `test_tui_native_proof.py`, `test_tui_public_api.py`.
Public-API tests use isolated PostgreSQL, not the user's project data. Run markdown
links, stale wording and diff checks. Exercise a discriminating layout or sanitizer
defect to demonstrate the new regression detects it. No new coverage quota.

## Human review focus

Find instructions immediately; identify project/collection/resource/section;
distinguish checker evidence from outcome; inspect exact locked context without
hashes crowding out prose; confirm coherent light/plain/compact presentation.

## Evidence

Discovery inspected existing view/model/request boundaries and current tests;
baseline and brief match. Plan review identified hidden confirmation after resize.
`TestHiddenConfirmationCannotStageOrDispatch` failed on the pre-fix owner because
`y` staged a download while only resize guidance was visible, then passed after
the size guard. The same test restores the exact confirmation and verifies the
deliberate positive publication. A native terminal regression covers this boundary.

The old flat Guide assertion is replaced by server-order rows plus exact selected
metadata before and after selection. Finding assertions retain every prior value
in the new grouping. Native resize proof scrolls to exact references and back to
instructions rather than requiring both to occupy the initial viewport. No test
is removed or skipped. Representative renders are fixtures, not live product
proof; native socket and signed-API/PostgreSQL journeys remain distinct checks.

A narrow-but-tall 40x24 probe failed against the height-only compact-footer
selection. Compact controls now depend on width as well as height; boundary
reflow tests cover both sides of the compact and two-pane thresholds, and native
light/dark terminal checks cover 40x10 and 40x24 without extra requests.

Native rendering exposed two proof-host assumptions: the minimal screen observer
must apply the renderer's bounded scroll-region commands, and bare Windows
ConPTY does not expose the background query to the outer fixture. Preserve raw
hostile-output assertions while testing the observed scroll sequence directly.
Bare Windows ConPTY proves neutral unknown-background output, not detected-color
transport: neither the query nor an injected response produced a usable round-trip
in the native fixture. POSIX PTYs prove the real query/response and exact light/dark
palette; an explicitly withheld response separately proves their neutral fallback.
Go tests on every matrix OS prove exact BackgroundColorMsg-to-palette rendering.
The unsupported unsolicited-response expectation is replaced by these explicit
proof boundaries without skipping any platform or changing production styling.
Neither repair changes product authority, the renderer dependency, or CI selection.
41 changes: 28 additions & 13 deletions cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,41 +27,56 @@ non-terminal input/output and JSON mode before making an API request.
Start with your exact-grant projects, then browse **Ready**, **Mine** (active
assignments) and **Submissions**. Enter opens fresh contributor-safe task or
owned Submission detail. Active Mine details offer Context, Intake and Guide
sections. Submission detail also offers paged Findings. Each list fetches one page; filtering searches only that loaded
page. Project membership, terms and action hints are observations, not authority
for a later operation. Workstream rechecks each public read.
sections after Overview. Submission detail offers Overview and paged Findings.
The header keeps the project, collection and active section visible. At
100×24 or larger, a stable left worklist and scrollable right detail pane keep
long instructions and acceptance criteria readable. Guide confirmation replaces
both panes with a scrollable exact-target review; smaller usable terminals
show one pane at a time, and `--plain` is always single-column. Below 40×10,
the workspace shows only resize/quit guidance and cannot confirm a download.
An unopened row previews only loaded-page facts; Enter makes a fresh exact read.
Each list fetches one page, and filtering searches only that loaded page. The
status line labels loaded rows, page/continuation and local observation time,
not a total or a server-wide search. Project membership, potential locked terms
and action hints are observations, not authority for a later operation.
Instructions and criteria lead task detail; exact IDs, hashes and decimal
terms remain available separately. Workstream rechecks each public read.

| Key | Action |
|---|---|
| Arrows / Enter | Select, scroll and inspect |
| Arrows / Enter | Select a row or scroll detail; Enter inspects freshly |
| Tab / Esc | Change section / go back or cancel |
| `g` | Fetch the project picker again |
| `n` / `r` | Fetch the next page / refresh the current view |
| `/` | Filter loaded names/titles locally; Enter finishes and Esc cancels |
| `c` / `?` | Show inert CLI arguments / keyboard help |
| `d` in Guide | Enter an existing download directory; Enter reviews the target, `y` confirms |
| `d` in Guide | Enter an existing download directory; Enter reviews the scrollable exact target, `y` confirms |
| `q` / Ctrl+C | Quit and cancel outstanding client reads; `q` is text during text entry, Ctrl+C always quits |

The workspace makes no product mutation requests: it does not claim/start work,
prepare or submit ZIPs, export records, poll, acquire tokens or save local
history. Guide metadata is not proof of downloaded-byte integrity. In Guide,
select one document, enter an existing real directory and confirm the exact
target. Verified bytes are published under the document's UUID filename without
overwriting an existing file. Cancelled or failed downloads are not published.
select one document, enter an existing real directory and confirm its label,
document/task IDs, path, UUID filename, byte count and hash. Verified bytes are
published under that filename without overwriting an existing file. Cancelled
or failed downloads are not published.
PDF/Office documents are downloaded, not rendered or opened automatically.
Findings display each returned run's identity, current flag and checker evidence;
they do not imply acceptance. `n` fetches one next findings page.
they do not imply the stored Submission outcome or acceptance. `n` fetches one
next findings page. Contribution facts, available through the explicit CLI,
do not establish payment or fulfillment.
Contribution evidence remains a manual CLI handoff: use
`contributions --project PROJECT_ID`. Displayed arguments never execute or copy
automatically.

A denial clears affected content; expired authentication clears the session's
work data. Network failure is shown as unavailable, never as an empty queue or
successful operation. Refresh is deliberate. No background request retries or
write recovery occur. The profile read may perform Workstream's existing actor
work data. A failed current read clears its content and continuation and is
shown as unavailable, never as an empty queue or successful operation. Refresh
is deliberate. No background request retries or write recovery occur. The
profile read may perform Workstream's existing actor
admission, last-seen and audit effects; “read-only” does not mean no server-side
effects. This local interface does not establish a deployed service, payment,
or completion of the broader [terminal design](../docs/design/cli-terminal-experience.md).
or future write/management workflows. See the [terminal presentation contract](../docs/design/cli-terminal-experience.md).

## Explicit commands

Expand Down
46 changes: 46 additions & 0 deletions cli/internal/tui/confirmation_visibility_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package tui

import (
"context"
"os"
"strings"
"testing"

tea "charm.land/bubbletea/v2"
"github.com/Flow-Research/workstream/cli/internal/api"
)

func TestHiddenConfirmationCannotStageOrDispatch(t *testing.T) {
doc := api.TaskGuideDocument{DocumentID: actorID, Label: "Exact original", MediaType: "text/markdown", ByteCount: 5, SHA256: "sha256:" + strings.Repeat("a", 64)}
f := &fakeClient{context: func(context.Context, string) (api.Result[api.WorkContext], error) {
return api.Result[api.WorkContext]{Value: guideContext(doc)}, nil
}}
m := openMineGuide(t, f)
t.Cleanup(m.Close)
directory := t.TempDir()
press(t, m, "d")
press(t, m, directory)
press(t, m, "enter")
before := len(f.calls)
m.Update(tea.WindowSizeMsg{Width: 30, Height: 8})
_, cmd := m.Update(keyMessage("y"))
if cmd != nil || m.download != nil || m.loading || len(f.calls) != before {
t.Fatal("hidden confirmation staged or dispatched a download")
}
entries, err := os.ReadDir(directory)
if err != nil || len(entries) != 0 {
t.Fatal("hidden confirmation touched destination", entries, err)
}
m.Update(tea.WindowSizeMsg{Width: 80, Height: 24})
if m.guideMode != guideConfirm || m.guideDirectory != directory || m.context.GuideDocuments[m.guideSelected].DocumentID != doc.DocumentID {
t.Fatal("resize lost exact confirmation target")
}
if !strings.Contains(m.View().Content, "Confirm download") {
t.Fatal("restored confirmation is not visible")
}
press(t, m, "y")
entries, err = os.ReadDir(directory)
if err != nil || len(entries) != 1 || entries[0].Name() != doc.Filename() {
t.Fatal("visible deliberate confirmation did not publish exact original", entries, err)
}
}
Loading
Loading