Skip to content

docs: Day 1 working-backwards spec (admin + user halves)#3

Open
prasithg wants to merge 18 commits into
mainfrom
feat/day-1-spec
Open

docs: Day 1 working-backwards spec (admin + user halves)#3
prasithg wants to merge 18 commits into
mainfrom
feat/day-1-spec

Conversation

@prasithg

@prasithg prasithg commented Jul 3, 2026

Copy link
Copy Markdown
Owner

Working-backwards Day 1 spec, Pocket-style: administrator half (doubles as the Session F+G acceptance checklist) and user half (five first-day scenarios in the user's words, one hard success criterion). Gaps are marked inline and ranked into the slice queue: F+G install → hands-free invocation/latency → mic A/B → med-adherence v0 → settings surface.

Docs-only change off origin/main.

🤖 Generated with Claude Code

prasithg and others added 18 commits July 2, 2026 21:34
Phase 0 of the Parker.app milestone: study June AI (MIT; sidecar
lifecycle, port/readiness, TCC flow), MacClaw (backoff, menu-bar), and
OpenClaw's macOS app (launchd gateway pattern; unsigned builds avoid
launchd — hence direct child-process management for our unsigned v0).
Records the decision, process model, PARKER_HOME layout, permission
flow, update path, and the two-sidecar future.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Phase 1 of the desktop-app milestone (docs/desktop-architecture.md):
the engine becomes installable without changing what it does.

- app/paths.py: every state path (DB, digests, models, logs, config)
  resolves through PARKER_HOME. Dev checkouts keep byte-identical
  repo-local paths (backend/parker.db, backend/digests) via checkout
  detection; the desktop default is ~/Library/Application Support/Parker.
- config.json layered UNDER env vars (pydantic-settings custom source):
  family-administered, allowlisted keys only; secrets refused on write
  and dropped on read, both pinned by tests.
- parker console script (backend/pyproject.toml, installed editable by
  make backend-venv): serve (port preflight with shell-distinguishable
  exit codes, --parent-pid orphan watchdog), talk (the loop), onboard
  (terminal wizard fallback), doctor (7 checks, --json), download-model,
  version. Verified all-green on this machine.
- /setup surface for the shell: status (needs_onboarding), config
  writes, whisper model download with pollable progress; model loading
  prefers PARKER_HOME/models, keeps using an existing HF cache, never
  re-downloads for dev flows (0 live ASR runs in the eval re-run).
- /parker/loop/state + loop_states table: the talk loop publishes
  idle/listening/processing/speaking for the shell's tray icon; publish
  failures can never break the voice loop.
- Report generator: date lines are paragraphs, not two-space hard
  breaks, so refreshed reports stay whitespace-clean.

Tests: 583 passed (was 530). Evals: release-readiness PASS,
hands 8/8 0-unsafe, audio-real base 58.27→76.26→82.01 0-unsafe
(baseline unchanged, all-cache), audio-autodata 31/31, brain-lane
keyless PASS.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Phase 2 of the desktop-app milestone. backend/parker.spec builds a
onedir bundle (183 MB) carrying the whole engine: FastAPI/uvicorn,
SQLite, faster-whisper + ctranslate2, sounddevice + PortAudio, PyAV's
ffmpeg, onnxruntime for the VAD. hiddenimports cover uvicorn's
by-string app loading; collect_dynamic_libs belts-and-braces the two
fiddly natives.

- make sidecar: venv + voice deps + requirements-build.txt
  (PyInstaller) + spec build to backend/dist/parker/ (gitignored;
  the spec is committed).
- parker selftest [--load-model]: one real engine turn on an
  in-memory DB (capture → stage → medication refusal) plus voice-native
  probes — a bundle missing a ctranslate2/PortAudio dylib fails the
  smoke, not the first family conversation.
- scripts/sidecar_smoke.sh: clean shell, temp PARKER_HOME, no venv —
  version, selftest with native probes, serve + /health +
  /setup/status, graceful shutdown, doctor. PASS on this machine,
  including a real whisper-base load inside the bundle
  (model_loadable: true from the HF cache).
- create_tables(bind=...) so the selftest never touches real state.

Tests: 584 passed. Smoke: PASS.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… wizard

Phase 3 of the desktop-app milestone (docs/desktop-architecture.md).

Engine side (the wizard is an engine page, same-origin with its own
endpoints — usable from a plain browser too):
- GET /setup/ui: single-file onboarding wizard (welcome → name →
  contacts → lexicon → voice picker with spoken preview → plain-language
  consent with repair-capture opt-IN → mic permission moment with level
  meter → model download with progress → ready + pilot-protocol
  pointer). Self-contained, no external resources; pinned by tests.
