R1: chat actions on the durable engine - #81
Conversation
Research + decided direction: intents and MCP as primary action paths, vision-based agent loop as fallback, engine as @offgrid/use in shared, vision model as a downloadable catalog entry (GUI-Owl-1.5 / Qwen3-VL). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Five phases, Aug 12 - Dec 2 2026, one demoable checkpoint per phase. Phase 1 (semantic rail) ships standalone value by Sep 9; the vision model install is only needed from phase 3 week 3. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
16 weeks to 9 (Aug 12 - Oct 14). Code-heavy phases shrink the most (engine 4wk to 2wk); integration-heavy phases keep slack since review, TCC flows, and real-app iteration do not compress. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sibling shared checkout + file: consumption decision added to phase 0; mobile follows desktop as an adapter-only project on the same engine. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…bile adapter Approach doc's open questions become a decision log (graph roles, eval harness, sequencing decided; model pick narrowed to install time; package name pending lead confirm). Plan gets an After v1 section with the mobile adapter's prerequisites. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Timeline table now shows which repo each phase builds in; dependencies record the OGAD push-access ask (pull-only as of Aug 11, shared has push). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… re-phased timeline From the Clawbot/product-UX research: embedded agent browser (WebContentsView + webContents.debugger CDP, indexed snapshot, per-site cards, takeover with capture-kill) becomes phase 3, ahead of native GUI - zero OS permissions, no new models, shippable cut at Sep 23. Native adapter + vision moves to phase 4, hard targets to phase 5 (ends Oct 27). Direct-reuse list added (UI-TARS sdk/ScreenMarker, nanobrowser, nut-js fork, macos-automator-mcp, bytebot takeover pattern, Peekaboo). Brand guidelines (off-grid-ai/brand + @offgrid/design tokens + docs/DESIGN.md) bound as standing build rules. OpenClaw teardown informs the zero-setup bar and the safety avoid-list. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Phase 0 of computer use. Widens the MCP-only `mcp:proposeApproval` hook into a shared `actions:proposeApproval` seam every executor (MCP today, computer + browser next) can gate through. Adds an ActionRisk taxonomy (read/navigate/mutate/irreversible) with a single shouldGate() source of truth, and per-executor riskOf() classification - a GUI click's risk is not derivable from a tool name the way the old isActionTool regex assumed. Backward compatible: proposeActionApproval prefers the new hook but falls back to the legacy name via hasHook(), so a desktop-pro build that has not yet migrated keeps gating MCP writes instead of silently running them. MCP behaviour is unchanged (read-verb tools -> read, everything else -> mutate), pinned by the existing queue-vs-execute dbtest plus new risk tests. Verified: tsc (node + web), 41 unit tests, 7 dbtest, eslint clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Phase 0 packaging groundwork. Adds the Info.plist usage-description keys the semantic action rail needs — Apple Events (Messages/Mail/Notes), Calendars (+ pre-14 legacy key), Reminders, Contacts, Photos — so a hardened-runtime build is granted each capability instead of being refused before the OS prompt. The apple-events entitlement was already present. Copy follows off-grid-ai/brand: outcome first, privacy as proof, no em dashes. A source-reading test pins every key + the entitlement and enforces the no-em-dash rule on the strings added here. Verified: 8 new tests, YAML parses, config-reading tests green, eslint clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Phase 1 semantic rail, first slice. Adds the single seam every native
capability goes through: a Swift one-shot helper (scripts/actions-helper)
that takes one JSON command, performs a scoped EventKit action, and prints
one JSON line; and a Node invoker (runNativeAction) that resolves the
binary packaged-vs-dev like ocr.ts and parses the reply. Handled failures
(denied permission, bad args) are in-band { ok: false } results, never
throws, so the tool loop has one shape to report.
Backend covers calendar create + list to start; the switch and command
namespacing leave reminders/contacts/photos as additive cases. Pure logic
(contract, path resolution, response parsing) is split into
native-helper-logic.ts and unit tested; the Swift compiles clean under
swiftc 6.2 targeting macos13. Not yet wired to a tool or shipped in CI -
that lands with the tool that calls it, so no dead binary ships early.
Verified: tsc node, 11 logic tests, swiftc build, eslint clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Phase 1 semantic rail, made reachable. Registers a native-action tool extension (macOS-only) exposing calendar_create_event and calendar_list_events to the model; create is a mutate that offers itself to the shared approval seam (queues in pro, runs in the free build), list is a read that runs directly. Both route through runNativeAction to the EventKit helper. Adds 'native' to ActionKind so the approval UI and audit can label semantic OS actions apart from GUI computer use. The release workflow now builds + stages the helper into resources/bin, so a packaged build ships it (self-contained; if it fails the tools report 'not available' and nothing else breaks). Boundary injection mirrors the MCP extension, so the gate-then-run contract is unit tested end to end without a real EventKit call. Verified: tsc node, 90 tests across actions+tools+hooks, release.yml parses, eslint clean on new files. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
reminders_create (mutate, gated) and reminders_list (read) alongside the calendar tools, via EventKit reminder access in the helper. Extracts a shared formatCreated() so each create tool reuses one confirmation shape instead of re-encoding it. Verified: swiftc build, tsc node, 16 tool tests, eslint clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
contacts_search (read) via the Contacts framework (CNContactStore), returning matching names with phones and emails - the lookup the message and event tools need to resolve a person. Read-only, so it runs without approval. Verified: swiftc build, tsc node, 82 tests across actions+tools, eslint clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
messages_send (iMessage) and mail_send (Mail), both mutates gated through the approval seam - the 'message Ali' half of the rail that composes with contacts_search to resolve a name to a handle. Backed by AppleScript via NSAppleScript in the helper; user-supplied values are escaped before interpolation so a quote or backslash cannot break the script or inject statements. Uses the apple-events entitlement + NSAppleEventsUsageDescription already staged in phase 0. Verified: swiftc build, tsc node, 19 tool tests (incl. a messages_send gating case), eslint clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
open_url opens a web page, mailto: draft, or app scheme (whatsapp://send) via NSWorkspace - the navigate that starts the WhatsApp path and the first use of the non-gating navigate risk class (it opens, it does not submit, so no approval). Verified: swiftc build, tsc node, 85 tests across actions+tools, eslint clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
build-mac-local.sh now builds and copies actions-helper into resources/bin alongside the other native helpers, mirroring the release.yml step, so a local packaged build includes the semantic-rail backend (otherwise the calendar/messages/mail tools report 'not available'). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
parseDate now tries full ISO 8601 (with timezone) first, then falls back to the local forms a model commonly emits - 2026-08-13T15:00:00, 2026-08-13T15:00, and 2026-08-13 - interpreted in the user's timezone. Without this a create-event/reminder call from the model would fail whenever it omitted the timezone. Verified: swiftc build; invalid dates still rejected. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts: # electron-builder.yml # src/main/bootstrap/hookRegistry.ts # src/main/index.ts
Supersedes the mobile-use-replication framing. Leads with the product: a proactive, context-grounded local assistant. Two generators (routine: detected + demonstrated; reasoned: commitment + world-knowledge + gap-check) feed one gated spine (resolve slots from memory -> gate shows resolved values -> execute via rails cheapest-first). Rail hierarchy with vision correctly placed last; three-kinds-of-seeing distinction; the demonstration recorder; memory-grounded slot resolution; honest reliability tiers; the moat (knows you + proactive + private + routes to the cheapest reliable rail). Plan re-phased: reasoning engine first (the magic, memory-driven, safe), vision fallback last. Records rail 1 as already built. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Phases 2-6 now run Aug 13-26 (phases 0-1 already done). Reasoning engine Aug 13-16, engine Aug 17-18, recorder+replay Aug 19-22, agent browser Aug 23-24, vision fallback + hard targets Aug 25-26. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Self-contained brief for generating the demo artifacts: the product vision, the inlined brand system (Menlo, emerald-on-black, brutalist, dense), a five-screen day-in-the-life story (assistant home, resolved approval card, flight nudge, record-a-routine, routines library), copy voice, deliverable format, and the anti-patterns to avoid. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Come-ups live in Day (Needs you section, ephemeral rows - never tabs); the gate is inline + the existing Actions queue; Routines is the one new tab; record is a modal from it; away-presence via toast + menu-bar count. Adds the general-engine point (no per-situation verticals - no Flights tab) and Screen 1 now shows a mix of situations (flight + deck + renewal + morning brief) so the generality reads at a glance. Uses the real left-rail nav names. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Surveys who is already doing each piece of the proactive assistant: proactive surfacing (Magic Cue, Pulse, Recall), context resolution (Glean, Shortwave, Copilot), commitment detection (Gmail Nudges, notetakers, MSR speech-act research), routines/teach-by-demo (Automator, Shortcuts, RPA recorders + self-healing), and confirm-before-acting (Operator, Manus, the false-confirmation failure). Three strategic findings: local-first is open whitespace (Rewind/Limitless->Meta, Dot shutdown), context-resolution-with-evidence-before-acting is unshipped (our differentiator), and the GUI-automation reliability ceiling is real (Mariner/ChatGPT-travel killed) - validating cheapest-rail-first. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Folds in the two parent researchers' consolidated syntheses. Routines section gains the academic build blueprint for slot induction + self- healing (Agent Workflow Memory, Alloy, SUGILITE/APPINITE, LUMOS AX-thesis, hierarchical-not-flat, action-effect verification, Morae consequential- step gating, tiered permissions, graduated trust, trycua background AX control). Adds two lessons: detect-completion-and-auto-retire commitments (only a local memory product can, our biggest anti-nag move) and bind the approval card to the exact executing payload (the Alexa+ read-back bug). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ence/confidence card Rewrites the brief from the actual app screenshots so generated artifacts look like Off Grid AI: the real left-rail nav (with Routines added after Actions) and its emerald active state, the real component vocabulary (outlined buttons, pill toggles, status tags, the bottom-CTA-card shape reused for come-ups/toasts), Menlo everywhere, flat + outlined + ~6px radius + dotted-grid, exact dark/light tokens. Corrects the earlier over-literal 'razor-sharp brutalist' framing that made output not look like the app. Screen 2 now shows each resolved slot with its evidence and a confidence tag, plus a low-confidence 'which deck did you mean' disambiguation variant - the screen no competitor ships. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…pen questions The system design from the architecture discussion: the model proposes / durable queue guarantees split, the Action durable record + state machine, the reliability stack that survives a weak local model, the typed action-handler registry + scope map (two reliability tiers), and the one cross-platform core + adapters (mobile included). Section 7 locks the answered decisions (incl. scope and the model-agnostic pipeline); section 8 explains the six open questions for the team - exactly-once per rail, scheduling, trust graduation, mobile v1 target, open-core placement, verification depth - each with options, the decision, and our lean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two layers: the assistant (brain) and the rails (actuation, behind the DeviceController interface). Computer use = the vision rail specifically, not the whole layer. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… adapters) An at-a-glance component diagram: generators -> the assistant (queue, resolver, gate, router, verify) -> DeviceController port -> the rails (semantic, browser, accessibility, vision) -> per-platform impls. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
In the Wednesday TRD + PRD house style: System Architecture as a C4 model (Context L1 + Container L2), a sequence/swimlane by actor for the send-the-deck flow, and the product user flows (Day + Chat entry -> gate -> verify, plus the two ways a routine is born). Mermaid so they render on GitHub / mermaid.live / an artifact. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… box 9) makeUseDriver wraps a better-sqlite3-shaped handle (structural type - the app's better-sqlite3-multiple-ciphers and plain builds both satisfy it) as the engine's async SqlDriver. Pure: no Electron imports, injectable, testable. One DB stays the source of truth - the engine's queue table lives in the SAME database the app owns, not a second store. Five integration tests at the real DB seam (dbtest suite, real SQLite file in a temp dir, fakes only at the true boundaries): migration coexists with app tables, a real action walks end to end with its effect landing in the same DB and read-back verifying it, a scheduled action survives a full engine restart over the same file, a dead worker's lease blocks a second engine until it expires, and dedup holds across engine instances. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… box 10)
Maps the engine's closed Action types onto the Swift helper's verbs:
calendar/reminder/message/email/open to their create-send-open commands,
lookup dispatched by kind (contacts/calendar/reminders) with the
discriminator dropped, and everything else refused before the helper is
invoked - file_share and web_task belong to other rails. Pure module with
the runner injected; the Electron-bound runNativeAction attaches at wiring
time. The executor never throws: a refused mapping, a helper-reported
failure, and a thrown runner all become { ok:false, detail }.
15 tests through the injected boundary: every verb mapping, lookup kinds,
unknown-kind and unknown-type refusals, and the three failure shapes.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…existing seam (R1 box 11) Two contracts meet: the engine's gate AWAITS approve/edit/reject bound to a payload hash; the app's actions:proposeApproval seam is fire-and-queue. The bridge proposes with actionId + actionType + payloadHash on the request, parks the decision in a pending registry, and the approval surface resolves it via resolveActionGate(actionId, decision). Rails map to the card's executor kinds (semantic->native, browser->browser, accessibility/vision-> computer). Free build: nothing listens, mutations keep the unchanged run- now behaviour - and the engine still verifies and journals them. A restart drops the in-memory registry while the Action survives at awaiting_approval in the DB, so the next tick re-offers it - nothing is lost. 8 unit tests through the real hook registry (park/resolve, request contents, decision passthrough, legacy-hook fallback) + 4 integration tests with the real engine on a real DB proving the box's done-when: approve runs exactly the approved payload (hash equality end to end), reject lands rejected with zero device fires, an edit re-binds and the edited payload is what runs, and the free build runs-and-verifies unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…val seam Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ounded retry (R1 box 12) Three layers so a weak local model reliably yields a valid ActionProposal: actionProposalJsonSchema() for llama-server's grammar-constrained response_format with type narrowed to the handlers actually registered (the model cannot propose what this build cannot execute); a SAP-style repair ladder (ported idea from BAML) - raw first, then fence-strip, balanced- object extraction that respects braces inside strings, trailing-comma drop, bare-key quoting - where repairs only ever ADD candidates against the fail- closed schema; and an Instructor-style bounded retry that feeds the validation error back and treats exhaustion as rejection, never a guess. 16 tests: schema narrowing and required/extras, the balanced scanner (prose, braces-in-strings, unclosed), one case per repair branch, unrepairable and engine-owned-field rejections, and the retry loop's three shapes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The chat tool loop's mutating tools (calendar_create_event, reminders_create, messages_send, mail_send) now become durable Actions through @offgrid/use - validated, journaled, executed on the semantic rail, verified - and the tool reports the REAL outcome (done / declined / needs attention / pending). Reads and navigation stay inline (decision 5). A listening pro approval queue keeps the legacy path byte-for-byte, so an unmigrated pro build behaves exactly as today; the engine path activates when no hook listens (free build), which now gets durability and verification for free. Pieces: the gate host gains park signals (whenActionParked + a global onGateParked); the worker races each tick against the park signal so an action waiting on a human never blocks the queue while its outcome still lands when the gate resolves; use-runtime composes the one production engine (app DB driver, semantic rail over runNativeAction, gate host, 24h visibility with releaseAll stale-lease recovery at startup, heartbeat kick for scheduled actions); the tool-to-Action-type map lives once in the logic file. The runtime import is static - the main bundle is one CJS chunk - and the package's CJS entry was verified to load (noble/zod/xstate all dual). 14 new tests (park-aware drain, timeout, single-drain kick; the engine path per outcome, dedup, refusal, pro-active legacy preservation, reads-inline) plus the existing 28 extension tests passing untouched. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…acOS free build Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…tays external accounts The taxonomy the user actually hit: native Mac actions were gated behind the Connectors toggle, which means external service accounts - so a fresh install could never discover that the assistant can act. Now ToolExtension declares a category: 'tool' (the assistant's own on-device abilities) rides every agentic turn; 'connector' (MCP, external accounts) joins only when Connectors is on; an undeclared category fails closed as a connector. The selection rule is one pure function (extension-select.ts), defined once and tested. The composer's Tools toggle defaults ON for fresh installs - acting on this Mac is the product's own capability, approval-gated per action - while a user's saved preference still wins. Decision + R2 follow-up (the cheap-first router retires the per-turn toggle; one master switch in Settings) recorded in the plan; free-build inline-confirm question flagged for the lead in the checklist. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Calendar and reminders now verify by reading the world back after a write: reminders.list checked for the exact title, calendar.listEvents over the event's own range padded a minute each side (missing end defaults to the helper's one-hour rule). Sends stay none_fuzzy and single-attempt behind the gate - no reliable read-back exists for 'did it send', and pretending otherwise is how double-sends happen. Everything fails closed: helper errors, malformed results, and missing args verify false and hand the decision to the retry policy. buildRegistry is now exported with the run boundary injected, so the integration test proves the done-when on the REAL registry the app ships: a clean create verifies in one attempt; a false-ok create (helper claims ok, nothing lands - the classic trust failure) is caught by read-back and retried exactly once to success; a write that never lands exhausts retry-once and asks instead of looping. 9 unit tests on the verifiers + 3 integration tests on the real engine and DB. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…d action (box 15) APP-250: production app end to end - tool loop, text tool-call parsing, the @offgrid/use engine, gate, semantic rail, read-back verification, IPC, MemoryChat - with two fakes at the true boundaries: a scripted llama-server that emits the tool call AS TEXT (the way small local models do) and a scripted actions helper that records creates and answers list read-backs. Proves on a fresh profile with no toggles touched (Tools defaults on): ask -> tool call -> durable Action -> create -> read-back verify -> confirmed in chat, with the helper log pinning exactly one create followed by a list. Screenshot validated: the tool activity row shows the engine's verified outcome. Runs in 5s. Two harness fixes this surfaced: - launchOffGrid strips ELECTRON_RUN_AS_NODE: a runner that itself lives inside Electron (VS Code tasks, agent sandboxes) exports it, and inherited it turns the app under test into plain Node - every spec dies with 'Process failed to launch'. - LaunchOptions.cwd (dev target): the native helper resolves dev candidates relative to the app's cwd, so a spec can plant a scripted helper in a temp dir; the app path arg is now absolute so it survives the cwd override. Note: the free-build flow auto-approves (the approval card is pro's surface), so this evidence covers the engine path; the card capture lands with the pro migration. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…s; Tools default reverts to off Three fixes, one revert - all found by actually running the gate: - vitest.config gates the pro test GLOBS on hasPro, mirroring how the pro thresholds are already gated: this core checkout tracks six orphan pro licensing test files with no implementations beside them (pro/ is not a submodule here), and collecting them failed the suite for anyone without desktop-pro access. - license-gate-smoke strips ELECTRON_RUN_AS_NODE like launchOffGrid now does: a runner living inside Electron exports it and the spawned app dies as plain Node before the gate can be observed. - The composer's + trigger gains aria-label 'Composer options' (it was an unnamed icon button), and APP-250 enables Tools through that real menu. The revert: Tools default returns to OFF. Defaulting it on routed EVERY turn through the agentic pipeline (toolChat), silently switching thinking, image, memory-scope, and project behaviour away from the plain stream - measured as 20 behaviour-test failures, which is the everyday chat experience changing wholesale days before a release. The category fix stands (native actions live under Tools); discoverability is the composer hint (checklist 18b); the real always-available answer is R2's per-turn router. Fast suite: 279 files green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
startModelServer is async (it awaits pickFreePort and listen); two tests called it unawaited and fetched immediately, passing only when the event loop happened to run listen first. On this machine's scheduling the fetch consistently won (ECONNREFUSED in 4ms) and the whole db-suite coverage report was suppressed with it. One word at two call sites; 7/7 green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The gate's own measure drove these: branches 49.7->60.3 (floor 57) and functions 41.8->60.0 (floor 52) on the code this branch adds, with statements/lines at 99.5. - use-runtime.integration.dbtest: the real composition on a real DB with only electron and the native helper mocked - lazy singleton, a reminder end to end through the real worker, waitForOutcome timeout, and the approval-hook probe across both hook names. - use-driver unit: the reader/non-reader routing matrix on a structural fake (the real-SQLite behaviour stays proven in the dbtest suite). - native-helper unit: candidate-miss, first-existing-candidate, the non-zero-exit-with-stdout salvage, and spawn failure - all degrade to reported failures, with electron and child_process mocked at the boundary. - gate-host: park-signal corners (immediate and later whenActionParked, onGateParked subscribe/unsubscribe, pending count + abandon). - extension: the spec-table completeness sweep (every title/buildArgs/ formatResult), schemas + systemHint, and the edited/poisoned/no-detail outcome arms. - emit: escaped quotes inside balanced-object strings; helper-logic: long invalid line truncation; semantic-rail: lookup with no kind; verification: unparseable calendar start never lists. - devices-sync e2e: the pro implementation import loads lazily behind PRO_PRESENT - a static import failed spec collection in a core-only checkout before the guard could skip. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Core carried pro/main/licensing/__tests__ (tests only, no implementations) even though .gitignore already ignores /pro/ - tracked files override the ignore. With desktop-pro access restored and the files verified byte- identical there, core stops tracking them: pro/ is the desktop-pro clone (the submodule-style layout CLAUDE.md describes), fully ignored by core. This is also what made the fast suite collect orphan tests in core-only checkouts; the hasPro glob gate covers anyone without access. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…id/use The first Windows CI run of the engine branch (31778949364) failed its typecheck on 'Cannot find module @offgrid/use' and '@offgrid/sync/portable': windows-build.yml predates the shared adoption and never checked out ../shared at all, and release.yml (both build-mac and build-win) builds only packages/sync - file-dep prepare alone does not emit @offgrid/use's dist types before the typecheck. windows-build now mirrors release.yml's shared checkout (matching-branch ref, main fallback, root ci) and all three shared steps build packages/use alongside packages/sync. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…x 17) Calendar, reminders (tasks), and mail run through LOCAL Outlook COM via PowerShell - the write lands in Outlook's local store and syncs when the network returns, matching the mac EventKit/Mail behaviour instead of failing offline like a cloud API. The scripts print the same one-JSON-line contract the mac helper speaks, so parseHelperResponse is shared. open goes through Electron's shell; message is refused honestly (iMessage is macOS- only). Microsoft Graph is the online-only fallback for setups without local Outlook: the port and fallback logic ship boundary-tested (only consulted when COM says not-registered AND the port reports signed-in); the OAuth wiring is a recorded fast-follow, so production passes no port and the failure names both paths. The runtime picks the rail by platform in exactly one place; a DSP test drives both rails through one dispatch with zero caller changes. 21 tests: script building and quoting (embedded quotes doubled), the COM-unavailable matcher, every mapping and refusal, ordinary-error vs absent-Outlook vs signed-out-Graph vs Graph-failure paths, and the never-throws guarantee. Follow-ups (win tool exposure, Outlook read-back verbs, Graph sign-in) recorded in the checklist. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Run 31779453356: shared checkout resolved at the matching branch, @offgrid/use built, typecheck + bundle passed, NSIS packaged, 414MB installer artifact uploaded. Cert + real-Windows model-load smoke remain recorded release items. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
CI's dependency-boundaries gate caught the circle the category seam introduced: tools.ts imports selectToolExtensions, and extension-select imported ToolExtension back from tools.ts (a type import still counts). The selector only needs the category field, so it now asks for exactly that - a structural CategorizedExtension, generic over the caller's richer type - and imports nothing from tools.ts. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… and routines follow The lead's steer plus R1 field feedback, in the build doc: R1 is done (PRs open); R2 (~5-6 days) ships all four rails chat-driven on both platforms - Windows exposure, the browser rail, the supervised vision rail (UI-TARS- 1.5-7B) - plus Approval UX v2: inline approval cards in chat, outcome feedback everywhere via the pro approval-executor migration to the engine gate, and risk-tiered gating (reversible mutations auto-run with verified confirmation + Undo; sends keep the gate). Notices-you moves to R3, routines to R4. The R1 checklist records the three pro-path UX verdicts that drove the approval rebuild. One versioned release ships after R2. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
ⓘ Qodo reviews are paused because your trial has ended. Ask your workspace admin to add credits to resume reviews. Manage billing |
| ) | ||
| } | ||
|
|
||
| const HOUR_MS = 60 * 60 * 1000 | ||
| const PAD_MS = 60 * 1000 | ||
|
|
There was a problem hiding this comment.
Title-only verification confirms wrong effects
When a requested calendar is unavailable, a due date is invalid, or a same-title item already exists, read-back accepts title equality alone, causing the engine to report completion even though the event is in the wrong calendar, the reminder lacks its due date, or the requested write did not land.
| ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | ||
| SRC="$ROOT_DIR/actions-helper/main.swift" | ||
| OUT="$ROOT_DIR/actions-helper/actions-helper" | ||
| swiftc -O -target arm64-apple-macos13.0 -emit-executable "$SRC" -o "$OUT" |
There was a problem hiding this comment.
| - name: Checkout shared at the matching ref | ||
| id: shared_branch | ||
| continue-on-error: true | ||
| uses: actions/checkout@v4 |
There was a problem hiding this comment.
Mutable action handles build credentials
The new shared-repository checkout uses mutable actions/checkout@v4 while receiving CI_CROSS_REPO_TOKEN, leaving branch packaging credentials and installer output exposed to an upstream tag repoint; pin this step and its fallback to the immutable checkout SHA already used in release.yml.
How this was verified: The changed checkout steps pass CI_CROSS_REPO_TOKEN to actions/checkout@v4, while the equivalent release steps use a full commit SHA.
|



