Skip to content

fix(graph): resolve status-footer stuck-progress, log clobbering, and rewalk loop#714

Merged
germanamz merged 1 commit into
mainfrom
fix/graph-status-footer
Jul 14, 2026
Merged

fix(graph): resolve status-footer stuck-progress, log clobbering, and rewalk loop#714
germanamz merged 1 commit into
mainfrom
fix/graph-status-footer

Conversation

@germanamz

Copy link
Copy Markdown
Owner

Summary

Fixes the three defects in the tusk graph status footer reported in the issue:

  1. Footer read as stuck progress. The footer showed index gen N, the
    reindex_gen walk counter that bumps on every walk — including no-op walks
    — so a quiet, fully-indexed workspace left it frozen at some N that reads as N
    pending items. The footer now names the state (synced / indexing… /
    walk error) and, once a walk has completed, summarizes it
    (last walk 1ms (0 changed)), sourced from a new goroutine-safe WalkStatus
    tracker updated by the walk sites. reindex_gen semantics are unchanged (it
    is load-bearing for generation-based orphan reap); it is simply no longer the
    prominent number on screen.

  2. -v logs glued onto the footer. On an interactive TTY the sticky footer
    (\r+erase-line, no trailing newline) and the background slog lines share the
    terminal, so log lines concatenated onto the footer text (…[q] quittime=…).
    A new footerWriter multiplexes the footer and the logs onto one stream,
    erasing and redrawing the footer around each log line, mutex-serialized.

  3. Redirect-into-tree rewalk loop. tusk graph -v > graph.log inside the
    workspace armed a permanent ~500ms walk loop: each walk's own log write was a
    MODIFY the watcher turned into the next walk. The watcher now drops events
    whose path can never be a node — anything that is not a node file
    (.md/.html/.htm), the manifest (tusk.toml), or a directory. This also
    fixes the same footgun in tusk watch.

Verification

  • Full suite green: go test ./... (37 packages, 0 fail), make vet,
    make lint (0 issues).
  • Live end-to-end against the issue's repro workspace with the built binary:
    • Defect 3: after one real change the generation counter went 3→4 and stayed
      at 4; only 2 walks total (was climbing ~2/sec indefinitely).
    • Defect 1 (PTY): footer transitions indexing…synced · 2 nodes · 2 edges · 0 clients · last walk 1ms (0 changed); no index gen.
    • Defect 2 (PTY, -v): every log line is preceded by an erase-line; no
      [q] quittime= glue.

Notes

  • Extensionless files (e.g. Makefile) still trigger a walk — conservative, so
    directory renames/deletes (whose events name the extensionless dir) still
    reindex; no loop risk since the walk never writes those.
  • The graph command's background logs now flow through one shared logger over the
    footer coordinator (still stderr); non-interactive runs leave it a transparent
    passthrough.

… rewalk loop

The `tusk graph` status footer had three related defects (see issue):

1. It rendered `index gen N` — the reindex_gen walk counter, bumped on every
   walk including no-op walks — which reads as N stuck pending items on a quiet,
   fully-indexed workspace. A new goroutine-safe WalkStatus tracker (shared
   across runtime swaps and updated by the walk sites) drives a stateful footer:
   `synced` / `indexing…` / `walk error`, plus a `last walk 1ms (0 changed)`
   summary. reindex_gen semantics are unchanged (still load-bearing for orphan
   reap); it is simply no longer surfaced as the prominent number.

2. Under `-v`, background slog lines glued onto the sticky footer on an
   interactive TTY (footer and logs share the terminal; the `\r`+erase-line
   footer leaves the cursor mid-line). A new footerWriter multiplexes the footer
   and the logs onto one stream, erasing and redrawing the footer around each
   log line under a mutex.

3. `tusk graph -v > graph.log` inside the workspace armed a permanent ~500ms
   rewalk loop: each walk's own log write was a MODIFY the watcher turned into
   the next walk. The watcher now schedules a reindex only for paths that can
   affect the index — node files, the manifest, or (via os.Stat, so a dotted
   directory name is not mistaken for a file) a directory. This also closes the
   same footgun in `tusk watch`.
@germanamz germanamz merged commit 364e678 into main Jul 14, 2026
9 checks passed
@germanamz germanamz deleted the fix/graph-status-footer branch July 14, 2026 02:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant