Skip to content

Remove the Python implementation (and its web dashboard) - #55

Merged
missingbulb merged 3 commits into
mainfrom
claude/merge-prs-51-54-dwrf1w
Jul 28, 2026
Merged

Remove the Python implementation (and its web dashboard)#55
missingbulb merged 3 commits into
mainfrom
claude/merge-prs-51-54-dwrf1w

Conversation

@missingbulb

@missingbulb missingbulb commented Jul 28, 2026

Copy link
Copy Markdown
Owner

Owner decision across two steps in review: first remove the unwanted web dashboard (#57), then remove the entire Python implementation that contained it (#58). The native menu-bar app in mac/ is now the whole product.

Why

Git history is unambiguous about provenance:

  • The Python side was built first (282b188), before the native app existed (7ac1a72).
  • The scoping requirements captured afterwards (18cee43) say the opposite: "Keep the Mac clean; no unfamiliar installers → Native app uses only built-in frameworks — no Python/TensorFlow/Homebrew." The design doc lists a bundled-Python app as option B, a fallback, explicitly not chosen.
  • It was relabelled a "Python reference / simulator" in the README once the native app won — a retroactive justification for code that already existed.
  • It never ran: not shipped in the DMG, never invoked by the app, and no CI workflow executes it. The owner's machine had no ~/.laughcounter/ at all.

Removed

  • laughcounter/ — 17 modules (~2,100 lines): CLI, YAMNet detector, counting state machine, SQLite + JSONL storage, stats, speaker attribution, clip saving, and the dashboard.py HTTP server removed in the first commit.
  • tests/ — all 8 test files.
  • pyproject.toml, requirements-yamnet.txt, and the Python section of .gitignore.
  • Python warning-suppression entries in .claudinite-checks.json (now empty).

Docs

  • Root README rebuilt around the single native app: what it is, how it works (Sound Analysis → counting → you-vs-TV → JSONL), setup pointing at mac/README.md, the voice-feedback loop, and a Privacy section that is now much stronger — no network access at all, no audio saved, one deletable directory.
  • Design doc §7 "The Python reference" becomes a short record of why it was removed. The option-comparison tables stay: they document why the native shape won, which is now the load-bearing history.

on-device-privacy pack

  • no-network-client drops its Python half and scans only mac/Sources/**.swift. It also becomes absolute: the [yamnet] / [speaker] extras were the only accepted egress, and they're gone — the app downloads nothing and connects nowhere. Verified: grep -ri 'URLSession|import Network|http' over mac/Sources/ returns nothing.
  • RULES.md rewritten for one implementation, stating the stronger invariants the app actually holds: no audio persisted anywhere (verified — the app has no clip saving at all), no egress, no listener.
  • The loopback-default check was already deleted in the first commit (nothing binds a socket).

Accepted cost — stated plainly

This removes the repo's only automated tests. There are no Swift tests (find mac -iname '*test*' is empty), so the shipping app's logic is now untested. The deleted tests covered the Python counting/stats/storage logic, which the Swift app mirrors but does not share — so they never tested the shipping app either. Worth a follow-up issue to add Swift tests for the counting state machine and the you-vs-TV attribution.

Kept deliberately: mac/scripts/gen-icon.py, a manual icon generator for the app whose output is committed and which the build never invokes. It's app tooling, not the reference implementation.

Verified

  • Pack fixtures 4/4; check_the_world and check_the_work both exit 0.
  • No dangling references to the deleted tree anywhere: a repo-wide grep for laughcounter/*.py, pip install, pytest, LAUGHCOUNTER_HOME, and ~/.laughcounter comes back clean.
  • Net diff: 57 files, +137 / −3,846.

Closes #58. Supersedes #57.

@missingbulb missingbulb changed the title on-device-privacy: convert two standing prose rules to checks on-device-privacy: convert the mutating-endpoint JSON guard from prose to a check Jul 28, 2026
@missingbulb
missingbulb force-pushed the claude/merge-prs-51-54-dwrf1w branch from ddc03db to 914930b Compare July 28, 2026 13:31
@missingbulb missingbulb changed the title on-device-privacy: convert the mutating-endpoint JSON guard from prose to a check Remove the web dashboard Jul 28, 2026
Owner decision: the `laughcounter serve` web dashboard was an unwanted
surface — an unauthenticated HTTP server with mutating endpoints — and the
CLI feedback commands (mark, reject, who) already cover its workflow.

Removed: laughcounter/dashboard.py and its tests, the serve subcommand,
the dashboard_host/dashboard_port config fields, and the dashboard-only
thread-safe storage helpers (read_rows, apply_mark, apply_label). Docs
(README, DESIGN-AND-TRADEOFFS) now describe the CLI-only feedback loop,
and the design roadmap's v2 dashboard item is dropped.

The on-device-privacy pack loses the loopback-default check (nothing
listens anymore) and its RULES.md dashboard paragraph becomes a "there is
no server" rule: reintroducing any listener is an owner decision needing
loopback defaults and an auth/CSRF story, not a routine feature. The
stale dashboard.py suppression entry in .claudinite-checks.json is gone.

63/63 pytest, 4/4 pack fixtures, check_the_world and check_the_work
exit 0. laughcounter simulate/stats/mark verified working;
laughcounter serve now correctly reports an invalid choice.

Closes #57.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018hj3WpvTZJdKBX6gnfXxW8
@missingbulb
missingbulb force-pushed the claude/merge-prs-51-54-dwrf1w branch from 914930b to 92174d9 Compare July 28, 2026 13:32
@missingbulb missingbulb changed the title Remove the web dashboard Remove the Python implementation (and its web dashboard) Jul 28, 2026
Owner decision: the Python side was a second, complete implementation of the
product that nobody asked for. Git history shows it was built before the
native app existed and relabelled a "reference" afterwards; the scoping
requirements point the other way ("keep the Mac clean — no
Python/TensorFlow/Homebrew"), and it never ran — not shipped in the DMG,
never invoked by the app, no CI workflow executes it.

Deleted laughcounter/ (17 modules), tests/ (8 files), pyproject.toml and
requirements-yamnet.txt; trimmed the Python section of .gitignore and the
Python warning-suppression entries from .claudinite-checks.json. The root
README is rebuilt around the single native app, and the design doc's
"Python reference" section becomes a short record of why it was removed
(the option-comparison tables stay — they document the decision).

The on-device-privacy pack narrows to mac/Sources/: no-network-client drops
its Python half and becomes absolute, since with the optional [yamnet] and
[speaker] extras gone the app has no accepted egress at all. RULES.md is
rewritten for one implementation and now states the stronger invariants the
app actually holds — no audio persisted anywhere, no network client, no
listener.

Accepted cost, stated plainly: this removes the repo's only automated tests.
There are no Swift tests, so the app's own logic is currently untested.

4/4 pack fixtures pass; check_the_world and check_the_work exit 0; no
dangling references to the deleted tree remain anywhere in the repo.

Closes #58. Supersedes #57 (the dashboard lived inside this package).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018hj3WpvTZJdKBX6gnfXxW8
@missingbulb
missingbulb force-pushed the claude/merge-prs-51-54-dwrf1w branch from a37565d to e8693ac Compare July 28, 2026 16:17
Deletes mac/scripts/gen-icon.py, the icon generator kept in the previous
commit. Its output (Resources/AppIcon.png) is committed and the build
consumes that PNG directly, so nothing referenced the script at build or
run time — only the docs describing how to regenerate the art. mac/README
now says to replace the PNG to change the icon, and build-app.sh's comment
no longer points at a deleted script.

With no .py file left, the bytecode lines added to .gitignore in the
previous commit are unnecessary and go too.

Also fixes two stale comments the removal left behind: pack.mjs claimed the
pack "spans both implementations — the Python reference (laughcounter/) and
the native app", naming a deleted directory, and Store.swift's header
compared its log format to "the Python reference".

Audited the build and environment for Python requirements: none. The three
workflows install no Python and run no pytest; Claudinite's hooks are node
and bash; no enabled pack requires a Python environment. The repo now
tracks zero .py files, and the remaining prose mentions are deliberate
history (why Python was rejected, why the privacy rules are absolute) plus
the README's "nothing to install" claim.

4/4 pack fixtures; check_the_world and check_the_work exit 0; both build
scripts pass bash -n.

Refs #58.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018hj3WpvTZJdKBX6gnfXxW8
@missingbulb
missingbulb merged commit cda58ba into main Jul 28, 2026
1 check passed
@missingbulb
missingbulb deleted the claude/merge-prs-51-54-dwrf1w branch July 28, 2026 17:09
missingbulb added a commit that referenced this pull request Aug 7, 2026
Three lessons from the 2026-07-26..08-02 window, into the laughcounter local
pack as prose.

#74/#75: diagnosing the installTap crash stalled on "which binary is
installed?" — the menu said only "LaughCounter", and several distinct builds
all reported 0.2.1, because the release workflow keys its Release on
v<version> from Info.plist, so a merge that leaves CFBundleShortVersionString
alone refreshes the same Release behind the latest/download link. Durable
part: show version and build from Bundle.main (not a source constant that
could disagree with the DMG), and bump per distinguishable build.

#56: the scheduler ran green nightly while silently skipping baselining ("no
vendored mount (no stamp)") because the vendored loadConfig dropped the
`claudinite` key it had just validated. Durable part: a job whose success and
whose no-op look identical from outside is telling you nothing — read the skip
line; and a bug inside the mechanism that updates itself has to be fixed out
of band.

#34: claudinite-isolation fired on CLAUDE.md's mount path, which carried
nothing a reader could act on. Durable part: before adding an `accept`, delete
the flagged text and see whether anything actionable went with it — an accept
is for a crossing that must exist.

Nothing new from the mac window (#59, #73, #77, #78, #87, #100, #101, #108):
dev/procedures/mac-audio-lifecycle.md already records the engine-per-start
rule, the inputFormat-vs-outputFormat trap, the aggregate churn, the
three-state health reporting, the witnessed-arrival settle rule and the
observation-gap rule in full. #55, #69, #84 and #99 are already carried by
this pack's existing prose and the on-device-privacy checks. #32's
"prove the check is live" is the see-it-fail discipline the canon owns.
Conversation-logs half: the 2026-08-01 logs are the #108 session (fully
covered above) and unattended task runs; no new friction lesson. No
retention_days configured, so no prune.

Refs #113.


Claude-Session: https://claude.ai/code/session_01G52dxZvLCxyZJJnvLrYcQs

Co-authored-by: Claude <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.

Remove the Python implementation

2 participants