feat(lifeboard): proactivity, scheduled boards, and Google sign-in - #310
Open
ivanmkc wants to merge 2 commits into
Open
feat(lifeboard): proactivity, scheduled boards, and Google sign-in#310ivanmkc wants to merge 2 commits into
ivanmkc wants to merge 2 commits into
Conversation
…boards The hard part of conflict detection is restraint, not detection. A rule that fires on every adjacent pair produces an app people mute in a week. So: timed events only, inside a fortnight, one conflict per pair with an order-independent id, and nothing at all when it does not know where either thing is -- an unknown location is not a problem, and inventing one is how an assistant becomes noise. The case worth getting right is the one plain overlap detection misses: you land at 18:40 and dinner is at 19:00 across town. Those two events do not overlap. Travel time is what makes it a conflict, and the estimator is injected so a later plan can use real routing. A clash becomes a proposal, so it lands in the same inbox, is accepted or declined the same way, and is raised exactly once. Accepting proposes nothing automatic -- the fix is a decision about someone's day -- and declining changes nothing. Scheduling reuses what exists rather than inventing a second scheduler: board definitions stay in .termchart/boards and running one is `termchart run`, the same command a crontab would call. The bridge is one more host. It is off unless asked for with --schedule, because every tick spends money on someone's subscription and a program that starts doing that because it was launched is one people learn not to launch. Cadence is reported in words next to the cron, since "0 7 * * *" does not tell anyone what it will cost. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Closes the gap between having the calendar and mail subsystems and having them do anything: Connections can now sign in to Google, and opening the app runs a catch-up pass -- pull the calendar, read what is new, triage it. The client id is asked for rather than shipped. A Desktop-app OAuth client belongs to the person who made it, and Testing mode with up to a hundred named users needs no verification review and no CASA assessment; publishing one for everybody would drag the whole app into a restricted-scope audit it does not need. That is a deliberate position, and the screen says so. The pass is interruptible and repeatable by construction. Calendar events reconcile on the provider's id, so running it twice updates rather than duplicating a term of school events; messages already turned into a proposal are skipped rather than triaged again; and the last-run time is only written at the end. It runs in the background and never delays the board coming up -- the family's own records are already on screen, and Google is the slow, failable part. Also adds Store.settled(), which resolves once every queued write has landed. Three tests were waiting on fixed sleeps and failed under load in a full run -- a flaky test is a defect in the suite, and the fix is to wait for the condition rather than to guess at a longer delay. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ivanmkc
force-pushed
the
feat/lifeboard-foundation
branch
from
September 2, 2026 12:12
41823e9 to
a55ec34
Compare
ivanmkc
changed the base branch from
design/lifeboard
to
lifeboard/08-bridge-jobs
September 2, 2026 12:13
This was referenced Sep 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The stack
localStoragefor the test suite on Node 25@ivanmkc/termchart-canvas; injectable interact transportEvery branch in the stack was checked out on its own and verified independently:
npm install,tsc --noEmitfor every package,npm testacross the workspace, and the offline e2e where it exists. All twenty are green — no branch depends on a later one to build or pass. Full viewer e2e (11 suites, 106 assertions) was run on #312 as the behaviour-preservation evidence for the extraction.Stack position: 10 of 10 — the top of the stack. Base:
lifeboard/08-bridge-jobs.(This PR was originally the whole branch. It has been split into a ten-PR stack; this is now the last of them.)
Two things: the assistant noticing problems before you do, and the Google sign-in that makes the calendar and mail subsystems actually run.
The hard part of conflict detection is restraint, not detection. A rule that fires on every adjacent pair produces an app people mute in a week. So: timed events only, inside a fortnight, one conflict per pair with an order-independent id, and nothing at all when it does not know where either thing is — an unknown location is not a problem, and inventing one is how an assistant becomes noise.
The case worth getting right is the one plain overlap detection misses: you land at 18:40 and dinner is at 19:00 across town. Those two events do not overlap. Travel time is what makes it a conflict, and the estimator is injected so a later plan can use real routing.
A clash becomes a proposal, so it lands in the same inbox and is raised exactly once. Accepting proposes nothing automatic — the fix is a decision about someone's day — and declining changes nothing.
Scheduling reuses what exists rather than inventing a second scheduler: board definitions stay in
.termchart/boardsand running one istermchart run, the same command a crontab would call. The bridge is one more host. It is off unless asked for with--schedule, because every tick spends money on someone's subscription. Cadence is reported in words next to the cron, since0 7 * * *does not tell anyone what it will cost.The Google wiring closes a real gap I found on the last pass: the calendar and mail subsystems existed and were tested, but nothing in the app signed in or called them. Connections now signs in, and opening the app runs a catch-up pass. The client id is asked for rather than shipped — a Desktop-app OAuth client belongs to the person who made it, and Testing mode with up to a hundred named users needs no verification review and no CASA assessment; publishing one for everybody would drag the whole app into a restricted-scope audit it does not need.
The pass is interruptible and repeatable by construction: events reconcile on the provider's id, messages already turned into a proposal are skipped, and the last-run time is written only at the end. It runs in the background and never delays the board coming up.
Verified: lifeboard 343 tests, CLI 320, offline e2e 17/17.
🤖 Generated with Claude Code