Skip to content

docs(SPEC-034): active-install count via Sparkle appcast hits - #42

Open
larryxiao wants to merge 2 commits into
mainfrom
docs/spec-029-install-count-appcast
Open

larryxiao wants to merge 2 commits into
mainfrom
docs/spec-029-install-count-appcast

Conversation

@larryxiao

@larryxiao larryxiao commented May 16, 2026

Copy link
Copy Markdown
Owner

Summary

Adds SPEC-034 — extract a real active-install count from the Sparkle update-check requests that every install already makes (functionally) once SPEC-026 ships.

Why

Today's user-count proxies (49 DMG downloads, 329 unique clone IPs in 14d, 17 stars) give a 100-300 user estimate. None of them measure "apps actually launching this week." Sparkle's appcast.xml fetch is a natural pulse; if hosted on a Cloudflare Worker, the daily request count = real active-install number, without per-user identification.

What's specified

  • Host: Cloudflare Worker (free tier 100k req/day, includes Workers KV for daily counter)
  • Logged: daily counter only (PR-A); optional version × OS-major × country breakdown (PR-B, only if PR-A useful)
  • Never logged: IP, exact UA, cookie, install UUID, sub-day timestamps
  • PR shape:
    • PR-A: Worker + KV daily counter
    • PR-B: optional richer breakdown
    • PR-C: docs/VISION.md privacy-contract update disclosing the update-check ping
  • Gated on: SPEC-026 implementation lands first (so the first appcast URL goes to the Worker from day one)

Privacy contract framing

The app's no-telemetry promise is about the binary not exfiltrating data. The appcast request is a functional update check, not telemetry. The Worker aggregates in a way that's structurally incapable of identifying a user. PR-C makes this explicit in docs/VISION.md and the Settings → Updates pane (already in SPEC-026) is the real opt-out.

Test plan

  • Review the "what's logged / what's never logged" lists — confirm the structural anonymity claim holds
  • Decide on Cloudflare account ownership (personal vs project-owned — both work for now)
  • Confirm SPEC-026 implementation order: SPEC-026 ships → PR-A here → first signed/notarised release points at Worker URL
  • Merge → builder team picks up PR-A once SPEC-026 is in flight

Renumbered from SPEC-032 → SPEC-034 to resolve an ID collision (032 = engine-prompt-token-cache; 029 = ane-cache-only-model). Paired with #41 (SPEC-033); cross-refs updated together. (SPEC-026 dependency unchanged.)

🤖 Generated with Claude Code

@larryxiao
larryxiao force-pushed the docs/spec-029-install-count-appcast branch from 1d10ac3 to 5c8d86c Compare May 16, 2026 22:28
@larryxiao larryxiao changed the title docs(SPEC-029): active-install count via Sparkle appcast hits docs(SPEC-030): active-install count via Sparkle appcast hits May 16, 2026
Renumbered from SPEC-030 — the local ANE-cache volunteer-bench SPEC took
that slot. The SPEC-029 cross-reference (Pages analytics) now points at
SPEC-031 to match the cascade.
@larryxiao
larryxiao force-pushed the docs/spec-029-install-count-appcast branch from 5c8d86c to af243f2 Compare May 17, 2026 07:29
@larryxiao larryxiao changed the title docs(SPEC-030): active-install count via Sparkle appcast hits docs(SPEC-032): active-install count via Sparkle appcast hits May 17, 2026
larryxiao added a commit that referenced this pull request May 31, 2026
…ID collision)

