docs(13): capture phase context
This commit is contained in:
+319
@@ -0,0 +1,319 @@
|
||||
# Phase 13: AIUI — Conversational Node Control & Content Surfaces - Context
|
||||
|
||||
**Gathered:** 2026-08-03
|
||||
**Status:** Ready for planning
|
||||
|
||||
<domain>
|
||||
## Phase Boundary
|
||||
|
||||
Make the embedded AIUI functional in three directions: (1) **human-language node control** —
|
||||
a typed request in AIUI chat reaches a real node action and returns a real result;
|
||||
(2) **conversational settings** — system settings reachable by conversation, scoped to what
|
||||
the user granted; (3) **content surfaces made real** — peer files, music, IndeeHub movies and
|
||||
owned/paid content rendered live in the design AIUI already has. All of it inside a
|
||||
**user-granted capability sandbox** that keeps keys, secrets and identity material away from
|
||||
both the browser and the model.
|
||||
|
||||
**Not in scope:** cross-node content distribution with payments (the "archipelago content
|
||||
source"); wallet spends, seed/key operations, federation trust changes and factory reset as
|
||||
chat-reachable actions; Nostr integration polish; reviving the dead `ContentPanel.vue`
|
||||
architecture.
|
||||
|
||||
</domain>
|
||||
|
||||
<decisions>
|
||||
## Implementation Decisions
|
||||
|
||||
### Where the agent loop lives
|
||||
|
||||
- **D-01:** The agent loop (model call → tool call → result → model) runs **node-side in
|
||||
Rust**. The `archipelago` binary owns the loop, the tool registry, and the model key. AIUI
|
||||
becomes a thin chat client. Rationale: the key never reaches the browser; tool authorization
|
||||
sits where session auth already lives; Pine/voice can reuse the same tools later.
|
||||
— **Reversibility:** costly — the RPC surface becomes a contract AIUI, and later the voice
|
||||
pipeline, are written against; moving the loop browser-side afterwards means re-homing key
|
||||
handling and re-implementing every tool in TypeScript.
|
||||
|
||||
- **D-02:** **One assistant, many front doors.** Extend the existing mesh assistant into a
|
||||
shared service: one tool registry, one backend selector, one place keys live. Mesh/LoRa,
|
||||
AIUI chat and (later) Pine voice are callers distinguished by permission scope. Avoids two
|
||||
divergent security models. Note the existing peer-facing controls — `trusted_only`,
|
||||
`allowed_contacts`, `denied_askers` — are a per-caller scope mechanism that already exists.
|
||||
|
||||
- **D-03:** **Split by nature.** The node-side registry owns everything that reads or changes
|
||||
the node (system, bitcoin, network, wallet, files, media). The existing `ContextBroker`
|
||||
keeps only what must run in the browser — `navigate`, `open-app`, `launch-app`, `theme` —
|
||||
and remains the consent surface pushing `permissions:update`. Nothing is discarded; each
|
||||
side owns what only it can do.
|
||||
|
||||
- **D-08:** Chat history lives **node-side in the per-node data dir** (`/var/lib/archipelago`),
|
||||
inheriting the node's backup, factory-reset and future LUKS story rather than growing a
|
||||
second sensitive-data location.
|
||||
|
||||
### Model backends
|
||||
|
||||
- **D-04:** Backend chain is **local Ollama first, with Claude *and* Routstr as fallbacks**.
|
||||
Node data never leaves the node when a local model is available. The assistant already
|
||||
reports `ollama_detected` / `claude_available`, so the selection signals exist.
|
||||
**Routstr (<https://github.com/routstr>) is explicitly in scope at the user's request** —
|
||||
it is an OpenAI-compatible endpoint paid per request in Cashu ecash, with providers, models
|
||||
and prices discovered over Nostr. All three of those substrates already exist in this
|
||||
codebase (`core/archipelago/src/streaming/` holds Cashu token handling and the
|
||||
`list-mints`/`configure-mints` RPCs; Nostr discovery is ADR-003/ADR-006).
|
||||
|
||||
- **D-05:** Routstr spending is authorized by a **prepaid budget the user sets**. Inference
|
||||
spends silently within the allowance, then stops and asks. The ceiling is hard — a
|
||||
prompt-injected model cannot exceed it.
|
||||
— **Reversibility:** reversible — the ceiling is a config value, not a contract.
|
||||
|
||||
- **D-07:** The **local model does get tools**, and every write needs confirmation regardless
|
||||
of backend. A mis-called tool from a weak local model surfaces as a confirmation prompt the
|
||||
user rejects, not a wrong action. Consequence: the confirm gate does the safety work, so
|
||||
**backend choice stays a privacy decision rather than a safety one**.
|
||||
|
||||
### Authority and sandboxing
|
||||
|
||||
- **D-06:** Tools are a **curated allowlist of hand-written tools** — each with its own
|
||||
schema, permission category, and destructive/confirm flag. The model never sees the full RPC
|
||||
surface. No auto-generation from the dispatcher: every capability the chat has must be a
|
||||
decision someone made, which is the only way the sandbox claim stays true.
|
||||
— **Reversibility:** reversible — adding tools later is additive; the allowlist is the point.
|
||||
|
||||
- **D-09:** First-cut authority is **reads within granted categories + app lifecycle
|
||||
(start/stop/restart) + settings writes**. Explicitly excluded from chat reach: keys, seeds,
|
||||
wallet spends, federation trust, factory reset. Those stay UI-only.
|
||||
— **Reversibility:** costly — widening later is safe, but any capability shipped and then
|
||||
withdrawn breaks a behaviour users will have learned.
|
||||
|
||||
- **D-10:** **Tool authority never derives from content.** Peer-supplied text (file names,
|
||||
content descriptions, mesh chat, Nostr posts) enters the context inside explicit
|
||||
untrusted-content delimiters that mark it as data, not instructions. The tool layer takes
|
||||
its permissions solely from the user's grants and the confirm gate. An injected "now restart
|
||||
bitcoin" still has to clear a human confirmation naming the real action. Pattern-stripping
|
||||
filters were considered and **rejected** as an arms race that reads as a guarantee it isn't.
|
||||
|
||||
- **D-11:** Write confirmations render **in neode-ui's trusted chrome, outside the iframe**,
|
||||
drawn by the host from the node's own description of the pending action — never by AIUI and
|
||||
never from model-authored text. The iframe cannot spoof, restyle or pre-click it. Uses the
|
||||
project's mandated Teleport-to-body modal pattern.
|
||||
— **Reversibility:** costly — this is the load-bearing anti-spoofing property; moving the
|
||||
dialog inside the iframe later would invalidate the threat model, not just the styling.
|
||||
|
||||
- **D-16:** All 10 permission categories (`apps`, `system`, `network`, `wallet`, `files`,
|
||||
`media`, `search`, `ai-local`, `notes`, `bitcoin`) **default closed** on a fresh node.
|
||||
Nothing is shared with the model until deliberately granted. The assistant looks
|
||||
unconfigured until the user opens categories — accepted cost.
|
||||
|
||||
- **Hard constraint from Phase 10:** the `UNAUTHENTICATED_METHODS` hard-refuse gates and the
|
||||
loopback/auth boundaries must hold with AIUI on the other side of them. They are not to be
|
||||
widened to accommodate this phase. See `10-CONTEXT.md` D-01..D-04.
|
||||
|
||||
### Content surfaces
|
||||
|
||||
- **D-12:** **Feed the existing grids from Archy, replacing the LLM-synth source.** AIUI's
|
||||
design is kept exactly — `FilmGrid`, `SongGrid`, `NewsGrid`, the detail views — and what
|
||||
fills them changes: peer files, IndeeHub movies, owned/paid content and node media arrive as
|
||||
real records instead of being regex-scraped out of model prose.
|
||||
— **Reversibility:** reversible — the grids are prop-driven; the data source behind them is
|
||||
swappable.
|
||||
|
||||
- **D-13:** **Build a real music library** — albums, artists, tracks, tag/metadata extraction,
|
||||
an index that stays fresh. The user chose this over the narrower MIME-filtered-files option
|
||||
after being told no library domain exists today. It lands as **its own wave of plans inside
|
||||
Phase 13, not blocking the rest** — peer files, movies and conversational control ship on
|
||||
their own track and the library lights up `SongGrid` when ready.
|
||||
— **Reversibility:** one-way — an album/artist/track schema and its on-disk index become a
|
||||
persisted data model with a migration cost once nodes have indexed libraries; changing the
|
||||
entity model afterwards needs a reindex path, not just a code change.
|
||||
|
||||
- **D-14:** **IndeeHub and peer video are surfaced through the content + paid-unlock
|
||||
subsystem that already exists** (invoices, `X-Payment-Token`, Range streaming). No new
|
||||
payment rail. The cross-node "archipelago content source" from the Phase 2 note is deferred
|
||||
— it is a distribution and payments feature spanning federation, not an AIUI surface.
|
||||
|
||||
### Delivery and the two-repo split
|
||||
|
||||
- **D-15:** AIUI is **built and shipped with the frontend, versioned and verified** — the
|
||||
rsync path is kept because it is the one that works, but made deliberate: AIUI's commit
|
||||
pinned in this repo, `VITE_BASE_PATH=/aiui/` enforced by the build script rather than
|
||||
remembered, and a post-deploy check that **fetches a live asset** instead of trusting a
|
||||
directory listing. Making AIUI a signed-catalog app was considered and rejected for this
|
||||
phase: `*-ui` apps are outside the catalog by design today, and changing that platform rule
|
||||
mid-phase is its own work.
|
||||
|
||||
- **D-17:** AIUI **keeps its standalone mode**; embedded mode delegates to the node. It goes
|
||||
on working on its own with its own proxy for development and for anyone running it outside a
|
||||
node; when `embedded=true` it hands the loop, the tools and the key to Archy. The dev loop
|
||||
stays fast — no node required to work on the UI.
|
||||
|
||||
- **D-18:** **Push access to the AIUI repo is confirmed before planning starts**, treated as a
|
||||
prerequisite rather than discovered mid-plan. Last time this surfaced at execution and left
|
||||
neode-ui shipping two query params that were inert no-ops against every deployed AIUI build
|
||||
until a maintainer merged (see `.planning/WINDOWS.md` window 4).
|
||||
|
||||
### Claude's Discretion
|
||||
|
||||
- What the music library indexes over (own filebrowser `Music` folder, peer audio, or both),
|
||||
the tag-extraction library, and where the index lives — within D-13's bounds.
|
||||
- Streaming/token delivery for chat responses; context-window budgeting over node data.
|
||||
- Which specific tools make the first curated allowlist, within D-09's authority ceiling.
|
||||
- Routstr provider selection strategy among Nostr-advertised providers.
|
||||
- Per-category mapping of the 10 permission categories onto individual tools.
|
||||
|
||||
</decisions>
|
||||
|
||||
<canonical_refs>
|
||||
## Canonical References
|
||||
|
||||
**Downstream agents MUST read these before planning or implementing.**
|
||||
|
||||
### The existing AIUI bridge (this is NOT greenfield — read before designing anything)
|
||||
- `neode-ui/src/types/aiui-protocol.ts` — protocol v1.0.0, `aiui:` message prefix, the
|
||||
request/response contract. Defines `AIContextCategory` (10 categories) and `AIActionType`
|
||||
(`install-app | open-app | navigate | launch-app | search-web | read-file | tail-logs`).
|
||||
- `neode-ui/src/stores/aiPermissions.ts` — the 10 user-toggled permission categories with
|
||||
labels; `isEnabled` / `toggle`.
|
||||
- `neode-ui/src/services/contextBroker.ts` — the 624-line origin-scoped postMessage broker
|
||||
that "checks permissions, fetches data from Pinia stores, sanitizes it (strips sensitive
|
||||
fields), and responds". The asset D-03 splits.
|
||||
- `neode-ui/src/services/__tests__/contextBroker.test.ts`, `neode-ui/src/views/__tests__/chatAiuiEmbed.test.ts` — existing coverage to keep green.
|
||||
- `neode-ui/src/views/Chat.vue` — the iframe embed, `aiuiUrl` construction, origin check, the
|
||||
`ready` handshake, `allow="microphone"`.
|
||||
|
||||
### The existing node-side assistant (the thing D-02 extends)
|
||||
- `core/archipelago/src/api/rpc/mesh/assistant.rs` — `mesh.assistant-status` /
|
||||
`mesh.assistant-configure`; reports `ollama_detected`, `claude_available`, `models`,
|
||||
`trusted_only`, `allowed_contacts`, `denied_askers`; key at `data_dir/secrets/claude-api-key`.
|
||||
- `core/archipelago/src/mesh/listener/assist.rs` — `run_assist`, `is_sender_allowed`,
|
||||
`call_ollama`, `call_claude`, `cap_reply`. **Q&A only — no tool-calling today.**
|
||||
- `core/archipelago/src/api/rpc/dispatcher.rs` — the method registry (`mesh.assistant-*` at
|
||||
~445). **Confirmed: there are no `pine.*` methods** — Pine has no RPC surface.
|
||||
|
||||
### Routstr (new integration, user-requested)
|
||||
- <https://github.com/routstr> — org; `routstr-core`, `routstrd`, `routstr-sdk`, `routstr-chat`.
|
||||
- <https://docs.routstr.com/> — protocol docs.
|
||||
- `core/archipelago/src/streaming/` — existing Cashu handling (`gate.rs` verifies/receives
|
||||
tokens, `pricing.rs`, `session.rs`) and the `streaming.list-mints` / `.configure-mints` RPCs.
|
||||
Note: currently `#![allow(dead_code)]`, "suppress dead_code until callers land".
|
||||
|
||||
### Content subsystem (what D-12/D-14 wire the grids to)
|
||||
- `core/archipelago/src/content_server.rs` — `ContentItem` shape (`id`, `filename`,
|
||||
`mime_type`, `size_bytes`, `description`, `access`, `availability`, `added_at`),
|
||||
`AccessControl` (`Free | PeersOnly | Paid`), `parse_range_header`, the paid-preview logic
|
||||
and the ISOBMFF faststart check.
|
||||
- `core/archipelago/src/api/handler/content.rs` — `GET /content`, `/content/<id>`,
|
||||
`/preview`, `/invoice`; Range → 206 with `Content-Range`; 402 body with `price_sats`.
|
||||
- `core/archipelago/src/api/handler/proxy.rs:188-265` — the peer Range-streaming proxy
|
||||
(`/api/peer-content/<onion>/<id>`). Its docstring explains why base64 blobs broke seeking.
|
||||
- `core/archipelago/src/api/rpc/content.rs` — the `content.*` RPCs including
|
||||
`browse-peer`, `download-peer*`, `preview-peer`; auto-filing by MIME at ~668.
|
||||
- `neode-ui/src/composables/useAudioPlayer.ts`, `neode-ui/src/components/GlobalAudioPlayer.vue`
|
||||
— the singleton bottom-bar player. **Audio never opens the lightbox** — enforced in 5 places.
|
||||
- `neode-ui/src/api/filebrowser-client.ts` — the scoped-token pattern (`app.filebrowser-token`)
|
||||
that D-01 follows. **Known leak to fix rather than propagate:** `streamUrl` puts the JWT in
|
||||
the URL query string.
|
||||
|
||||
### Prior phase context (locked decisions that constrain this phase)
|
||||
- `.planning/phases/10-key-material-hardening/10-CONTEXT.md` — D-01..D-04, the
|
||||
`UNAUTHENTICATED_METHODS` hard-refuse gates. **Must not be widened.**
|
||||
- `.planning/phases/02-ui-performance/02-CONTEXT.md` — D-14 (the shipped AIUI embed defaults)
|
||||
and the Deferred Ideas block, which is the origin of this phase.
|
||||
- `.planning/phases/02-ui-performance/02-AIUI-D14.md` — the embed parameter contract, AIUI's
|
||||
repo location and branch, and the push-access history.
|
||||
- `.planning/WINDOWS.md` window 4 — the 403 that made D-18 a prerequisite.
|
||||
|
||||
### Project invariants
|
||||
- `CLAUDE.md` — commit/push discipline, rootless-Podman invariant, the frontend-build verify
|
||||
rule (grep the built bundle), "verify on the real node before any tag".
|
||||
- `.planning/PROJECT.md` — ADR-003 (Nostr discovery), ADR-006 (DID-signed, trust tiers),
|
||||
ADR-008 (dual keys from one seed), ADR-009 (container security).
|
||||
|
||||
</canonical_refs>
|
||||
|
||||
<code_context>
|
||||
## Existing Code Insights
|
||||
|
||||
### Reusable Assets
|
||||
- **The permission + consent layer already exists** — 10 categories, a store, a broker that
|
||||
sanitizes, and tests. This phase extends it rather than inventing it.
|
||||
- **The assistant already abstracts two model backends** and already holds a key server-side
|
||||
at `data_dir/secrets/claude-api-key` — the pattern D-01 generalizes.
|
||||
- **Cashu, Nostr and Lightning are all already in-tree**, which is why Routstr is a smaller
|
||||
lift here than it would be elsewhere.
|
||||
- **Range-streaming media delivery is solved** — both own files (filebrowser `/api/raw`) and
|
||||
peer files (the Rust proxy). The grids need data, not a transport.
|
||||
|
||||
### Established Patterns
|
||||
- Audio belongs to the global bottom-bar player, never the lightbox (enforced in 5 call sites).
|
||||
- Modals Teleport to body for a full-screen backdrop (project rule, repeatedly reinforced).
|
||||
- Scoped tokens minted by an authenticated RPC, credentials never reaching the browser.
|
||||
|
||||
### Integration Points
|
||||
- `dispatcher.rs` — where new assistant/tool RPCs register.
|
||||
- `ContextBroker.handleMessage` — where the browser-only action split (D-03) lands.
|
||||
- `ChatPage.vue` → `ContentGridView.vue` → the `*Grid` components — the live render tree the
|
||||
Archy data must reach (**note `ContentPanel.vue` is dead; do not build through it**).
|
||||
|
||||
### Landmines found during scouting (verified, not assumed)
|
||||
- **AIUI's grids are fed by regex-parsing the model's own reply text** (`updatePanelFromText`
|
||||
→ `contentExtraction.ts`), resolving IDs against fixture catalogs that are themselves
|
||||
injected into the system prompt (`useAI.ts:24-34`). The largest data bucket is
|
||||
LLM-synthesized, not an API awaiting a base URL.
|
||||
- **Every "real" data path in AIUI is Vite dev middleware** — all six plugins are
|
||||
`configureServer`/`configurePreviewServer` only, so they are **absent from a static `dist/`
|
||||
deploy**. On a node, TMDB posters, web search, RSS and filesystem all 404.
|
||||
- **`vite-fs.ts:7` hardcodes `PROJECTS_ROOT = '/Users/dorian/Projects'`** — broken on any
|
||||
other machine, including the Linux dev box.
|
||||
- **`ContentPanel.vue` is dead code**, taking `ArchyAppsGrid` (the Archy bridge grid),
|
||||
`FavoritesGrid`, `DiscoverPanel`, `RecipeDetail` and `AppDetail` with it. Clicking a recipe
|
||||
or an app currently does nothing.
|
||||
- **`ShareModal.vue`'s mime map omits `m4a`/`aac`/`opus`/`wma`** — those share as
|
||||
`application/octet-stream`, so they never route to the audio player and are auto-filed to
|
||||
`Documents` instead of `Music`. Relevant to D-13.
|
||||
|
||||
</code_context>
|
||||
|
||||
<specifics>
|
||||
## Specific Ideas
|
||||
|
||||
- Routstr was named by the user directly, with the repo link, and asked to be planned in as
|
||||
part of the backend work — not treated as a future option.
|
||||
- The sandbox framing is the user's own: "we must sandbox and protect the users sensitive
|
||||
keys, information, etc whatever they allow access to." The last clause is the design brief —
|
||||
authority is bounded by what the user allows, not by what the model asks for.
|
||||
- The origin of this phase is the user's Phase 2 wording: AIUI "talks to the node safely when
|
||||
permissioned, without leaking data, **using the same command surface as Pine** and everything
|
||||
else enableable in settings." D-02's shared-service shape is that sentence made concrete.
|
||||
|
||||
</specifics>
|
||||
|
||||
<deferred>
|
||||
## Deferred Ideas
|
||||
|
||||
- **Cross-node "archipelago content source" with payments** — any IndeeHub install plugs into
|
||||
every node's content, with payments; same for music. A federation distribution + payments
|
||||
feature; its own phase (deferred at D-14).
|
||||
- **AIUI Nostr integration polish** — "make the Nostr integration in AIUI more beautiful."
|
||||
Carried over from Phase 2's deferred list, still not scoped here.
|
||||
- **Reviving `ContentPanel.vue` and the plugin-renderer path** — considered and rejected for
|
||||
this phase; the dead-code inventory should be resolved as cleanup, not as architecture.
|
||||
- **AIUI's dev-only Vite middleware** (`vite-tmdb`, `vite-rss`, `vite-web-search`, `vite-fs`,
|
||||
`vite-music-search`, `vite-dev-chats`) — needs a production answer eventually; only the parts
|
||||
D-12 replaces are in scope now.
|
||||
- **Pine voice reusing the tool registry** — D-02 makes it possible and is the reason for the
|
||||
shared-service shape, but wiring the voice pipeline to it is not in this phase.
|
||||
|
||||
### Reviewed Todos (not folded)
|
||||
- *Connected-nodes list must scroll at row-matched height* — keyword match only; belongs to
|
||||
Phase 1 (UIFIX-02, already complete).
|
||||
- *Fedimint gateway must not install with a pre-set password* — keyword match only; Phase 1
|
||||
FED-07 territory.
|
||||
- *Keep FIPS/Tor pills on cloud files and show them on mobile* — keyword match only; Phase 1
|
||||
UIFIX-01.
|
||||
|
||||
</deferred>
|
||||
|
||||
---
|
||||
|
||||
*Phase: 13-AIUI — Conversational Node Control & Content Surfaces*
|
||||
*Context gathered: 2026-08-03*
|
||||
+201
@@ -0,0 +1,201 @@
|
||||
# Phase 13: AIUI — Conversational Node Control & Content Surfaces - Discussion Log
|
||||
|
||||
> **Audit trail only.** Do not use as input to planning, research, or execution agents.
|
||||
> Decisions are captured in CONTEXT.md — this log preserves the alternatives considered.
|
||||
|
||||
**Date:** 2026-08-03
|
||||
**Phase:** 13-aiui-functional-conversational-node-control-and-content-surf
|
||||
**Areas discussed:** Where the tool-calling loop lives, How much authority the chat gets, Content scope and what "music" means, Two-repo split and delivery
|
||||
|
||||
---
|
||||
|
||||
## Where the tool-calling loop lives
|
||||
|
||||
| Option | Description | Selected |
|
||||
|--------|-------------|----------|
|
||||
| Node-side in Rust | Binary owns loop, tool registry and key; AIUI is a thin client | ✓ |
|
||||
| Node proxies the model, AIUI runs the loop | Key stays server-side but tools execute through the ContextBroker | |
|
||||
| Browser-side in AIUI | AIUI calls the model directly; key lives in the browser | |
|
||||
|
||||
**User's choice:** Node-side in Rust
|
||||
**Notes:** Chosen with the tradeoff stated — this makes the RPC surface a contract AIUI and the later voice pipeline are written against.
|
||||
|
||||
| Option | Description | Selected |
|
||||
|--------|-------------|----------|
|
||||
| One assistant, many front doors | Extend the existing mesh assistant into a shared service | ✓ |
|
||||
| Separate subsystem for AIUI | Leave the radio-shaped mesh assistant alone, build beside it | |
|
||||
| Shared backend, separate authority | Share the key/plumbing, keep tool registries strictly separate | |
|
||||
|
||||
**User's choice:** One assistant, many front doors
|
||||
**Notes:** Directly realizes the user's Phase 2 wording — "the same command surface as Pine".
|
||||
|
||||
| Option | Description | Selected |
|
||||
|--------|-------------|----------|
|
||||
| Split by nature: node does data+control, broker does UI | Node owns node-touching tools; broker keeps navigate/open-app/theme + consent | ✓ |
|
||||
| Broker becomes consent-only | Strip back to permissions and theme | |
|
||||
| Keep the broker as the single front door | Everything forwards through the broker | |
|
||||
|
||||
**User's choice:** Split by nature
|
||||
|
||||
| Option | Description | Selected |
|
||||
|--------|-------------|----------|
|
||||
| Local Ollama when present, Claude as fallback | Node data stays local when a local model exists | ✓ (amended) |
|
||||
| Claude by default, Ollama opt-in | Best tool-calling reliability, context leaves the node | |
|
||||
| User picks at setup, no default | Explicit choice, no implicit default | |
|
||||
|
||||
**User's choice:** Option 1, **amended by the user** — "but we also want to integrate this as part of it, please plan that too `https://github.com/routstr` so it would be local Ollama or Claude/Routstr as fallback"
|
||||
**Notes:** Routstr was researched during the discussion rather than assumed: OpenAI-compatible endpoint, Cashu ecash per request, Nostr provider/model/price discovery. All three substrates already exist in-tree, which is why it is a smaller lift here than elsewhere.
|
||||
|
||||
| Option | Description | Selected |
|
||||
|--------|-------------|----------|
|
||||
| Prepaid budget, auto-spend within it | Hard ceiling a prompt-injected model cannot exceed | ✓ |
|
||||
| Confirm every paid request | Maximum control, unusable with a multi-call tool loop | |
|
||||
| Routstr only when explicitly selected | No automatic fallback to a paid path | |
|
||||
|
||||
**User's choice:** Prepaid budget the user sets
|
||||
|
||||
| Option | Description | Selected |
|
||||
|--------|-------------|----------|
|
||||
| Curated allowlist of hand-written tools | Every capability is a deliberate decision | ✓ |
|
||||
| Auto-generate from the RPC dispatcher | Fast coverage, blast radius = whatever the allowlist forgets | |
|
||||
| Tiered: curated for writes, generated for reads | Broad reads, hand-written mutations | |
|
||||
|
||||
**User's choice:** Curated allowlist of hand-written tools
|
||||
|
||||
| Option | Description | Selected |
|
||||
|--------|-------------|----------|
|
||||
| Local model gets tools, writes confirmed anyway | Confirm gate does the safety work | ✓ |
|
||||
| Reads local, writes escalate to the strong model | Undercuts the privacy default at the sensitive moment | |
|
||||
| Require a tool-capable local model | Honest but costs weak-hardware users the feature | |
|
||||
|
||||
**User's choice:** Local model gets tools; every write needs confirmation regardless
|
||||
**Notes:** Consequence recorded in CONTEXT.md — backend choice becomes a privacy decision, not a safety one.
|
||||
|
||||
| Option | Description | Selected |
|
||||
|--------|-------------|----------|
|
||||
| Node-side, in the existing per-node data dir | Inherits backup, factory-reset, future LUKS | ✓ |
|
||||
| Browser-only, never persisted server-side | Nothing accumulates on disk | |
|
||||
| Ephemeral — no history at all | Strongest privacy, no memory | |
|
||||
|
||||
**User's choice:** Node-side in the per-node data dir
|
||||
|
||||
---
|
||||
|
||||
## How much authority the chat gets
|
||||
|
||||
| Option | Description | Selected |
|
||||
|--------|-------------|----------|
|
||||
| Reads + app lifecycle + settings writes | Keys, seeds, wallet spends, federation trust, factory reset excluded | ✓ |
|
||||
| Read-only first | Prove the sandbox before granting power | |
|
||||
| Full control including wallet and payments | An LLM adjacent to spending authority | |
|
||||
|
||||
**User's choice:** Reads within granted categories + app lifecycle + settings writes
|
||||
|
||||
| Option | Description | Selected |
|
||||
|--------|-------------|----------|
|
||||
| Authority never derives from content; untrusted text fenced and labelled | Injected instructions still face a human confirm | ✓ |
|
||||
| Keep peer content out of the model entirely | Removes the injection path and much of the appeal | |
|
||||
| Sanitize and strip suspicious patterns | Rejected as an arms race that reads as a guarantee | |
|
||||
|
||||
**User's choice:** Fenced and labelled; authority never derives from content
|
||||
|
||||
| Option | Description | Selected |
|
||||
|--------|-------------|----------|
|
||||
| In neode-ui's trusted chrome, outside the iframe | Iframe cannot spoof, restyle or pre-click it | ✓ |
|
||||
| Inside AIUI, styled as part of the conversation | Better feel, drawn by the influenced context | |
|
||||
| Node-issued confirmation token, UI-agnostic | Strongest and works for voice; more protocol to build | |
|
||||
|
||||
**User's choice:** neode-ui's trusted chrome, outside the iframe
|
||||
|
||||
| Option | Description | Selected |
|
||||
|--------|-------------|----------|
|
||||
| All closed; user opens what they want | Matches the sandbox promise literally | ✓ |
|
||||
| Low-sensitivity open, sensitive closed | Immediately useful, harder claim to defend | |
|
||||
| Open on first grant, per-category prompts in context | Just-in-time consent, more moving parts | |
|
||||
|
||||
**User's choice:** All 10 categories default closed
|
||||
|
||||
---
|
||||
|
||||
## Content scope — and what "music" means
|
||||
|
||||
Presented alongside verified research findings: AIUI's grids are fed by regex-parsing the model's own reply text against fixture catalogs injected into the system prompt; every "real" data path is Vite dev middleware absent from a static `dist/` deploy; `vite-fs.ts:7` hardcodes `/Users/dorian/Projects`; `ContentPanel.vue` is dead code taking `ArchyAppsGrid`, `FavoritesGrid`, `DiscoverPanel`, `RecipeDetail` and `AppDetail` with it.
|
||||
|
||||
| Option | Description | Selected |
|
||||
|--------|-------------|----------|
|
||||
| Feed the existing grids from Archy | Keep the design, replace the LLM-synth source | ✓ |
|
||||
| New Archy-native surfaces alongside | Doubles surface area, splits the design language | |
|
||||
| Revive ContentPanel and the Archy bridge path | Risks investing in an abandoned architecture | |
|
||||
|
||||
**User's choice:** Feed the existing grids from Archy
|
||||
|
||||
| Option | Description | Selected |
|
||||
|--------|-------------|----------|
|
||||
| Audio files from the two transports you already have | MIME-filtered files, no new entities; folds in the m4a/aac/opus mime bug | |
|
||||
| Build a real library — albums, artists, metadata | A substantial backend domain | ✓ |
|
||||
| Leave music to wavlake, wire only files and video | Music already works in prod against wavlake | |
|
||||
|
||||
**User's choice:** Build a real library
|
||||
**Notes:** Chosen after being told explicitly that no library domain exists today and that it deserves its own phase. Concern raised once, user decided, proceeded — sequencing handled by the follow-up below.
|
||||
|
||||
| Option | Description | Selected |
|
||||
|--------|-------------|----------|
|
||||
| Its own plans inside Phase 13, not blocking the rest | Phase still delivers if the library runs long | ✓ |
|
||||
| Library first — the rest follows | Cleanest data model, delays everything visible | |
|
||||
| Split it into its own phase | Its own discussion round | |
|
||||
|
||||
**User's choice:** Its own non-blocking wave inside Phase 13
|
||||
|
||||
| Option | Description | Selected |
|
||||
|--------|-------------|----------|
|
||||
| Surface this node's + peers' existing content; no new payment rail | Uses the invoice/X-Payment-Token/Range flow that exists | ✓ |
|
||||
| Include the cross-node content source with payments | The full Phase 2 vision; a federation distribution feature | |
|
||||
| Movies out of scope this phase | Narrowest cut | |
|
||||
|
||||
**User's choice:** Surface existing content through the existing paid-unlock subsystem
|
||||
|
||||
---
|
||||
|
||||
## Two-repo split and delivery
|
||||
|
||||
| Option | Description | Selected |
|
||||
|--------|-------------|----------|
|
||||
| Built and shipped with the frontend, versioned and verified | Pin the commit, enforce the base path, fetch a live asset to verify | ✓ |
|
||||
| Make AIUI a real catalog app | Architecturally right; changes a platform rule mid-phase | |
|
||||
| Vendor AIUI's build output into this repo | One artifact, loses source separation | |
|
||||
|
||||
**User's choice:** Built and shipped with the frontend, versioned and verified
|
||||
|
||||
| Option | Description | Selected |
|
||||
|--------|-------------|----------|
|
||||
| Keep standalone; embedded mode delegates to the node | Dev loop stays fast, no node needed to work on the UI | ✓ |
|
||||
| Embedded-only from here | Less surface, loses AIUI's independent life | |
|
||||
| Standalone with the node as an optional backend | "Optional" risks the secure path being the forgotten one | |
|
||||
|
||||
**User's choice:** Keep standalone; embedded mode delegates
|
||||
|
||||
| Option | Description | Selected |
|
||||
|--------|-------------|----------|
|
||||
| Confirm push access before planning starts | Treats it as a prerequisite, not a mid-plan discovery | ✓ |
|
||||
| Work on a branch, hand merges to a maintainer | Human gate mid-phase, same inert-until-merged risk | |
|
||||
| Plan the archy side to degrade gracefully | Robust, but designs for a half-landed state throughout | |
|
||||
|
||||
**User's choice:** Confirm push access before planning starts
|
||||
|
||||
---
|
||||
|
||||
## Claude's Discretion
|
||||
|
||||
- What the music library indexes over, the tag-extraction library, and where the index lives.
|
||||
- Streaming/token delivery for chat responses; context-window budgeting over node data.
|
||||
- Which specific tools make the first curated allowlist, within the authority ceiling.
|
||||
- Routstr provider selection among Nostr-advertised providers.
|
||||
- Per-category mapping of the 10 permission categories onto individual tools.
|
||||
|
||||
## Deferred Ideas
|
||||
|
||||
- Cross-node "archipelago content source" with payments (federation distribution feature).
|
||||
- AIUI Nostr integration polish (carried from Phase 2's deferred list).
|
||||
- Reviving `ContentPanel.vue` and the plugin-renderer path — cleanup, not architecture.
|
||||
- A production answer for AIUI's dev-only Vite middleware beyond what this phase replaces.
|
||||
- Wiring Pine's voice pipeline to the shared tool registry.
|
||||
Reference in New Issue
Block a user