Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
859c244
Core: one Duration-to-seconds helper and one dictionary merge
dinooo13 Oct 8, 2026
5394cff
Coordinator, app and settings: one end-of-recording path, a narrow se…
dinooo13 Oct 8, 2026
e0724f5
Processors: ordinary words, sentence marks and named marks survive cl…
dinooo13 Oct 8, 2026
a1dbbe5
Engine loader: a superseded load leaves the next engine alone
dinooo13 Oct 8, 2026
7ada459
Engine: an utterance's end clears only its own session
dinooo13 Oct 8, 2026
e3bed63
Engines: one catalog for the engine's name and description
dinooo13 Oct 8, 2026
3d209c2
Capture: one sample accumulator per recording, drained in place
dinooo13 Oct 8, 2026
6d2eb27
CLI: one file per command, and the engine from the catalog
dinooo13 Oct 8, 2026
eb94ac5
CLI: bench-process times the processor pipeline
dinooo13 Oct 8, 2026
716ea63
Engine branch joins: the app registers engines from StandardEngines, …
dinooo13 Oct 9, 2026
e47ba9d
Hotkeys: ends before presses, and a lost key-up stops holding its key
dinooo13 Oct 8, 2026
86d31c5
Settings: one chord recorder at a time, and the hotkey back only afte…
dinooo13 Oct 8, 2026
f7be44c
Hotkeys: Escape its own event, one lifecycle for both monitors, retai…
dinooo13 Oct 8, 2026
eac6f21
Hotkeys: key names read the layout on the main actor, and stale comments
dinooo13 Oct 8, 2026
1b27dc3
Tests: the reversed hand-over at the gesture tracker on its own
dinooo13 Oct 8, 2026
f58e6ad
Hotkeys branch joins: the app's tap-or-Carbon choice calls HotkeySour…
dinooo13 Oct 9, 2026
74f99bf
Refine: bounded polish budgets, typed model errors, safer model files
dinooo13 Oct 8, 2026
85b05d0
Polish: a download stops when the user picks another model or turns p…
dinooo13 Oct 8, 2026
d6273c0
Coordinator tests: a manual clock, a keyboard clock, and a test per h…
dinooo13 Oct 8, 2026
c71885a
Overlay: one file per part
dinooo13 Oct 8, 2026
9fac4d5
Output: a newer copy survives a second paste, and the clipboard keepe…
dinooo13 Oct 8, 2026
83a7a2e
Mute: restore each channel as it was, and number the recordings
dinooo13 Oct 8, 2026
03a49ab
Learning: hold reviews while the model is busy, and leave other apps'…
dinooo13 Oct 8, 2026
44c530e
Output branch joins: the muter takes session numbers only, reviews wa…
dinooo13 Oct 9, 2026
1a6f5b0
Settings and overlay views: sections, one warning type, one set of pi…
dinooo13 Oct 8, 2026
9bf53df
The input level leaves DictationState
dinooo13 Oct 8, 2026
0ffc4c2
Docs: CLAUDE.md and BENCHMARKS.md describe the code as it now is
dinooo13 Oct 8, 2026
6b8b072
Paste: an owed Return goes before the next Cmd+V, early reads do not …
dinooo13 Oct 8, 2026
1b83bd4
Quit: the clipboard comes back after the target's read, and a hung ap…
dinooo13 Oct 8, 2026
cabfb6e
Build with Swift 6.3: no local named after the property its initialis…
dinooo13 Oct 9, 2026
26c0033
CI: the kill-every-copy check reads commands, not comments
dinooo13 Oct 9, 2026
df58e5b
CI and tests: a stalled test run names itself instead of holding the …
dinooo13 Oct 9, 2026
9cb86d1
Coordinator tests: one builder, a start helper and a dictate helper
dinooo13 Oct 9, 2026
ef9fc89
Tests: one inserted-event lookup, no second mute-order test, a harnes…
dinooo13 Oct 9, 2026
dd7fda4
Settings tests: one scratch-store helper, one round trip through the …
dinooo13 Oct 9, 2026
204e3a5
Hotkey tests: the lost key-up's release and re-press in one test
dinooo13 Oct 9, 2026
fd96012
Paste: the restore timings are the keeper's constants, and the owed R…
dinooo13 Oct 9, 2026
390ae52
Tests: one ManualClock and one Recorder, in a shared test-support target
dinooo13 Oct 9, 2026
bedb1d2
Coordinator: the feed task returns its count, one reset timer, member…
dinooo13 Oct 9, 2026
67a54c5
Settings: the encoder is synthesised again; dead helpers go
dinooo13 Oct 9, 2026
404ac55
Polish: one race helper, one log line, one polisher protocol for the CLI
dinooo13 Oct 9, 2026
22f4136
CLI and hot paths: bench-process uses the CLI's helpers, less repeate…
dinooo13 Oct 9, 2026
154f2f7
Carbon and permissions: entries built once, Escape taken in one lock,…
dinooo13 Oct 9, 2026
c4ad88c
Small duplicates: one mute address builder, no CommonWords.contains w…
dinooo13 Oct 9, 2026
da4469b
Coordinator tests: one loop per behaviour the chord changes and disca…
dinooo13 Oct 9, 2026
e782e5b
Settings tests: the defaults compared whole, the unknown polish model…
dinooo13 Oct 9, 2026
4396376
Paste tests: the harness starts with the user's clipboard when asked
dinooo13 Oct 9, 2026
a67eaa1
Hotkey tests: the key codes declared once
dinooo13 Oct 9, 2026
73f7425
One run-loop thread for the hotkey tap and the AX observer
dinooo13 Oct 9, 2026
5566d50
Capture and hotkeys: one input-format check, one Carbon modifier table
dinooo13 Oct 9, 2026
ecaf120
Coordinator tests: press(_:) and cycleFinished() for the monitor-driv…
dinooo13 Oct 9, 2026
541ee19
Tests: the correction learner's gate is the shared Gate
dinooo13 Oct 9, 2026
4adb246
Tests: the real-pasteboard tests run one at a time
dinooo13 Oct 9, 2026
2376d7d
Spoken punctuation: "ein" counts as an article only before a mark adj…
dinooo13 Oct 10, 2026
1c68c40
Custom words: the one-edit Soundex cap is keyed on the term's length
dinooo13 Oct 10, 2026
9938f6a
Clipboard keeper: a failed Cmd+V restores the way a paste does
dinooo13 Oct 10, 2026
e06286c
S1-mini: a load after unload waits for the abandoned one
dinooo13 Oct 10, 2026
6c03f2b
Settings store: one backup per broken file, and a value this build ca…
dinooo13 Oct 10, 2026
b823b40
Coordinator: a chord and its stand-in restart the monitor once, and a…
dinooo13 Oct 10, 2026
cd57a95
Polish model: the file's cancel and ensure run in the order asked
dinooo13 Oct 10, 2026
bc41b39
Hotkey recorder: the session is keyed on a token, and a freed recorde…
dinooo13 Oct 10, 2026
51b16d7
Overlay: a stop and start leaves one observation chain
dinooo13 Oct 10, 2026
c536743
CLAUDE.md: the settings row says a dropped value survives a save
dinooo13 Oct 10, 2026
ba0f557
Engine: an utterance is a handle, and a call naming a stale one does …
dinooo13 Oct 10, 2026
1c75108
Coordinator: a cancel's cleanup waits for the cancel before it
dinooo13 Oct 10, 2026
506de91
Coordinator: a press cancelled while it waits for a cleanup leaves th…
dinooo13 Oct 10, 2026
2faf220
Coordinator: one update hands over the settings, the stand-in and the…
dinooo13 Oct 10, 2026
7a6d0f6
Hotkeys: a recorded chord gets the monitor it needs at once, not at t…
dinooo13 Oct 10, 2026
e2cdf4a
Coordinator: only a dictionary change rebuilds the processors
dinooo13 Oct 10, 2026
c7fc8b4
Polish model: a cancel reaches the checksum instead of waiting for it
dinooo13 Oct 10, 2026
5b2afc3
Polish and quit: one firstOf, in Core, which the app's quit uses too
dinooo13 Oct 10, 2026
e163190
Polish: a call that times out while draining the last one never start…
dinooo13 Oct 13, 2026
9f4d763
Hotkeys: a grant flip hands the coordinator the monitor and its stand…
dinooo13 Oct 13, 2026
ee9ebb5
Clipboard keeper: a restore moved by a later read cannot fire at its …
dinooo13 Oct 13, 2026
d0628a6
Settings store: a dictionary row without an id no longer hides that n…
dinooo13 Oct 13, 2026
e9909ed
App: copying the last transcript goes through the keeper, with the cl…
dinooo13 Oct 13, 2026
7f19ed1
Polish model: a checksum whose read fails is a disk failure, not a co…
dinooo13 Oct 13, 2026
8866671
Coordinator: the last transcript is the processed text even when the …
dinooo13 Oct 13, 2026
c2957c0
Learning: a review held for a dictation waits on the coordinator's st…
dinooo13 Oct 13, 2026
d37fb06
Coordinator and polish: one word count, in Core, for the minimum to p…
dinooo13 Oct 13, 2026
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
83 changes: 64 additions & 19 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,40 +1,85 @@
name: CI

