feat: Focus Flow task bridge — push expiry alerts as external tasks #156

Open
opened 2026-07-05 19:24:44 -07:00 by pyr0ball · 0 comments
Owner

Context

Design spec: circuitforge-plans/shared/superpowers/specs/2026-07-05-focus-flow-task-bridge-design.md. Companion tickets: Circuit-Forge/circuitforge-core#66 (shared schema), Circuit-Forge/focus-flow#5 (importer side, external AGPL-3.0 project by Ashley Venn).

Kiwi is the pilot product for pushing tasks into Focus Flow, an ADHD-first scheduler, so pantry expiry alerts show up as calm backlog tasks instead of only living in Kiwi's own UI.

Scope

Free tier feature, gated by new focus_flow_bridge key in KIWI_FEATURES (app/tiers.py) at "free". No LLM (large language model) call, no cloud, no cf-orch involvement, opt-in default off.

New app/services/focus_flow/:

  • exporter.py — diffs current expiry alerts against last-pushed state, builds ExternalTask records via circuitforge_core.task_bridge, pushes to the configured local Focus Flow endpoint. Runs from the existing expiry-alert background task, not on every pantry mutation.
  • callback.py — receives {external_id, status, completed_at} from Focus Flow. On "completed", calls the existing partial_consume_item(item_id, full_qty, consumed_at) (status -> consumed, row not deleted, reversible). On "cancelled", no-op.

New settings keys (extend _ALLOWED_KEYS in app/api/endpoints/settings.py): focus_flow_enabled (bool, default false), focus_flow_endpoint (str), focus_flow_token (str). Manual one-time setup, no auto-discovery, matches Kiwi's existing settings pattern.

New endpoints:

  • POST /integrations/focus-flow/test-connection — validate endpoint + token before saving
  • POST /integrations/focus-flow/callback — receiver described above

Settings toggle needs plain-language consent text: "Send pantry expiry reminders to Focus Flow on this computer. Nothing leaves your machine." Everything is 127.0.0.1 to 127.0.0.1, no CF server touches this data, Kiwi Cloud is out of scope for this ticket.

Open question flagged in the design doc

Completion in Focus Flow marks the pantry item consumed via the existing (non-destructive, status-only) partial_consume_item call. If a user completes the Focus Flow task without actually using the item, Kiwi's inventory will read as consumed when it is not. Worth surfacing in the consent copy rather than silently assuming.

Testing

Unit tests for exporter.py (diff logic, idempotent external_id generation) and callback.py (unknown external_id does not throw), httpx mocked at the boundary. Contract test against a fake local HTTP server standing in for Focus Flow's import API.

Dependency

Blocked on Circuit-Forge/circuitforge-core#66 landing and an editable-install refresh.

## Context Design spec: `circuitforge-plans/shared/superpowers/specs/2026-07-05-focus-flow-task-bridge-design.md`. Companion tickets: `Circuit-Forge/circuitforge-core#66` (shared schema), `Circuit-Forge/focus-flow#5` (importer side, external AGPL-3.0 project by Ashley Venn). Kiwi is the pilot product for pushing tasks into Focus Flow, an ADHD-first scheduler, so pantry expiry alerts show up as calm backlog tasks instead of only living in Kiwi's own UI. ## Scope Free tier feature, gated by new `focus_flow_bridge` key in `KIWI_FEATURES` (`app/tiers.py`) at `"free"`. No LLM (large language model) call, no cloud, no cf-orch involvement, opt-in default off. New `app/services/focus_flow/`: - `exporter.py` — diffs current expiry alerts against last-pushed state, builds `ExternalTask` records via `circuitforge_core.task_bridge`, pushes to the configured local Focus Flow endpoint. Runs from the existing expiry-alert background task, not on every pantry mutation. - `callback.py` — receives `{external_id, status, completed_at}` from Focus Flow. On `"completed"`, calls the existing `partial_consume_item(item_id, full_qty, consumed_at)` (status -> `consumed`, row not deleted, reversible). On `"cancelled"`, no-op. New settings keys (extend `_ALLOWED_KEYS` in `app/api/endpoints/settings.py`): `focus_flow_enabled` (bool, default false), `focus_flow_endpoint` (str), `focus_flow_token` (str). Manual one-time setup, no auto-discovery, matches Kiwi's existing settings pattern. New endpoints: - `POST /integrations/focus-flow/test-connection` — validate endpoint + token before saving - `POST /integrations/focus-flow/callback` — receiver described above ## Consent copy Settings toggle needs plain-language consent text: "Send pantry expiry reminders to Focus Flow on this computer. Nothing leaves your machine." Everything is `127.0.0.1` to `127.0.0.1`, no CF server touches this data, Kiwi Cloud is out of scope for this ticket. ## Open question flagged in the design doc Completion in Focus Flow marks the pantry item consumed via the existing (non-destructive, status-only) `partial_consume_item` call. If a user completes the Focus Flow task without actually using the item, Kiwi's inventory will read as consumed when it is not. Worth surfacing in the consent copy rather than silently assuming. ## Testing Unit tests for `exporter.py` (diff logic, idempotent `external_id` generation) and `callback.py` (unknown `external_id` does not throw), `httpx` mocked at the boundary. Contract test against a fake local HTTP server standing in for Focus Flow's import API. ## Dependency Blocked on `Circuit-Forge/circuitforge-core#66` landing and an editable-install refresh.
pyr0ball added the
enhancement
label 2026-07-05 19:24:44 -07:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: Circuit-Forge/kiwi#156
No description provided.