SPEC-031 is already assigned to agent-kickoff (shipped) and SPEC-028 (the
branch/body number) to dictation-distribution (merged). Renumber to the next
free monotonic ID 033 and repoint the appcast cross-ref to SPEC-034 (#42).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… collision)

SPEC-032 is already assigned to engine-prompt-token-cache and SPEC-029 (the
branch/body number) to ane-cache-only-model. Renumber to the next free
monotonic ID 034 and repoint the pages-analytics cross-ref to SPEC-033 (#41).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@larryxiao larryxiao changed the title docs(SPEC-032): active-install count via Sparkle appcast hits docs(SPEC-034): active-install count via Sparkle appcast hits May 31, 2026
larryxiao added a commit that referenced this pull request May 31, 2026
Roadmap marked shipped work as spec-only and the spec index was missing 11
entries and listed shipped features as 'draft'. Reconcile both against main:

- ROADMAP: SPEC-026 Sparkle + SPEC-011 update-flow corrected to their real
  state, SPEC-025 (signing/notarisation) marked the top adoption task with
  its blocker noted, demo-GIF scoped to the actually-missing artifact, and
  #62 re-transcribe-from-History added as a recovery-flow idea.
- Spec index: rebuilt from disk (34 specs) with accurate implementation
  status (shipped / partial / draft / parked); reserves SPEC-033/034 for
  the renumbered docs PRs #41/#42.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
larryxiao added a commit that referenced this pull request Jun 8, 2026
ROADMAP's "Pending docs PRs" section already reserves SPEC-033 for PR #41
(Pages analytics) and SPEC-034 for PR #42 (active-install). The crash-sentinel
spec was a stray 033; move it to the next free id 039:
- rename SPEC-033-crash-sentinel-bug-report.md → SPEC-039-…
- update the 4 SPEC-033 code comments in OpenQuackApp.swift
- update the SPEC-036 "Report Bug" cross-ref

Also drop the "roughly doubling per-chunk inference" aside from SPEC-036's
background — the stream-bench A/B (min-detect 10 vs 9999) showed per-chunk
re-detect is free (WER + RTF identical), so the claim is false.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
larryxiao added a commit that referenced this pull request Jun 8, 2026
033/034 are reserved for PRs #41/#42 (ROADMAP "Pending docs PRs"). The
"Becoming autonomous" field-feedback row and SPEC-037's privacy note referenced
the crash-sentinel (→039) and the future consented-reporting spec (→040), so
point them at the free ids: SPEC-036 / 039 / 040.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
larryxiao added a commit that referenced this pull request Jun 8, 2026
ROADMAP's "Pending docs PRs" section already reserves SPEC-033 for PR #41
(Pages analytics) and SPEC-034 for PR #42 (active-install). The crash-sentinel
spec was a stray 033; move it to the next free id 039:
- rename SPEC-033-crash-sentinel-bug-report.md → SPEC-039-…
- update the 4 SPEC-039 code comments in OpenQuackApp.swift
- update the SPEC-036 "Report Bug" cross-ref

Also drop the "roughly doubling per-chunk inference" aside from SPEC-036's
background — the stream-bench A/B (min-detect 10 vs 9999) showed per-chunk
re-detect is free (WER + RTF identical), so the claim is false.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
larryxiao added a commit that referenced this pull request Jun 10, 2026
…utonomy reflection (#78)

* docs(SPEC-037/038): agent-harness + CI eval-gate proposals; ROADMAP autonomy reflection

Reflection on making the repo agent-autonomous across product / ops / GTM.

- ROADMAP.md gains a "## Becoming autonomous" north-star section: what exists
  (the contract), the meta-gap (no committed .claude/ harness), the three
  unlocks, and the per-domain autonomy ceilings (product privacy-capped, ops
  needs signing, GTM assisted-not-autonomous).
- SPEC-037 (proposal): committed .claude/ harness — six scoped subagent roles,
  saved workflows, cron + GitHub-event triggers, and a deny-by-default
  permissions model with HARD human gates at every irreversible/outward step
  (merge, release, public post). release-bot PREPs; the cut blocks on SPEC-025.
- SPEC-038 (proposal): CI eval-gate running medium-model WER/RTF on the real
  corpora (today gitignored → CI smokes tiny/short only). Hosted+cached corpus
  fetch (no audio in git, per AGENTS hard rule); WER hard-gate, RTF same-runner
  soft-gate; delta reported in the PR.

Design-first per AGENTS (spec PRs precede implementation). e2e/app-behaviour
test and the field-feedback loop noted as siblings/follow-ups.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore: point field-feedback refs at free ids (033→039, 034→040)

033/034 are reserved for PRs #41/#42 (ROADMAP "Pending docs PRs"). The
"Becoming autonomous" field-feedback row and SPEC-037's privacy note referenced
the crash-sentinel (→039) and the future consented-reporting spec (→040), so
point them at the free ids: SPEC-036 / 039 / 040.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
larryxiao added a commit that referenced this pull request Jun 16, 2026
…77)

* feat(SPEC-036): recording diagnostics, health & graceful interruption

The "dictation stops mid-recording, waveform freezes, partial transcript"
class of bug is intermittent and was undiagnosable: the capture tap drives
the WAV write, level meter, and streaming frames from one closure, so when
it stops all three freeze together — and there was no observer, no logging,
and no captured-vs-wall check to notice or attribute it.

This adds (SPEC-036):
- OpenQuackPlatform/Diagnostics: os.Logger (recording/streaming/transcription
  /app) + a bounded in-memory event ring for an attachable text dump.
- RecordingHealth (pure): assess(wall, captured) → .incompleteCapture when the
  tap stopped feeding audio mid-recording (the freeze signature).
- DiagnosticsReport (pure): renders the attachable .txt (version/OS/chip,
  wall-vs-captured, chunks, RTF, lang, recent events).
- AudioRecorder: captured-frame counter → capturedSeconds; an
  AVAudioEngineConfigurationChange observer that auto-stops ONLY when the
  engine actually stopped (gated on !isRunning, so benign route changes don't
  truncate long dictations); lifecycle logging.
- StreamingTranscriber: per-chunk duration/decision/RTF logging — the data
  that confirms the SPEC-035 "slow + inaccurate" reports (per-chunk re-detect).
- App: graceful auto-stop + "interrupted" notice; health check + summary on
  every stop; a diagnostics .txt written + revealed in Finder from "Report Bug"
  and "Send feedback…".

Also lands the previously-uncommitted SPEC-033 crash-sentinel bug-report base
(checkAndMarkCrashSentinel / offerCrashBugReport / applicationWillTerminate),
which SPEC-036's bug-report enrichment hooks into — they share OpenQuackApp.swift
and can't be split. SPEC-033's acceptance criteria are manual (simulated crash)
and not yet verified.

Build + 196 tests green (12 new, covering RecordingHealth / DiagnosticsReport /
the event ring). Interruption path and the file-reveal still need manual
verification on a machine that reproduces the freeze.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(SPEC-036): Settings → Stats recording-health view

Surface the SPEC-036 diagnostics locally so you (and users) can self-diagnose
without filing a bug. Settings → Stats gains a "Recording health" subsection,
gated behind the existing showUsageStats display toggle (tracking stays
always-on, local):
- a session incomplete-capture count + a per-recording list (wall / captured /
  RTF / path / lang, warning-marked when the tap stopped early),
- a compact warn/error tail from Diagnostics.shared,
- a "Reveal diagnostics file" button into the existing reveal flow.

AppState gains a newest-first, cap-10 `recentRecordings` ring (pushed in
stopAndTranscribe); `writeDiagnosticsFileAndReveal` becomes internal so the pane
reaches it via the same (NSApp.delegate as? AppDelegate) handle it already uses
for usageStats. Local-only — nothing leaves the Mac. Build + 196 tests green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore(SPEC-039): renumber crash-sentinel 033→039 (033 reserved for #41)

ROADMAP's "Pending docs PRs" section already reserves SPEC-033 for PR #41
(Pages analytics) and SPEC-034 for PR #42 (active-install). The crash-sentinel
spec was a stray 033; move it to the next free id 039:
- rename SPEC-033-crash-sentinel-bug-report.md → SPEC-039-…
- update the 4 SPEC-039 code comments in OpenQuackApp.swift
- update the SPEC-036 "Report Bug" cross-ref

Also drop the "roughly doubling per-chunk inference" aside from SPEC-036's
background — the stream-bench A/B (min-detect 10 vs 9999) showed per-chunk
re-detect is free (WER + RTF identical), so the claim is false.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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