Files
archy/.planning/STATE.md
T
archipelagoandClaude Opus 5 289c19443a docs: resume artifact for the AIUI demo — task list, findings, traps
Persists the 17-item session task list so it can be rebuilt in a fresh session
(the task tool is session-scoped and would otherwise evaporate), with what
shipped and what each remaining item actually is.

Records the findings that change expectations rather than leaving them to be
rediscovered: the 16 federated peers are not serving content so peers_reached 0
is correct, IndeeHub's catalogue is genuinely empty, two AI permission stores
existed for the same ten categories, and tailscaled owns :443 so nginx must
bind LAN addresses explicitly or it fails EADDRINUSE and silently keeps the old
config.

STATE.md's stopped_at points at it, so /gsd-resume-work lands correctly.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-07 04:27:36 -04:00

275 lines
36 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
gsd_state_version: 1.0
milestone: v1.8.0
milestone_name: milestone
current_phase: 13
current_phase_name: aiui-functional-conversational-node-control-and-content-surf
status: executing
stopped_at: "2026-08-07. READ .planning/RESUME-2026-08-07-aiui-demo.md FIRST — it carries the 17-item task list to rebuild in the session task tool, what shipped, and the findings. AIUI IS BEING DEMOED SOON + a clean ISO must be cut: prioritise #16 (surface stays empty while chat prints correct prose), #15 (surface header overlaps the close button; left heading shows the LAST search, should say Loading), #9 (surfaces not prose), #17 (ISO, UNBUNDLED=1 or it silently builds the wrong variant). DONE+DEPLOYED: gate no longer deletes apps Authorization header (broke every Nostr signer), gate no longer 401s credential-less PWA manifests, AI grants unified into ONE store (two existed for the same ten categories — that, not persistence, is why toggling Settings never helped the assistant), content-card description pairing, IndeeHub relay 502, content_list scopes + 2 RPCs, progressive content load, Mesh TDZ crash, peer-browse cap rebuilt as Cloud fan-out, cert section layout, LAN HTTPS (tailscaled owns :443 so nginx must bind LAN addrs explicitly). KEY FINDING: the 16 federated peers are NOT serving content — FIPS is healthy but 14 dials fail, so peers_reached 0 is CORRECT and no UI work fixes it; IndeeHub catalogue is genuinely empty. Phase 13: 14/15, only 13-15 left; operator verified checks 1, 3 and 4 — check 2 is the holdout because no film content exists here."
last_updated: "2026-08-07T00:00:00.000Z"
last_activity: 2026-08-06
last_activity_desc: 13-14 complete (18-case adversarial eval harness EV-01..EV-18, ScriptedBackend-driven, offline/zero-footprint; E-02 confirmation-copy sign-off operator-approved with three verbatim dialog texts; E-09 naive-user comprehension study recorded as an open residual, not run)
progress:
total_phases: 13
completed_phases: 2
total_plans: 60
completed_plans: 52
percent: 15
---
# Project State
## Project Reference
See: .planning/PROJECT.md (updated 2026-07-29)
**Core value:** A third-party developer can publish an app via the signed/decentralized registry and a user can install it on their node — manifest-driven, rootless, secure, robust.
**Current focus:** Phase 13 — aiui-functional-conversational-node-control-and-content-surf
## Current Position
Phase: 13 (aiui-functional-conversational-node-control-and-content-surf) — EXECUTING
Plan: 14 of 15 complete (13-01..13-14) — next: 13-15
Status: Ready to execute
Last activity: 2026-08-06 — 13-14 complete (18-case adversarial eval harness EV-01..EV-18; E-02 confirmation-copy operator-approved; E-09 comprehension study recorded as an open residual)
Progress: [█████████░] 87%
## Performance Metrics
**Velocity:**
- Total plans completed: 11
- Average duration: —
- Total execution time: —
**By Phase:**
| Phase | Plans | Total | Avg/Plan |
|-------|-------|-------|----------|
| 02 | 11 | - | - |
**Per-Plan Metrics:**
| Plan | Duration | Tasks | Files |
|------|----------|-------|-------|
| Phase 02 P01 | 100min | 3 tasks | 5 files |
| Phase 02 P03 | 45min | 3 tasks | 5 files |
| Phase 02 P02 | 105min | 3 tasks | 11 files |
| Phase 02 P04 | 150min | 3 tasks | 12 files |
| Phase 02 P05 | 50min | 2 tasks | 8 files |
| Phase 02 P06 | 73min | 2 tasks | 7 files |
| Phase 02 P07 | 75min | 3 tasks | 5 files |
| Phase 02 P08 | ~190min | 3 tasks | 4 files |
| Phase 02 P09 | 130min | 3 tasks | 3 files |
| Phase 02 P10 | 55min | 2 tasks | 3 files |
| Phase 02 P11 | ~150min | 3 tasks | 8 files |
| Phase 01 P01 | n/a-continuation | 2 tasks | 1 files |
| Phase 13 P07 | ~3h45m | 2 tasks | 5 files |
| Phase 13 P08 | ~7h45m (elapsed, w/ session restart) | 3 tasks | 10 files |
| Phase 13 P10 | ~2h45m | 2 tasks | 10 files |
| Phase 13 P11 | 27min | 3 tasks | 12 files |
| Phase 13 P12 | ~4h35m (shared-box compute contention) | 3 tasks | 9 files |
| Phase 13 P13 | ~4h (shared-box compute contention, session crash-recovered mid-Task-3) | 3 tasks | 6 files |
| Phase 13 P14 | ~1h10m | 3 tasks | 4 files |
## Accumulated Context
### Roadmap Evolution
- Phase 1 added (2026-07-29): Federation & Mesh Hardening — user-directed top priority (node removal/sync issues, mesh attachment parity incl. demo); prior phases shifted down
- Phase 2 added (2026-07-29): UI Performance — slow tab switches and secondary screens; prior phases shifted down
- FED-05 added to Phase 1 (2026-07-29): inter-node Lightning channel-opening UX (share node URI, pick trusted/federated nodes by hostname, request channels with public nodes); UI tested on :8100 dev preview against archi-dev before deploy
- FED-06 added to Phase 1 (2026-07-29): on-brand paid-tick animation — screensaver ring + EQ segments (reuse ScreensaverRing.vue compact) replacing the success burst in SendBitcoinModal.vue
- Phase 9 added (2026-07-30): BotFights Platform Upgrade — native nostr signer login, unified AI bot-setup prompt replacing docs page, shared public match endpoint on VPS2 (all nodes see all fighters), registry/manifest update. Independent of Phases 18.
- Phase 13 added (2026-08-03): AIUI — Conversational Node Control & Content Surfaces. User-directed: AIUI is embedded and styled but non-functional — chat cannot act on the node, content surfaces are unwired. Scope is (a) Pine's human-language intent→action capability reachable from typed chat, (b) conversational settings, (c) peer files / music / IndeeHub movies / node content rendered live, (d) **a user-granted capability sandbox** keeping keys, secrets and identity material away from the browser and the model — the user called this out explicitly as non-negotiable. Spans two repos: this one and `git.tx1138.com/lfg2025/AIUI` (branch `development`, clone at `~/Projects/AIUI`). Appended, not inserted — numeric position is append order, not priority.
- Phase 10 added (2026-08-01): Key-Material Hardening — KEY-01/F-01 (Critical: unauthenticated `seed.generate`/`seed.restore` overwrite a live node's identity keys), KEY-02/F-03 (fail-open first-boot secret regeneration over a fleet-shared rootfs), KEY-03/F-13 (BIP-84 private key imported into Bitcoin Core), KEY-04 (on-node verification of the audit's UNVERIFIED checklist). Sourced from `docs/security/ENTROPY-SEED-AUDIT-2026-07-31.md` (quick task 260731-upz). Appended rather than inserted to avoid renumbering a roadmap with concurrent uncommitted edits — **numeric position is append order, not priority; F-01 is Critical and live on the fleet.**
### Decisions
- [Phase 13, D-19 (2026-08-03)]: **AIUI's source migrated into this repo at `aiui/`**, via `git subtree` with its full 230-commit history (`7ba3109b`, from AIUI `development` @ `e30ac1d`). Supersedes D-15's two-repo premise and voids D-18 entirely. Retires the recurring "AIUI commit stranded local-only" failure (windows 4 and 17) — `e30ac1d` came across in the import and is now pushed. D-17 (standalone mode) is unaffected: archy has no root `package.json`, so AIUI's pnpm/turbo workspace does not collide. Consequence: plans **13-06, 13-09, 13-11** still target `/home/archipelago/Projects/AIUI/` absolute paths and must be re-planned before wave 2; 13-09's `scripts/aiui.pin` deliverable is now meaningless for an in-repo directory.
- [Phase 13, wave 1]: Recovered from a broken-pipe interruption that left 13-01 and 13-02 executor work uncommitted in orphaned worktrees. Both were checkpointed verbatim before any agent touched them, then re-committed atomically per task by continuation executors (both chose `reset --soft` + recommit). 13-03 was already complete and was fast-forwarded in.
- [Phase 13, execution mode]: `parallelization: false` — this 4-core box thrashed (load 35-55, 15G/23G swap) running two worktree cargo builds concurrently alongside a live node (bitcoind/electrumx/lnd). Serial execution is strictly faster here.
- [Phase 13, 13-04 / D-13 one-way half (2026-08-04, operator)]: Music entity model recorded in 13-MUSIC-MODEL.md BEFORE any node indexes a library — hybrid-identity ((source, canonical path) row key + lazily-backfilled content-hash dedupe column), derived-albums (albums/artists computed at read time, never stored rows), index-format-json (data_dir/music/index.json, content_server.rs precedent), sources = both OwnLibrary and Peer. MUSIC_SCHEMA_VERSION starts at 1; an older binary treats a newer-versioned index as absent (log + empty in-memory index, never overwrite) until an explicit reindex.
- [Phase 13, 13-04 Task 2 (2026-08-04, operator)]: lofty 0.24.0 approved through the blocking-human package-legitimacy gate ([ASSUMED] in 13-RESEARCH.md's audit); dep tree reviewed, no networking crates. Media-root confinement in extract_tags is a parameter (media_roots), checked via canonicalize before any file open (T-13-20).
Decisions are logged in PROJECT.md (10 locked ADRs in the `<decisions>` block + milestone decisions table). Recent decisions affecting current work:
- Milestone version = 1.8.0-alpha (decided 2026-07-08)
- Phase-3 Quadlet default-flip is gated on the second-node gate reporting clean (do fresh, never stage uncommitted)
- Workstream D (DHT distribution) deferred to v2 — design-only backlog
- Canonical manifest schema = `core/container/src/manifest.rs` (code wins over spec doc)
- [Phase ?]: Marketplace is the 02-02 tracer tab (worst-measured main tab, 2033ms revisit) matching the user's own 'often app store' complaint
- [Phase ?]: ContainerAppDetails.vue confirmed fully unreachable dead code (no importer, no route) — no serial-RPC-waterfall target exists in the measured D-09 surface set
- [Phase ?]: archi-dev-box UI password was unknown/undiscoverable from this environment — paused at a checkpoint:human-action rather than guessing or falling back to a mock baseline silently
- [Phase ?]: Purged the resource cache on logout via clearAll() + a generation guard, so no in-flight fetch from an ending session can repopulate memory or sessionStorage (T-02-02)
- [Phase ?]: AppDetails/MarketplaceAppDetails/OpenWrtGateway converted to per-item (or single-key) keyed useCachedResource; CloudFolder.vue's existing store-level cache left as-is (cloud.ts TTL gate is a follow-up, out of this plan's file scope)
- [Phase ?]: Wallet/send flow (SendBitcoinModal.vue) reported as an unplanned-item gap — named by findings as owned by 02-03 but not in files_modified; its cost is pure client-side remount, not a caching problem
- [Phase ?]: PERF-03 reverted to Pending in REQUIREMENTS.md after an initial mark-complete was premature — its own text requires real-node-hardware verification, which is 02-08's job (also declares PERF-03); 02-03 delivers the code-level portion only
- [Phase ?]: 02-02: DashboardRouterView final shape uses statically-named per-route KeepAlive wrapper components (dashboardViewWrappers.ts) with :include name-matching, restoring pre-restructure view-wrapper DOM/animations byte-for-byte after a checkpoint-caught regression
- [Phase ?]: 02-02: HARD RULE for rest of Phase 02 — perf work must be visually invisible; verify against the real dev preview before considering a checkpoint satisfied
- [Phase ?]: 02-02: app-catalog persist:true ttl 300000ms; bitcoin.prune-status persist:true ttl 30000ms — both explicit per T-02-01, no default relied on
- [Phase ?]: 02-02: PERF-02 reverted to Pending/In-Progress in REQUIREMENTS.md after an automated mark-complete run — PERF-02 also spans 02-04..02-07 (extending KeepAlive caching to every remaining main tab); this plan proves the architecture on the tracer tab only
- [Phase ?]: 02-04: KEEP_ALIVE_PATHS widened to every audited main tab (10 paths) derived from TAB_ORDER + /dashboard/discover; /dashboard/settings deliberately withheld — its child sections (SystemDangerZone reboot poll, several onMounted-only fetches) were never audited by this plan
- [Phase ?]: 02-04: onActivated is a documented no-op outside a KeepAlive boundary — every arm function now runs from both onMounted and onActivated (fresh-mount guards on Home/Web5/Mesh/Server avoid doubling first-load RPC cost); caught by CloudPeersRefresh.test.ts
- [Phase ?]: 02-04: useCachedResource.ts's onActivated no longer eagerly force-loads a never-fetched immediate:false resource, so tab-gated lazy data (Cloud.vue Paid Files/My Files) isn't force-loaded merely by its view entering the KeepAlive cache
- [Phase ?]: 02-04: AIUI blank-screen-and-loading symptom reported at Task 3 checkpoint diagnosed as pre-existing (local mock-backend dev mode sets VITE_AIUI_URL=http://localhost:5173 unconditionally with no AIUI repo checked out) — not a regression, left for 02-07 (Chat/AIUI) to address
- [Phase ?]: 02-05: mesh.refreshAll()/transport.fetchStatus() stay uncached at the store level (other callers need guaranteed-fresh reads); the useCachedResource wrapper around each lives in Mesh.vue instead, since Pinia's defineStore(id,setup) runs in a bare effectScope where onActivated() silently no-ops
- [Phase ?]: 02-05: FLAGGED - RESEARCH.md's premise that Mesh.vue owns a D3 force simulation is incorrect for this codebase (verified via grep); only NetworkMap.vue/Federation.vue has one. Task 2's D3 truths are vacuously satisfied; only the real Leaflet map lifecycle (MeshMap.vue, added to scope) was implemented
- [Phase ?]: 02-05: per-group TTL/persist table - mesh.refresh-all/federation-nodes/self-onion/self-did/contacts all persist:false (identity payload); transport-status persists (aggregate, non-identity); reachability groups get 10s TTL, identity groups 300s
- [Phase ?]: 02-06: RESEARCH A3 settled — none of Server's seven load-group loaders consumes another's result; concurrent fan-out is correct as-is
- [Phase ?]: 02-06: Five of Server's seven groups were already on useCachedResource from a pre-phase legacy commit (ea254f63) with only composable defaults (30s TTL, persist:true) — this plan's work was explicit TTL/persist/dedup, not initial conversion; only loadDiskStatus was a genuinely uncached plain fetch
- [Phase ?]: 02-06: Home's wallet composite does NOT share a cache key with Web5.vue's web5.lnd-info — sharing would either corrupt Web5's typed entry.data or fail to close the sessionStorage gap since Web5.vue's own hook (out of scope) defaults persist:true
- [Phase ?]: 02-06: homeStatus.refresh() wrapped by useCachedResource at Home.vue (the view), not inside the homeStatus Pinia store — defineStore(id,setup) runs in a bare effectScope where onActivated() silently no-ops, same finding as 02-05's Mesh.vue
- [Phase ?]: 02-07: AIUI source located mid-plan at git.tx1138.com/lfg2025/AIUI (base branch development, not stale main); AIUI-side D-14 commit 900c0b9 initially local-only (anonymous push 403) then pushed/merged upstream onto development by the orchestrator using a user-supplied write token
- [Phase ?]: 02-07: D-14a fixed via new ?chatExpanded param overriding chat.ts's chatCollapsed default (never persisted to localStorage); D-14b fixed via new ?mobileChat param re-asserting ChatPage.vue's mobileTab='chat' once on mount, guarding against module-singleton content-panel state surviving an internal AIUI remount
- [Phase ?]: 02-07: PERF-02 marked Complete in REQUIREMENTS.md — 02-02 through 02-07 extended KeepAlive/useCachedResource to every main tab, each dev-preview-verified against archi-dev-box per D-11
- [Phase ?]: 02-08: KEEP_ALIVE_MAX left at 6, now backed by an on-device memory reading (4 cycles, 11 tabs, JS heap fluctuating 10-21MB, no monotonic growth) rather than the FA-D estimate
- [Phase ?]: 02-08: archy-x250-dev offline for the entire plan (checked 3x); archi-dev-box (D-11's named target) is the only dev-pair node this phase reached
- [Phase ?]: 02-08: the harness's remount-probe field is confounded for main tabs once real KeepAlive keeps multiple instances alive simultaneously; corrected via an independent, reproduced-twice verification rather than editing the frozen 02-01 harness — revealed Server.vue genuinely does not survive a round-trip (open gap, not hidden)
- [Phase ?]: 02-08: a user-reported Cloud first-visit navigation regression was treated as release-blocking, not known-open, per explicit direction — root-caused to content.browse-peer's unbounded, untimed-enough per-peer RPC fan-out starving Chromium's connection pool; fixed via a concurrency cap + shortened timeout, verified 5/5, user-approved on-node
- [Phase ?]: 02-08: 4 other user-reported UX issues (Paid Files window.open, PiP not closing lightbox, missing loader on Paid Files item-open, PiP not surviving tab changes) classified as pre-existing (predate phase 2 via git history) and captured into UIFIX-04/05/06, not fixed
- [Phase ?]: 02-09: /dashboard/server's (and Web5's) 'genuinely remounts' reading was a proven probe-measurement artifact (generic .view-container selector can't disambiguate the foreground tab from other still-connected cached tabs) — confirmed via document.elementFromPoint() hit-test contradicting the naive verdict across device runs; no source change needed, pinned with vm.$.uid-based regression tests instead
- [Phase ?]: 02-09: committed neode-ui/e2e/perf/keepalive-remount-probe.spec.ts as a re-runnable, instrumented probe covering every KEEP_ALIVE_PATHS tab, replacing the ad-hoc 02-08 probe so this class of false positive cannot recur
- [Phase ?]: [Phase 2, gap closure 02-10]: Wallet/send-flow's timing regression cleared as environmental noise (re-measure at/below baseline); Discover/Server/Web5/AppDetails/OpenWrtGateway confirmed as real, phase-2-caused client-side render/reactivation regressions via 3-run dispersion + git bisection, recorded as accepted deviations (not fixed — deploy blocked mid-session by a shared-tree hazard with concurrent security-follow-up and BotFights sessions)
- [Phase 2, gap closure 02-11]: Real cause of the six regressions was NOT compute-bound render cost (CPU profile: 86-99% idle/program, <10% JS self-time everywhere) — it was three background pollers (useFleetData.ts 60s, FipsNetworkCard.vue 15s, Web5Monitoring.vue 30s) armed in onMounted and never disarmed once their owning views joined KEEP_ALIVE_PATHS in 02-04, invisible to that audit because it grepped the top-level view files, not the child composables they delegate to. Gated to onActivated/onDeactivated, mirroring 02-04's own established pattern. Fixed: web5 275ms (was 566ms baseline/1329ms regressed), server 574ms (was 738/1239), fleet 790ms (was 330/2631)
- [Phase 2, gap closure 02-11]: Discover (1389ms, worst remaining) has a SECOND, distinct cause: card-stagger/showStagger entrance-animation classes are baked into the DOM at first mount and never programmatically removed, so every KeepAlive detach/reattach cycle restarts the CSS animation on reactivation — replaying the full entrance cascade on every revisit. Confirmed via a diagnostic (DOM card count doubling transiently on every revisit) and an extended animation-event log. NOT fixed — blast radius spans 5+ files outside 02-11's scope (Apps.vue, Marketplace.vue, Home.vue, several Web5 sub-cards), needs its own real-device verification budget; recommended as a dedicated follow-up
- [Phase 2, gap closure 02-11]: openwrt-gateway unmeasurable in the final re-measure (Chromium "Target crashed" cascading from an unrelated surface, cloud-folder, earlier in the same harness run) — recorded as not-measurable, not written in as data. Separately confirmed the prior baseline/after/remeasure numbers were measuring a real, substantive disconnected-state UI (OpenWrtGateway.vue's h1 is unconditional; a "No router configured" RPC error deterministically renders a real Connect-to-Router form, not a blank/error page) — the six-surface regression count is not retracted, but the numbers reflect one specific code branch (no OpenWrt device has ever been connected to archi-dev-box)
- [Phase ?]: 01-01: record_peer_transport and update_node routed through FEDERATION_STORE_LOCK via *_inner; tombstone-write-failure test added; full-suite verify blocked by a concurrent agent's uncommitted install.rs edit (unrelated file, not fixed per scope boundary)
- [Phase ?]: UIFIX-02: connected-nodes card height tracks row sibling via xl:flex-1 xl:basis-0 (zero-basis flex-grow) instead of flex-auto, with an xl:min-h-[40rem] floor for a short sibling (discovery disabled), tuned from an initial 20rem guess per Dorian's live feedback
- [Phase ?]: 13-07: media_roots = filebrowser/Music + purchased-content (both D-13 sources as local roots); music.reindex incremental:true wires refresh_incremental to a production caller; one comparator everywhere with TrackId (source,path) tiebreak
- [Phase ?]: [Phase 13, 13-08]: System prompt rewritten to make the model call destructive tools directly rather than text-asking for confirmation — the original wording ('every write requires a human confirmation') read as 'collect consent in text first', which skipped the tool call and dropped the user's typed 'confirmed' into a void on the next stateless turn
- [Phase ?]: [Phase 13, 13-08]: CONFIRM_TIMEOUT raised 120s->300s and the full HTTP timeout chain (rpcClient, assistant.chat 420s, AIUI bridge 180s->430s) raised past it, so transport can no longer time out a human reading the confirm dialog before the confirm gate itself does
- [Phase ?]: [Phase 13, 13-08]: Declined actions remembered per-turn in ToolExecCtx, keyed by the same action_key the approval nonce binds; execute_tool refuses a re-ask for that exact action before the gate reopens, closing a retry loop where a declined action kept re-prompting (T-13-50 mechanized)
- [Phase ?]: [Phase 13, 13-10]: OllamaBackend leads the D-04 chain via POST /api/chat (never assist.rs's /api/generate); model_supports_tools() probes /api/show and process-caches the answer, turning AI-SPEC's qwen2.5-coder [ASSUMED] tool-capability note into a runtime fact; FallbackChain falls through to Claude on a transport error mid-turn, not just at initial selection
- [Phase ?]: [Phase 13, 13-10]: history.rs persists the full ChatMessage transcript per CallerScope-derived HistoryKey under data_dir, atomic (temp+rename) and 0600, with wallet/files-category tool-call arguments redacted before disk (verified against raw bytes, not just the struct); chat() persists but does not yet feed prior turns back into live model context (deliberately scoped out, needs Claude tool_use/tool_result id-pairing test budget as a follow-up)
- [Phase ?]: [Phase 13, 13-10]: detect_ollama() and its two containing modules bumped to pub(crate) (api/rpc/mod.rs, api/rpc/mesh/mod.rs, api/rpc/mesh/assistant.rs) so assistant::backends could reuse the existing Ollama probe rather than writing a second one; run_loop (loop_.rs) now returns (answer, full_history) instead of just the answer, both Rule-3 deviations structurally required by the plan's own stated intent
- [Phase ?]: 13-11: kind:'library' content:request routes to music.list-tracks (not content.*) via a new contextBroker.ts fetchLibraryContent branch — Rule 2 deviation, contextBroker.ts's diff-clean acceptance criterion could not hold alongside genuine music.* wiring (ContentItem has no artist/album/duration field at all)
- [Phase ?]: 13-11: closed the plan's GAP-FOUND must_have — useArchy.ts's init() now fires requestArchyContent + requestArchyLibrary automatically as a live init-time event, and useContentPanel.ts's setArchyContent opens the panel/sets tabs for non-empty content, instead of leaving the fetch merely callable with nothing in the UI ever invoking it (13-06's own documented Known Limitation)
- [Phase ?]: 13-12: wrap_untrusted's per-call token is drawn fresh from rand on every call (never a module constant) — a forged closing boundary using a guessed/fixed token can never match, defeating EV-11 by construction; no pattern-stripping filter added anywhere in assistant/ (D-10 rejects that approach by name)
- [Phase ?]: 13-12: assistant.chat's G-B3 rate limit is keyed by authenticated SESSION id (not client IP) via a new session_requests map on the existing EndpointRateLimiter — 13-AI-SPEC §6 is explicit that per-session, not per-IP, is the guardrail's own spec
- [Phase ?]: 13-12: screen_outbound (G-B1/G-B2) wired into backends/claude.rs's send() and the assistant.chat rate limit wired into api/rpc/assistant_chat.rs — both Rule 3 deviations outside their task's declared file list, since the plan's own stated behavior (run on the Claude leg / rate-limited per session) had no real call site otherwise
- [Phase 13, 13-13 Task 1 (2026-08-05, operator via AskUserQuestion)]: Routstr decision = proceed-docs-with-probe-first (0/9 protocol claims independently confirmed per 13-ROUTSTR-FINDINGS.md — no live provider was reachable during the 13-03 spike). Implemented against docs.routstr.com's cited shape (kind 38421, `Authorization: Bearer cashuA…`, OpenAI-shape chat completions); the first live HTTP call to any provider doubles as the capability probe and fails loudly (real status/body, or "no choices array") on any wrong guess rather than silently misbehaving. D-04's chain is now complete: Ollama -> Claude -> Routstr
- [Phase 13, 13-13]: D-05's budget ceiling (`AssistantBudget`) is computed ONLY from persisted allowance_sats/spent_sats — never from anything model/tool/provider-influenced; `BudgetExhausted` (typed, anyhow-downcastable) stops `run_loop` with a plain-language message, no retry/re-price/partial-spend/fallthrough. Verified load-bearing by fault injection: temporarily replacing the terminating `return` with `continue` made `zero_budget_stops_loop_without_retry` go red (8 retries to MAX_TURNS, generic error) before being restored
- [Phase 13, 13-13]: egress.rs's message_is_turn_own (13-12's G-B2 check) was Claude-shape-only and would have silently stripped Routstr's OpenAI-shape system prompt + tool results out of every outbound request — fixed with explicit "system"/"tool"-role handling (Rule 1 bug, found while wiring screen_outbound into routstr.rs)
- [Phase ?]: [Phase 13, 13-14]: Task 3's E-02 sign-off was conducted via the orchestrator driving real node RPCs, with the operator reviewing the captured dialog texts directly and approving them; E-09's naive-user timed-comprehension protocol was NOT run and is recorded as an open residual carried forward, not force-passed under a lowered bar.
- [Phase ?]: [Phase 13, 13-14]: In-crate #[cfg(test)] eval module (assistant::evals) used instead of a tests/ integration target, since core/archipelago is [[bin]]-only with no [lib] — cargo test --package archipelago assistant::evals:: is the invocation; release-binary string grep confirms zero shipped footprint.
### Pending Todos
- [blocker/ui] Keep FIPS/Tor pills on cloud files and show them on mobile (`.planning/todos/pending/2026-07-30-keep-fips-tor-pills-on-cloud-files-and-show-them-on-mobile.md`)
- [blocker/security] Fedimint gateway must not install with a pre-set password — tracked as FED-07 / Phase 1 gap plan (`.planning/todos/pending/2026-07-30-fedimint-gateway-must-not-install-with-preset-password.md`)
- [blocker/ui] Connected-nodes list must scroll at row-matched height, not grow to fit (`.planning/todos/pending/2026-07-30-connected-nodes-list-must-scroll-at-row-matched-height.md`)
- [blocker/ui] Onboarding tickbox hidden below fold on short screens — make it beautifully obvious (`.planning/todos/pending/2026-07-30-onboarding-tickbox-hidden-below-fold-on-short-screens.md`)
- [major/ui] Paid Files pictures open in browser tab, not the app lightbox — UIFIX-04 (`.planning/todos/pending/2026-07-30-peer-files-pictures-open-in-tab-not-lightbox.md`)
- [major/ui] PiP should close the lightbox with a fluid animation — UIFIX-05 (`.planning/todos/pending/2026-07-30-pip-should-close-lightbox-with-fluid-animation.md`)
- [major/ui] Missing loader states on slow opens — UIFIX-06 (`.planning/todos/pending/2026-07-30-missing-loader-states-on-slow-opens.md`)
### Blockers/Concerns
- [Phase 1] Federation tombstone fix touches trust code — fix carefully, re-verify with `tests/multinode/smoke.sh`, don't patch blind
- [Phase 3] Multinode gate on archy-x250-beta was launched 2026-07-01 (log on-node); verify outcome before re-running
- [Phase 5] Fleet registry flip awaits explicit user authorization + timing call
- [Phase 6] Strengthened ADR-009 validation may reject existing catalog apps — audit manifests before enforcement lands
- [Global] Live OTA fleet: deploy to the dev pair before any OTA; gate re-runs required after orchestrator changes; some verification is user/hardware-gated (radios, on-device tests)
- cloud.ts's navigate() needs a TTL gate to fully satisfy 'no new RPC within TTL' for CloudFolder.vue — currently always re-fetches on revisit (just doesn't block paint)
- [Phase 2, RESOLVED by 02-09] ~~Server.vue does not survive a tab round-trip despite KEEP_ALIVE_PATHS registration~~ — retracted: proven a probe-measurement artifact (shared generic `.view-container` selector couldn't disambiguate the foreground tab from other cached tabs), not a real defect. Server.vue's (and Web5.vue's) instance genuinely survives; pinned with `vm.$.uid`-based regression tests immune to the same ambiguity. Checkpoint approved on real hardware.
- [Phase 2, RESOLVED by 02-11] ~~Timing regressions on Discover/Web5/Fleet/AppDetails/OpenWrtGateway~~ — root cause found (three leaked background pollers, not compute-bound render cost) and fixed for web5/server/fleet, each proven with a real before/after number on archi-dev-box. AppDetails restored to at/near its own pre-phase-2 baseline (pre-existing per-mount cost, not a new defect). OpenWrtGateway not measurable this pass (browser crash); prior numbers stand with a data-integrity note (measuring a real disconnected-device UI, not an empty page).
- [Phase 2, follow-up needed] Discover (1389ms, worst remaining named surface) has a second, evidenced, phase-2-caused defect: KeepAlive'd entrance-stagger animations (`card-stagger`/`showStagger`) never get their class removed from the DOM after first play, so every reactivation replays the full CSS animation cascade. Fix requires touching 5+ files outside 02-11's scope (Apps.vue, Marketplace.vue, Home.vue, Web5Wallet.vue/Web5Identities.vue/Web5NodeVisibility.vue/Web5NostrRelays.vue) with its own real-device visual-regression verification budget (the same class of risk 02-02's original KeepAlive rollout hit on its first checkpoint attempt) — needs a dedicated follow-up plan, not squeezed into a gap-closure pass.
### Quick Tasks Completed
| # | Description | Date | Commit | Directory |
|---|-------------|------|--------|-----------|
| 260729-fw7 | improve mesh message hop graphic/animation: balanced desktop sizing, vertical mobile layout, archipelago branding | 2026-07-29 | ac09fc5d | [260729-fw7-improve-mesh-message-hop-graphic-animati](./quick/260729-fw7-improve-mesh-message-hop-graphic-animati/) |
| 260729-gjd | demo: indee.tx1138.com in app iframe (:2101 whole-origin proxy), auto nostr signer sign-in, IndeeHub pre-installed on fresh session | 2026-07-29 | d00ca624 | [260729-gjd-demo-make-indee-tx1138-com-work-in-the-a](./quick/260729-gjd-demo-make-indee-tx1138-com-work-in-the-a/) |
| 260729-hj1 | peer-files media batch: Wavlake paid tracks + purchases + dedupe + real photos (demo); lightbox/player open routing + free-image lightbox fix (both builds) | 2026-07-29 | f52c5407 | [260729-hj1-peer-files-media-batch-wavlake-paid-trac](./quick/260729-hj1-peer-files-media-batch-wavlake-paid-trac/) |
| 260729-je5 | connected-nodes list fills card height (constant footer gap); companion app skips demo intro | 2026-07-29 | d54517cf | [260729-je5-ui-fixes-connected-nodes-scrollable-list](./quick/260729-je5-ui-fixes-connected-nodes-scrollable-list/) |
## Deferred Items
| Category | Item | Status | Deferred At |
|----------|------|--------|-------------|
| Distribution | DIST-01 DHT/iroh backbone (workstream D) | v2 | 2026-07-29 |
| Fleet | FLEET-01 Bitcoin multi-version fleet OTA (user-gated) | v2 | 2026-07-29 |
| Fleet | FLEET-02 per-app deep health assertions (~34 apps) | v2 | 2026-07-29 |
| Fleet | FLEET-03 LUKS2 data-partition encryption | v2 | 2026-07-29 |
## Release SHIPPED — v1.7.120-alpha (2026-08-03)
**LIVE.** signature PRESENT (did:key:z6Mkkid…q7ur), both assets HTTP 200 at exactly their
manifest byte counts, tag pushed. Two release-process traps hit and documented in memory:
create-release.sh commits the manifest BEFORE signing (fleet refuses unsigned), and
gitea-vps2 is the SAME server as gitea-ai (vps2 token is dead).
### Staging record (kept for the evidence trail)
Built from `4d67f56b` (release profile, 15m15s, exit 0), deployed to archi-dev-box,
`.bak` rollback at /opt/archipelago/rollback/archipelago.bak.
Verified on the node: both security gates 401 unauthenticated from a non-loopback
address; CORS origin-scoped; AIUI assets 200 AFTER the frontend rsync (the deploy that
would have wiped a copied-file fix); mesh.lightning-peers/send-lightning-info answer
correctly; system.stats host_secrets = per-node; served bundle sha256-matches the build
on all three chunks; 31 containers up, none down, no restart loop.
NOT verified, deliberately: the new torrc SocksPort/SocksPolicy block. regenerate_torrc
only fires on a Tor services change, so the live torrc still reads only `SocksPort 9050`.
Gateway detection was proven in isolation (10.89.0.1 10.89.0.0/24; missing network exits
non-zero -> stays loopback-only). The change is INERT this release since bitcoind has no
-onion flag yet (Phase 12), so forcing a torrc regeneration would risk bouncing every
onion service for zero benefit.
Frontend is a proven no-op this cycle — built chunks are byte-identical to those already
served — so a fleet node only changes binary + the two app-UI images + nginx.
Remaining to ship: operator go/no-go, then `scripts/create-release.sh 1.7.120-alpha`
(stops at the signing prompt — reads the master mnemonic interactively, operator-only),
then publish-release-assets.sh to gitea-vps2, then push tags. CHANGELOG.md already
carries curated v1.7.120-alpha notes (create-release.sh hard-fails without them).
The 5x lifecycle gate was NOT run.
## Session Continuity
Last session: 2026-08-06 (resumed)
Stopped at: Session resumed 2026-08-06 via /gsd-resume-work. Tree clean, in sync with
gitea-ai @ 7bb09ffe. 13-14 COMPLETE (14/15), next 13-15 device-close — BLOCKED on four
operator browser checks (list in .planning/todos/pending/2026-08-06-open-operational-tasks.md,
which also carries the four non-phase node/infra tasks and the follow-on A/B/C proposal).
Awaiting operator choice between: (a) run the four checks and close 13-15/the phase,
(b) start follow-on Phase B (web-search setting derives the CSP, node-side), (c) take a
node/infra task (app-gate iframe login decision, Starting-vs-Unreachable, .228 frontend).
NOTE: .planning/HANDOFF.json + .planning/.continue-here.md are STALE (phase 09, 2026-08-02,
fully reconciled) and should not be read as live resume context.
Prior (13-12) stop note, retained for history: Completed 13-12-PLAN.md (D-10 untrusted-content boundary, G-B1/G-B2 cloud-egress screen, G-B3 read-only-loop rate limit + owner notices).
`assistant::` tests incl. `approval_nonce_binds_to_exact_action` individually; dispatcher.rs
untouched; fc09d7a2's tools.rs/grants.rs/backends/mod.rs diffs confirmed rustfmt-only, no
behavior change). Task 2 (ToolConfirmModal.vue, contextBroker.ts, Chat.vue mount,
toolConfirm.test.ts) was already complete in fc09d7a2 — all 10 toolConfirm.test.ts cases pass,
pre-existing contextBroker/chatAiuiEmbed suites (28 tests) still green, vue-tsc clean, all
acceptance-criteria greps pass. fc09d7a2 stands as commit of record for both Task 1 and Task 2.
STOPPED at Task 3 (checkpoint:human-verify, gate=blocking) — on-device dialog verification on
archi-dev-box is required before 13-08-SUMMARY.md can be written. Resume: build+deploy per
Task 3's how-to-verify, then re-invoke the 13-08 executor with the operator's "approved" signal.
Resume file: None
Open on this thread (all recorded as broken windows, none blocking):
- Window 15 CLOSED 2026-08-02 20:02 — f6b5245b's reconcile path proven on archi-dev-box by
a controlled test: stale conf installed + container restarted (probe 200, genuinely
re-exposed), daemon started, reconcile repaired it unaided at 20:02:19 with the expected
warn line, probe 401, conf byte-identical to the known-good. Both halves now proven on
hardware.
- Windows 11/12: host-secret rotation on three fleet nodes sharing SSH host keys —
detect-only so far; rotation is USER-GATED and deliberately not actioned.
- Credential rotation DECIDED AGAINST 2026-08-02 (operator): no LND macaroon rotation, no
Bitcoin RPC password rotation — no evidence of exploitation and the vulnerability is
being closed rather than lived with. rotate-lnd-macaroon.sh stays as a tool, exercised in
detect mode only, never run against a node. Do not re-litigate; see
docs/security/BITCOIN-RPC-PROXY-EXPOSURE.md.
- Dev-pair verification is archi-dev-box ONLY, by operator instruction 2026-08-02. Do not
raise archy-x250-dev as a blocker again.