<?xml version="1.0" encoding="UTF-8"?>
<spec xmlns="https://vibevm.org/spec/1">
  <title>vibe tree — the interactive spec-tree browser</title>
  <p p="1"><fact id="purpose" status="impl/done">**Purpose.** `vibe tree` (PROP-036) is an interactive terminal UI: it renders
the resolved package tree, lets a human navigate/fold it, opens a detail modal,
and cycles ordering + display modes. The automated suite proves the *model*
(the engine + `--json` validate against the schema, and the flat renderer has
unit tests), but it cannot drive a real terminal and confirm that the tree
*renders and reads right* — the box-drawing aligns, the selection highlights,
the keys respond, the modal overlays cleanly, and colour works on this
terminal. That is what a human proves here. `vibe tree` is **read-only** (it
mutates nothing — no per-user state, no project files), so this test needs no
state isolation; it runs against the vibevm repo itself, which is a rich real
tree.</fact></p>
  <section title="Preconditions">
    <list ordered="false" p="2">
      <item><fact id="PRE-TTY" status="impl/done">A real interactive terminal (a tty) — this is the whole point; the TUI does
  not launch when stdout is piped or redirected.</fact></item>
      <item><fact id="PRE-BINARY" status="impl/done">The working-tree binary built from this repo: `cargo build -p vibe-cli`
  (invoke it as `./target/debug/vibe`, never a stale PATH `vibe`).</fact></item>
      <item><fact id="PRE-REPO-ROOT" status="impl/done">Run from the vibevm repo root (its `vibe.lock` + `vibevm/vibespecs/boot/{STATIC,INDEX}.md`
  are the tree under test). No network, no credentials.</fact></item>
    </list>
  </section>
  <section title="Setup">
    <fence p="3">cargo build -p vibe-cli
cd &lt;vibevm repo root&gt;          # the project whose tree is rendered</fence>
    <p p="4"><fact id="setup-no-isolation" status="impl/done">No scratch/state redirect is needed: `vibe tree` reads `vibe.lock`, the
