Skip to content

Comments

feat(mesh): interactive memory viewer with pipeline view#78

Open
marklubin wants to merge 5 commits intomainfrom
feat/mesh-view
Open

feat(mesh): interactive memory viewer with pipeline view#78
marklubin wants to merge 5 commits intomainfrom
feat/mesh-view

Conversation

@marklubin
Copy link
Owner

@marklubin marklubin commented Feb 21, 2026

Summary

  • Interactive memory viewer (synix mesh view) with seven views: overview, artifacts, detail, search, config, builds, and pipeline — all navigable via single-key commands
  • Pipeline view (p) loads the pipeline definition and renders: metadata panel (name, dirs, concurrency, LLM config), layer DAG as a Rich tree with dependency arrows and level coloring, projections table (SearchIndex/FlatFile with sources and details), and validator/fixer counts
  • Full e2e test coverage: 48 tests covering all render functions, dispatch routing, edge cases (missing files, empty state, prefix resolution), and the new pipeline view

Test plan

  • uv run pytest tests/e2e/mesh/test_mesh_view.py -v — 48/48 pass
  • uv run release — all checks pass (1481 tests, lint, template sync, demos)
  • Manual: uv run synix mesh view --name <mesh>, press p to see pipeline view

Add a Rich-based interactive TUI for browsing built memory in a running
mesh. Navigable via single-key commands with views for artifact listing,
detail/provenance, search, config inspection, and build status.
@github-actions
Copy link
Contributor

Warning

AI Review failed — openai | RateLimitError

The openai blind review could not be completed. This does not affect the PR.

@github-actions
Copy link
Contributor

Note

Architectural Review — Claude Opus | Blind review (docs + diff only)

Summary

Adds an interactive terminal viewer for Mesh deployments (synix mesh view --name <mesh>). The viewer is a Rich-based TUI with six views — overview, artifacts, detail, search, config, builds — navigated via single-key commands in a REPL loop. Includes ~384 lines of tests covering rendering and dispatch logic.

Alignment

This directly advances the Pipeline Explorer concept from DESIGN.md §XIII — the three-column drill-down from high-altitude artifacts through provenance to sources. The detail view renders provenance trees with recursive parent traversal, which is the "altitude-aware search + provenance drill-down" the design calls the strongest novelty. Artifacts remain immutable and content-addressed; the viewer is read-only. Scoping this to Mesh first is a reasonable incremental step, though the design envisions synix serve as the general-purpose explorer — tying this to Mesh only may create a parallel path.

Observations

  1. [concern] render_artifacts has inconsistent return semantics — it returns ordered_labels (a list) on the happy path but None implicitly on all early-exit paths (no build dir, empty manifest, no matching filter). The caller in run_viewer does if labels: which handles None, but the type annotation says -> None is the signature. This will confuse contributors and could break if anyone chains on the return value.

  2. [concern] _add_parents in render_detail does recursive traversal with no depth limit. With deep provenance chains (thousands of layers or a fan-out DAG), this risks stack overflow. DESIGN.md §4.6 specifies max_depth=10 for leaves() — a similar bound belongs here.

  3. [concern] The viewer accesses store._manifest directly in multiple places (overview, artifacts, builds). This couples to a private attribute. If ArtifactStore changes its internals, this breaks silently. A public method like store.list_artifacts() would be more defensible.

  4. [question] This viewer is Mesh-only (synix mesh view). The DESIGN.md explorer (§XIII) is pipeline-general (synix serve). Is there a plan to extract the render functions for the general case, or will there be two parallel viewers? The render logic itself has no Mesh dependency — only render_overview and render_builds hit Mesh APIs.

  5. [question] render_search tries server-side hybrid search, then falls back to local FTS. If the server returns a 200 with {"error": ...}, the code falls through to local search — is that intentional? The control flow mixes HTTP-level and application-level error handling in a way that's hard to follow.

  6. [nit] dispatch creates a full copy of ViewState by manually copying each field. A dataclasses.replace(current, ...) would be cleaner and wouldn't silently drop new fields added later.

  7. [nit] The _format_toml_value function doesn't handle bool — Python True renders as "True" not "true", which could confuse users expecting TOML conventions.

  8. [positive] Test coverage is strong — every render function and every dispatch path is tested, including edge cases (missing build dir, nonexistent layer, out-of-range index, prefix resolution, provenance traversal depth). The StringIO-backed Console is a clean pattern.

  9. [positive] The provenance tree in detail view (_add_parents with cycle detection via visited) correctly handles DAG structures and prevents infinite loops from any data corruption.

  10. [positive] Local search fallback means the viewer works offline, which fits the "local-first" model well.

