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
9 changes: 8 additions & 1 deletion .claude/hooks/glob-guard.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,17 @@ writeFileSync(path.join(CWD, 'notes.md'), '');
process.on('exit', () => rmSync(CWD, { recursive: true, force: true }));

/** @returns {{blocked: boolean, message: string}} */
// WHY an empty fake /proc: the hook refuses to signal Destin's LIVE app, looked up
// by pid in /proc. Against the real one, a literal like `kill -9 4321 5678` failed
// the day pid 4321 was the live app's zygote (2026-09-27). The live-app cases below
// build their own fake /proc (runProc); every other case sees no processes at all.
const NO_PROC = mkdtempSync(path.join(tmpdir(), 'glob-guard-noproc-'));
process.on('exit', () => rmSync(NO_PROC, { recursive: true, force: true }));

function run(command, tool_name = 'Bash') {
const r = spawnSync('python3', [HOOK], {
input: JSON.stringify({ tool_name, tool_input: { command }, cwd: CWD }),
encoding: 'utf8',
encoding: 'utf8', env: { ...process.env, GLOB_GUARD_PROC: NO_PROC },
});
return { blocked: r.status === 2, message: (r.stderr || '').trim() };
}
Expand Down
4 changes: 2 additions & 2 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,9 @@ Target: `v1.3.1`
| [dev-workspace](docs/roadmap/dev-workspace.md) β€” building the app, not the app | 101 | 32 | 4 | 9 |
| [native-harness](docs/roadmap/native-harness.md) β€” the app's own agent doing work | 57 | 10 | 5 | 25 |
| [user-interface](docs/roadmap/user-interface.md) β€” shared primitives, chrome, layout, copy | 40 | 16 | 2 | 6 |
| [remote-access](docs/roadmap/remote-access.md) β€” reaching the app from another device | 29 | 6 | 1 | 4 |
| [remote-access](docs/roadmap/remote-access.md) β€” reaching the app from another device | 30 | 7 | 1 | 4 |
| [sync](docs/roadmap/sync.md) β€” moving your stuff between devices | 26 | 10 | 8 | 5 |
| [chat-data](docs/roadmap/chat-data.md) β€” everything kept about a chat | 22 | 7 | 2 | 2 |
| [chat-data](docs/roadmap/chat-data.md) β€” everything kept about a chat | 23 | 8 | 2 | 2 |
| [other-features](docs/roadmap/other-features.md) β€” real features too small for their own area | 22 | 5 | 6 | 5 |
| [marketplace](docs/roadmap/marketplace.md) β€” finding, installing and rating plugins and themes | 20 | 7 | 0 | 5 |
| [files](docs/roadmap/files.md) β€” documents the user opens, edits or organises | 17 | 4 | 0 | 9 |
Expand Down
11 changes: 11 additions & 0 deletions docs/active/investigations/2026-09-10-android-parity-audit.md
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,17 @@ dev-workspace).

### Found after the consolidation