manifests, and the committed boot artifacts, and writes nothing.</fact></p>
  </section>
  <section title="Steps">
    <list ordered="true" p="5">
      <item><fact id="STEP-1-MACHINE-SURFACE" status="impl/done">The machine surface still works (non-tty fallbacks).</fact></item>
    </list>
    <fence p="6">   ./target/debug/vibe tree --json | head -c 200
   ./target/debug/vibe tree --plain | head -20</fence>
    <p p="7"><fact id="EXP-1-MACHINE-SURFACE" status="impl/done">**Expected.** `--json` prints an object opening `{"ok":true,"command":"tree",`
   with `"schema_version":1`. `--plain` prints a static ASCII tree: a header
   line (`project: …`), a `STATIC.md: … bytes / … lines` line, a `columns: load
   T=… C=… S=…` legend, then rows drawn with `│ ├ └` and a `load` column
   (`static`/`dynamic`/`none`) plus three checkbox columns. `redbook` shows
   `static` with `S = x`; `rust-ai-native` (the umbrella) shows `none`. Neither
   command clears the screen or waits for input.</fact></p>
    <list ordered="true" p="8">
      <item><fact id="STEP-2-LAUNCH-TUI" status="impl/done">Launch the interactive TUI.</fact></item>
    </list>
    <fence p="9">   ./target/debug/vibe tree</fence>
    <p p="10"><fact id="EXP-2-LAUNCH-TUI" status="impl/done">**Expected.** The terminal switches to a full-screen view. A **status line**
   reads `ordering: topological   mode: all   STATIC.md: &lt;N&gt; bytes / &lt;N&gt; lines
   packages: &lt;N&gt;`. A **footer** shows the keymap hint (`F1 search · F2 sort ·
   F3 mode · F4 settings · F6 copy · ↑↓ move · ←→ pan · Space fold ·
   Enter details · Esc quit`).
   The tree fills the body; the first row is highlighted (reverse/coloured).</fact></p>
    <list ordered="true" p="11">
      <item><fact id="STEP-3-NAVIGATE" status="impl/done">Navigate with the arrow keys.</fact></item>
    </list>
    <p p="12"><fact id="EXP-3-NAVIGATE" status="impl/done">**Expected.** `↓`/`↑` move the highlight one row and the view scrolls to keep
   the selection on screen when you reach the bottom/top. `←`/`→` pan the name
   column horizontally (deep/long ids that ran off the right edge come into
   view; the `load`/checkbox columns stay fixed).</fact></p>
    <list ordered="true" p="13">
      <item><fact id="STEP-4-FOLD" status="impl/done">Fold and unfold.</fact></item>
    </list>
    <p p="14"><fact id="EXP-4-FOLD" status="impl/done">**Expected.** With a node that has children selected, `Space` collapses its
   subtree and the node's indicator flips to `+`; `Space` again expands it back
   to `-`. `F` folds the whole tree to its roots (all `+`); `F` again unfolds
   everything. A package reached twice (a diamond) shows once expanded and once
   as a `(*)` leaf.</fact></p>
    <list ordered="true" p="15">
      <item><fact id="STEP-5-DETAIL-MODAL" status="impl/done">Open the detail modal.</fact></item>
    </list>
    <fence p="16">   (press Enter on a selected package row)</fence>
    <p p="17"><fact id="EXP-5-DETAIL-MODAL" status="impl/done">**Expected.** A bordered popup overlays the tree (the cells beneath are
   cleared, not bled through) showing the package's detail **vertically**:
   name, group, version, kind, load type, transitive (+ why), condition,
   in-STATIC.md, source, content hash, dependencies, boot file. `Esc` closes it
   and returns to the tree at the same selection. While the modal is open, other
   keys are swallowed (do not move the tree).</fact></p>
    <list ordered="true" p="18">
      <item><fact id="STEP-6-ORDERING" status="impl/done">Change the ordering.</fact></item>
    </list>
    <fence p="19">   (press F2, choose "alphabetical")</fence>
    <p p="20"><fact id="EXP-6-ORDERING" status="impl/done">**Expected.** The F2 sort menu opens. Choosing `alphabetical` closes it, the
   status line's `ordering:` flips to `alphabetical`, and the
   siblings re-sort by `group/name` (the tree structure is preserved — a parent
   still precedes its children). F2 again and `topological` returns.</fact></p>
    <list ordered="true" p="21">
      <item><fact id="STEP-7-MODES" status="impl/done">Cycle the display modes.</fact></item>
    </list>
    <fence p="22">   (press F3, choose each mode in turn)</fence>
    <p p="23"><fact id="EXP-7-MODES" status="impl/done">**Expected.** The F3 mode menu opens. **sub-tables**: a flat list under bold
   subheaders `static dependencies`, `dynamic dependencies`, `no-boot`
   (`mode: sub-tables` in the status line). **tabs**: a tab bar `Static | Dynamic |
   No-boot` with one group's flat list below (`mode: tabs`). **all**: back to
   the tree. In every mode the `load`/T/C/S columns stay meaningful.</fact></p>
    <list ordered="true" p="24">
      <item><fact id="STEP-8-SWAP-TABS" status="impl/done">Swap priority and switch tabs.</fact></item>
    </list>
    <fence p="25">   (in tabs mode: press Shift+→, then Shift+←)</fence>
    <p p="26"><fact id="EXP-8-SWAP-TABS" status="impl/done">**Expected.** In tabs mode `Shift+→` advances to the next tab (wrapping) and
   `Shift+←` goes back; the shown flat list changes to the active group. The
   static/dynamic priority is a setting, reachable from the F4 settings menu —
   the pre-Spec-2 bare `t` / `Tab` / `[` / `]` bindings do not ship.</fact></p>
    <list ordered="true" p="27">
      <item><fact id="STEP-9-QUIT" status="impl/done">Quit.</fact></item>
    </list>
    <fence p="28">   (press Esc, then confirm)</fence>
    <p p="29"><fact id="EXP-9-QUIT" status="impl/done">**Expected.** A `Really quit?` confirm dialog appears; confirming exits the TUI,
   the alternate screen is torn down, and the
   normal terminal (with your scrollback intact) is restored — no leftover
   raw-mode, no garbled prompt, exit code 0.</fact></p>
  </section>
  <section title="Teardown">
    <p p="30"><fact id="teardown-none" status="impl/done">None — `vibe tree` wrote nothing. (If a crash ever leaves the terminal in raw
mode, `reset` restores it.)</fact></p>
  </section>
  <section title="What to file if it fails">
    <list ordered="false" p="31">
      <item><fact id="FAIL-STEP-NUMBER" status="impl/done">The failing step number; what you saw beside its **Expected**.</fact></item>
      <item><fact id="FAIL-SCREENSHOT" status="impl/done">A screenshot or a copy of the mis-rendered frame (the exact glyphs/colours).</fact></item>
      <item><fact id="FAIL-MODEL-OUTPUT" status="impl/done">`./target/debug/vibe tree --json` output (the model the TUI renders) and
  `./target/debug/vibe tree --plain` (the same tree, copy-pasteable).</fact></item>
      <item><fact id="FAIL-PLATFORM" status="impl/done">Platform, terminal emulator + `$TERM`, `./target/debug/vibe --version`, shell.</fact></item>
    </list>
  </section>
</spec>
