docs: add ADR-0060 and ADR-0061 for network-aware UI gating and AI prompt bridge (guard — from commits 739e1b3, 7933fe1)
This commit is contained in:
28
docs/adr/0060-network-aware-ui-gating-for-remote-features.md
Normal file
28
docs/adr/0060-network-aware-ui-gating-for-remote-features.md
Normal file
@@ -0,0 +1,28 @@
|
||||
---
|
||||
type: ADR
|
||||
id: "0060"
|
||||
title: "Network-aware UI gating for remote-dependent features"
|
||||
status: active
|
||||
date: 2026-04-13
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
Some app features require an active internet connection (e.g., cloning the Getting Started vault template from GitHub). Prior to this decision, the UI would attempt the operation and surface a generic error only after failure. Users on first launch in offline environments got a confusing error when trying to use the template.
|
||||
|
||||
## Decision
|
||||
|
||||
**Introduce a `useNetworkStatus` hook that tracks `navigator.onLine` via `online`/`offline` DOM events, and use it to proactively gate UI surfaces that require a network.** Features that depend on remote access (clone, sync) show an explanatory message and disable their action button when the device is offline, rather than failing silently at execution time.
|
||||
|
||||
## Options considered
|
||||
|
||||
- **Option A** (chosen): `useNetworkStatus` hook + proactive UI disable — disables the action before the user tries it, with inline copy explaining the offline state.
|
||||
- **Option B**: Attempt and catch — let the operation run and surface the error in a toast. Simpler, but poor UX for first-launch users who don't know what went wrong.
|
||||
- **Option C**: Check connectivity with a ping on demand — more accurate but adds latency and complexity; `navigator.onLine` is sufficient for the use case.
|
||||
|
||||
## Consequences
|
||||
|
||||
- Positive: cleaner first-run experience for offline users; no misleading error messages.
|
||||
- Positive: `useNetworkStatus` is a reusable hook for future remote-gated features.
|
||||
- Negative: `navigator.onLine` can return `true` on a captive-portal / no-internet network — the hook reflects OS-level connectivity, not end-to-end reachability. The operation may still fail with a network error, which must still be handled.
|
||||
- Re-evaluate if the app adds more remote features that need finer-grained reachability checks.
|
||||
29
docs/adr/0061-ai-prompt-bridge-event-bus.md
Normal file
29
docs/adr/0061-ai-prompt-bridge-event-bus.md
Normal file
@@ -0,0 +1,29 @@
|
||||
---
|
||||
type: ADR
|
||||
id: "0061"
|
||||
title: "AI prompt bridge — module-level event bus for cross-component prompt routing"
|
||||
status: active
|
||||
date: 2026-04-13
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
The AI panel is a sibling subtree to the command palette in the component tree. When the user submits a prompt from the command palette's AI mode, the AI panel (mounted elsewhere) needs to receive it and start processing. Props-down / callbacks-up wiring between the two would require threading state through multiple layers of unrelated components.
|
||||
|
||||
## Decision
|
||||
|
||||
**Introduce `aiPromptBridge.ts` as a module-level singleton event bus.** The bridge exposes `queueAiPrompt(text, references)` (write path) and `takeQueuedAiPrompt()` (consume path), backed by a module variable and a `CustomEvent` on `window` (`tolaria:ai-prompt-queued`). The command palette enqueues a prompt; the AI panel listens for the event, consumes the prompt via `takeQueuedAiPrompt`, and dispatches it to the agent. A companion `requestOpenAiChat()` function fires a separate `tolaria:open-ai-chat` event to open the panel before the prompt is sent.
|
||||
|
||||
## Options considered
|
||||
|
||||
- **Option A** (chosen): module-level singleton + `window` events — zero dependencies, no new global state manager, consistent with the existing `window.dispatchEvent` pattern already used for menu-command bridging.
|
||||
- **Option B**: Lift AI panel state to a shared ancestor (e.g., `App.tsx`) and pass `onPrompt` callback down — would require `App.tsx` to own AI agent state, bloating it further; conflicts with ADR-0026 (props-down principle).
|
||||
- **Option C**: Zustand / Jotai global store atom — adds a dependency and architecture overhead for a narrow, two-participant channel.
|
||||
|
||||
## Consequences
|
||||
|
||||
- Positive: decouples command palette from AI panel with no shared ancestor coupling.
|
||||
- Positive: any future surface (e.g., wikilink context menu, note action bar) can call `queueAiPrompt` without tree-level wiring.
|
||||
- Negative: module-level mutable state is harder to test in isolation; tests must call `takeQueuedAiPrompt` to drain state between runs.
|
||||
- Negative: the event is fire-and-forget — if the AI panel is not mounted when the event fires, the prompt is silently dropped (currently not an issue as the panel is always mounted).
|
||||
- Re-evaluate if the number of AI entry points grows large enough to warrant a proper state management solution.
|
||||
@@ -115,3 +115,5 @@ proposed → active → superseded
|
||||
| [0057](0057-alpha-stable-release-channels-and-beta-cohorts.md) | Alpha/stable release channels with PostHog beta cohorts | active |
|
||||
| [0058](0058-claude-code-first-launch-onboarding-gate.md) | Claude Code first-launch onboarding gate | active |
|
||||
| [0059](0059-local-only-git-commits-without-remote.md) | Local-only git commits for vaults without a remote | active |
|
||||
| [0060](0060-network-aware-ui-gating-for-remote-features.md) | Network-aware UI gating for remote-dependent features | active |
|
||||
| [0061](0061-ai-prompt-bridge-event-bus.md) | AI prompt bridge — module-level event bus for cross-component prompt routing | active |
|
||||
|
||||
Reference in New Issue
Block a user