# `paths` with negations rather than `paths-ignore`: GitHub documents the `!`
# re-include only for `paths`, and this is what makes an edit to this file
# run CI while the rest of .github and the docs do not. Later patterns win.
on:
push:
branches: [main]
paths-ignore:
- 'docs/**'
- '.github/**'
- '!.github/**/*.yml'
- 'README.md'
- 'LICENSE'
- '**/*.md'
paths:
- '**'
- '!docs/**'
- '!**/*.md'
- '!LICENSE'
- '!.github/**'
- '.github/workflows/*.yml'
pull_request:
paths-ignore:
- 'docs/**'
- '.github/**'
- '!.github/**/*.yml'
- 'README.md'
- 'LICENSE'
- '**/*.md'
paths:
- '**'
- '!docs/**'
- '!**/*.md'
- '!LICENSE'
- '!.github/**'
- '.github/workflows/*.yml'

jobs:
build-and-test:
# Pladder targets macOS 26 and needs Xcode 26.
runs-on: macos-26
timeout-minutes: 45
steps:
- uses: actions/checkout@v4
- name: Select Xcode 26
run: sudo xcode-select -s /Applications/Xcode_26.app || true
# The newest Xcode 26 on the runner. No fallback: building with the
# runner's default Xcode would test a toolchain Pladder does not use.
run: |
XCODE=$(ls -d /Applications/Xcode_26*.app | sort -V | tail -1)
test -n "$XCODE"
sudo xcode-select -s "$XCODE"
- name: Swift version
run: swift --version
- name: Build
run: swift build
# Warnings in Pladder's own sources fail the build; the dependencies'
# are theirs to fix.
run: |
set -o pipefail
swift build 2>&1 | tee build.log
if grep -E "^$PWD/Sources/.*warning:" build.log; then exit 1; fi
- name: Test
run: swift test
- name: Bundle (ad-hoc signed)
run: CODESIGN_IDENTITY=- ./scripts/bundle.sh
# The suite takes seconds. If it stalls, the stack of every thread of
# the test process goes into the log before it is stopped, so a hang
# says where it is instead of holding the runner for an hour.
timeout-minutes: 15
run: |
set +e
swift build --build-tests || exit 1
swift test --skip-build &
TEST=$!
for _ in $(seq 1 300); do
kill -0 "$TEST" 2>/dev/null || break
sleep 1
done
if kill -0 "$TEST" 2>/dev/null; then
echo "::error::swift test still running after 5 minutes; sampling its threads"
for pid in $(pgrep -f 'swiftpm-testing-helper|PladderPackageTests'); do
sample "$pid" 3 -mayDie -file "sample-$pid.txt"
cat "sample-$pid.txt"
done
pkill -P "$TEST"; kill "$TEST"
exit 1
fi
wait "$TEST"
- name: Scripts never stop every Pladder
# The developer dictates with a running copy while scripts run; a
# bare kill by name would stop it mid-recording (see CLAUDE.md).
run: |
# Commands only: a comment may name what not to do.
if grep -rnE '^[^#]*(pkill -x Pladder|killall Pladder)' scripts; then exit 1; fi
- name: Bundle
# No CODESIGN_IDENTITY on purpose: the runner has no certificate, so
# this runs the auto-detection and its ad-hoc fallback, which once
# ended the script silently on a Mac without a certificate.
run: ./scripts/bundle.sh
- uses: actions/upload-artifact@v4
with:
name: Pladder.app
Expand Down
25 changes: 14 additions & 11 deletions CLAUDE.md

Large diffs are not rendered by default.

7 changes: 4 additions & 3 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,11 @@ let package = Package(
dependencies: ["PladderCore", "PladderEngines", "PladderAudio", "PladderBench", "PladderRefine", "PladderSystem"]
),

.testTarget(name: "PladderCoreTests", dependencies: ["PladderCore"]),
.target(name: "PladderTestSupport", path: "Tests/PladderTestSupport"),
.testTarget(name: "PladderCoreTests", dependencies: ["PladderCore", "PladderTestSupport"]),
.testTarget(name: "PladderAudioTests", dependencies: ["PladderAudio"]),
.testTarget(name: "PladderBenchTests", dependencies: ["PladderBench"]),
.testTarget(name: "PladderSystemTests", dependencies: ["PladderSystem"]),
.testTarget(name: "PladderRefineTests", dependencies: ["PladderRefine"]),
.testTarget(name: "PladderSystemTests", dependencies: ["PladderSystem", "PladderTestSupport"]),
.testTarget(name: "PladderRefineTests", dependencies: ["PladderRefine", "PladderTestSupport"]),
]
)
Loading
Loading