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
14 changes: 2 additions & 12 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,6 @@ jobs:
python3 scripts/verify-workflow-pinning.py --self-test
python3 scripts/verify-workflow-pinning.py

- name: Check release cleanup policy
run: python3 scripts/test_release_history.py

- name: Check public documentation links
run: python3 scripts/check-doc-links.py

Expand All @@ -39,16 +36,9 @@ jobs:
package_version=$(python3 -c 'import tomllib; print(tomllib.load(open("Cargo.toml", "rb"))["workspace"]["package"]["version"])')
python3 scripts/changelog-notes.py "v$package_version-alpha.1" > /dev/null \
|| python3 scripts/changelog-notes.py "v$package_version" > /dev/null
python3 scripts/check_metainfo.py

- name: Check Linux packaging tools
run: |
python3 scripts/rewrite_linux_package_identity.py --self-test
python3 scripts/test_rewrite_linux_package_identity.py
python3 scripts/test_linux_package_metadata.py
python3 scripts/check_apt_installer.py
python3 scripts/test_apt_repository.py
python3 scripts/check_apt_repository.py
# Packaging tool tests (metainfo, package identity, APT) live in
# release / release-policy, which is a required pull-request check.

frontend:
runs-on: ubuntu-latest
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ jobs:
python3 scripts/verify-tag-policy.py --self-test
python3 scripts/generate-desktop-sbom.py --self-test

# Required on pull requests (with check / check). Owns packaging-tool
# tests so check.yml does not run the same Python twice.
- name: Validate changelog parser
run: python3 scripts/changelog-notes.py --self-test

Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,6 @@ __pycache__/
*.pyc
.idea
.vscode
.flow/
.audit/
frontend/.flow/
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# Changelog


## v1.0.1 - 2026-09-08

- Empty dictation no longer inserts or appears in History.

## v1.0.0 - 2026-09-07

- The Debian and RPM package is now `echo`. Existing `io.github.ddv1982.echo` installs upgrade in place. The desktop id and `echo-desktop` binary are unchanged.
Expand Down
12 changes: 6 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ edition = "2021"
license = "MIT"
repository = "https://github.com/ddv1982/echo"
rust-version = "1.89"
version = "1.0.0"
version = "1.0.1"

[workspace.lints.rust]
unsafe_code = "forbid"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ Ubuntu build packages.
- [Architecture](docs/architecture.md)
- [Quality assurance](docs/qa/README.md)
- [Release process](docs/RELEASING.md)
- [Release history cleanup](docs/history/releases.md)
- [Project history](docs/history/README.md)
- [Third-party component notices](THIRD_PARTY.md)

## License
Expand Down
15 changes: 4 additions & 11 deletions benchmarks/stt/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,23 +28,16 @@ python3 scripts/fetch-stt-corpus.py \
--output-dir target/stt-fleurs-corpus
```

The generated `fixtures.json` retains the corpus-level coverage and license record. Each utterance retains its class, source URL and digest, attribution, license, and a verbatim-copy derivation record. Benchmark bundles snapshot it byte-for-byte, and admission replay requires external coverage metadata to match that immutable snapshot. Editing a class, license, source, or coverage declaration after measurement therefore cannot improve a decision.
The generated `fixtures.json` retains the corpus-level coverage and license record. Each utterance retains its class, source URL and digest, attribution, license, and a verbatim-copy derivation record.

The generated `fixtures.json` can drive the normal benchmark. A CPU-only candidate uses the same runtime binary with upstream `--no-gpu`, so it is a valid negative control:
The generated `fixtures.json` can drive the normal benchmark:

```sh
python3 scripts/benchmark-stt.py \
--binary target/release/echo-desktop \
--manifest target/stt-fleurs-corpus/fixtures.json \
--candidate 'whisper:base-q5_1@threads=4,beam=1,best-of=1,no-fallback' \
--candidate 'whisper:base-q5_1@threads=4,beam=1,best-of=1,no-fallback,cpu-only' \
--warmups 1 --repeats 10 --output-dir target/stt-host-matrix
--warmups 1 --repeats 10 --output-dir target/stt-fleurs
```

Evaluate the paired rows with `scripts/analyze-stt-host-matrix.py`. This subset covers clean read speech only. It cannot pass the production corpus gate until project-owned dictation, technical identifiers, fast and quiet speech, noise, false starts, silence, and nonspeech are added.

Keep fresh-cache first-use and populated-cache measurements in separate output directories. Record reset/reboot runs separately; a warmed run must never be presented as first-use evidence.

Pass `--cache-state`, `--reset-cycle`, `--driver-identity`, and `--icd-identity` to every production-gate benchmark. Concatenate the JSONL rows from fresh and populated runs across at least two reset cycles before analysis. The analyzer fails closed when any of this evidence is absent or changes between rows.

Admission sweeps additionally require `--expected-echo-commit` and `--expected-echo-binary-sha256`. The sweep and benchmark reject a dirty checkout, a different `HEAD`, or a different binary digest. Generic benchmarks may omit these flags, but their evidence cannot satisfy the admission identity gate.
This subset covers clean read speech only. Keep fresh-cache first-use and populated-cache measurements in separate output directories. Record reset/reboot runs separately; a warmed run must never be presented as first-use evidence.
15 changes: 15 additions & 0 deletions crates/echo-core/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,17 @@ impl Session {
}
}

/// Empty transcription returns to Idle without inserting.
pub fn skip_insertion(&mut self) -> Result<(), SessionError> {
match self.state {
SessionState::Transcribing => {
self.state = SessionState::Idle;
Ok(())
}
_ => Err(self.illegal("skip_insertion")),
}
}

pub fn fail(&mut self, reason: FailReason) -> Result<(), SessionError> {
match self.state {
SessionState::Idle | SessionState::Failed { .. } => Err(self.illegal("fail")),
Expand Down Expand Up @@ -145,6 +156,7 @@ mod tests {
StartRecording,
FinishRecording,
BeginInjecting,
SkipInsertion,
CompleteInject,
Fail,
Ack,
Expand Down Expand Up @@ -177,6 +189,7 @@ mod tests {
Event::StartRecording => session.start_recording(),
Event::FinishRecording => session.finish_recording(),
Event::BeginInjecting => session.begin_injecting(),
Event::SkipInsertion => session.skip_insertion(),
Event::CompleteInject => session.complete_inject(),
Event::Fail => session.fail(FailReason::EngineError),
Event::Ack => session.ack(),
Expand All @@ -198,6 +211,7 @@ mod tests {
(Kind::Idle, Event::StartRecording) => Some(Kind::Recording),
(Kind::Recording, Event::FinishRecording) => Some(Kind::Transcribing),
(Kind::Transcribing, Event::BeginInjecting) => Some(Kind::Injecting),
(Kind::Transcribing, Event::SkipInsertion) => Some(Kind::Idle),
(Kind::Injecting, Event::CompleteInject) => Some(Kind::Idle),
(Kind::Recording | Kind::Transcribing | Kind::Injecting, Event::Fail) => {
Some(Kind::Failed)
Expand All @@ -220,6 +234,7 @@ mod tests {
Event::StartRecording,
Event::FinishRecording,
Event::BeginInjecting,
Event::SkipInsertion,
Event::CompleteInject,
Event::Fail,
Event::Ack,
Expand Down
Loading