- **Swiping the app away and reopening it leaves every running conversation's chat blank**
(2026-09-27). Swiping from recents closes the screen but the background service keeps the
sessions running (`SessionService.onTaskRemoved` does nothing, on purpose). The reopened
screen asks each session for its first history page, and Android has no `transcript:page`
handler (the shim refuses it quietly) while its transcript watcher only pushes new lines β€” so
the chat shows "Start a conversation" while the terminal and Claude still have everything,
until close + resume. Read from the code during the desktop blank-chat fix (youcoded#582),
not reproduced on a handset. The desktop cure (read a rebuilt screen's first page to the end)
needs the Kotlin tail reader the paging item already asks for.
`android` `needs-verify` `checked 2026-09-27`

- **Dogfood APKs count as a separate person in our own numbers** (2026-09-13). Android's device
id is scoped to the app-signing key, and `android-test-build.yml` signs with a throwaway debug
key β€” so a dogfood build installed beside the real app on one phone reports a DIFFERENT device
Expand Down
5 changes: 5 additions & 0 deletions docs/roadmap/chat-data.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ Filing test: everything kept about a chat β€” transcript, title, tags, notes, se
resume state. Not here: the model is running right now (native-harness); the files a chat
produced and the panel that shows them (files).

- [ ] A streamed reply was split mid-sentence across two chat bubbles ("…for your review. Now" |
"the invites.") in one practice-app run while the computer was busy; seen once in ~30
loaded runs (2026-09-27), not yet seen in the real app
`chat` `desktop` `needs-verify` `checked 2026-09-27` `needs-repro`

- [ ] The Projects page's conversation list shows only Claude Code conversations and carries no
tags, note or last-used model, so its cards look sparser than the same conversations in the
Resume browser, and assistant conversations in that folder never appear there (seen while
Expand Down
11 changes: 5 additions & 6 deletions docs/roadmap/dev-workspace.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,16 +60,15 @@ seen-on is always n/a here.
bigger budget
`n/a` `confirmed` `checked 2026-09-16`

- [ ] Three small tooling papercuts from the 2026-09-18 premium-motion session, each costing a
whole cycle: (1) `run-dev.sh --stop` lists the dev window's own `claude` children with no
- [ ] Two small tooling papercuts from the 2026-09-18 premium-motion session, each costing a
whole cycle (a third, line budgets only reported at the end of verify, was fixed
2026-09-27: verify checks them first): (1) `run-dev.sh --stop` lists the dev window's own `claude` children with no
sign they are its children β€” have it say so from the process's ancestry, instead of a doc
asking sessions to remember; (2) a fresh session worktree has no `scratch/perf-lab/assets`,
so `fixture.mjs --ensure-assets` re-downloads ~490 MB and a slow link times the whole run
out after the 3-minute build and the quiet-machine wait β€” copy or hardlink from the shared
checkout's `scratch/perf-lab/assets` when it is there; (3) `verify.sh` found six separate
line-budget overruns of one to thirteen lines, each only at the END of a full run β€” run
`tests/line-budgets.test.ts` first, it takes under a second
`n/a` `confirmed` `checked 2026-09-18`
checkout's `scratch/perf-lab/assets` when it is there
`n/a` `confirmed` `checked 2026-09-27`

- [ ] The perf lab's new "blank on arrival" count has never been shown to FAIL. It was added
2026-09-18 (`scenario-workload.mjs` β†’ `switchBlank`) because the painted clock counts entry
Expand Down
7 changes: 7 additions & 0 deletions docs/roadmap/remote-access.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
# remote-access β€” reaching the app from another device
Filing test: reaching the app from another device β€” the protocol, the browser client.

- [ ] A phone connected to the computer can lose the messages it is showing: when the computer
sends its copy of the conversations and its copy of one is empty (it had not loaded that
conversation yet, or its own chat went blank), that empty copy replaces the phone's. Read
from the code during the 2026-09-27 blank-chat fix; left out when Destin scoped that work
to desktop
`desktop` `needs-verify` `checked 2026-09-27`

- [ ] With a phone connected, the computer sends it the terminal output and chat events of every
open session, not only the one the phone is showing β€” more sessions running means a busier
computer and phone. Found by the 2026-09-23 performance review; not built because remote
Expand Down
8 changes: 6 additions & 2 deletions docs/roadmap/user-interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,12 @@ layout, copy. Not here: one screen only β€” that screen's area, with the surface
`all` `confirmed` `checked 2026-09-11` `v1.3.1` β†’ docs/active/investigations/2026-09-10-error-inventory/README.md

- [ ] Chat panel vanished from a live session (beta.16, 2026-08-27) β€” no messages, and new
sessions showed no "Start a conversation" text; Destin said ignore for now
`chat` `desktop` `needs-verify` `checked 2026-08-27` `needs-repro` β†’ docs/archive/investigations/2026-08-27-terminal-black-glyphs-mipmap-driver.md
sessions showed no "Start a conversation" text; Destin said ignore for now. 2026-09-27: a
friend on Windows and Destin on Linux saw messages disappear MID-conversation behind
"Start a conversation" while Claude and the terminal still had them. Four causes fixed
(youcoded#582); what rebuilds the chat mid-conversation in the built app is still unknown β€”
next step is a tripwire that logs what emptied an open chat, or the friend's desktop.log
`chat` `desktop` `needs-verify` `checked 2026-09-27` `needs-repro` β†’ docs/archive/investigations/2026-08-27-terminal-black-glyphs-mipmap-driver.md

- [ ] Switching sessions in terminal view redraws the letters of EVERY open terminal each time
(the black-glyph safety net in `TerminalView.tsx`). Measured 2026-09-10 with the new perf-lab
Expand Down
11 changes: 11 additions & 0 deletions docs/wrap-ups.md
Original file line number Diff line number Diff line change
Expand Up @@ -782,3 +782,14 @@ recurred β€” the repetition is the data.
- Line budgets raised on App.tsx, SettingsPanel, SyncPanel, StatusBar, SessionStrip. RECURRENCE of the budget friction already in `dev-workspace.md` β†’ no new entry
- Destin: "the simplest possible version … fewest error cases … least thinking from the model", and journeys run automatically because "a check nobody runs goes stale" (his call when asked) β†’ applied: spec decisions + the verify.sh comment
- deleted/merged: run-review.sh, cdp-ports.sh, probe-ports.sh, montage.sh, make-gallery.py and their 3 tests + CI step deleted; 82 click plans archived (site-gallery kept); 16 per-shot port/offset mechanisms replaced by one engine; ui-probe and the two drag probes deliberately kept (reasons in the spec)

## 2026-09-27 β€” chat goes blank over a live conversation; native "unreadable" read as "empty" (youcoded#582, session/chat-vanish)
- Line budgets tripped six times (App.tsx, types, ipc-handlers, native-session-host, remote-server, chat-reducer), each only at the END of verify, plus two line-budgets.json merge conflicts. RECURRENCE (4th session) of the 2026-09-18 papercut β†’ applied: `scripts/verify.sh` runs the budget test first (~2 s) and prints the overruns before the parallel checks start; shown red with a one-line probe; roadmap papercut (3) closed in `dev-workspace.md` [~3 extra verify runs]
- Static reading could not find what empties a live chat in the built app; the renderer has no way to write to desktop.log, so the trigger stays unknown β†’ roadmap: the existing `user-interface.md` "Chat panel vanished" item updated with the four fixed causes and the tripwire as next step
- Two independent reviews of my own work each found a real gap (duplicate tool card from an overlapping page; resume's sync header read made the new retry inert) β†’ applied in #582; no new rule: the global rules already ask for unintended-consequence review, and it worked
- A pre-existing journey flake (resume-conversation, ~1 in 6 under load, on master too): step 2's "Resume" matched a chatsearch card's own Resume button when the menu opened slowly β†’ applied: the journey waits for `chat/sessions` (8/8 under 32-core load)
- I read a STALE verify log (verify keeps logs only for failed runs) and briefly believed a green --full run had failed β†’ dropped: verify prints its own log path on failure; my mistake, caught by re-running the suite
- The glob-guard hook blocked a cp-backup/restore toggle for a red-check; a reversible sed toggle worked β†’ no change: the hook did its job
- Destin: "ignore android" (scope), "investigate more thoroughly and fix… check our own work" β†’ no new rule (global.md covers both); Android and phone findings filed (android audit appendix, `remote-access.md`), a split reply bubble filed in `chat-data.md`
- The workspace hook suite failed 1/430 at close-out, on master too: `glob-guard.test.mjs` asserted `kill -9 4321 5678` is allowed, and pid 4321 was Destin's live app that day, so the live-app guard (correctly) blocked it β†’ applied: every non-live-app case runs against an empty fake /proc (`GLOB_GUARD_PROC`); shown red against the real /proc
- deleted/merged: App.tsx's first-page closure moved to `state/first-page-loader.ts` (App.tsx βˆ’27 lines, budget lowered to match)
17 changes: 17 additions & 0 deletions scripts/verify.sh
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,22 @@ fi
# caught before release. Checkouts that predate tsgo fall back to tsc.
TSC=tsc
[[ -x "$DESKTOP/node_modules/.bin/tsgo" ]] && TSC=tsgo

# Line budgets FIRST, synchronously (~2 s), printed before the parallel checks start.
# WHY: an over-budget file was the most repeated verify failure in docs/wrap-ups.md
# (four sessions; six overruns in one, 2026-09-27), and it only surfaced when every
# check had finished, minutes later. Reported now, it is fixed while the rest run.
# Still counted as a failure at the end; the related-tests run repeats it harmlessly.
BUDGETS_FAILED=0
if [[ -f "$DESKTOP/tests/line-budgets.test.ts" ]]; then
if ! ( cd "$DESKTOP" && npx vitest run tests/line-budgets.test.ts ) >"$LOGDIR/budgets.log" 2>&1; then
BUDGETS_FAILED=1
echo "FAIL line budgets (checked first β€” the other checks still run)"
grep -E 'lines, budget' "$LOGDIR/budgets.log" | grep -vE '^\s*[-+]' | sed 's/^ */ /' | sort -u
echo ""
fi
fi

start types "types ($TSC --noEmit)" npx "$TSC" --noEmit -p tsconfig.json
# The test tree is its own TS project (different module resolution, allowJs for
# the .mjs orchestrator). Separate check so a failure names which tree broke.
Expand Down Expand Up @@ -326,6 +342,7 @@ fi

FAILED=0
FAILED_KEYS=()
if [[ $BUDGETS_FAILED -eq 1 ]]; then FAILED=1; FAILED_KEYS+=("budgets"); fi
for key in types testtypes tests knip lint design invariants screens journeys; do
[[ -n "${PID[$key]:-}" ]] || continue
wait "${PID[$key]}"; rc=$?
Expand Down
Loading