Verdict

A solid incremental step that brings the Explorer vision to life within Mesh; the main risks are the _manifest coupling, unbounded recursion depth, and the open question of whether this viewer will generalize or fork.

Review parameters
  • Model: claude-opus-4-6
  • Context: README.md, DESIGN.md, synix.dev, PR diff
  • Diff size: 1,118 lines
  • Prompt: .github/prompts/claude_review.md
  • Timestamp: 2026-02-21T01:20:44Z

- render_artifacts returns list[str] consistently (no implicit None)
- depth-limit provenance traversal to 10 levels (avoid stack overflow)
- use dataclasses.replace() in dispatch (no silent field drops)
- handle bool in _format_toml_value (true/false not True/False)
@github-actions
Copy link
Contributor

Warning

AI Review failed — openai | RateLimitError

The openai blind review could not be completed. This does not affect the PR.

@github-actions
Copy link
Contributor

Note

Architectural Review — Claude Opus | Blind review (docs + diff only)

Summary

Adds synix mesh view --name <mesh> — an interactive terminal UI for browsing mesh artifacts, searching, inspecting config, viewing provenance trees, and checking build status. Implemented as a rich-based REPL with a state machine (ViewState + dispatch) driving navigation across six views. Includes 384 lines of e2e tests covering all render functions and the dispatch logic.

Alignment

This advances the Pipeline Explorer vision from DESIGN.md §XIII directly — the three-column drill-down concept of "search results → sources → detail" is present here as overview → artifacts → detail with provenance tree rendering. The provenance walk in render_detail (recursive parent traversal with depth limit) is exactly the sources() / leaves() pattern the design calls for. Content-addressed artifact identity is respected: short SHA display, resolve_prefix for lookup. The viewer is read-only, so it can't violate immutability or cache invariants.

One tension: this is scoped exclusively to mesh, but the Explorer in DESIGN.md §XIII is envisioned as a general pipeline capability (synix serve). Coupling this to mesh means non-mesh users — the more common case — don't get an artifact browser. This risks the viewer becoming mesh-specific infrastructure rather than a reusable component.

Observations

  1. [concern] Mesh-only scoping. render_overview, render_artifacts, render_detail are all general-purpose artifact browsing backed by ArtifactStore and ProvenanceTracker. But they live in synix/mesh/viewer.py and require MeshContext. Extracting the rendering logic would let a future synix view command reuse it without mesh provisioning. This creates coupling the design doesn't call for.

  2. [concern] Direct _manifest access. render_overview, render_artifacts, and render_builds all access store._manifest (underscore-prefixed = private). If ArtifactStore internals change, three call sites in this file break. Should use a public API or add one.

  3. [question] _local_search fallback. render_search tries the mesh server first, then falls back to local FTS5. But the fallback instantiates SearchIndexProjection(str(ctx.build_dir)) — is that constructor signature correct? It takes a string path, but the class may expect a build dir with specific structure. No test exercises this path (test only covers empty-query and no-server-no-index cases).

  4. [concern] Search test coverage is thin. TestRenderSearch has two tests: empty query and no-server-no-index. The happy path (server returns results, local fallback returns results) is untested. The search-then-drill-into-detail flow via number dispatch is tested in TestDispatch but without actual rendered output.

  5. [positive] Dispatch is clean and well-tested. The ViewState dataclass + pure dispatch function pattern makes the navigation logic fully testable without I/O. 13 dispatch tests cover shortcuts, full words, number selection, out-of-range, and quit variants. Good use of dataclasses.replace for immutability.

  6. [positive] Provenance depth limit. _add_parents caps recursion at max_depth=10 with a visited set. This prevents stack overflow on deep or cyclic (corrupted) DAGs — appropriate for the scale concern of 10,000+ conversations.

  7. [nit] _add_parents default mutable argument. visited=None with if visited is None is the correct pattern, but the parameter is also passed recursively, so the default is never hit after the first call. Fine, just slightly misleading signature.

  8. [nit] render_config TOML import. The tomllib/tomli fallback is fine, but the rest of the codebase presumably already handles this — could use a shared import utility.

  9. [question] input() in the main loop. The REPL uses bare input() which blocks. If this is meant to support the mesh dashboard use case with live-updating status, it won't refresh until the user presses enter. Is that intentional? The existing dashboard command uses a different approach with --refresh.

  10. [positive] Test fixtures are thorough. The build_dir fixture creates a realistic multi-layer artifact set with provenance records, testing the full L0→L1→L3 chain.

