stackmapis a macOS-targeted Rust TUI prototype for local Git branches with optional Graphite and GitHub enrichment.- Structural refresh, diff enrichment, GitHub lookup, checkout, and platform actions use bounded independent coordinators so the UI and branch inventory remain responsive.
- Structural and enriched refresh events are distinct; only a successful structural inventory clears stale refresh health.
- App snapshot ordering is generation-monotonic; PR enrichment is preserved and matched by branch ID plus tip OID.
- Diff work is capped at four subprocesses with a 2,048-entry cache. Refresh/event/request queues are bounded.
- Obsolete diff generations stop scheduling between tasks, and identical OID pairs share one diff subprocess result.
- Graphite edges are trusted only when their complete local chain reaches one of the ordered configured local trunks, with metadata re-read before accepting a snapshot. Missing/invalid chains remain visible in the final Untrunked section.
- Git repository paths are discovered once per adapter. Structured or diff output truncation is rejected.
- Config updates use a bounded cross-process lock and atomic rename; parse errors retain the last valid in-memory config. Stack colors, archive membership, and bounded single-line stack names apply immediately and persist through one active plus one coalesced pending background write with per-identity sequence protection.
- The minimum supported terminal width is 40 columns. Persistent stale refresh health clears on the next valid snapshot.
- Deep narrow stacks use compact connectors so 40-column rows never wrap from indentation alone.
- GitHub failures remain typed through the UI, and macOS open/copy helpers have bounded subprocess timeouts.
- Child subprocesses run in separate process groups so a timeout terminates descendants as well as the direct child.
- The viewer uses fixed bottom-up Graphite lanes, aligned branch labels, ordered trunk sections, an Untrunked section, green additions/red deletions, and a fixed right-side
WTmarker. - Reducer-owned
t,h,H, andsviews project in memory.J/Kand shifted arrows use precomputed visible stack heads.cchanges only the selected stable stack ID. - Recent is the startup order.
Tselects Recent/Alphabetical/Graphite,+/-/0controls global lane pitch,Copens the color picker, andg/Gare the terminal-portable section-edge fallback for Option+Arrow. xis reversible archive/restore and moves focus to the nearest visible row above,atoggles Archive view, andvpreviews an inclusive contiguous range committed with Enter. Archive state persists by branch name in the repository-local config; structural refresh automatically unarchives names that become current or configured trunks. Archive view renders required unarchived ancestry as dim, nonselectable stack context.nedits a persistent repository-local name for the selected stable stack ID. The white label is a nonselectable semantic row immediately above that stack's head; Enter saves, empty Enter clears, and Esc cancels. Trunks are intentionally unnamed.- Remote-ref/upstream evidence is local-only and no-fetch in both Active and Archive views. Containment work runs only for the bounded visible working set through one active/latest-pending coordinator.
- Checkout and deletion share one mutation state. Post-mutation refreshes carry causal request epochs, so queued pre-mutation snapshots cannot release the mutation slot.
- Deletion is exact, local-only, confirmed with uppercase
Xtheny/n, and non-force. Lowercasexnever deletes. Git-only deletion is merged-to-HEAD and expected-OID atomic. Graphite deletion is tracked-leaf-only, validates raw children, uses a cached allowlisted CLI contract, re-reads Git plus raw metadata after every invocation, and blocks inconsistent results. - Config persistence drains active and latest coalesced writes after terminal restoration during quit. The drain is capped at five seconds, retries one failed final write, and exits nonzero if persistence still fails.
- Graphite CLI 1.8.6 was characterized in a disposable repository: noninteractive leaf deletion removed the exact local ref and metadata while retaining the trunk. The provider still cannot offer expected-OID atomicity.
- Rendering uses direct snapshot-row, projected-row, lane-count, and lane-span indexes; viewport work does not scan the complete branch or stack set.
- Connector junction cells retain the parent/left rail color; the horizontal segment and child corner switch to the child stack color. The selected row fills edge-to-edge with its stack/trunk identity color while the checked-out branch retains its subtler tint when not selected.
- Enhanced terminals receive the complete Crossterm keyboard protocol flags. Shift+Arrow and Command+Arrow both map to stack jumps when the terminal reports their modifier; Stackmap decodes standard
ESC [1;2A/BShift sequences, andJ/Kremains the portable fallback when a terminal intercepts or erases modifiers. - Downward stack navigation treats the configured trunk as the final destination after the lowest real stack, so Shift+Down and
Jcan land on the trunk even though it is not itself a stack. - In focused views the trunk remains a sticky bottom row; when Shift+Down or
Jlands on it from the lowest stack, the scrollable stack rows also align to their bottom-most viewport position. - The crate and lockfile are pinned to Rust 1.88.0. Formatting, strict offline Clippy, 175 all-target/all-feature tests, the offline release build, focused Tier-2 review, real Git/Graphite integration, and PTY smoke tests pass on that toolchain.
- The open-source alpha identity is
0.1.0-alpha.1. Cargo publication is disabled; GitHub source and two-architecture macOS prerelease assets are the intended distribution paths. - The executable exposes a narrow documented runtime facade. White-box integration coverage is crate-internal and benchmarks use a feature-gated benchmark facade rather than public application internals.
- Release policy includes pinned macOS 15 ARM64/Intel CI, a stable-Rust compatibility lane, cargo-deny policy, Dependabot, fail-closed release aggregation, checksums, and artifact attestations.
- Dependency policy runs on every pull request because
cargo-denyis a requiredmaincheck; path filtering would leave unrelated pull requests permanently unmergeable. - Core responsibilities are split behind private modules: topology projection/index/emission, Git inventory/mutation, App state/overlays/archive/mutation, and tree details/connectors.
- Recoverable production paths return typed or degraded outcomes. Remaining topology
expectcalls represent documented iterative-emission programmer invariants. - Render tests cover both ordinary color output and
NO_COLOR; selected colored rows use the identity accent as their background with a black identity glyph. Deadline tests assert bounded work counts instead of scheduler-sensitive wall-clock thresholds. - The installed release binary is 3,713,072 bytes. In a synthetic 2,001-branch repository the preceding release measured about 15.4 MB RSS after startup, warmed to about 19.3 MB with Archive evidence, and plateaued at 19.856-19.888 MB after 100 refresh requests and repeated view/order/layout/navigation toggles.
- Release benchmarks measured about 0.108 ms per 500-branch projection, 1.10 ms per 5,000-branch projection, and 0.94 ms per projection of one 5,000-branch deep stack. A 5,000-level/10,000-branch deep comb emits iteratively without call-stack recursion; broad attach-parent lookup is indexed.
- Public development lives at
https://github.com/fieldsofland/stackmapon protectedmain. Native macOS ARM64/Intel CI, current-stable compatibility, and dependency policy pass at commit0f01e4346448c700c0474061734005f08e767405. stackmap 0.1.0-alpha.1is installed at/Users/matt/.cargo/bin/stackmap, resolves onPATH, and passes startup/quit smoke testing in a disposable Git repository.- Visual feature sections are repository-local presentation ranges anchored by branch name.
itoggles a boundary; successive boundaries cumulatively indent only branch-name/label text while real circles, rails, connectors, and Git/Graphite state remain unchanged. - Visual sections persist an atomic optional name plus concrete color. Their effective colors differ from adjacent base/section ranges;
c/Cact on an exact boundary or selected section label, while ordinary member branches retain stack-color behavior. - Stack and visual-section labels are selectable rows.
ncreates only a missing label, Enter edits an existing selected label inline, empty Enter removes only the label, and Escape cancels. Name editing owns raw printable input (includingj/k/g/G/J/K), repeats, and Backspace before normal bindings; Ctrl-C is inert until editing ends. - Inline name editing has a Unicode-safe character cursor: Left/Right and Home/End move it, typing inserts at it, Backspace removes before it, and Delete removes after it.
- Named stack rows show the total number of real branches owned by that topology group, excluding the trunk and separate child/side stacks and remaining stable under filtering.
- The wide branch-detail sidebar is session-only, hidden by default, and toggled with
dat 120 columns or wider. - Selected rows use their full identity-color fill with black foreground content across branch name, time, diff, worktree, and PR metadata. The unselected checked-out row uses a 40%-strength blend of its identity color over black.
- Metadata geometry reserves a blank gutter between relative time and diff columns and a blank trailing cell after the PR column so dense wide rows remain readable.
- Compact diff counts below ten thousand retain one decimal digit (
4.3Kinstead of4K); larger compact values remain integer thousands to preserve fixed-width alignment. - Branch checkout requires two consecutive Enter presses on the same branch. The first opens a centered confirmation popup naming the target and showing
Enter switch · Esc cancel; Enter confirms, while Escape or navigation cancels before Git runs. Label Enter still edits immediately. - Consecutive structural snapshots compare existing branch tip OIDs. Selection follows the most recently committed changed branch that remains selectable in the current view; enrichment-only updates, initial load, deletions, and hidden changes do not move the cursor.
- Selected stack and visual-section label rows retain their stack/section identity color as the highlight and use white foreground content, including aggregate diff text.
- Focused sections shorter than the viewport bottom-align their complete visible content immediately above the pinned trunk/bottom row; long focused sections retain the existing scrolling and continuation cues.
- The current test build, including checkout confirmation, changed-branch cursor following, identity-colored label selection, focused-view bottom alignment, precise compact diffs, sticky-trunk bottom navigation, cursor-aware name editing, and named-stack branch counts, is installed at
/Users/matt/.cargo/bin/stackmapwith SHA-2569ca3c2d70475360caaf553d019cbb349bb523ca345a8c9fa2a7762ad38e51dc7. It exactly matchestarget/release/stackmap. - The agent integration plan is
docs/plans/2026-07-21-002-feat-agent-status-cli-plan.md: v1 is a versioned read-onlystackmap agent statuscontract with complete per-worktree cleanliness and integrations forfm-mobile-review/worktree-rules; JSONL watch, annotations, MCP, and mutations are deferred until usage proves demand. - The reviewed stack-summary plan is
docs/plans/2026-07-21-003-feat-stack-summary-hierarchy-plan.md: named stack titles show a true displayed-group base-to-tip net diff, stack titles get a dedicated spacer, section titles stay adjacent to owned branches, and metadata gains a diff-to-worktree gutter. Aggregate scheduling must pass a 500/5,000-stack responsiveness characterization or fall back to named/on-demand targets. - Named stack summaries are now generation-scoped
DiffStatevalues keyed by real displayed topology-group ID. They compare the bottom branch's validated parent OID directly to the group's primary head OID; side stacks therefore exclude parent/sibling work and intermediate reversions produce a true net result. - Diff enrichment runs branch/shared OID-pair tasks first and publishes that immutable partial snapshot before aggregate-only tasks. Aggregate work remains deduplicated, cache-bounded, cancellation-aware, capped at four workers, and characterized at 500/5,000 groups.
- Named stack projection is
StackLabel -> dedicated nonselectable Spacer -> section label or branch; section labels remain adjacent to their first visible owned branch. Metadata reserves time-to-diff, diff-to-worktree, and PR-to-edge gutters. - Passive Git monitoring runs with optional locks disabled, so inventory/status/diff commands cannot refresh or lock the index. Explicit checkout and deletion retain normal Git locking and use a separate 30-second mutation deadline.
- Repository notifications are path-filtered and quiet-period debounced; transient locks, object-store writes, logs, and temporary files do not trigger structural refreshes. Five-minute reconciliation is a dropped-event safety net rather than the primary monitor.
- Normal quit, terminal-close signals, and recoverable error exits stop the watcher, terminate registered subprocess groups, and join refresh/upstream workers. Timed-out children receive TERM before KILL.
- A release-build smoke test against the FactMachine monorepo settled at 0.0% CPU, created no
index.lock, and left no Stackmap or Git child afterq. - User-authored stack and visual-section titles render in white in every row state; branch names retain their stack/section identity colors and selected-row contrast treatment.
- GitHub enrichment requests all pull-request states and renders
Merged,Closed, orApprovedin the PR column, falling back to the PR number for other open requests. Matching remains branch-ID plus tip-OID guarded. - The main-page remote column renders
✓ pushed,↑n ahead,↓n behind,↕n/n div,× gone,○ no remote, or? remote. No configured/contained remote is explicitly distinct from a configured upstream whose local remote-tracking ref is gone. - The current verified
stackmap 0.1.0-alpha.1release is installed at/Users/matt/.cargo/bin/stackmapwith SHA-256125d5706162938ad224e1bbe9fe94c134c5fb07026469374758e237850b50e02. - The reviewed workflow-preflight plan is
docs/plans/2026-07-29-001-feat-stackmap-workflow-preflight-plan.md: manualstack-buildandworktree-rulesgain shared read-only preflight; explicit alternate committed parents can proceed beside a dirty checkout, while dirty current-HEAD continuations/variants ask whether to exclude or wait. The main map gains a color-coded, non-color-accessible activity field immediately left of timestamp.
- Treat cross-host agent activity as deferred roadmap work: first prove the read-only agent status contract, then evaluate a bounded local registry with heartbeat/TTL, Claude hooks, a cooperative Codex skill, optional cmux enrichment, and clearly labeled passive inference. Do not scrape terminals or private app databases.
- Evaluate assisted visual reorganization only as a reviewable proposal workflow; keep Graphite authoritative for branch movement and restacking.
- Implement the agent status plan only after reviewing the schema-v1 fixture matrix and keeping worktree cleanliness fail-closed at mutation boundaries.
- Execute the workflow-preflight plan from
codex/agent-coordinationcommit16b04f9or a descendant; treat the personal workflow-skill edits as a reversible local pilot with hashes and rollback evidence. - Exercise visual feature sections and named-stack summaries in representative real stacks, especially multiple adjacent sections, real side-stack forks, filtering/archive views, and narrow terminals; adjust interaction feel before opening a PR.
- Exercise the public alpha in representative repositories and record manual Terminal.app evidence for both macOS architectures.
- Cut
v0.1.0-alpha.1only after reviewing the protected prerelease environment and the release checklist indocs/releasing.md. - Resolve alpha feedback and make the Developer ID signing/notarization decision before a stable
0.1.0release.