Skip to content

init: friendly summary + menu when re-running on a configured install#181

Merged
platypii merged 2 commits into
masterfrom
no-args-when-configured
Jun 28, 2026
Merged

init: friendly summary + menu when re-running on a configured install#181
platypii merged 2 commits into
masterfrom
no-args-when-configured

Conversation

@platypii

Copy link
Copy Markdown
Contributor

What

Re-running hypaware with no args (or hyp init) on an install that already has a valid config used to drop straight into the first-run picker as if starting fresh. Now it prints a short, friendly summary of the current setup and offers a small single-select menu instead.

HypAware is set up.

  Collecting:  Claude, Codex
  Saving to:   local Parquet files
  Daemon:      running
  Cache:       65 MB · 30-day retention

What would you like to do?
    Reconfigure
    See full status
  › Quit
  • Quit is the default, so a bare enter (or any cancel) leaves the existing config untouched. Re-running on a working install never reconfigures by accident.
  • Reconfigure re-enters the existing walkthrough; See full status defers to hyp status.
  • Fleet-managed installs are locked locally, so the summary says "managed by your fleet" and the menu drops Reconfigure.
  • A missing or invalid config still falls straight through to the first-run walkthrough, which owns repair of a broken file.

How

  • A runConfiguredEntry gate in runInit collects the existing status report and, when the config is present and valid, renders the summary and prompts. The TUI uses the same arrow-navigable select as the picker; a numbered readline menu is the fallback (HYP_NO_TUI / non-TTY stdin).
  • The gate only fronts the picker; it does not replace it.

Design

Documented in LLP 0011 ("Returning to a configured install"), with an @ref on the entry gate.

Tests

New test/core/init-configured-entry.test.js covers the summary text (local + fleet), the locked-vs-local menu options, the readline fallback selection logic, and an end-to-end dispatch run proving the gate fronts the picker on quit. Full suite: 1472 pass.

Follow-up

The stderr "sink not materialized" warnings that print before this summary on fleet installs are tracked separately in #180.

platypii added 2 commits June 28, 2026 11:37
Re-running hypaware with no args (or hyp init) on an install that
already has a valid config no longer drops straight into the first-run
picker. It prints a short friendly summary (what's collected, where it
saves, daemon state, cache size and retention) and offers a small
single-select menu: Reconfigure, See full status, or Quit. Quit is the
default, so a bare enter leaves the setup untouched.

Centrally-managed (fleet-joined) configs are locked locally, so the
summary says so and the menu drops Reconfigure. A missing or invalid
config still falls through to the walkthrough unchanged.

Documents the decision in LLP 0011 and annotates the entry gate with a
ref to it. Adds traditional tests for the summary text, the locked vs
local menu, the readline fallback, and an end-to-end dispatch path.
- Declare the test-facing exports (buildConfiguredMenuOptions,
  legacyConfiguredActionPrompt, renderConfigSummary) in the hand-written
  core_commands.d.ts so tsc sees them; the missing decls were the
  typecheck failure.
- Drop em dashes from new prose/comments and the user-facing summary
  string (now parenthesised) per house preference.
- Use an @import for HypAwareStatusReport in the test instead of an
  inline import() type.
- Round the bytes fallback branch in formatBytesShort.
- Add an end-to-end test for the See full status menu branch, proving
  runStatus renders correctly under the init boot ctx.
@platypii

Copy link
Copy Markdown
Contributor Author

Self-review (/code-review high) — verdict: approve

Reviewed at head e1e359e. High-effort pass: 8 finder angles (3 correctness, reuse/simplify/efficiency, altitude, conventions) over the diff and the touched callers/callees in dispatch.js, daemon/status.js, and the TUI helpers, then a verify pass on each candidate.

Risk note: UX-only change to the no-args hyp init path. The new gate runs only when a valid config already exists; the default action is Quit (non-destructive), and the first-run, non-TTY, preset, and --from-file paths are untouched. Blast radius is the interactive summary + menu a returning user sees.

Findings & resolution

sev angle finding status
blocker typecheck new test-facing exports missing from the hand-written core_commands.d.ts, so tsc failed fixed in e1e359e (declared buildConfiguredMenuOptions / legacyConfiguredActionPrompt / renderConfigSummary)
minor correctness runConfiguredEntry calls runStatus([], ctx); the "See full status" branch was untested, so a missing ctx.query/storage under the init boot profile would crash it verified safe + test added. The no-args path re-enters init reusing the booted kernel, so cmdCtx carries query/storage/sinks; new end-to-end test drives the status branch and asserts it renders and exits 0
minor conventions em dashes in new prose/comments and the user-facing summary string fixed (summary now reads set up (managed by your fleet).; @ref gloss keeps the house — gloss delimiter)
minor conventions test used an inline import('...') type in a JSDoc @param fixed (now an @import at the top of the file, per CLAUDE.md)
nit robustness formatBytesShort did not round its sub-KB branch fixed (Math.round)

Considered, not blocking

  • No try/catch around runConfiguredEntry. A throw from collectHypAwareStatus would now surface instead of silently falling into the walkthrough. Judged acceptable: collectHypAwareStatus already backs hyp status and is robust, and a hard error on a broken status collection is more honest than masking it. Left as-is.
  • Non-TTY stdin with a TTY stdout (e.g. echo | hypaware) prints the summary then takes the Quit default. This is intended: we cannot prompt without an interactive stdin, and Quit changes nothing.

Follow-ups (deferred, not in scope here)

  • Friendly client/sink labels are a hardcoded map in core (FRIENDLY_CLIENT_LABELS / FRIENDLY_SINK_LABELS); newer plugins fall back to raw names. Plugin-contributed labels would fit the LLP 0011 "plugins contribute picks" model better.
  • promptConfiguredAction's "TUI select on a TTY, else readline" routing duplicates the shape of walkthrough.js's backfill-consent prompt; a shared single-select helper would dedupe both.
  • Pre-existing stderr "sink not materialized" noise that prints before this summary on fleet installs is tracked in Read-only CLI commands print noisy 'sink not materialized' warnings on fleet installs #180.

Checks: npx tsc --noEmit clean; npm run lint clean (423 files); npm test green (1473 pass / 0 fail / 1 pre-existing skip).

VERDICT: approve.

@platypii platypii merged commit d8eed5a into master Jun 28, 2026
6 checks passed
@platypii platypii deleted the no-args-when-configured branch June 28, 2026 19:06
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