Verdict

A solid incremental step that delivers a useful artifact browser with good test coverage on dispatch and rendering, but the mesh-only scoping and private API access should be addressed before this pattern calcifies — the viewer logic belongs at the build layer, not the mesh layer.

Review parameters
  • Model: claude-opus-4-6
  • Context: README.md, DESIGN.md, synix.dev, PR diff
  • Diff size: 1,114 lines
  • Prompt: .github/prompts/claude_review.md
  • Timestamp: 2026-02-21T01:24:32Z

Browse the pipeline definition from within the mesh viewer: metadata,
layer DAG with dependency arrows and level coloring, projections table,
and validator/fixer counts. Wired into dispatch as `p`/`pipeline`.
@github-actions
Copy link
Contributor

Warning

AI Review failed — openai | RateLimitError

The openai blind review could not be completed. This does not affect the PR.

@marklubin marklubin changed the title feat(mesh): interactive memory viewer feat(mesh): interactive memory viewer with pipeline view Feb 21, 2026
@github-actions
Copy link
Contributor

Note

Architectural Review — Claude Opus | Blind review (docs + diff only)

Summary — Adds synix mesh view, an interactive terminal UI for browsing artifacts, searching, inspecting pipeline DAGs, viewing config, and build status within a mesh context. It's an ~800-line viewer module with a REPL loop, plus ~530 lines of tests covering every view and the dispatch logic.

Alignment — This directly serves the Pipeline Explorer vision from DESIGN.md Part XIII. The three-column drill-down concept (search → sources → detail) maps onto the overview → artifacts → detail navigation here. Provenance is rendered as a recursive tree with depth-limiting, which respects the DAG model. Altitude-aware browsing is present: layers are styled and sorted by level, and search results show layer/level metadata. The viewer is read-only — it doesn't mutate artifacts, which is consistent with immutable, content-addressed artifacts.

Observations

  1. [positive] render_detail walks the provenance tree recursively with cycle detection (visited set) and depth-limiting (max_depth=10), matching the leaves() contract from DESIGN.md §4.6 (max_depth=10, max_count=100). Well done.

  2. [positive] Dispatch is a pure function (ViewState in → ViewState out via dataclasses.replace), making it trivially testable. The 20+ dispatch tests confirm this pays off.

  3. [concern] render_artifacts and render_overview both access store._manifest directly — a private attribute. If ArtifactStore evolves its internals, this breaks silently. Should there be a public API (store.list_artifacts() or similar)?

  4. [concern] run_viewer uses bare input() in a while True loop with console.clear(). This blocks the thread and makes the viewer untestable as an integrated flow — notably, the main loop itself has no test. If a render function raises, the loop crashes with no cleanup. A try/except around the render dispatch would be safer.

  5. [question] The viewer is scoped to mesh (synix mesh view). The non-mesh local build experience has no equivalent. DESIGN.md §13 describes the explorer as a general pipeline feature. Is there a reason this is mesh-only? Users doing synix build locally would benefit from the same drill-down.

  6. [concern] _local_search instantiates SearchIndexProjection(str(ctx.build_dir)) inside a broad except Exception that silently swallows all errors. A schema mismatch or corrupt DB would be invisible. At minimum, log at warning level, not debug.

  7. [nit] _format_toml_value handles bool, str, list but not int/float explicitly — they fall through to str(val), which works but feels accidental. A comment would help.

  8. [positive] Tests cover edge cases well: missing build dir, nonexistent layers, out-of-range numeric selection, missing config file, empty pipeline path. The provenance test (test_provenance_shows_parents_of_parents) verifies multi-hop lineage, which is the core differentiator.

  9. [question] render_search tries the server first with mode="hybrid", then falls back to local FTS. The fallback is silent — the user doesn't know they got degraded results. Should there be a [dim](local search — server unreachable)[/dim] indicator?

  10. [nit] The SAMPLE_PIPELINE fixture string uses f-string with {"a" * 60} inside the TOML token — clever but visually confusing. A plain variable would read better.

  11. [concern] render_pipeline calls load_pipeline(pipeline_path) which executes arbitrary Python. In a mesh context where the pipeline file could come from a remote server, this is a trust boundary worth documenting, even if not blocking for pre-1.0.

