Skip to content

Usage ledger integration, retired-model unpin, and a PII guard on the repo root - #471

Merged
evinjohnn merged 9 commits into
mainfrom
feat/usage-ledger
Aug 16, 2026
Merged

Usage ledger integration, retired-model unpin, and a PII guard on the repo root#471
evinjohnn merged 9 commits into
mainfrom
feat/usage-ledger

Conversation

@evinjohnn

Copy link
Copy Markdown
Collaborator

Three commits that had accumulated unpushed/untracked in the working directory.

What is here

e5a77987 — gitignore working-directory artifacts. natively-control/ (a separate 1.8 GB checkout), chargeback_evidence/, undefined/ (written by a bug that resolved a path to the literal string undefined), and natively_debug.size*. None are part of this application.

83589883 — unpin retired vision models on the live path, and throttle repeating Whisper errors.

61e2cadc — two regression tests, a submodule bump, and a PII guard.

The part worth reviewing carefully

KAUSHAL_12_DISPUTE_HANDOVER.md was sitting untracked at the repo root — a byte-identical copy of the file already held in the correctly-ignored dispute-evidence-kaushal-shivaprakashan/. Every existing dispute rule is directory-scoped (/dispute-evidence-*), so the root copy was fully committable, and the next git add -A would have published it.

This repository is public, and that document contains a named customer's email address, phone number, and home address.

