Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
10540d5
fix(input): stop adopting stale terminal text
Lint111 Jul 25, 2026
dafad2b
fix(terminal): drain deferred output without a wake event
Lint111 Jul 25, 2026
0736e1a
fix(input): preserve rapid submission boundaries
Lint111 Jul 25, 2026
c6afa9c
fix(mobile): keep keyboard focus taps non-activating
Lint111 Jul 25, 2026
98136e5
feat(mobile): unify terminal navigation controls
Lint111 Jul 25, 2026
333cc4f
fix(terminal): let the active viewport reclaim PTY sizing
Lint111 Jul 25, 2026
b5eda07
fix(mobile): route terminal content taps to the CLI
Lint111 Jul 25, 2026
0d475f5
feat(server): add confirmed instance shutdown
Lint111 Jul 25, 2026
2ce509d
feat(mobile): disclose full setting descriptions
Lint111 Jul 25, 2026
127fcf2
fix(terminal): retain session replay ownership
Lint111 Jul 26, 2026
4f68260
fix(stream): distinguish empty terminal subscriptions
Lint111 Jul 26, 2026
b58ff97
fix(terminal): keep manual history scroll anchored
Lint111 Jul 26, 2026
7cd660f
fix(mobile): route Claude terminal gestures
Lint111 Jul 26, 2026
53fbaa1
fix(mobile): settle keyboard viewport once
Lint111 Jul 26, 2026
fed999a
fix(mobile): keep drafts anchored during output
Lint111 Jul 26, 2026
84f6785
fix(mobile): preserve terminal paste input
Lint111 Jul 26, 2026
602b026
fix(mobile): preserve paste across input fallbacks
Lint111 Jul 26, 2026
233ad17
fix(mobile): coalesce segmented Android paste
Lint111 Jul 26, 2026
a430655
fix(mobile): route Backspace past hidden input
Lint111 Jul 26, 2026
f13f217
fix(mobile): render live IME composition
Lint111 Jul 26, 2026
4be2ec6
fix(mobile): hide duplicate IME candidate
Lint111 Jul 26, 2026
ca1aa88
fix(mobile): persist IME fallback text
Lint111 Jul 26, 2026
09fdef7
fix(mobile): retain Android null-data input
Lint111 Jul 26, 2026
ef546aa
fix(mobile): recover interrupted IME state
Lint111 Jul 26, 2026
502d99b
fix(mobile): flush draft through control Enter
Lint111 Jul 26, 2026
58b05bb
fix(hooks): reawaken completed background commands
Lint111 Jul 28, 2026
6c09512
fix(transcripts): complete tools from user results
Lint111 Jul 28, 2026
085c5e3
feat(input): persist multiline terminal drafts
Lint111 Jul 28, 2026
4682d6d
feat(sessions): restore and stream live terminal state
Lint111 Jul 28, 2026
7a44b56
feat(files): expose repository worktree diffs
Lint111 Jul 28, 2026
1172b63
fix(notifications): quiet lifecycle hook noise
Lint111 Jul 28, 2026
eddd429
feat(mobile): stabilize terminal session lifecycle
Lint111 Jul 28, 2026
0511be3
feat(viewer): add repository and response inspection
Lint111 Jul 28, 2026
583abb6
feat(cases): add inline edit and delete actions
Lint111 Jul 28, 2026
7b07365
fix(sessions): preserve active terminal during launches
Lint111 Jul 28, 2026
acb1b98
feat(codex): make terminal animations configurable
Lint111 Jul 28, 2026
0624144
fix(settings): migrate quiet notification defaults
Lint111 Jul 28, 2026
f59a7d1
docs: document mobile terminal architecture
Lint111 Jul 28, 2026
d6de5b5
chore: merge upstream master
Lint111 Jul 28, 2026
50573fd
fix(terminal): preserve cursor boundaries across websocket frames
Lint111 Jul 28, 2026
8afe30e
fix(mobile): reconcile authoritative terminal frames
Lint111 Jul 28, 2026
b14c1bf
docs: explain authoritative terminal transitions
Lint111 Jul 28, 2026
9e07ffa
chore: merge upstream master
Lint111 Jul 28, 2026
e613d4a
test: isolate quick-start case fixtures
Lint111 Jul 28, 2026
b0a35a7
fix(hooks): preserve custom handlers during refresh
Lint111 Jul 28, 2026
7025fac
fix(security): confine repository worktree scopes
Lint111 Jul 28, 2026
9501644
fix(security): require authentication for shutdown
Lint111 Jul 28, 2026
86707c1
refactor(input): centralize browser terminal input
Lint111 Jul 28, 2026
092f1a3
fix(mobile): make terminal controls opt in
Lint111 Jul 28, 2026
b8d7c34
docs: record mobile experience PR split audit
Lint111 Jul 28, 2026
4b3f4a7
docs: normalize audit formatting
Lint111 Jul 28, 2026
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
14 changes: 8 additions & 6 deletions CLAUDE.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion config/vitest.ci.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export default defineConfig({
'test/mobile/**', // browser/visual (Playwright + chromium)
'test/perf-*.test.ts', // timing-sensitive perf benchmarks (flaky in CI)
'test/inline-rename.test.ts', // browser (Playwright)
'test/opencode-resize.test.ts', // browser (Playwright)
'test/terminal-viewport-resize.test.ts', // browser (Playwright)
'test/webgl-fallback.test.ts', // browser (Playwright)
],
setupFiles: ['./test/setup.ts'],
Expand Down
17 changes: 11 additions & 6 deletions docs/architecture-invariants.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/archive/phase7-test-infrastructure-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ This avoids port conflicts entirely and runs fast. Only tests that need SSE or W
| 3223 | `test/routes/ralph-routes.test.ts` | Ralph API |
| 3224–3229 | Reserved | Future route tests |

Most tests should NOT need real ports — `app.inject()` is preferred. Verified: ports 3220–3229 are completely unused by existing tests (highest used port is 3211 in `opencode-resize.test.ts`).
Most tests should NOT need real ports — `app.inject()` is preferred. Verified: ports 3220–3229 are completely unused by existing tests (highest used port is 3211 in `terminal-viewport-resize.test.ts`).

---

Expand Down
352 changes: 352 additions & 0 deletions docs/audits/2026-07-25-mobile-navigation-and-hooks-audit.md

Large diffs are not rendered by default.

164 changes: 164 additions & 0 deletions docs/audits/2026-07-28-mobile-experience-pr-split-audit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
# Mobile Experience Change-Set Audit

**Date:** 2026-07-28
**Scope:** `origin/master..agent/mobile-terminal-experience` plus the pending terminal input controller extraction
**Mode:** Full, with architecture, code-quality, and test specialists
**Size:** 112 tracked and pending files, 43 existing commits, approximately 21,000 added lines before audit commits

## Assessment

The combined branch is not reviewable as one pull request. It mixes terminal
transport, mobile controls, destructive instance management, Git-backed file
browsing, hook configuration, case management, and unrelated settings. The
features should be rebuilt from `origin/master` and published as independent
draft pull requests.

| Severity | Count | Status |
| --- | ---: | --- |
| Critical | 4 | Fixed in the audited working tree |
| High | 5 | Four fixed; CI coverage split remains follow-up work |
| Medium | 6 | Three fixed; remaining gaps are documented per PR |

## Blocking Findings

### Passwordless remote shutdown

`src/web/routes/system-routes.ts:144` relied on `requireAdmin`, while
`src/web/route-helpers.ts:185` treats passwordless single-user mode as admin.
Any network client reaching Codeman could therefore schedule a persistent
service shutdown.

**Resolution:** passwordless single-user shutdown now returns `403`; authenticated
single-user installs and multi-user admins retain access. Route tests cover
passwordless and non-admin denial.

### Self-deleting quick-start fixture

`test/quick-start.test.ts` used the real `~/codeman-cases` directory and removed
the default `testcase` recursively during cleanup. Running CI from a checkout at
`~/codeman-cases/testcase/Codeman` therefore deleted the repository, its Git
metadata, and `node_modules` while Vitest was still running.

**Resolution:** the test now assigns a unique temporary home before dynamically
importing `WebServer`, so its module-level `CASES_DIR` resolves inside the
fixture. The test restores the environment and removes only that temporary home.

### Cross-user repository worktrees

`src/web/routes/file-routes.ts:462` accepted a linked-worktree root returned by
Git without reapplying `isWorkingDirAllowed`. A regular multi-user session in
one allowed worktree could select and read a sibling worktree outside its user
space.

**Resolution:** every repository scope transition is authorized, overview
metadata filters disallowed worktrees, and commit, diff, tree, content, raw,
preview, and thumbnail routes share the same check. Tests cover a linked
worktree outside the user's case space.

### Mixed hook configuration loss

`src/hooks-config.ts:354` identified the entire hooks object as Codeman-owned
when any command referenced `/api/hook-event`, then replaced the full object.
Mixed Codeman and user hooks lost user handlers during self-healing.

**Resolution:** ownership is now determined per command handler. Installation
and refresh replace only Codeman handlers and preserve user events, matchers,
and handlers sharing a matcher.

### Mobile terminal could become unfocusable

`src/web/public/terminal-ui.js:3602` recognized only a narrow set of prompt
glyphs and otherwise classified live Claude rows as content. Touch handling
prevented the browser compatibility focus event, leaving no way to open the
keyboard on promptless redraws.

**Resolution:** known menus, working indicators, and transcript rows remain TUI
content; the live cursor and a lower-screen fallback band remain focusable.
The Playwright regression asserts the helper textarea becomes
`document.activeElement` and no mouse report is sent.

### Input ownership invariant was false

Voice input, image paths, accessory commands, and fallback Enter called
`sendInput` directly despite the documented controller-only boundary.
The pending controller extraction also left three path-picker tests bound to
the deleted implementation.

**Resolution:** all interactive producers now enter semantic
`TerminalInputController` methods. A static producer boundary test rejects
future direct transport calls, DOM-adapter tests dispatch real composition,
delete, and paste events, and the path-picker harness asserts delegation.

### Controls were not opt-in

`src/web/public/settings-ui.js:2006` and the corresponding HTML controls enabled
mobile controls and haptics by default despite the feature description calling
them optional.

**Resolution:** canonical defaults are off. Explicit canonical and legacy true
values still migrate to enabled; device detection alone no longer enables the
feature.

### Phone header policy was weakened

`test/mobile-header-buttons-policy.test.ts:32` allowlisted File Viewer and
instance shutdown on the phone header.

**Resolution:** the allowlist is empty again and CSS explicitly hides both
buttons on phone widths.

## Remaining Test Gaps

- The main CI config excludes the Playwright mobile suites. Each frontend PR
must report its focused Playwright command until a stable browser smoke job
is added.
- The broad mobile browser run still carries unrelated baseline debt: 24 visual
snapshots need an intentional refresh, while 23 structural assertions already
disagree with `origin/master` behavior such as disabled pinch zoom and the
legacy 430px phone breakpoint. These should be repaired separately instead of
weakening feature-specific gates.
- Terminal history paging and warm-cache tests still lean heavily on source
assertions. The streaming PR should add executable state-machine coverage.
- `Session.setWorkingDir` needs a focused collaborator synchronization test.
- Instance shutdown orchestration needs injected timer/process ports before its
idempotency and supervisor rollback paths can be unit tested safely.
- Volume-key support is progressive enhancement only. Browser tests can verify
DOM key mapping, not whether Android or iOS exposes physical volume keys.

## Pull Request Slices

1. Self-contained quick-start test fixture.
2. Mobile terminal controls and opt-in settings.
3. Mobile terminal tap routing.
4. Persistent terminal draft state and the centralized input controller.
5. PTY viewport sizing ownership.
6. Terminal history streaming, cache, and frame reconciliation.
7. Background-command reawake hooks.
8. Transcript tool-result completion.
9. Lifecycle notification noise reduction.
10. Repository/worktree browser and file diff UI.
11. Response viewer.
12. Secure instance shutdown.
13. Inline case edit/delete actions.
14. Active-session launch preservation.
15. Codex animation preference.

Backend terminal protocol changes should precede frontend replay/cache changes.
The draft store should precede the controller adapter if those input changes are
published as stacked PRs. All other slices can target `master` independently.

## Validation Recorded During Audit

- Controller/input focused unit tests: passed.
- Shutdown and header policy tests: passed.
- Hook configuration and self-heal tests: passed.
- Repository scope, symlink, binary, and size-limit tests: passed.
- Promptless mobile focus Playwright regression: passed.
- Focused keyboard, controls, header, tabs, settings, and repository Playwright
suites: 160 passed.
- Full CI: 200 files passed, 3,977 tests passed, 12 skipped.
- Self-contained quick-start regression: 15 passed and the checkout remained
intact.
- TypeScript typecheck: passed.
- Frontend syntax and public asset checks: passed.
- `git diff --check`: passed.
Loading