Verdict — A solid incremental step that brings the DESIGN.md explorer vision into the mesh workflow, with good test coverage and clean separation between state management and rendering; the main risks are reliance on private _manifest access and the mesh-only scoping decision.

Review parameters
  • Model: claude-opus-4-6
  • Context: README.md, DESIGN.md, synix.dev, PR diff
  • Diff size: 1,379 lines
  • Prompt: .github/prompts/claude_review.md
  • Timestamp: 2026-02-21T01:48:41Z

Bracket chars like [a] were consumed as Rich style tags, making the
hotkey letters invisible.  Use raw strings with \[ to display them
literally.
@github-actions
Copy link
Contributor

Warning

AI Review failed — openai | RateLimitError

The openai blind review could not be completed. This does not affect the PR.

@github-actions
Copy link
Contributor

Note

Architectural Review — Claude Opus | Blind review (docs + diff only)

Summary

Adds synix mesh view --name <mesh>, an interactive terminal viewer for browsing mesh artifacts, searching, inspecting config, viewing build status, and visualizing the pipeline DAG. Implemented as a rich-based REPL loop with ~810 lines of viewer code and ~530 lines of tests.

Alignment

This directly advances the Pipeline Explorer concept from DESIGN.md Part XIII — "the strongest novelty is altitude search + provenance drill-down." The viewer renders artifacts grouped by layer level, shows provenance trees with depth-limited traversal, and supports numeric drill-down from search results into artifact detail. It respects the DAG structure: render_detail walks parent labels recursively, and render_overview groups by level. The altitude-aware search with layer styling is consistent with the "search build artifacts at different levels of the dependency graph" vision.

However, scoping this exclusively to mesh feels like an odd choice. The Explorer in DESIGN.md is a general pipeline feature (synix serve), not mesh-specific. Tying artifact browsing to mesh means standalone pipeline users don't get it.

Observations

  1. [concern] Viewer is mesh-only. render_detail, render_artifacts, render_pipeline are all general-purpose — they read from ArtifactStore and ProvenanceTracker. Coupling them to MeshContext limits reuse. A non-mesh user building locally can't access the viewer. Consider extracting a shared viewer core.

  2. [concern] _manifest accessed directly. render_artifacts, render_overview, render_builds all read store._manifest (private attribute) repeatedly. This couples tightly to ArtifactStore internals and will break silently if the storage format changes. Expose a public method.

  3. [concern] _local_search instantiates SearchIndexProjection with a string path but the constructor signature isn't visible in the diff. If it expects a Path, this will fail at runtime. The test for search (test_no_server_no_index) only covers the no-index case — no test exercises the local fallback with an actual search DB.

  4. [concern] run_viewer uses bare input() and console.clear(). This blocks on stdin and clears the terminal on every iteration. No test covers the main loop itself (understandable, but the input() call means the viewer can't be used non-interactively or tested end-to-end without monkeypatching). Consider accepting an input stream.

  5. [question] Provenance _add_parents uses sorted parent labels — is the sort for display stability, or does ProvenanceTracker.get_record return them unsorted? The visited set prevents cycles, but cycles in a DAG indicate a bug; should this log a warning?

  6. [question] dispatch returns the same ViewState unchanged for unrecognized commands. This is silent — the user types a typo, the screen redraws identically with no feedback. Consider printing "unknown command" or staying put with a hint.

  7. [nit] _get_output and _get_pipeline_output in tests are identical functions. Consolidate.

  8. [nit] The test token f"msh_testtoken{"a" * 60}" is an f-string with nested braces — it works but is hard to read at a glance. A variable would be clearer.

  9. [positive] Test coverage is strong. Dispatch logic has thorough combinatorial coverage (all commands, out-of-range numbers, full-word aliases). Render functions test happy paths, missing data, and not-found cases. The pipeline_ctx fixture with a real SAMPLE_PIPELINE string that exercises load_pipeline is a solid integration test.

  10. [positive] Provenance depth-limiting (max_depth=10 with truncation indicator) prevents stack overflow on deep DAGs — directly addresses the scale concern for large conversation histories.

  11. [positive] Graceful degradation — server-unreachable paths fall back to local search/status, with dim indicators instead of crashes.

Verdict

A solid incremental step that brings the Explorer vision to life within mesh, with good test coverage and sensible fallbacks — but the mesh-only scoping and _manifest coupling should be addressed before this pattern calcifies.

Review parameters
  • Model: claude-opus-4-6
  • Context: README.md, DESIGN.md, synix.dev, PR diff
  • Diff size: 1,379 lines
  • Prompt: .github/prompts/claude_review.md
  • Timestamp: 2026-02-21T01:55:13Z

Prevents leftover escape sequences from corrupting the terminal after
the viewer exits.  Uses Rich's console.screen() context manager which
cleanly switches to/from the alt buffer.
@github-actions
Copy link
Contributor

Warning

AI Review failed — openai | RateLimitError

The openai blind review could not be completed. This does not affect the PR.

@github-actions
Copy link
Contributor

Note

Architectural Review — Claude Opus | Blind review (docs + diff only)

Summary — Adds an interactive TUI memory viewer to Synix Mesh, accessible via synix mesh view --name <mesh>. The viewer lets users browse artifacts by layer, inspect individual artifacts with provenance, search, view config/builds/pipeline DAG — all within an alternate-screen Rich console. Includes ~530 lines of tests covering rendering and navigation dispatch.

Alignment — This directly realizes the Pipeline Explorer from DESIGN.md §XIII — "altitude search + provenance drill-down… the strongest novelty." The viewer renders artifacts grouped by layer level, shows provenance trees with depth limits, and supports drilling from search results into artifact detail. It respects the DAG structure: render_detail walks parent labels via ProvenanceTracker, and render_overview displays layers sorted by level. The altitude concept is visible in the UI through get_layer_style(level) and L{level} annotations. Content-addressed artifact IDs are shown truncated (sha256 prefix). This is a good incremental step toward the three-column drill-down described in §XIII.2.

Observations

  1. [positive] dispatch() is a pure function over an immutable-ish ViewState using dataclasses.replace. Clean state machine, easy to test. The 20+ dispatch tests confirm this.

  2. [positive] Provenance rendering in render_detail has cycle detection (visited set) and depth limiting (max_depth=10), matching the max_depth=10 contract from DESIGN.md §4.6's leaves() API.

  3. [concern] render_artifacts and render_overview access store._manifest directly — a private attribute. If ArtifactStore changes its internal representation, this breaks silently. Should there be a public API for iterating artifacts with metadata?

  4. [concern] run_viewer uses input() inside console.screen() (alternate buffer). On some terminals, input() doesn't play well with the alternate screen — cursor positioning, line editing, and echo can misbehave. This works but may produce UX issues. A Prompt.ask from Rich or a proper keypress handler would be more robust.

  5. [concern] _local_search instantiates SearchIndexProjection(str(ctx.build_dir)) on every search call. For 10,000+ artifacts with large indexes, this could be expensive if the constructor does I/O. Not a correctness issue, but worth caching.

  6. [question] The viewer is mesh-only (synix mesh view). The DESIGN.md Explorer (§XIII) is described as a general pipeline feature (synix serve). Is there a reason this isn't also available for non-mesh builds? Feels like the rendering logic could serve both contexts.

  7. [question] render_search tries server first with mode: "hybrid", then falls back to local FTS5. If the server is reachable but returns an error, the fallback triggers on "error" in results_data — but a 500 response with no JSON body would hit the else branch and also fall back. Is silent degradation the intended behavior, or should some server errors surface?

  8. [nit] _format_toml_value doesn't handle int/float distinctly — both fall through to str(val). Fine for display, but 0 and 0.0 will look different than TOML convention.

  9. [nit] render_detail checks if chain: from provenance.get_chain() but then uses provenance.get_record() inside _add_parents. The two APIs seem redundant — could just walk records directly. Minor clarity issue.

  10. [positive] Test coverage is thorough: happy paths, empty states, missing directories, nonexistent layers, out-of-range indices, prefix resolution, and provenance chain traversal. The pipeline_ctx fixture with SAMPLE_PIPELINE exercises the real pipeline loader.

  11. [concern] No test for the run_viewer main loop itself. The interactive loop with input() is untested. A test that feeds a sequence of commands and asserts final state would catch regressions in the integration between dispatch and rendering.

Verdict — A solid incremental step that brings the Explorer vision from DESIGN.md into a working, well-tested TUI, though the mesh-only scoping and _manifest access pattern deserve follow-up.

Review parameters
  • Model: claude-opus-4-6
  • Context: README.md, DESIGN.md, synix.dev, PR diff
  • Diff size: 1,378 lines
  • Prompt: .github/prompts/claude_review.md
  • Timestamp: 2026-02-21T02:05:31Z

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