Added /*_DISPUTE_HANDOVER.md and /*_DISPUTE_*.md. Verified both directions: git check-ignore now catches the file, and README.md plus other root docs stay committable, so the rule is scoped rather than a blanket.

Also in 61e2cadc

  • Tests (new, joining 279 tracked siblings in that directory): V3SkillInjection2026_08_05 covers PR docs(bugs): answering pipeline bug reports — Aug 2026 (Telegram user issues) #429 Bug 003 — skill injection silently dropped when Context Intelligence V3 is active (default ON since 2026-07-30) — exercising both drop sites independently. ManualScreenshotScreenContext2026_08_05 covers manual screenshot screen context.
  • natively-api submodule: cecbfdfbedc55e, which is merged to that repo's main via its PR Allow keyboard shortcut for scrolling window #7 and is the deployed revision (Railway Online, /health 200).
  • transitions/: 27 CSS transition reference docs. Scanned for credentials and customer data before publishing to a public repo — the only hit is the word "password" inside a prose description of form-validation UX. These are tooling reference material rather than application source; happy to drop them from the PR if you would rather they stayed out.

🤖 Generated with Claude Code

https://claude.ai/code/session_01SiDsWPD5XtBYgXWt7ZPizu

Hardening v2.7 and others added 8 commits August 15, 2026 16:38
…esses

`--outDir ${target}` was interpolated unquoted, so a temp path containing a
space splits into two argv entries and tsc emits to the wrong place. `target`
comes from mkdtempSync(os.tmpdir()) — space-free on GitHub's Windows runners,
but not on a developer machine whose username has a space. So: local-Windows
failure, not CI. Quoting is inert on macOS.

I did not introduce this (the line was already unquoted) but I touched it when
repointing these four at typescript7. Scoped to MY four files only — 8 others
share the pattern and are another task's active sweep.

The other half of that bug class is already fixed here incidentally: these
harnesses used to run `node node_modules/.bin/tsc`, and on Windows .bin/tsc is
a shell shim, not JavaScript. node_modules/typescript7/bin/tsc is a real .js
entry on both platforms.

Verified inert on macOS: all four return exactly their prior numbers
(2/5, 18/6, 7/0, 14/1). Those runs first needed `npm run build:electron` — the
earlier failed `npm run dist` had rimraf'd dist-electron and never repackaged,
which makes these harnesses take their non-bundled branch and fail for an
unrelated reason. Nearly misattributed that to the quoting; it was not.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KwKaQSuKgsV6NBY6Ljktf4
… wrong

npm run dist exit 0: four artifacts, both architectures verified with lipo
(release/mac -> x86_64, release/mac-arm64 -> arm64). The earlier ENOSPC failure
was environmental — the disk was at 100% — and every stage before packaging had
already passed on that run too.

Corrects §14 rather than quietly deleting it: the arch-poisoning risk I listed as
"suspected" does NOT happen. package-app.js restores native addons to the
Electron ABI on both the failed and successful builds, and verify-native-arch
passes after each. The real reason not to run dist unattended here is only the
shared-worktree one — its `rimraf dist-electron` broke four emit harnesses until
build:electron was re-run, which I nearly misread as a regression from my own
quoting change.

Notes the packaging is UNSIGNED; dist:signed was not run (keychain credentials +
uploads a release, neither of which this migration should trigger).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KwKaQSuKgsV6NBY6Ljktf4
This branch and `main` fixed the same Windows-only defect independently, and
they disagreed. aad9f21 here quoted the interpolated temp path:

    --outDir "${target}"

`main` (a74641b) instead removed the shell from the equation entirely:
execFileSync with an ARGS ARRAY, tsc invoked as `node <entry>`, path.join for
every fragment, and the symlink type made platform-aware
(`win32 ? 'junction' : 'dir'` — a directory symlink needs privileges on Windows
that a junction does not).

Quoting is the weaker fix: the path still round-trips through a shell, and it
leaves the `.bin/tsc` and symlink-type defects untouched. Left alone, merging
this branch would have reverted main to the weaker form on all four files.

Taking main's version verbatim so the merge is a no-op on these hunks. No other
file on this branch is affected, and the emitted tree is unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011bzmen9WFv4jN1mXYriqUk
…docs

Completes the usage-ledger work on the client side and lands the documents
that make it maintainable.

All nine answer handlers now emit feature_started plus exactly one terminal
event, through a single `runTracked` wrapper rather than nine hand-edits. The
handlers end three different ways — throwing, returning `{ error, hint: null }`,
and returning a null result with no error — and only the first looks like
failure. Deciding that per call site was already got wrong once, when the early
returns in generate-what-to-say were recorded as successes.

PRIVACY.md gains the five rows this system actually needs: the usage ledger and
its 8-year statutory retention, licence activity, app-reported feature activity,
app context, and 45-day diagnostics. The "we do not store your content"
paragraph now covers the ledger explicitly, states that the installation
identifier is random rather than hardware-derived, and says plainly that
app-reported activity is labelled self-reported and is not presented as the same
kind of evidence as what the servers observed. The erasure right now describes
the real pseudonymisation behaviour, including that the salt is not stored.

The three docs are allowlisted out of the blanket docs/* ignore. The progress
file is the mandated handoff contract — 21 architectural decisions, five closed
findings, and the forensics record for three campaigns. Untracked, none of it
survived a fresh clone.

Bumps the natively-api submodule to the ledger backend.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X16jeMP4PQFKmDHVFCb9bK
…is app

Four things had accumulated as untracked noise in the working tree and are not
part of this application:

  natively-control/     a separate project checkout — 41,721 files, 1.8 GB.
                        Committing it would bloat every future clone and could
                        only be undone by rewriting published history.
  chargeback_evidence/  payment-dispute documents. Business records, not code,
                        and not something to publish into a source repository.
  undefined/            written by a bug that resolved a path to the literal
                        string "undefined". If this reappears, fix the caller
                        rather than deleting the directory.
  natively_debug.size*  one-off debug dumps.

Ignoring them keeps `git status` meaningful, so real untracked work stays
visible instead of being lost in the noise.

The usage-ledger client instrumentation, PRIVACY.md, and the ledger docs landed
separately in 960df42 from a concurrent session in this shared working tree;
the progress-doc line here is the remainder of that edit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…e repeating Whisper errors

Two production defects, plus the tests written alongside them.

1. A retired vision model stayed pinned forever on the path users hit.
   The NON-streaming vision path told the version manager when a model 404'd,
   but the STREAMING path — the live one — did not. So a decommissioned id
   (Groq llama-4-scout, 2026-08-12) stayed pinned indefinitely with no way to
   recover. visionStreamFallback now passes an onModelGone callback into the
   live path, mirroring generateWithVisionFallback's onModelError handling.
   MODEL_GONE_COOLDOWN_MS is exported so the config default and the use-site
   fallback cannot drift apart.

2. A deterministic Whisper worker error buried every other diagnostic.
   The streaming loop re-dispatches once per audio window, so a deterministic
   failure (a bad decoder option, a corrupt model file) is re-raised about
   every 1.5s. The 2026-08-12 log carried 10,183 byte-identical ERROR lines in
   a single day. LocalWhisperSTT now logs the first few verbatim, then every
   100th with a running count. This throttles the LOG only — transcription
   behaviour is unchanged.

Also lands three test files a previous findings wave left untracked, all green:
coding-repair fence handling (7 pass), doc-grounded routing (12 pass), and the
retired-model/English-only Whisper guard (24 pass).

Two further untracked test files were deliberately NOT included:
ManualScreenshotScreenContext2026_08_05 (0/2) and V3SkillInjection2026_08_05
(0/1). Both are red — they assert a hasScreenContext/skill-injection contract
that is not implemented. Landing them would add fresh failures to a Build Smoke
that is already red and actively being burned down in #461. They remain
untracked, to land with their fix.

Cross-platform: both changes are platform-independent — the vision path is
provider-side, the Whisper throttle is log bookkeeping around an existing worker
listener. No macOS or Windows branch is touched.
`Reviewed but not executed on Windows`.

Authored by a concurrent session in this shared working tree; committed here
after review at the repository owner's request.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…pute docs

Sweeps up what was left untracked in the working directory, with one deliberate
exclusion.

gitignore — the reason this is not a routine chore:
  KAUSHAL_12_DISPUTE_HANDOVER.md sits at the repo ROOT, a byte-identical stray
  copy of the file already held in the correctly-ignored
  dispute-evidence-kaushal-shivaprakashan/. The existing rules are all
  directory-scoped (/dispute-evidence-*), so the root copy was fully
  committable and the next `git add -A` would have published it. This repo is
  PUBLIC and that document carries a named customer's email address, phone
  number and home address. Adds /*_DISPUTE_HANDOVER.md and /*_DISPUTE_*.md so
  the root copies can never be staged. README.md and other root docs stay
  committable — the rule is scoped, not a blanket.

Tests (new, previously untracked alongside 279 tracked siblings):
  V3SkillInjection2026_08_05 — PR #429 Bug 003, skill injection silently
  dropped when Context Intelligence V3 is active (default ON since 2026-07-30),
  covering both drop sites independently.
  ManualScreenshotScreenContext2026_08_05 — manual screenshot screen context.

natively-api: cecbfdf → bedc55e, which is merged to that repo's main via PR #7
and is the deployed revision (Railway reports Online, /health 200).

transitions/: 27 CSS transition reference docs. Scanned for credentials and
customer data before publishing — the single hit is the word "password" inside
a prose description of form-validation UX. These are tooling reference material
rather than application source; say the word and they come back out.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SiDsWPD5XtBYgXWt7ZPizu
@github-actions

github-actions Bot commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

React Doctor found no issues. 🎉

⚠️ Warning: .github/workflows/react-doctor.yml is configured incorrectly. See below to fix.

React Doctor compares against main to report only the issues this pull request introduces. This run couldn't complete that comparison (usually a shallow CI checkout with no merge base), so it listed every issue in the changed files, including ones that already existed on main.

Add fetch-depth: 0 to the actions/checkout step in .github/workflows/react-doctor.yml so the checkout includes the history React Doctor needs:

 jobs:
   react-doctor:
     steps:
       - uses: actions/checkout@v5
+        with:
+          fetch-depth: 0

       - uses: millionco/react-doctor@v2

To silence this warning, set silence-missing-baseline-warning: true on the React Doctor action.

Reviewed by React Doctor for commit 6cb12be.

The Windows leg of Build Smoke failed on `Run src/lib unit tests` with all
nine orchestratorClass tests dying at once:

  failureType: 'hookFailed'
  The package "@esbuild/win32-x64" could not be found, and is needed by esbuild.
    at loadModule (src/lib/onboarding/__tests__/orchestratorClass.test.mjs:109)

The suite bundled orchestrator.ts through esbuild inside before(), so it needed
esbuild's platform-specific optional binary at test time. `npm ci` reports
success and every other Windows step passes, so the failure looks like an
onboarding regression — but nothing in the message mentions onboarding, and all
nine failures are one hook, not nine assertions.

`npm run test:lib` already runs Node with --experimental-strip-types, so the
bundler was never needed: orchestrator.ts imports './persistence.ts' with an
explicit extension and stageCatalog imports orchestrator type-only, which is
exactly what Node's type stripping resolves natively. The suite now imports the
.ts directly. Still the real shipped class — no twin, no drift — and now no
native binary, no temp directory, and no bundle files left behind in tmpdir
(loadModule mkdtemp'd on every call and never cleaned up).

pathToFileURL is kept deliberately: on Windows a bare absolute path like
`D:\...\orchestrator.ts` is not a valid ESM specifier and import() rejects it
with ERR_UNSUPPORTED_ESM_URL_SCHEME.

Verified:
  - `npm run test:lib` → 327/327 pass (was 327 tests / 317 pass / 9 fail on the
    Windows leg; macOS was already green, which is why this hid on this machine)
  - MUTATION-PROBED, because swapping a bundler for type stripping is exactly
    how a suite goes quietly vacuous: removing the
    `this.dismissedThisSession.add(id)` guard from markDismissed() turns the
    suite red (2 failures) through the new loader, and orchestrator.ts was
    restored byte-identical to HEAD afterward.

This fixes the Windows leg only. The macOS leg fails separately and for an
unrelated reason — `npm test` (Electron unit tests) has 298 failures across 61
files, a pre-existing suite-wide baseline unrelated to this change.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SiDsWPD5XtBYgXWt7ZPizu
@evinjohnn
evinjohnn merged commit 5513e0a into main Aug 16, 2026
3 of 4 checks passed
Abitesh pushed a commit to Abitesh/Sneak-Peek that referenced this pull request Aug 30, 2026
…nt/feat/usage-ledger

Usage ledger integration, retired-model unpin, and a PII guard on the repo root
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