Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
name: CI
# PRs only: main is squash-merge-only, so a push to main is always a tree
# that just passed this exact suite β€” re-running it burned a macOS runner
# per merge for nothing (auto-release does its own version self-test).
on:
push:
branches: [main]
pull_request:

jobs:
Expand Down
13 changes: 8 additions & 5 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,10 @@ dictation, or the device payload. Add a regression test with every bug fix.
the typing worker converges on the latest hypothesis.
- TranscriptTyper corrections are bounded to the volatile region; any
external typing during dictation must freezeVolatile() first.
- TCC (mic/accessibility) keys off the code signature: ad-hoc rebuilds of
the .app re-prompt every time until Developer ID signing lands. The dev
binary attributes permissions to the invoking terminal instead.
- TCC (mic/accessibility) keys off the code signature: release builds are
Developer ID-signed so grants persist across updates; ad-hoc .app
rebuilds re-prompt every time. The dev binary attributes permissions to
the invoking terminal instead.
PermissionsMonitor owns the UX: "!" icon badge, fix-it menu items, launch
prompts, and a tccutil-reset repair for the stale-Accessibility-row case.

Expand Down Expand Up @@ -162,8 +163,10 @@ public key live in scripts/bundle.sh's Info.plist; private key is in the
SPARKLE_ED_PRIVATE_KEY repo secret and Josh's login keychain, account
"tingle") β†’ tags β†’ GitHub Release with the .app zip β†’ bumps the cask in
tutorintelligence/homebrew-tap. `tools/test_next_version.py` covers the
version math. Until the Apple Developer secrets land the build is unsigned
but releases still cut. Optional secrets: MACOS_CERT_P12_BASE64,
version math. Release builds are Developer ID-signed, notarized, and
stapled (hardened runtime + entitlements in packaging/entitlements.plist;
Sparkle nested executables signed inside-out β€” the bare Autoupdate binary
is the one notarization rejects when missed). Secrets: MACOS_CERT_P12_BASE64,
MACOS_CERT_PASSWORD, NOTARY_KEY / NOTARY_KEY_ID / NOTARY_ISSUER_ID (App
Store Connect API key β€” the team Apple ID is Microsoft-federated, so
app-specific passwords are unavailable), TAP_DEPLOY_KEY (SSH deploy key
Expand Down
15 changes: 8 additions & 7 deletions DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,18 +180,19 @@ summon-agent script.
## Distribution

`scripts/bundle.sh` assembles `tingle.app` (SwiftPM release build + Info.plist
+ resource bundle). Release flow (`.github/workflows/release.yml`): tag β†’
tests β†’ Developer ID sign β†’ notarize β†’ GitHub Release β†’ bump the cask
(template: [packaging/tingle.rb](packaging/tingle.rb)) in
`tutorintelligence/homebrew-tap`. Blocked on Apple Developer enrollment; until
then ad-hoc signing re-prompts TCC on every rebuild.
+ resource bundle) and signs it: Developer ID with hardened runtime, secure
timestamps, and entitlements (mic, Apple Events); Sparkle's nested
executables are signed inside-out. Release flow
(`.github/workflows/auto-release.yml`, on every push to main): version from
the merge subject β†’ build β†’ sign β†’ notarize + staple β†’ Sparkle-signed
appcast β†’ GitHub Release β†’ bump the cask in `tutorintelligence/homebrew-tap`.
The stable signing identity is what lets TCC grants survive updates.

## Roadmap

1. Custom language model (`SFCustomLanguageModelData`: phrases, templates,
custom pronunciations) for domain adaptation beyond contextual strings.
2. Apple Developer enrollment β†’ signing/notarization/tap β†’ first release.
3. Exploration: the firmware's ADC event messages (type 0x1X) may carry
2. Exploration: the firmware's ADC event messages (type 0x1X) may carry
higher-rate handle data (merged-tap recovery, analog gestures).

## Device reference (fw 1.0.4, all measured on hardware)
Expand Down
15 changes: 4 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,11 @@ You need:
2. **A USB line-in adapter.** The ting's curly cable outputs *line-level*
audio, and Mac headphone jacks don't accept line-in β€” plugging the ting
straight into your laptop's 3.5mm port will not work. Any USB audio
interface with a line input is fine; a cheap one that works well is the
interface with a line input is fine; two that are tested and work well:
the [Sonos Line-In adapter](https://www.bhphotovideo.com/c/product/1754583-REG/sonos_ldnglww1blk_sonos_line_in_adapter.html)
(smallest option β€” a bare USB-C dongle) and the
[Cubilux USB-C line-in adapter](https://www.amazon.com/dp/B0CNCL21RR)
(line-in + mic-in + headphone-out on one USB-C plug).
(bulkier; adds mic-in + headphone-out).
3. Optionally, **a USB-C cable** to the ting for docked use (instant button
events, battery readout) and for the one-time flash.

Expand All @@ -49,15 +51,6 @@ volume knob under the ting's lid up to around halfway.
brew install --cask tutorintelligence/tap/tingle
```

tingle isn't code-signed yet (Apple Developer enrollment in progress).
macOS tags downloaded apps with a quarantine flag so Gatekeeper can vet
them on first launch β€” and unsigned apps fail that check with "Apple
could not verify tingle is free of malware". The cask therefore removes
the quarantine flag after install. If you'd rather keep Gatekeeper in
the loop, build from source below instead, then approve the app under
System Settings β†’ Privacy & Security β†’ "Open Anyway". Once signing
lands, none of this applies.

### Install from source

You need Xcode Command Line Tools (`xcode-select --install`) and macOS 26+
Expand Down
Loading