agent: lumotia — v0.1 release-completion run
Some checks failed
check / cargo check (macos-latest) (push) Has been cancelled
check / cargo check (ubuntu-22.04) (push) Has been cancelled
check / cargo check (windows-latest) (push) Has been cancelled
check / svelte build + lint (push) Has been cancelled

Closes the code-side v0.1 ship gate. All quality gates green:
cargo fmt/clippy/test (~327 tests), npm check (0/0), vitest 13/13,
scripts/dogfood-rebrand-drill.sh 8/8.

Phase F — first-run onboarding promoted to v0.1
- FirstRunPage with skip-to-main + failure recovery + event recording
- Six onboarding commands (record/list/has-completed + lumotia_events)
- Storage migration v17 (onboarding_events + lumotia_events tables)

UI hardening (in-scope items from v0.1-ui-hardening.md)
- StatusPill + PostCaptureCard components, 21st preview entry
- Sidebar recording-as-sacred-state (opacity + aria-disabled, reduced-motion)
- Settings 6-section regroup + Help section + Activation log + Privacy toggle
- Error-state copy sweep (DictationPage + SettingsPage, plain-language)
- Global :focus-visible rule, textarea outlines restored
- Ctrl+K / Ctrl+, / Escape bindings in +layout

LLM resilience
- rule_based_extract_tasks (regex-free imperative-verb extractor) +
  extract_tasks_with_fallback wrapper — task extraction never returns zero
- tokio::time::timeout(120s) wraps cleanup/tags/tasks commands

Release artefacts
- LICENSE (canonical AGPL-3.0), CHANGELOG (Keep-a-Changelog format)
- v0.1-release-notes, privacy-and-ai-use, install-warnings,
  tester-onboarding-kit, tester-acceptance-runbook, code-signing-setup,
  apple-silicon-rb08-runbook, virtual-audio-setup, v0.1-contrast-audit
- Workspace versioning + AGPL spdx; npm exact-pin (10 ranges removed)
- AppImage SHA-256 sidecar in build.yml
- README v0.1 section + Reporting-issues; canonical repo slug

Closure pass — items moved from human-required to code-complete
- KI-02 Linux idle inhibit: zbus 5 → org.freedesktop.login1.Manager.Inhibit
- KI-03 Windows sleep prevention: SetThreadExecutionState(ES_CONTINUOUS|...)
- acquire/release_idle_inhibit Tauri commands, wired in DictationPage
- Diagnostic-bundle frontend wire-up (Settings → Help button)
- WCAG-AA contrast fix via .btn-filled-text utility (no token changes)
- 8 destructive-action sites wrapped in plain-language confirm() guards
- KNOWN-ISSUES.md + v0.1-known-limitations.md updated (KI-02/03 fixed)

Scripts
- pre-tag-verify.sh, tag-day.sh, smoke-linux + driver
- parse-diagnostic-bundle.sh, parse-activation-log.py

Per-item audit trail: docs/release/v0.1-completion-status.md
Remaining: W-01…W-08 (signing certs, hardware probes, smoke matrix,
tester recruitment) — see docs/release/v0.1-known-limitations.md.
This commit is contained in:
2026-05-15 06:59:08 +01:00
parent bf1b68275a
commit 3770815fbf
77 changed files with 8697 additions and 1017 deletions

View File