- POST /setup/mic-check: the TCC moment — opens the default input for a
  moment, returns RMS/peak/device; frames discarded in memory, nothing
  written. GET /setup/tts-voices + POST /setup/tts-preview: say voice
  picker and audition with explicit voice (not the saved one).

Shell (desktop/, Rust-only toolchain — no node):
- Generic SidecarManager (spawn/kill/is_running, PARKER_HOME env,
  size-rotated logs to PARKER_HOME/logs, kill-all on drop) — engine now,
  talk loop as second entry, the family's OpenClaw gateway later.
- Lifecycle: free-port pick (bind 0), spawn parker serve --parent-pid,
  45s /health wait, crash-restart with 1→15s backoff, single-instance,
  clean kill on quit, ExitRequested guard so closing a window never
  quits the tray app.
- Tray: state icon mirrors /parker/loop/state (idle/listening/speaking
  template PNGs, stdlib-generated by scripts/gen_icons.py), menu: Start/
  Pause Listening (spawns/kills parker talk), Dad Screen (fullscreen),
  Family Review, Daily Digest, Settings/Setup, Start-at-Login toggle
  (autostart plugin; enabled once automatically after onboarding), Quit.
- Windows are webviews on the engine's own localhost pages — no UI
  rebuilt, no shell-side policy, DB, or send paths.
- Info.plist: NSMicrophoneUsageDescription + LSUIElement.

Tests: 593 passed (was 584). cargo check clean; release build bundles
Parker.app + Parker_0.3.0_aarch64.dmg.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… sends

Decisions folded in: macOS voice now / licensed natural voice later; one
Anthropic key with per-task model routing (Groq/Cerebras fallback if the
conversational tier is too slow); outbound send paths deferred out of v0 in
favor of context (calendar/mail/browsing/YouTube) + on-computer actions (CUA)
+ calendar writes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…wsing deferred

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Everything below was caught by installing the dmg on this machine and
having a conversation with it — none of it was visible to the suite or
evals, all of it now is.

1. Whisper echoes its lexicon bias prompt on silent windows. The first
   live run with a configured lexicon (the app writes one; dev flows
   default to empty) showed Parker 'hearing' its own initial prompt on
   every quiet window and offering nuisance repair choices on the dad
   screen. filter_prompt_echo drops transcript lines whose tokens are
   ≥80% prompt vocabulary; pinned with the verbatim hallucinated line
   from the live screen state. Real commands sail through (eval harness
   has its own ASR path — public numbers unchanged).

2. "Yes, go ahead." was not a yes. The spoken-confirmation matcher was
   an exact-phrase set; the completely natural compound confirmation
   fell through to repair choices — observed live after a perfect
   transcription. _confirmation_reply_kind adds a bounded token rule
   (≤4 words, affirmative lead, all-affirmative vocabulary; mirrored
   for no; negations cannot cross-match). Mixed replies still defer.

3. Frozen binaries ignore PYTHONUNBUFFERED (isolated interpreter
   config), so the talk transcript only flushed on exit — a family
   member tailing PARKER_HOME/logs/talk.log saw nothing live. The talk
   loop now line-buffers its own stdout/stderr.

Also: sidecar_smoke.sh absolutizes its binary argument (it cds to /).

Tests: talk-loop compound yes/no/defer cases + prompt-echo cases
(verbatim live artifacts as fixtures).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ces entry

- docs/desktop.md: install (incl. the unsigned right-click-open
  Gatekeeper route), the wizard walkthrough, daily tray use, the
  PARKER_HOME data map, manual update path (data survives — verified),
  uninstall, developer corner with honest known quirks, and the
  signing/notarization checklist ready for the Apple Developer ID.
- README: 'Parker as an app (beta)' section; test count refreshed (600).
- docs/next-slices.md: the full Session F+G record — four slices, the
  acceptance evidence, and the three tester-zero product fixes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Tauri v2 menu-bar shell + PyInstaller sidecar; installed and
acceptance-tested from the unsigned dmg on this machine. 600 tests,
all eval gates green, audio-real baseline unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ccess routes

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… sends

Decisions folded in: macOS voice now / licensed natural voice later; one
Anthropic key with per-task model routing (Groq/Cerebras fallback if the
conversational tier is too slow); outbound send paths deferred out of v0 in
favor of context (calendar/mail/browsing/YouTube) + on-computer actions (CUA)
+ calendar writes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…wsing deferred

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ccess routes

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…into feat/day-1-spec

# Conflicts:
#	docs/day-1.md
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