chore: prepare automation loop for Plan 2 (M8–M20)

- Add PLAN2.md with 116 tasks across M8–M20 with testing gates
- Populate loop/plan.md with all new tasks (30-attempt retry policy)
- Update loop/prompt.md to enforce glass design system and PLAN2.md
- Fix PassphraseDialog to use glass-card/gradient-button design system
- Fix crypto.randomUUID fallback for non-secure contexts
- Fix dev.sh to skip proxy startup if port 3141 already in use
- Fix PWA manifest for Android A2HS (purpose:any, display_override, id)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-03 22:29:18 +00:00
co-authored by Claude Opus 4.6
parent 69c32dce1c
commit 9f6158ddd2
8 changed files with 703 additions and 132 deletions
@@ -6,44 +6,40 @@
>
<!-- Backdrop -->
<div
class="absolute inset-0 bg-black/60 backdrop-blur-sm"
class="absolute inset-0 bg-black/70 backdrop-blur-sm"
@click.self="handleSkip"
/>
<!-- Dialog -->
<div
class="relative w-full max-w-sm rounded-2xl p-6 space-y-4 animate-scale-in"
:class="isDark
? 'bg-gray-900 border border-white/10'
: 'bg-white border border-gray-200 shadow-xl'"
>
<h2
class="text-lg font-bold"
:class="isDark ? 'text-white/90' : 'text-gray-900'"
>
{{ isCreating ? 'Create Passphrase' : 'Enter Passphrase' }}
</h2>
<p
class="text-xs"
:class="isDark ? 'text-white/50' : 'text-gray-500'"
>
{{ isCreating
? 'Set a passphrase to encrypt your data. You\'ll need it to access your conversations.'
: 'Enter your passphrase to decrypt your data.'
}}
</p>
<!-- Dialog uses glass-card from design system -->
<div class="glass-card relative w-full max-w-sm p-6 space-y-5 animate-scale-in">
<div class="space-y-3">
<!-- Header -->
<div class="flex items-center gap-3">
<div class="flex items-center justify-center w-10 h-10 rounded-xl bg-accent/15 border border-accent/30 shrink-0">
<svg class="w-5 h-5 text-accent" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M16.5 10.5V6.75a4.5 4.5 0 10-9 0v3.75m-.75 11.25h10.5a2.25 2.25 0 002.25-2.25v-6.75a2.25 2.25 0 00-2.25-2.25H6.75a2.25 2.25 0 00-2.25 2.25v6.75a2.25 2.25 0 002.25 2.25z" />
</svg>
</div>
<div>
<h2 class="text-base font-semibold text-white/96 leading-tight">
{{ isCreating ? 'Create Passphrase' : 'Unlock AIUI' }}
</h2>
<p class="text-xs text-white/40 mt-0.5">
{{ isCreating ? 'Encrypts all your data locally' : 'Enter your passphrase to decrypt' }}
</p>
</div>
</div>
<!-- Inputs -->
<div class="space-y-2.5">
<input
ref="inputRef"
v-model="passphrase"
type="password"
:placeholder="isCreating ? 'Create a passphrase...' : 'Enter your passphrase...'"
class="w-full px-4 py-3 rounded-xl text-sm outline-none transition-colors"
:class="isDark
? 'bg-white/5 text-white/90 placeholder:text-white/25 focus:bg-white/10 border border-white/10'
: 'bg-gray-50 text-gray-800 placeholder:text-gray-400 focus:bg-gray-100 border border-gray-200'"
:placeholder="isCreating ? 'Create a passphrase' : 'Enter passphrase'"
class="w-full px-4 py-3 rounded-xl bg-white/5 border border-white/10 text-white/90 placeholder:text-white/25 outline-none focus:border-white/30 focus:bg-white/8 transition-colors"
style="font-size: 16px"
autocomplete="current-password"
@keydown.enter="handleSubmit"
/>
@@ -51,42 +47,39 @@
v-if="isCreating"
v-model="confirmPassphrase"
type="password"
placeholder="Confirm passphrase..."
class="w-full px-4 py-3 rounded-xl text-sm outline-none transition-colors"
:class="isDark
? 'bg-white/5 text-white/90 placeholder:text-white/25 focus:bg-white/10 border border-white/10'
: 'bg-gray-50 text-gray-800 placeholder:text-gray-400 focus:bg-gray-100 border border-gray-200'"
placeholder="Confirm passphrase"
class="w-full px-4 py-3 rounded-xl bg-white/5 border border-white/10 text-white/90 placeholder:text-white/25 outline-none focus:border-white/30 focus:bg-white/8 transition-colors"
style="font-size: 16px"
autocomplete="new-password"
@keydown.enter="handleSubmit"
/>
<p
v-if="errorMessage"
class="text-xs text-red-400"
>
<p v-if="errorMessage" class="text-xs text-red-400 px-1">
{{ errorMessage }}
</p>
</div>
<!-- Actions -->
<div class="flex gap-2">
<button
class="flex-1 py-2.5 rounded-xl text-sm font-medium transition-colors"
:class="isDark
? 'bg-white/5 text-white/50 hover:bg-white/10'
: 'bg-gray-100 text-gray-500 hover:bg-gray-200'"
class="glass-button glass-button-sm flex-1 rounded-xl text-sm text-white/50 hover:text-white/80 transition-colors"
@click="handleSkip"
>
Skip
</button>
<button
class="flex-1 py-2.5 rounded-xl text-sm font-medium transition-colors bg-accent text-white hover:bg-accent/90"
class="gradient-button flex-1 h-10 rounded-xl text-sm font-medium text-white transition-opacity"
:disabled="!canSubmit"
:class="{ 'opacity-50 cursor-not-allowed': !canSubmit }"
:class="{ 'opacity-40 cursor-not-allowed': !canSubmit }"
@click="handleSubmit"
>
{{ isCreating ? 'Create' : 'Unlock' }}
</button>
</div>
<p class="text-xs text-white/25 text-center">
Data never leaves your device · AES-256-GCM
</p>
</div>
</div>
</Teleport>
@@ -94,7 +87,6 @@
<script setup lang="ts">
import { ref, computed, onMounted, nextTick } from 'vue'
import { useTheme } from '@/composables/useTheme'
const props = defineProps<{
visible: boolean
@@ -106,7 +98,6 @@ const emit = defineEmits<{
skip: []
}>()
const { isDark } = useTheme()
const passphrase = ref('')
const confirmPassphrase = ref('')
const errorMessage = ref('')