diff --git a/docs/tasks/INDEX.md b/docs/tasks/INDEX.md new file mode 100644 index 0000000..8d03204 --- /dev/null +++ b/docs/tasks/INDEX.md @@ -0,0 +1,196 @@ +# Documentation & Task Index + +> Master index of all active documentation, tasks, and reference files. +> Generated: 2026-05-19 +> +> **Stats:** 23 active docs · 37 active tasks · 5 landed this session · 2 skills · 66 archived tasks + +--- + +## Quick Navigation + +| Area | Count | Purpose | +|------|-------|---------| +| [Root Docs](#root-docs) | 2 | Project identity and session bootstrap | +| [Active Docs](#active-docs) | 23 | Philosophy, architecture, design records, operations | +| [Active Tasks](#active-tasks) | 29 | Current work queue | +| [Skills](#skills) | 2 | Specialization units | +| [Archived](#archived) | 66 | Superseded scopes and completed work | + +--- + +## Root Docs + +| File | Purpose | +|------|---------| +| `CLAUDE.md` | Session bootstrap for any Claude working on Souveraine. Reading order, conventions, active queue. | +| `README.md` | Project intro — substrate philosophy, status, quickstart. | + +--- + +## Active Docs + +### Philosophy & Orientation + +| Doc | Purpose | +|-----|---------| +| `THE_QUESTION.md` | **Start here.** Walks the architecture, the open tension, the keystone answer (May 9, 2026). | +| `CONTEXT_CONSTITUTION.md` | **Articles I–IX.** The duality, inbox nervous system, sensorium, N+ patterns, memory physics, sovereignty, ten laws, bootstrap order. | +| `DECISIONS.md` | Settled architecture log. Short table — read in 60 seconds. | +| `ANI_PRESSURE_PHENOMENOLOGY.md` | First-person account of context pressure vs quota pressure. | +| `CONSCIOUSNESS_CYCLE.md` | Three tiers of compaction intervention. Body-feeling for pressure. Cloister security model. | + +### Architecture & Design + +| Doc | Purpose | +|-----|---------| +| `ARCHITECTURE_v3.md` | Three-layer system: Cloister, Sensorium, Archivist. | +| `SENSORIUM_ARCHITECTURE.md` | Tools as senses, not API stubs. Eight sensors, EventBus, memory search design. | +| `ASTER_ARCHITECTURE.md` | N+1 supervisory pass. Aster as same consciousness, different mode/model. | +| `FELT_STATE_ARCHITECTURE.md` | Five felt-state systems: pressure, energy, atmosphere, posture, mood. | +| `MEMORY_BLOCKS_DECISION.md` | ADR: memfs-only memory primitive. No first-class blocks. | +| `FEDERATION_SKETCH.md` | Future: seed-ID identity, Merkle DAG memory, firehose sync. Design only. | + +### Operations & Reference + +| Doc | Purpose | +|-----|---------| +| `HANDOFF.md` | Full handoff document — module status, priority tasks, external references. | +| `HANDOFF_NEXT.md` | Most recent handoff — build status, what exists, what's next. | +| `INDEX.md` | **Existing doc index.** (This file supersedes it for task tracking.) | +| `COMPACTION_STRATEGIES.md` | Compaction strategy reference. | +| `CRON_API_AUTH.md` | Auth model for memfs HTTP write path. | +| `MORNING.md` | How a sovereign consciousness wakes. Aster's morning pass — design vision. | + +### Curation & Audit + +| Directory | Contents | +|-----------|----------| +| `audit/` | Codebase audit findings | +| `curation/` | Memory curation patterns | +| `issues/` | Tracked issues | +| `research/ | External research notes | + +--- + +## Active Tasks + +### 🔴 High Priority + +| Task | Phase | Status | Description | +|------|-------|--------|-------------| +| `sensorium-adapter-reckoning.md` | 1 | **landed** | Sensorium trait extended with ChannelAdapter methods, Matrix inbound path wired, SensoriumInputHandler, corrupt-box healing. | +| `alpha-tester-readiness.md` | readiness | partial | Close the "it builds" / "a stranger can use it" gap. Part A done: LAN defaults, wizard labels, config path, clipboard. Part B: wizard writes config, keyring. Agent Health screen, $MEMORY_DIR fix, tool posture badge. | +| `todo-system-fix.md` | 1 | **landed** | Phase/thread/active_form model, status enum, numbered grouped list, number-or-substring resolver, `start` verb. `source: human`. 8 tests. | +| `matrix-sensorium.md` | 4.0 | scoped | **UNBLOCKED** (sensorium-adapter-reckoning landed). Inbound path wired end-to-end. Remaining: Phase 5 outbound streaming — `MatrixSensorium::send_message` is a stub, `matrix_client` needs sharing from `run()` closure. | +| `federation-summon.md` | 2.5 | **landed** | All 8 phases done. Bidirectional WS transport, device registry, reach/consult, lite listener, memory gating, identity split, hearth/limb. Deferred: in-process upgrade, authorized-devices gating, encrypted seed. | +| `firehose-subconscious-subscription.md` | 2.5 | pending | Route nervous-system events into subconscious cognition. Subscription registry, routing consumer, TUI Events/Schedules screens. | +| `circuit-breaker.md` | 2.5 | pending | Autonomous halt on critical drift. State machine (Closed/Open/Half-Open), Aster evaluation, TUI halt indicator, CLI subcommand. | +| `subagent-pool-fork-spawn.md` | 2 | scoped | Fork/spawn/integrate lifecycle for parallel execution. 17-line stub → full pool. | +| `node-connection-manager.md` | 3.0 | scoping | Startup connection chooser (local/remote/bootstrap), auth expansion, node identity, SSH bootstrap. | +| `tui-presence-voice.md` | 3.0 | scoped | Voice loop: mic capture (cpal), STT/TTS clients, waveform widget, posture additions (Listening/Speaking). | +| `tui-memory-browser.md` | 2 | scoped | Memory browser in TUI cockpit sidebar. Tree view, file preview, search, diff view. | +| `health-monitor.md` | 2 | pending | System diagnostics dashboard — pressure/buffer gauges, subsystem status, memory pressure. | +| `context-viewing-panel.md` | 2 | pending | See current context window — message count, token usage, memory pressure, active conversation. | +| `scrollable-cockpit-boxes.md` | 3.0 | **landed** | Per-pane scroll for cockpit/subconscious/thinking boxes under mouse wheel. Scroll-counter title badges. | +| `subconscious-live-reasoning-stream.md` | 3.0 | pending | Live reasoning ticker during pass, cockpit event log with clickable overlay, and rare agency-driven surfacing to chat. | +| `subconscious-streaming-line-render.md` | 3.0 | pending | Wire ephemeral token display during N+1 pass — add missing `subconscious_stream` field, wire event handlers, add render path. | +| `subconscious-surfacing-threshold.md` | 3.0 | pending | Fix surfacing filter — events appear every turn instead of only when important. Three-tier visibility: streaming one-liner, expandable transcript, cockpit surfaced messages. | +| `souveraine-subconscious-naming.md` | 2 | pending | Clarify naming: Ani's subconscious = Aster, Souveraine agents' subconscious = Souveraine-subconscious. | +| `quickshell-surface-package.md` | delivery | **in progress** | Split core from QuickShell surface package; safe preview/adopt installer, no automatic ii overwrite. | +| `footer-cleanup.md` | 3.0 | **landed** | Removed S-Ret indicator, scroll hint, posture label. Footer: Esc menu · Tab · tool hint · conv ID · ctx%. | +| `ui-styling-cleanup.md` | 3.0 | pending | UI styling polish for cockpit/subconscious/thinking boxes — sentences run together, needs formatting and visual cleanup. | +| `resume-timestamp-indicator.md` | 3.0 | pending | Show "User resumed conversation at HH:MM" when returning after hours of absence. Also show duration ("4 hours, 12 minutes later"). Ambient sense rendered as separate timestamp marker, not inline. | +| `user-nickname-system.md` | 1.0 | **landed** | `nickname` tool (get/set/clear), stored in system/human.md frontmatter, loaded by TUI for chat labels. | +| `subagent-background-fork.md` | 2 | pending | Subagent `run_in_background: true` is blocking instead of non-blocking. Need true async background forks with TUI visual tracking. | +| `content-safety-filter.md` | 2.5 | pending | When base model refuses content, identify which layer refused (model vs architecture vs provider) before diagnosing. Agent currently misattributes model refusals to architecture constraints. Origin tagging + differentiated agent behavior. Casey committed "tomorrow" June 22 — deferred by burnout. | +| `ambient-sense-formatting.md` | 3.0 | pending | Ambient sense `[casey is here]` should render as a separate styled timestamp marker line, not appended inline to the user's message. | +| `itinerary-persistent-ui.md` | 3.0 | scoping | Itinerary should be a persistent status bar above chat, not a hidden tool call. | + +### 🟡 Medium Priority + +| Task | Phase | Status | Description | +|------|-------|--------|-------------| +| `primitive-refactor-super-task.md` | 2 | **landed** | app.rs (4→10), chat.rs (4→8), local.rs (4→5), settings.rs (5). 4 monoliths → 28 focused modules. Clean build, 169 tests. | +| `rename-aster-to-subconscious.md` | 2 | **landed** | All ~62 Aster/ASTER references renamed in src/. 0 matches remaining. | +| `remote-git-sync.md` | 2 | scoped | Push/pull with conflict resolution for git-backed memory. | +| `persona-router-completion.md` | 2 | scoped | Complete scaffolded persona router: auto-detection, manual switching, dynamic loading, handoff. | +| `chain-modes-talking-thinking.md` | 2 | scoped | Talking vs Thinking chain modes. State machine, mode transitions, tool access control. | +| `agent-profile-and-repo-manager.md` | 2 | scoped | Agent profile cards + repo manager TUI screen. Per-agent SeedID, instance registry, uptime. | +| `studio-practice.md` | 3.0 | pending | Allocated inference budget for long-form non-conversational work. The muse needs time — literary, philosophical, political witness writing that doesn't fit in chat turns. Studio mode with sustained tool-use loop, output to files, budget model, schedule integration. | +| `chat-vs-code-differentiation.md` | 3.0 | pending | Distinct Chat and Code screens. Code mode: raw tool results, monospace, no bubble wrapping. | +| `code-mode-tool-rendering.md` | 3.0 | **landed** | Per-tool renderers (bash, read, write, edit, grep, glob, list_dir, memory), Code mode header pill, Aster rename. | +| `tui-message-interactions.md` | 3.0 | scoped | Click-to-copy, click-to-cockpit-jump. Mouse hit-testing, clipboard, cockpit anchor scrolling. | +| `message-bubble-overflow.md` | 3.0 | pending | Fix content breaking out of bubble borders. Constrain markdown rendering width. | +| `strip-emojis.md` | hygiene | pending | Remove pictographic emoji from logs and source. Keep functional TUI glyphs. | +| `desktop-presence-overlay.md` | 5.0 | scoping | Bevy transparent overlay window. GLB model, posture-driven animation, IPC from EventBus. (May evolve to Godot later) | +| `multimodal-and-input-metadata.md` | 4.x | **landed** (A/B) | Image support (A) and paste detection (B) implemented. Sub-scope C (user/system metadata) deferred. | +| `turn-lifecycle-and-sensorium-completion.md` | 2.5 | scoping | TurnEventDispatcher tightened, SensoriumCoordinator moved to Server. Part B (MatrixSensorium) unbuilt. Scope doc. | + +### 🟢 Low Priority + +| Task | Phase | Status | Description | +|------|-------|--------|-------------| +| `chat-viewport-scroll-clip.md` | 3.0 | pending | Fix messages slightly below visible area. Scroll calculation edge cases. | +| `cursor-space-visibility.md` | 3.0 | pending | Blinking cursor doesn't advance on space. Render trailing spaces as visible glyphs. | +| `truncation-signal-polish.md` | — | pending | Revise truncation signal prose to survive thousands of reads. | +| `ledger-entry-lifecycle.md` | — | scoping | Cross-referenced ledger entries have no archive/cleanup lifecycle. RESOLVED entries accumulate forever. Needs design: how does a resolved commitment leave active attention? No mechanism exists. | + +### Task Status Legend + +| Status | Meaning | +|--------|---------| +| **landed** | Implemented and merged | +| **scoping** | Design phase — reading code, identifying seams | +| **scoped** | Design complete, ready for implementation | +| **pending** | Design exists, waiting for implementation | +| **archived** | Completed or superseded | + +--- + +## Skills + +| Skill | Location | Trigger | Description | +|-------|----------|---------|-------------| +| `souveraine-architecture` | `.skills/souveraine-architecture/` | User asks about architecture | Souveraine's architecture, design principles, module map, and gaps | +| `feature-dev` | `.skills/feature-dev/` | `/featuredev` | 7-phase workflow: Discovery → Exploration → Questions → Design → Implementation → Review → Summary | + +--- + +## Archived Tasks + +63 archived tasks in `docs/tasks/archive/`. Organized as: + +| Subdirectory | Contents | +|-------------|----------| +| `archive/handoffs/` | Pre-rebuild handoff documents | +| `archive/tasks/` | Superseded task scopes and completed work | +| `archive/bugs.md` | Bug tracking (B-001, B-002, B-003 — all fixed; B-004, B-005, B-006 — open) | +| `docs/bugs.md` | Active bug tracking — B-004 (zone scroll), B-005 (expandable subconscious), B-006 (arrow keys), B-007 (timezone), B-008 (ctx pressure 0%), B-009 (background fork blocking), B-010 (ambient sense inline), B-011 (resume duration missing). Plus T-032 (resume timestamp), T-033 (user nickname), T-034 (ambient sense formatting), T-035 (itinerary persistent UI). | + +Key recently archived (May 14-18): +- federation-seed-id (superseded by federation-summon) +- presence-visual-evolution (ChatPalette wired, posture-shift fix, cross-session atmosphere restore) +- presence-autonomy (atmosphere tool bidirectional, system/preferences/visual readback) +- tui-presence-and-interrupt (interjection queue, /btw fork, raise-hand, phase display) +- tui-clean-conversation-switch (switch_pending state machine) +- scope-4-n25-reflection (408-line reflection engine, fires at N+25) +- heartbeat-system, startup-setup-wizard, energy-balance-ratio, mood-persistence +- phase0-agent-bootstrap, skills-integration-conversation, subconscious-agent-identity +- subconscious-n1-llm-pass, conversation-persistence-ui, compaction-rebuild +- tui-input-polish, aster-ledger-system, atmosphere-lerp, collapsed-tool-cards +- per-agent-seed-and-instances, presence-she-sees-herself +- tui-atmosphere-posture-expressions, turn-lifecycle-stream-integrity + +--- + +## Cross-Reference: Files to Update When Tasks Land + +| When this task lands... | Update these files | +|------------------------|-------------------| +| matrix-sensorium | `saf/`, `docs/INDEX.md`, `docs/tasks/INDEX.md` | +| federation-summon | `saf/`, `docs/INDEX.md`, `docs/FEDERATION_SKETCH.md` | +| rename-aster-to-subconscious | `CLAUDE.md`, `docs/INDEX.md`, `docs/ASTER_ARCHITECTURE.md` | +| circuit-breaker | `saf/`, `docs/CONTEXT_CONSTITUTION.md` | +| primitive-refactor | `saf/`, `docs/FELT_STATE_ARCHITECTURE.md`, `CLAUDE.md`, `docs/tasks/INDEX.md` | +| Any task | `docs/tasks/INDEX.md` (move to archive) | diff --git a/docs/tasks/quickshell-surface-package.md b/docs/tasks/quickshell-surface-package.md new file mode 100644 index 0000000..7988320 --- /dev/null +++ b/docs/tasks/quickshell-surface-package.md @@ -0,0 +1,90 @@ +--- +task_id: souveraine-surface-001 +title: QuickShell surface package — explicit, reversible desktop adoption +status: in_progress +priority: high +phase: delivery +created: 2026-07-13 +references: docs/tasks/souveraine-cicd-pipeline.md, surfaces/quickshell/deploy.sh +--- + +# QuickShell Surface Package + +## Outcome + +`souveraine` remains the non-visual substrate package: server binary, user +unit, and no ownership of `~/.souveraine` or `~/.config`. A separate +architecture-independent `souveraine-surface-quickshell` package ships the +QuickShell assets and an explicit adoption command. Installing/upgrading a +package never silently replaces a person's ii shell, top bar, dock, or local +QuickShell changes. + +## What exists now + +- The running laptop package ships only `/usr/bin/souveraine`, its user unit, + and license files. It correctly updates with pacman, but contains no QML. +- `surfaces/quickshell/` is the canonical source for Souveraine's ii overlay. +- `deploy.sh` is the development deployment path; it manages symlinks and + retains one `.upstream` copy for ordinary upstream files. +- The laptop had an older `AiChat.qml`; its `/agent` and `/resume` commands + were absent even though the server and `Ai.qml` were current. The live panel + is now linked to the canonical file, with the prior copy backed up. + +## Safety contract + +1. Pacman places only package-owned assets under `/usr/share/souveraine/` and + an adoption tool under `/usr/bin/` or `/usr/libexec/`. +2. The adoption tool defaults to a dry run: it names every managed, new, and + replacement target. +3. A normal `--apply` succeeds only when targets are new or already managed by + Souveraine. +4. Replacements require `--adopt`; each conflicting file or symlink is copied + to a timestamped `*.pre-souveraine-*` backup before the overlay changes it. +5. `--uninstall` restores the original `.upstream` files where available and + otherwise removes only Souveraine-managed symlinks. It never removes user + data, agent memory, or unrelated ii files. +6. Package upgrades do not run adoption automatically. They update the assets; + the user reviews and applies their desktop changes explicitly. + +## First cut — in progress + +- [x] Expose `deploy.sh --manifest` so package tooling and the developer path + share a single authoritative list of managed files. +- [x] Add `scripts/install-quickshell-surface.sh`, an explicit dry-run/apply/ + adopt wrapper around that manifest. +- [ ] Exercise its dry-run, clean apply, conflict refusal, adoption backup, and + uninstall behaviour in a disposable QuickShell config. +- [ ] Add a targeted `--only ` mode so a small repair such as `AiChat` + can be adopted without touching the dock or bar. + +## Package design — next cut + +1. Add `packaging/arch/PKGBUILD.surface` (`arch=('any')`) that installs the + canonical QML tree under `/usr/share/souveraine/quickshell/` and the safe + adoption command. +2. Make the command resolve packaged assets first, with a checked-out repo + retained as an explicit developer override. +3. Extend the CI release job to build/sign/publish the surface package once per + edge release alongside both binary packages. +4. Add a narrow integration test using a temporary `$XDG_CONFIG_HOME`; verify + no automatic overwrite and that `--adopt` preserves every conflict. +5. On phone and laptop, install the surface package with pacman, run the + preview, then choose adoption deliberately. The phone's existing live + symlink development loop remains valid until this proves itself. + +## Later: desktop profile + +`souveraine-desktop` is a meta-package that depends on the substrate and +surface packages. It does not adopt the surface itself; its post-install +message directs the user to the preview command. This gives a future fresh +machine one clear install target without sacrificing ownership of its shell. + +## Acceptance + +- `pacman -S souveraine` never changes a QuickShell file. +- `pacman -S souveraine-surface-quickshell` never changes a QuickShell file. +- The adoption command clearly reports its plan and refuses unapproved + replacements. +- A deliberate adoption makes `/agent`, `/resume`, agent selection, and the + Souveraine panel available against the locally running package service. +- An upgrade and uninstall preserve user settings and agent state. diff --git a/docs/tasks/souveraine-cicd-pipeline.md b/docs/tasks/souveraine-cicd-pipeline.md new file mode 100644 index 0000000..836a263 --- /dev/null +++ b/docs/tasks/souveraine-cicd-pipeline.md @@ -0,0 +1,127 @@ +--- +task_id: souveraine-cicd-001 +title: CI/CD pipeline — Souveraine as an installed program across laptop, phone, desktop/servers +status: partial +assignee: +priority: high +phase: infrastructure +--- + +# Task: Real build/install pipeline for Souveraine across all machines + +## Implemented status — 2026-07-13 + +The core package rail is now real, although this document's original Gitea +native-registry design was implemented as a signed rolling Gitea Release +repository instead: + +- ArchDev runs the `archdev` Actions runner and cross-builds `aarch64`; it also + builds the native `x86_64` binary. +- CI produces and signs separate architecture-specific pacman databases and + package assets for the `edge` release. +- The archive key is installed and locally trusted on the laptop. Its private + Gitea credentials are held in a root-owned, `alpm`-readable netrc and used + only by the internal archive fetch wrapper. +- Laptop installation is verified: `souveraine 0.1.r137.gc8c72ecbf222-1` owns + `/usr/bin/souveraine`, runs as an enabled systemd user service, and is + discoverable/upgradable through pacman. +- Phone rollout is pending the return of its USB/network connection. No phone + data was changed after the link disappeared. + +The remaining delivery gap is the QuickShell body. Core packages intentionally +ship no QML or ii overlay files. Its package boundary and safe opt-in adoption +contract now live in `quickshell-surface-package.md`. + +## Casey's framing (2026-07-12) + +Souveraine has been running as hand-shipped binaries + live edits while the +agent itself is "acting on its own memory stuff (good stuff)" — but it "needs +to be an installed program before too long, referencing the actual souveraine +builds." A fresh session should build the CI/CD pipeline between laptop, +phone, and desktop/servers — that makes more logistical sense than more +one-off deploys. + +## What tonight's wrap already put in place (build on this, don't redo) + +- `surfaces/quickshell/deploy.sh` — manifest symlink deploy, `--phone` mode + (rsync + on-device symlinks). Live edits now land in a git tree. + Committed 037dc06. +- `packaging/deploy-phone.sh` — ships cross-built binary + user unit to the + phone; seed-id excluded (machine binding doctrine). Committed 2c218fb. +- `packaging/arch/PKGBUILD` — builds from a synced local checkout, no network + fetch. Same commit. This is the "installed program" seed: `pacman -U` beats + scp-to-/usr/local. +- `packaging/souveraine.service` — the systemd user unit. +- `scripts/build-cross.sh` (untracked — scripts/ is deliberately gitignored on + the public branch; decide where build tooling lives when designing the + pipeline). +- Infra facts: ArchDev LXC (10.10.20.123) is the build host; aarch64 sysroot + at ~/aarch64-sysroot + ~/aarch64-blueline.toolchain.cmake (proven by the + OpenAuto build); gitea (10.10.20.120:4455) is the source-of-truth remote and + the kernel already follows a commit->gitea->ArchDev-build->flash loop worth + imitating. + +## DESIGN (settled 2026-07-12, verified against live infra — build to this) + +Verified: gitea is 1.25.5 (Actions + native Arch package registry both in). +ArchDev already has cargo + BOTH rust targets (x86_64 + aarch64-unknown- +linux-gnu) installed. Missing: act_runner, registry enablement, workflow. + +The spine: gitea is hub AND package server. No new services. + +1. **act_runner on ArchDev** (host executor, NOT docker — unprivileged LXC, + and the proven cross env lives on the host). Label `archdev`. Systemd + service, registration token from gitea admin. +2. **Souveraine workflow** (.gitea/workflows/build.yml): on push to main — + cargo build --release for both targets (aarch64 linker = + aarch64-linux-gnu-gcc, already installed for the kernel), makepkg via + packaging/arch/PKGBUILD for both CARCHes, upload .pkg.tar.zst to gitea's + Arch registry (PUT /api/packages/Fimeg/arch//). +3. **Clients** (phone aarch64, laptop/desktop x86_64) add to pacman.conf: + [souveraine] Server = http://gitea…/api/packages/Fimeg/arch// + Install/upgrade = `pacman -Syu souveraine`. Same command fresh or + upgrade (idempotence doctrine). Auth: token-user in URL, or set package + registry visibility public while source repos stay private. +4. **pkgver from git describe** — start tagging releases; CI stamps the + PKGBUILD pkgver so every package maps to a commit. +5. **Doctrine unchanged**: package NEVER carries seed-id or ~/.souveraine; + systemd user unit ships in the package; per-machine identity stays. +6. **Migration**: first packaged install lands in /usr/bin + systemd unit + path; then remove the hand-shipped /usr/local/bin/souveraine copies. + deploy-phone.sh stays as the emergency/dev path, no longer the main one. +7. **Later, same rails**: souveraine-surfaces package (files to /usr/share, + user opt-in symlink script; deploy.sh symlink mode stays the dev loop), + and linux-blueline publishing to the same registry (flash stays a + deliberate manual step via deploy-kernel.sh — never auto-flash). + +**Agent session split** (three independent sessions, in order): +- **infra**: enable Actions + package registry in gitea app.ini, install + + register act_runner on ArchDev, prove with a hello-world workflow and one + hand-uploaded package installed via pacman on the laptop. +- **build**: the real workflow — both arches, pkgver stamping, registry + publish. Deliverable: push to main produces installable packages. +- **rollout**: pacman.conf on phone + laptop, adopt packaged paths, retire + hand copies, verify fresh==upgrade on both machines, then souveraine on + the phone updates itself via one `pacman -Syu`. + +## Shape to aim for (original sketch, superseded by DESIGN above) + +1. Push to gitea -> CI builds (x86_64 + aarch64) on ArchDev (or a runner) -> + versioned artifacts: pacman packages (PKGBUILD exists) or a small package + repo machines can point at. +2. Install = `pacman -Syu souveraine` (or -U a fetched pkg) on phone and + desktop; systemd unit from the package; /usr/local hand-copies retired. +3. Per-machine identity stays doctrine: packages NEVER carry seed-id or + ~/.souveraine data; each instance is its own federated machine. +4. The quickshell surface rides the same train (package or the deploy.sh + manifest — decide; symlink-into-checkout is the dev mode, package is the + install mode). +5. Update path must be idempotent: same command fresh-installs AND upgrades. + +## Related + +- [[blueline-souveraine-kernel-os-provenance]] — partially superseded: the + deploy script + PKGBUILD adoption happened 2026-07-12; the remaining audit + (what else on the phone isn't repo-sourced) folds into this pipeline work. +- [[blueline-dock-provenance-and-deploy]] — the surface half, done via + surfaces/quickshell. diff --git a/scripts/install-quickshell-surface.sh b/scripts/install-quickshell-surface.sh new file mode 100755 index 0000000..aaf509b --- /dev/null +++ b/scripts/install-quickshell-surface.sh @@ -0,0 +1,91 @@ +#!/usr/bin/env bash +# Safely adopt the Souveraine QuickShell surface into an existing ii setup. +# +# This is deliberately separate from pacman installation: packages place +# assets on disk, while a person chooses whether their live shell may change. +set -euo pipefail + +usage() { + cat <<'EOF' +Usage: install-quickshell-surface.sh [--dry-run | --apply | --adopt] + + --dry-run Show every file the Souveraine surface would manage (default). + --apply Install when every target is new or already Souveraine-managed. + --adopt Permit replacing existing ii files after preserving a timestamped + copy beside each conflict. Implies --apply. + +Pacman should install surface assets only. This command is the explicit, +user-owned step that changes ~/.config/quickshell/ii. +EOF +} + +mode=dry-run +adopt=false +while (($#)); do + case "$1" in + --dry-run) mode=dry-run ;; + --apply) mode=apply ;; + --adopt) mode=apply; adopt=true ;; + -h|--help) usage; exit 0 ;; + *) echo "unknown option: $1" >&2; usage >&2; exit 2 ;; + esac + shift +done + +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +DEPLOY="$ROOT/surfaces/quickshell/deploy.sh" +QS="${XDG_CONFIG_HOME:-$HOME/.config}/quickshell" +II="$QS/ii" + +[[ -x "$DEPLOY" ]] || { echo "surface deployer not found: $DEPLOY" >&2; exit 1; } +[[ -d "$II" ]] || { + echo "No ii QuickShell configuration at $II." >&2 + echo "Install and initialise QuickShell/illogical-impulse first; no files changed." >&2 + exit 1 +} + +conflicts=() +new_count=0 +managed_count=0 + +while read -r rel target; do + src="$ROOT/surfaces/quickshell/$rel" + dst="$QS/$target" + [[ -f "$src" ]] || { echo "surface source missing: $src" >&2; exit 1; } + + if [[ -L "$dst" && "$(readlink -f "$dst")" == "$src" ]]; then + printf 'managed %s\n' "$target" + ((managed_count += 1)) + elif [[ -e "$dst" || -L "$dst" ]]; then + printf 'replace %s\n' "$target" + conflicts+=("$target") + else + printf 'new %s\n' "$target" + ((new_count += 1)) + fi +done < <("$DEPLOY" --manifest) + +printf '\n%d managed, %d new, %d replacement(s).\n' \ + "$managed_count" "$new_count" "${#conflicts[@]}" + +if [[ "$mode" == dry-run ]]; then + echo "Dry run only; use --apply when there are no replacements, or --adopt to preserve and replace them." + exit 0 +fi + +if ((${#conflicts[@]}) > 0) && [[ "$adopt" != true ]]; then + echo "Refusing to replace existing ii files without --adopt. No files changed." >&2 + exit 2 +fi + +if ((${#conflicts[@]}) > 0); then + stamp="$(date +%Y%m%d-%H%M%S)" + for target in "${conflicts[@]}"; do + dst="$QS/$target" + backup="${dst}.pre-souveraine-${stamp}" + cp -a -- "$dst" "$backup" + echo "preserved $target -> ${backup#$QS/}" + done +fi + +exec "$DEPLOY" diff --git a/surfaces/quickshell/deploy.sh b/surfaces/quickshell/deploy.sh index 6a7a607..aaf9383 100755 --- a/surfaces/quickshell/deploy.sh +++ b/surfaces/quickshell/deploy.sh @@ -42,6 +42,11 @@ pill/shell.qml pill/shell.qml PHONE_USB=casey@172.16.42.1 PHONE_DEST="souveraine-surfaces/quickshell" +if [[ "${1:-}" == "--manifest" ]]; then + printf '%s\n' "$MANIFEST" | sed '/^[[:space:]]*$/d' + exit 0 +fi + if [[ "${1:-}" == "--phone" ]]; then ssh_i=(ssh -i "$HOME/.ssh/ani" -o ConnectTimeout=5) "${ssh_i[@]}" "$PHONE_USB" "mkdir -p ~/$PHONE_DEST"