R1 - chat actions on the durable engine
The first release of the assistant's act pillar, built to
docs/COMPUTER_USE_PLAN.md(R1) anddocs/R1_CHECKLIST.md(17/19 boxes; the last two are this PR + the release dispatch). The model only proposes a structured Action; a durable on-device pipeline guarantees it - exactly once, gated, verified. Design:docs/ASSISTANT_ARCHITECTURE.md. Port decisions:docs/PORTING_MAP.md.What ships
macOS (the headline): ask in chat and it acts - reminders, calendar events, iMessage, mail, open URLs/app schemes, plus instant reads (calendar/reminders/contacts). Every mutation flows propose -> durable queue -> gate -> semantic rail -> verify. Calendar and reminders are read-back verified ("done" means we checked the app and it is there); sends are single-attempt behind the gate (a wrong verify can never double-send).
Windows: the full app builds and packages green (run 31779453356, 414MB NSIS artifact). The Windows semantic rail (local Outlook COM - writes land locally and sync, matching the mac approach; Graph as a boundary-tested online fallback port) ships behind the DeviceController port; chat exposure on Windows is a recorded fast-follow, as is the signing cert.
The engine (
@offgrid/use, in shared - companion PR): the durable queue (leases, visibility timeout, idempotency dedup, scheduling), the Action lifecycle state machine with crash-resume snapshots, the retry policy (retry-once-with-verify; irreversible/fuzzy never re-fire), the payload-hash-bound gate (approve = byte-for-byte what runs; edits re-bind and re-gate), the DeviceController port + handler registry (fail-closed registration), and the write-ahead effect journal that makes kill-mid-execute safe.The guarantees, each a passing test
use-storage.integration.dbteston the real app DBgate-host.integration.dbtestverification.integration.dbteston the shipped registrye2e/app250-chat-action-engine.spec.ts(5s, production code with fakes only at the model + OS boundaries)Evidence
e2e/screenshots/r1-chat-action-verified.png- the ask, the tool activity rowreminders_create -> Created the reminder., and the confirmation, on a fresh free profile.Test output
Also in this branch
ELECTRON_RUN_AS_NODEstripped at both Electron-spawn seams; a startModelServer await race fixed; pro test files untracked from core (they live in desktop-pro, verified identical).windows-build.ymlgained the shared checkout; both workflows now build@offgrid/usealongside sync (the release would have failed without this).Release items (recorded, not gates)
Windows signing cert - Windows chat-tool exposure - Outlook read-back verbs - Graph sign-in - the composer hint - pro approval-executor migration to
resolveActionGate(desktop-pro, unblocked now).🤖 Generated with Claude Code
Greptile Summary
The PR adds macOS chat actions backed by a durable action engine, native semantic rails, approval gating, and read-back verification, while adding Windows rail and build infrastructure.
Confidence Score: 3/5
The PR should not merge until semantic verification checks requested fields and the native helper is built for every supported macOS architecture.
Title-only read-back can report incorrectly created actions as complete, and the fixed-arm64 helper cannot execute inside the x64 local application path; the mutable workflow dependency is an additional non-blocking supply-chain concern.
Files Needing Attention: src/main/actions/verification.ts, scripts/actions-helper/main.swift, scripts/build-actions-helper.sh, .github/workflows/windows-build.yml
Security Review
The new Windows shared-checkout steps use mutable action tags while receiving a cross-repository token. Pin them to the same immutable checkout SHA used by the release workflow. How this was verified: The changed steps use
actions/checkout@v4withCI_CROSS_REPO_TOKEN, while their release-workflow counterparts use a full commit SHA.Important Files Changed
Sequence Diagram
Reviews (1): Last reviewed commit: "docs(plan): the re-cut - R2 is full rail..." | Re-trigger Greptile