Skip to content

Restructure: live UI, vendored C, single crate, flag-based CLI#3

Merged
singaraiona merged 5 commits into
mainfrom
feat/live-ui-fix
May 1, 2026
Merged

Restructure: live UI, vendored C, single crate, flag-based CLI#3
singaraiona merged 5 commits into
mainfrom
feat/live-ui-fix

Conversation

@singaraiona

Copy link
Copy Markdown
Contributor

Summary

Three slices that simplify raysense for new users:

  1. Live UI (3f97531). Drops <meta http-equiv=\"refresh\">. The visualize command now starts a tokio + axum server with /, /data, /events (SSE). The page reloads only when the new scan's content hash differs from the previous, so interactive state survives idle periods. C library is vendored — cargo build from a fresh clone just works, no external setup. README rewritten as a product page (~100 lines, down from 369).

  2. Single crate (cbdbef7). Five crates → one. New layout: Cargo.toml, build.rs, src/{lib,main,sys,scanner,health,facts,graph,profile,simulate,baseline,memory,cli,mcp}.rs, vendor/rayforce/. Cross-module references rewritten. CI / publish workflows trimmed. The duplicate [[bin]] warning is gone. 123 tests preserved, all green.

  3. Flag-based CLI (0235ae0). 16 subcommands → flags on a default raysense [PATH] invocation:

raysense .                  # health report (default)
raysense . --json           # JSON output
raysense . --check          # rule gate
raysense . --watch          # watch mode
raysense . --ui [PORT]      # live UI server
raysense --mcp              # MCP stdio server

Power-user subcommands kept: baseline, plugin, policy, trend, whatif.

Numbers

  • 3 commits, +1.4k / -1.0k (ignoring the 79k-line vendored C source).
  • Tests: 123 inline, all green.
  • Dependencies added: tokio, tokio-stream, axum, sha2, cc (build-dep).
  • Dependencies dropped: external rayforce checkout, RAYFORCE_DIR requirement.

Test plan

  • cargo build from clean — no external setup, no env vars.
  • cargo test — all 123 tests pass.
  • cargo run -q -- . — health report.
  • cargo run -q -- . --json — JSON.
  • cargo run -q -- . --check — rule gate, exit 0 if clean.
  • cargo run -q -- . --ui then open http://localhost:7000 — interactive UI, no auto-reload, edges toggle works, EventSource visible in dev tools.
  • cargo run -q -- --mcp over stdio — tools/list returns the same 43 tools.
  • cargo run -q -- baseline save . — subcommand path still works.

Three changes that work together:

1. Visualization is now a live HTTP server, not a static file. The
   `<meta http-equiv="refresh" content="10">` is gone — interactive state
   (filter selections, scroll, click highlights) survives across data
   updates. The `visualize` subcommand starts a tokio + axum server with
   GET / (page), GET /data (JSON), GET /events (SSE). A background task
   re-scans every --interval seconds and only emits a `data-changed`
   event when the new content hash differs from the previous one. The
   page subscribes to /events and reloads only on real change.

2. The C library is now vendored under crates/rayforce-sys/vendor/.
   build.rs compiles it via `cc::Build` on every fresh build — no
   external checkout, no submodule, no env var. RAYFORCE_DIR still works
   as an override for C-side development.

3. README rewritten as a product page (~100 lines). Drops the wall of
   `cargo run -q -p ... -- ...` commands and example outputs that made
   it look like an internal scratchpad. Leads with what raysense does,
   why it matters, and the three commands you actually need.
Layout becomes:
- Cargo.toml      one [package], all deps merged, single [[bin]]
- build.rs        moved from crates/rayforce-sys/ — vendor path adjusted
- src/lib.rs      module declarations + public re-exports
- src/main.rs     calls raysense::cli::run()
- src/sys.rs      was crates/rayforce-sys/src/lib.rs
- src/scanner.rs, health.rs, facts.rs, graph.rs, profile.rs, simulate.rs,
  baseline.rs    were under crates/raysense-core/src/
- src/memory.rs   was crates/raysense-memory/src/lib.rs
- src/cli.rs      was crates/raysense-cli/src/lib.rs
- src/mcp.rs      was crates/raysense-cli/src/mcp.rs
- vendor/rayforce was crates/rayforce-sys/vendor/rayforce

Cross-module references rewritten (raysense_core::, raysense_memory::,
raysense_cli::, rayforce_sys:: -> crate:: paths). Functions previously
private under the cli sub-crate that mcp.rs reaches via super:: are now
pub(crate). The duplicate [[bin]] declaration that warned on every
build is gone. CI and publish workflows trimmed to a single crate path
and no longer depend on an external rayforce checkout. Tests preserved:
123 inline tests, all green.
…flags

Replaces the Command enum's 16 subcommands with a top-level Args struct
that takes the scan path as an optional positional and exposes the
common modes as flags:

  raysense .              -> health report (default, was `health`)
  raysense . --json       -> JSON of the health summary
  raysense . --check      -> rule gate, was `check`
  raysense . --watch      -> watch mode, was `watch`
  raysense . --ui [PORT]  -> live UI server, was `visualize`
  raysense --mcp          -> stdio MCP server, was `mcp`

Advanced operations (baseline / plugin / policy / trend / whatif) stay
as subcommands so their multi-arg shapes don't pollute the simple path.
Drops `observe` / `health` (now default), `edges` / `memory` (rolled
into the default report or accessible via baseline tables), `gate`
(use `--check` plus `baseline diff`), `remediate` (out of scope here),
and `rayforce-version` (use `--rayforce-version` flag or `--version`).

README rewritten with the new shape: the user-facing surface is now six
flags plus five power-user subcommands.
@singaraiona singaraiona merged commit 23187a8 into main May 1, 2026
1 check passed
@singaraiona singaraiona deleted the feat/live-ui-fix branch May 1, 2026 10:53
@singaraiona singaraiona mentioned this pull request May 1, 2026
3 tasks
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