| 📦 Turbo Go 3d7798b k33g 12h ago | 1 | # Handoff — 2026-08-31 — project tree window |
| 2 | |
| 3 | ## State |
| 4 | |
| 5 | **Ticket 0003 is done and green**, on branch `feature/treeview-window`, **uncommitted**. |
| 6 | |
| 7 | `F9`, or **Window ▸ Project tree**, opens a window listing the project's files. Arrows walk it, `→`/`←` open and close branches, `Enter` opens a file, `F5`/`Ctrl-R` re-reads. |
| 8 | |
| 9 | ``` |
| 10 | ╔═[x]════════════ turbo-go ════════════2═[■]╗ |
| 11 | ║ ▶ .turbo-go ║ |
| 12 | ║ ▼ internal ║ |
| 13 | ║ ▶ app ║ |
| 14 | ║ go.mod ║ |
| 15 | ╚══════════════════════════════════════════╝ |
| 16 | ``` |
| 17 | |
| 18 | - New `internal/filetree` (94.7 %, 41 tests), 10 more in `internal/app`. |
| 19 | - Four `tree.*` theme keys, set in all three shipped themes and enforced by the existing completeness test. |
| 20 | - Whole suite green under `-race`. Quality gate **PASS** first time: 0/0/0, complexity 1228. |
| 21 | - Docs complete in EN and FR — three new pages each, six existing pages updated each. `docs/diagrams/packages.drawio` gained `filetree`; re-checked against `go list`, 31 edges each side. |
| 22 | - **Verified by rendering the real binary through the project's own VT emulator**: `F9` lists with `.git` hidden, `→` nests two levels, `Enter` opens a file into a third window. |
| 23 | |
| 24 | Earlier the same day, PR #3 merged the window frame boxes and the Open-dialog OK fix. |
| 25 | |
| 26 | ## In flight |
| 27 | |
| 28 | Nothing. Finished through Phase 8. |
| 29 | |
| 30 | ## Next steps |
| 31 | |
| 32 | 1. **Commit and open the PR.** `feature/treeview-window` is the branch. |
| 33 | 2. **Drive the tree with a real mouse.** Everything went through code and the emulator; clicking a row, the second-click-to-open rule and the wheel have never been exercised by hand. |
| 34 | 3. **Tickets.** 0002, 0003 and 0007 are all implemented and all still `state: open`. |
| 35 | |
| 36 | ## Open questions / blockers |
| 37 | |
| 38 | - **`.gitignore` is not respected.** The tree shows `bin/`, `release/` and anything else git ignores. Hiding them would be genuinely nicer and costs a gitignore pattern engine — negation, `**`, anchoring — which is a feature to decide on rather than a detail to slip in. Recorded in the explanation page as turned down *for now*. |
| 39 | - **The root is the working directory, not the module root.** Start the editor from `internal/app` and the tree shows only that. This was the user's choice, for one rule across the whole editor; if it turns out to annoy in practice, `main.moduleRoot` is already there and already tested. |
| 40 | - **A docked side panel was turned down**, not rejected forever. If it is wanted, it is a `ui` feature — `Desktop` needs reserved edges that `fitInto`, the grow modes, maximise, tile and cascade all respect — and should be designed on its own terms rather than arriving with a file browser. |
| 41 | |
| 42 | ## Watch out for |
| 43 | |
| 44 | - **The tree's theme keys are not decoration.** `list.selected` is coloured against a *dialog*: turbo-classic makes it white on navy, and `window.body` is navy. Borrowing it would make the selected row invisible in the editor's default theme. `TestTheHighlightIsVisibleInEveryShippedTheme` fails at 0 channel values if anyone "simplifies" `tree.selected` back to the list colours — I checked by doing exactly that. |
| 45 | - **`testDirectory` in `internal/app` does not create intermediate directories.** `testDirectory(t, "internal/app.go")` fails; use `"internal/"` and a separate file. `makeTree` in `internal/filetree` *does* nest, which is easy to confuse when moving a fixture between the two packages. |
| 46 | - **Refresh must not walk the project.** `Node.refresh` returns immediately for a directory that was never loaded, and `TestRefreshLeavesUnopenedDirectoriesUnread` is what stops that being lost. Removing the guard would turn every save into a full-tree walk. |
| 47 | - **`left` on a row has two meanings and both matter.** On an open directory it collapses; on anything else it moves to the parent — found as the nearest row above with a smaller depth, which needs no parent pointer. Making it only collapse turns it into a no-op on every file, which is most rows. |
| 48 | - **Collapsing can leave the highlight past the last row.** `keepSelectionInRange` after every toggle is what prevents it; `TestCollapsingABranchKeepsTheHighlightOnARow` covers it. |
| 49 | - **`a.treeWindow` must be cleared when the window closes**, or `F9` tries to focus a window that is no longer on the desktop. `closeWindow` has a branch for it beside the terminal one. |