Skip to content

Feat/hardening ci and tap - #3

Merged
0dillon merged 5 commits into
mainfrom
feat/hardening-ci-and-tap
Aug 22, 2026
Merged

Feat/hardening ci and tap#3
0dillon merged 5 commits into
mainfrom
feat/hardening-ci-and-tap

Conversation

@0dillon

@0dillon 0dillon commented Aug 22, 2026

Copy link
Copy Markdown
Owner

No description provided.

Picks up the typesafe `env` export added by a newer Convex version. No
behaviour change — the file is generated, and this keeps it matching the
installed client.
… poller

A DNS outage turned one dead host into a wall of stack traces: the
inbound-payment poller ran every fifteen seconds regardless, each pass
opening connections that took the Node default of many seconds to give
up, each failure printing in full. The real problem — the provider is
unreachable — was buried under its own repetition.

Two changes. Calls now carry an eight-second deadline, so a hung
connection is abandoned rather than left to occupy the poll it belongs
to. And repeat failures against the same host collapse: the first prints,
then every twentieth, until a success resets the count.

The poller itself moves from a fixed interval to self-scheduling with
exponential backoff, fifteen seconds out to five minutes. It only backs
off when no wallet reached the provider at all — a single wallet failing
is a wallet problem, not an outage, and must not slow down everyone
else's payments.
Four things a user had to sit through, each fixed at its cause.

Aide opened almost every sentence with "Let me", including twice in a
row, and the engine's own stall filler said much the same thing — so a
pause sounded like Aide starting over. The fillers now split in two:
openers only before the first tool call, continuations for a mid-reply
lull, worded so they can never be mistaken for the start of a turn. The
prompt allows the covering opener once per turn, not once per tool.

Aide also claimed to have opened pages it never opened, and asked a blind
user whether they could see something. Both are now explicit prompt
rules, and tests assert the rules still exist — a deletion inside a long
prompt is easy to miss in review.

The speech worker's request deadline started at enqueue rather than at
synthesis, so queued work burned its budget waiting its turn. Enough
short sentences at once and the last few timed out untouched, killing the
worker and taking the rest of the reply with it. The clock now belongs to
whatever the worker is actually synthesising, and a worker that dies has
its pending requests replayed on a fresh process instead of rejected. A
request is only text; failing it drops the user to the robotic browser
voice mid-sentence for no reason.

Finally, AIDE_DIST_DIR: two Next processes in one tree share one build
directory and silently overwrite each other, which surfaces much later as
a missing-chunk error in whichever server was there first.
Aide moves real money on behalf of users who cannot see the screen to
notice when something has gone wrong, so the checks that used to live in
one developer's terminal now run on every push and pull request.

Five checks, in parallel, each one guarding a failure this codebase has
actually had:

- Types and Tests are the two gates run by hand before every commit so
  far. The test job spans both vitest projects, including the Convex
  functions, which only run inside an edge-runtime VM.
- Production build catches routes that compile only under `next build` —
  the dev server is more forgiving than a deploy is.
- Speech worker installs edge-tts and imports both speech entry points.
  When that path breaks, a blind user hears the robotic browser fallback
  and gets no explanation anywhere on screen.
- No secrets committed refuses a tracked .env, local Convex state (it
  holds an admin key), or anything shaped like a live credential.

All five run against placeholders, never a real provider: what they
prove is the wiring, not the keys. Dependabot is monthly and grouped on
purpose — a wall of open PRs gets ignored, which is worse than a
slightly stale lockfile.
There was no way to tell Aide to stop listening. The mic closes itself
after ninety seconds of quiet, but that is Aide's decision, not the
user's, and any stray touch reopens it — so a user who wanted a private
moment had no way to take one.

A mute button would not solve it. A button is only a control if you can
find it, and finding it is exactly what these users cannot do. A count of
taps needs no target: anywhere on the screen or the trackpad, on the
surface their hand is already resting on. Three rather than two, because
a hand double-taps by accident and does not triple-tap by accident.

Both directions are announced, because the whole state change is
otherwise silent and invisible. The closing notice carries the way back
inside it — it is the last thing heard before Aide goes quiet, and there
is nothing on screen to remind them afterwards.

The hold is enforced at startRecognition(), the single function that can
open the mic. Its half-dozen callers — a tab regaining focus, a reply
finishing, the restart backoff, interrupt() — would each have undone it
otherwise, quietly, at a moment the user had no reason to be watching
for. The level meter releases its own capture stream too, or the
browser's recording dot stays lit and the announcement is a lie.

Two smaller things fall out of it: the third tap's trailing click lands
on the Aide orb's interrupt handler and would cut off its own
announcement, so interrupt() ignores a click that closely follows a
toggle; and the gesture is inert in speak-only browsers, where there is
no microphone to hold.

Aide is told about the gesture in the prompt so it can answer when asked,
and told it cannot perform it — the same rule as page navigation. A
claim with no action behind it leaves someone believing a microphone is
closed when it is open.
@0dillon
0dillon merged commit 23395ce into main Aug 22, 2026
5 checks passed
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