From 6346b4c5b9f943d26e0b640c8c94d3882c0ffc9f Mon Sep 17 00:00:00 2001 From: Jarvis Date: Sun, 5 Apr 2026 12:58:41 -0500 Subject: [PATCH] docs: mark IUH-M02 complete, start IUH-M03 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit M02 shipped as PR #431 (cd8b1f66) — password masking, hooks preview stage with consent capture, and headless install path via MOSAIC_ASSUME_YES + MOSAIC_ADMIN_*. Updates mission manifest, task table, and scratchpad Session 4 with completion notes and the finalize-stage hooks-gating follow-up to fold into M03. Co-Authored-By: Claude Opus 4.6 --- docs/MISSION-MANIFEST.md | 14 +++---- docs/TASKS.md | 26 ++++++------ .../install-ux-hardening-20260405.md | 42 +++++++++++++++++++ 3 files changed, 62 insertions(+), 20 deletions(-) diff --git a/docs/MISSION-MANIFEST.md b/docs/MISSION-MANIFEST.md index 78df74b..ab312ca 100644 --- a/docs/MISSION-MANIFEST.md +++ b/docs/MISSION-MANIFEST.md @@ -8,8 +8,8 @@ **ID:** install-ux-hardening-20260405 **Statement:** Close the remaining gaps in the Mosaic Stack first-run and teardown experience uncovered by the post-`cli-unification` audit. A user MUST be able to cleanly uninstall the stack; the wizard MUST make security-sensitive surfaces visible (hooks, password entry); and CI/headless installs MUST NOT hang on interactive prompts. The longer-term goal is a single cohesive first-run flow that collapses `mosaic wizard` and `mosaic gateway install` into one state-bridged experience. **Phase:** Execution -**Current Milestone:** IUH-M02 -**Progress:** 1 / 3 milestones +**Current Milestone:** IUH-M03 +**Progress:** 2 / 3 milestones **Status:** active **Last Updated:** 2026-04-05 **Parent Mission:** [cli-unification-20260404](./archive/missions/cli-unification-20260404/MISSION-MANIFEST.md) (complete) @@ -22,9 +22,9 @@ Post-merge audit of `cli-unification-20260404` (AC-1, AC-6) validated that the f - [x] AC-1: `mosaic uninstall` (top-level) cleanly reverses every mutation made by `tools/install.sh` — framework data, npm CLI, nested stack deps, runtime asset injections in `~/.claude/`, npmrc scope mapping, PATH edits. Dry-run supported. `--keep-data` preserves memory + user files + gateway DB. (PR #429) - [x] AC-2: `curl … | bash -s -- --uninstall` works without requiring a functioning CLI. (PR #429) -- [ ] AC-3: Password entry in `bootstrapFirstUser` is masked (no plaintext echo); confirm prompt added. -- [ ] AC-4: Wizard has an explicit hooks stage that previews which hooks will be installed, asks for confirmation, and records the user's choice. `mosaic config hooks list|enable|disable` surface exists. -- [ ] AC-5: `runConfigWizard` and `bootstrapFirstUser` accept a headless path (env vars + `--yes`) so `tools/install.sh --yes` + `MOSAIC_ASSUME_YES=1` completes end-to-end in CI without TTY. +- [x] AC-3: Password entry in `bootstrapFirstUser` is masked (no plaintext echo); confirm prompt added. (PR #431) +- [x] AC-4: Wizard has an explicit hooks stage that previews which hooks will be installed, asks for confirmation, and records the user's choice. `mosaic config hooks list|enable|disable` surface exists. (PR #431 — consent recorded in `state.hooks.accepted`; finalize-stage gating is a follow-up) +- [x] AC-5: `runConfigWizard` and `bootstrapFirstUser` accept a headless path (env vars + `--yes`) so `tools/install.sh --yes` + `MOSAIC_ASSUME_YES=1` completes end-to-end in CI without TTY. (PR #431) - [ ] AC-6: `mosaic wizard` and `mosaic gateway install` are collapsed into a single cohesive entry point with shared state (no two-phase handoff via the 10-minute session file). - [ ] AC-7: All milestones ship as merged PRs with green CI, closed issues, updated release notes. @@ -33,8 +33,8 @@ Post-merge audit of `cli-unification-20260404` (AC-1, AC-6) validated that the f | # | ID | Name | Status | Branch | Issue | Started | Completed | | --- | ------- | --------------------------------------------------------- | ----------- | ----------------------- | ----- | ---------- | ---------- | | 1 | IUH-M01 | `mosaic uninstall` — top-level teardown + shell wrapper | done | feat/mosaic-uninstall | #425 | 2026-04-05 | 2026-04-05 | -| 2 | IUH-M02 | Wizard remediation — hooks visibility, pwd mask, headless | in-progress | feat/wizard-remediation | #426 | 2026-04-05 | — | -| 3 | IUH-M03 | Unified first-run wizard (collapse wizard + gateway) | blocked | feat/unified-first-run | #427 | — | — | +| 2 | IUH-M02 | Wizard remediation — hooks visibility, pwd mask, headless | done | feat/wizard-remediation | #426 | 2026-04-05 | 2026-04-05 | +| 3 | IUH-M03 | Unified first-run wizard (collapse wizard + gateway) | in-progress | feat/unified-first-run | #427 | 2026-04-05 | — | ## Subagent Delegation Plan diff --git a/docs/TASKS.md b/docs/TASKS.md index 364651b..1490274 100644 --- a/docs/TASKS.md +++ b/docs/TASKS.md @@ -22,19 +22,19 @@ ## Milestone 2 — Wizard Remediation (IUH-M02) -| id | status | description | issue | agent | branch | depends_on | estimate | notes | -| --------- | ----------- | -------------------------------------------------------------------------------------------------------------- | ----- | ------ | ----------------------- | ---------- | -------- | ----- | -| IUH-02-01 | in-progress | Password masking: replace plaintext `rl.question` in `bootstrapFirstUser` with masked TTY read + confirmation | #426 | sonnet | feat/wizard-remediation | IUH-01-08 | 8K | | -| IUH-02-02 | not-started | Hooks preview stage in wizard: show `framework/runtime/claude/hooks-config.json` entries + confirm prompt | #426 | sonnet | feat/wizard-remediation | IUH-02-01 | 12K | | -| IUH-02-03 | not-started | `mosaic config hooks list\|enable\|disable` subcommands | #426 | sonnet | feat/wizard-remediation | IUH-02-02 | 15K | | -| IUH-02-04 | not-started | Headless path: env-var driven `runConfigWizard` + `bootstrapFirstUser` (`MOSAIC_ASSUME_YES`, `MOSAIC_ADMIN_*`) | #426 | sonnet | feat/wizard-remediation | IUH-02-03 | 12K | | -| IUH-02-05 | not-started | Tests + code review + PR merge | #426 | sonnet | feat/wizard-remediation | IUH-02-04 | 10K | | +| id | status | description | issue | agent | branch | depends_on | estimate | notes | +| --------- | ------ | -------------------------------------------------------------------------------------------------------------- | ----- | ------ | ----------------------- | ---------- | -------- | ----------------------------------------------- | +| IUH-02-01 | done | Password masking: replace plaintext `rl.question` in `bootstrapFirstUser` with masked TTY read + confirmation | #426 | sonnet | feat/wizard-remediation | IUH-01-08 | 8K | `prompter/masked-prompt.ts` | +| IUH-02-02 | done | Hooks preview stage in wizard: show `framework/runtime/claude/hooks-config.json` entries + confirm prompt | #426 | sonnet | feat/wizard-remediation | IUH-02-01 | 12K | `stages/hooks-preview.ts`; finalize gating TODO | +| IUH-02-03 | done | `mosaic config hooks list\|enable\|disable` subcommands | #426 | sonnet | feat/wizard-remediation | IUH-02-02 | 15K | `commands/config.ts` | +| IUH-02-04 | done | Headless path: env-var driven `runConfigWizard` + `bootstrapFirstUser` (`MOSAIC_ASSUME_YES`, `MOSAIC_ADMIN_*`) | #426 | sonnet | feat/wizard-remediation | IUH-02-03 | 12K | | +| IUH-02-05 | done | Tests + code review + PR merge | #426 | sonnet | feat/wizard-remediation | IUH-02-04 | 10K | PR #431, merge cd8b1f66 | ## Milestone 3 — Unified First-Run Wizard (IUH-M03) -| id | status | description | issue | agent | branch | depends_on | estimate | notes | -| --------- | ------- | ----------------------------------------------------------------------------------------------------------- | ----- | ----- | ---------------------- | ---------- | -------- | ----- | -| IUH-03-01 | blocked | Design doc: unified state machine; decide whether `mosaic gateway install` becomes an internal wizard stage | — | opus | feat/unified-first-run | IUH-02-05 | 10K | | -| IUH-03-02 | blocked | Refactor `runWizard` to invoke gateway install as a stage; drop the 10-minute session-file bridge | — | opus | feat/unified-first-run | IUH-03-01 | 25K | | -| IUH-03-03 | blocked | Preserve backward-compat: `mosaic gateway install` still works as a standalone entry point | — | opus | feat/unified-first-run | IUH-03-02 | 10K | | -| IUH-03-04 | blocked | Tests + code review + PR merge | — | opus | feat/unified-first-run | IUH-03-03 | 12K | | +| id | status | description | issue | agent | branch | depends_on | estimate | notes | +| --------- | ----------- | ----------------------------------------------------------------------------------------------------------- | ----- | ----- | ---------------------- | ---------- | -------- | ----- | +| IUH-03-01 | not-started | Design doc: unified state machine; decide whether `mosaic gateway install` becomes an internal wizard stage | #427 | opus | feat/unified-first-run | IUH-02-05 | 10K | | +| IUH-03-02 | not-started | Refactor `runWizard` to invoke gateway install as a stage; drop the 10-minute session-file bridge | #427 | opus | feat/unified-first-run | IUH-03-01 | 25K | | +| IUH-03-03 | not-started | Preserve backward-compat: `mosaic gateway install` still works as a standalone entry point | #427 | opus | feat/unified-first-run | IUH-03-02 | 10K | | +| IUH-03-04 | not-started | Tests + code review + PR merge | #427 | opus | feat/unified-first-run | IUH-03-03 | 12K | | diff --git a/docs/scratchpads/install-ux-hardening-20260405.md b/docs/scratchpads/install-ux-hardening-20260405.md index 298297d..33df841 100644 --- a/docs/scratchpads/install-ux-hardening-20260405.md +++ b/docs/scratchpads/install-ux-hardening-20260405.md @@ -156,3 +156,45 @@ ASSUMPTION: The `hooks` subcommands under `config` operate on `~/.claude/hooks-c ASSUMPTION: For the hooks preview stage, the "name" field displayed per hook entry is the top-level event key (e.g. "PostToolUse") plus the matcher from nested hooks array. This is the most user-readable representation given the hooks-config.json structure. ASSUMPTION: `config hooks list/enable/disable` use `CLAUDE_HOME` env or `~/.claude` as the target directory for hooks files. ASSUMPTION: The headless TTY detection (`!process.stdin.isTTY`) is sufficient; `MOSAIC_ASSUME_YES=1` is an explicit override for cases where stdin is a TTY but the user still wants non-interactive (e.g., scripted installs with piped terminal). + +--- + +## Session 4 — 2026-04-05 (orchestrator resume) — IUH-M02 closed, delegating IUH-M03 + +### IUH-M02 completion summary + +- **PR:** #431 merged as `cd8b1f66` +- **CI:** green (Woodpecker) +- **Issue:** #426 closed +- **Acceptance criteria:** AC-3 (password mask), AC-4 (hooks visibility — consent recorded), AC-5 (headless path) all satisfied +- **New files:** `prompter/masked-prompt.ts`, `stages/hooks-preview.ts` (+ specs) +- **Modified:** `wizard.ts`, `types.ts` (`state.hooks`), `commands/gateway/install.ts`, `commands/config.ts` + +### Follow-up captured from M02 agent + +**Hooks consent is recorded but not enforced.** The `hooks-preview` stage sets `state.hooks.accepted` when the user confirms, but the finalize stage still unconditionally runs `mosaic-link-runtime-assets`, which copies `hooks-config.json` into `~/.claude/` regardless of consent. This is a soft gap — the user sees the prompt and can decline, but declining currently has no effect downstream. + +Options for addressing: + +- Fold into IUH-M03 (since M03 touches the finalize/install convergence path anyway) +- Spin a separate small follow-up issue after M03 lands + +Leaning toward folding into M03 — the unified first-run flow naturally reworks the finalize→gateway handoff where this gating belongs. + +### IUH-M03 delegation + +Now delegating to an **opus** subagent in an isolated worktree. Scope from `/tmp/iuh-m03-body.md`: + +- Extract `runConfigWizard` → `stages/gateway-config.ts` +- Extract `bootstrapFirstUser` → `stages/gateway-bootstrap.ts` +- `runWizard` invokes gateway stages as final stages +- Drop the 10-minute `$XDG_RUNTIME_DIR/mosaic-install-state.json` session bridge +- `mosaic gateway install` becomes a thin standalone wrapper for backward-compat +- `tools/install.sh` single auto-launch entry point +- **Bonus if scoped:** honor `state.hooks.accepted` in finalize stage so declining hooks actually skips hook install + +Known tooling caveats to pass to worker: + +- `issue-create.sh` / `pr-create.sh` wrappers eval multiline bodies as shell — use Gitea REST API fallback with `load_credentials gitea-mosaicstack` +- Protected `main`: PR-only, squash merge +- Must run `ci-queue-wait.sh --purpose push|merge` before push/merge