@@ -0,0 +1,153 @@
#!/usr/bin/env bash
# parse-diagnostic-bundle.sh — summarise a Lumotia diagnostic bundle zip.
# Usage: ./scripts/parse-diagnostic-bundle.sh path/to/tester-bundle.zip
# Requires: unzip (required), jq (preferred; graceful grep fallback).
# Privacy: never prints transcript text, audio content, or .db content.
set -euo pipefail
BOLD='\033[1m'; GREEN='\033[0;32m'; RED='\033[0;31m'; YELLOW='\033[0;33m'; RESET='\033[0m'
pass() { printf "${GREEN}${RESET} %s\n" "$*"; }
fail() { printf "${RED} ×${RESET} %s\n" "$*"; OVERALL_FAIL=1; }
warn() { printf "${YELLOW} !${RESET} %s\n" "$*"; }
info() { printf " %s\n" "$*"; }
header(){ printf "\n${BOLD}%s${RESET}\n" "$*"; }
OVERALL_FAIL=0
# Argument + file validation
[[ $# -lt 1 ]] && { echo "Usage: $0 path/to/tester-bundle.zip" >&2; exit 1; }
BUNDLE="$1"; BUNDLE_NAME="$(basename "$BUNDLE")"
[[ ! -f "$BUNDLE" ]] && { echo "ERROR: file not found: $BUNDLE" >&2; exit 2; }
if ! file "$BUNDLE" 2>/dev/null | grep -qi 'zip'; then
(dd if="$BUNDLE" bs=2 count=2 2>/dev/null | grep -q 'PK') \
|| { echo "ERROR: $BUNDLE does not appear to be a zip archive." >&2; exit 2; }
fi
# jq check
HAS_JQ=0
command -v jq &>/dev/null && HAS_JQ=1 \
|| echo "WARNING: jq not found — falling back to grep-based extraction. Install jq for best results." >&2
# Extract
TMPDIR_WORK="$(mktemp -d)"; trap 'rm -rf "$TMPDIR_WORK"' EXIT
unzip -q "$BUNDLE" -d "$TMPDIR_WORK" 2>/dev/null \
|| { echo "ERROR: failed to extract $BUNDLE" >&2; exit 3; }
# Header
TITLE="LUMOTIA DIAGNOSTIC BUNDLE SUMMARY: $BUNDLE_NAME"
printf "\n${BOLD}%s${RESET}\n" "$TITLE"
printf '%0.s=' $(seq 1 ${#TITLE}); printf '\n'
# metadata.json → version + timestamps
META="$TMPDIR_WORK/metadata.json"; GEN_AT=""; VERSION=""
if [[ -f "$META" ]]; then
if [[ $HAS_JQ -eq 1 ]]; then
GEN_AT="$(jq -r '.generated_at // empty' "$META" 2>/dev/null)"
VERSION="$(jq -r '.lumotia_version // empty' "$META" 2>/dev/null)"
else
GEN_AT="$(grep -o '"generated_at":[^,}]*' "$META" | grep -o '[0-9]*' | head -1)"
VERSION="$(grep -o '"lumotia_version":"[^"]*"' "$META" | cut -d'"' -f4)"
fi
fi
GEN_HUMAN=""
if [[ -n "$GEN_AT" && "$GEN_AT" =~ ^[0-9]+$ ]]; then
GEN_HUMAN="$(date -u -d "@$GEN_AT" '+%Y-%m-%dT%H:%M:%SZ' 2>/dev/null \
|| date -u -r "$GEN_AT" '+%Y-%m-%dT%H:%M:%SZ' 2>/dev/null \
|| echo "$GEN_AT (epoch)")"
fi
info "Generated: ${GEN_HUMAN:-unknown}"
info "Lumotia version: ${VERSION:-unknown}"
# system_info.txt → platform
SYSINFO="$TMPDIR_WORK/system_info.txt"
if [[ -f "$SYSINFO" ]]; then
OS_LINE="$(grep -i '^OS:' "$SYSINFO" | head -1 | sed 's/^OS: *//')"
ARCH_LINE="$(grep -i '^Arch:' "$SYSINFO" | head -1 | sed 's/^Arch: *//')"
info "Platform: ${OS_LINE:-unknown} / ${ARCH_LINE:-unknown}"
fi
# Content inventory
header "CONTENT INVENTORY:"
check_path() {
[[ -e "$TMPDIR_WORK/$2" ]] && pass "$1" || warn "$1 (not present)"
}
check_path "system_info.txt" "system_info.txt"
check_path "preferences-redacted.json" "preferences-redacted.json"
check_path "metadata.json" "metadata.json"
LOG_DIR="$TMPDIR_WORK/logs"; LOG_COUNT=0
if [[ -d "$LOG_DIR" ]]; then
LOG_COUNT="$(find "$LOG_DIR" -type f | wc -l)"
pass "logs/ ($LOG_COUNT files, $(du -sh "$LOG_DIR" 2>/dev/null | cut -f1))"
else warn "logs/ (directory not present)"; fi
CRASH_DIR="$TMPDIR_WORK/crashes"
if [[ -d "$CRASH_DIR" ]]; then
CRASH_COUNT="$(find "$CRASH_DIR" -type f | wc -l)"
[[ "$CRASH_COUNT" -eq 0 ]] \
&& pass "crashes/ (0 files) — no crash dumps, good" \
|| warn "crashes/ ($CRASH_COUNT files) — crash dumps present, review carefully"
else pass "crashes/ (directory absent) — no crash dumps, good"; fi
# Redaction check — bundle MUST NEVER contain these
header "REDACTION CHECK (bundle MUST NEVER include these):"
DENY_CLEAN=1
check_absent() {
local hits; hits="$(find "$TMPDIR_WORK" -type f | { grep -iE "$2" 2>/dev/null || true; })"
[[ -z "$hits" ]] && pass "$1" \
|| { fail "$1 — FOUND: $(printf '%s' "$hits" | head -3 | tr '\n' ' ')"; DENY_CLEAN=0; }
}
check_absent "no .wav files" '\.wav$'
check_absent "no .mp3/.opus/.ogg/.flac files" '\.(mp3|opus|ogg|flac)$'
check_absent "no transcripts/ paths" '/transcripts/'
check_absent "no captures/ paths" '/captures/'
check_absent "no .db files" '\.(db|db-wal|db-shm)$'
check_absent "no .env files" '(^|/)\.env(\.|$)'
if [[ $DENY_CLEAN -eq 1 ]]; then
printf "\n${GREEN} PASS: bundle passed redaction check.${RESET}\n"
else
printf "\n${RED} FAIL: bundle contains DENIED content — do not share this bundle.${RESET}\n"
OVERALL_FAIL=1
fi
# Log analysis
header "LOG ANALYSIS (last 7 days):"
if [[ -d "$LOG_DIR" && "$LOG_COUNT" -gt 0 ]]; then
ALL_LOGS="$(find "$LOG_DIR" -type f -exec cat {} \;)"
ERR_COUNT="$(printf '%s' "$ALL_LOGS" | { grep -iE '(ERROR|ERRO|\bERR\b)' 2>/dev/null || true; } | wc -l)"
WARN_COUNT="$(printf '%s' "$ALL_LOGS" | { grep -iE '(WARN|WARNING)' 2>/dev/null || true; } | wc -l)"
info "Errors: $ERR_COUNT"
info "Warnings: $WARN_COUNT"
if [[ "$ERR_COUNT" -gt 0 ]]; then
info ""; info "TOP 3 ERROR PATTERNS:"
printf '%s' "$ALL_LOGS" \
| { grep -iE '(ERROR|ERRO|\bERR\b)' || true; } \
| sed 's/^[0-9TZ:. -]*//' | sort | uniq -c | sort -rn | head -3 \
| while IFS= read -r line; do info " × $line"; done
fi
else warn "No log files found."; fi
# Preferences (non-secret values)
PREFS="$TMPDIR_WORK/preferences-redacted.json"
header "PREFERENCES (redacted secrets):"
if [[ ! -f "$PREFS" ]]; then
warn "preferences-redacted.json not found"
elif [[ $HAS_JQ -eq 1 ]]; then
jq -r 'paths(scalars) as $p | getpath($p)
| select(. != "[redacted]" and . != null and . != "")
| "\($p | join(".")): \(.)"' "$PREFS" 2>/dev/null | head -30 \
| while IFS= read -r line; do info " $line"; done
REDACTED_COUNT="$(jq '[.. | strings | select(. == "[redacted]")] | length' "$PREFS" 2>/dev/null || echo '?')"
info " ($REDACTED_COUNT field(s) redacted by bundler)"
else
{ grep -oE '"[^"]+": *("[^"]*"|[0-9.]+|true|false)' "$PREFS" || true; } \
| grep -v '\[redacted\]' | head -30 | while IFS= read -r line; do info " $line"; done
fi
# Verdict
header "VERDICT:"
if [[ $OVERALL_FAIL -eq 0 ]]; then
printf "${GREEN} PASS: bundle looks healthy. Safe to inspect for bug triage.${RESET}\n\n"
else
printf "${RED} FAIL: one or more checks failed — review items marked × above.${RESET}\n\n"
exit 1
fi