- Device stays air-gapped; leave adapters ON for Standard/Hardened; turn adapters OFF only for Paranoid pass check.
- Run commands from repo root; ensure default PIN
123456and Samples indexData/index.jsonexist. - Voice toggle must remain OFF on launch; large-text UI assumed.
python - <<'PY'
from services.security import pin_gate
first = pin_gate.change_pin("123456", "654321")
second = pin_gate.change_pin("654321", "123456")
print(first)
print(second)
PYExpected: Each PinResult shows ok=True with messages "PIN changed."; lockout counters reset.
python - <<'PY'
from services.security import pin_gate
result = pin_gate.change_pin("000000", "222222")
print(result)
PYExpected: ok=False, message "PIN failed.", lockout counter increments (lockout.failed > 0).
python - <<'PY'
from services.security import pin_gate
states = []
for attempt in range(1, 7):
res = pin_gate.unlock_with_pin("999999")
states.append((attempt, res.ok, res.message, res.lockout.failed, res.lockout.lockout_until, res.lockout.hard_lock))
print(states)
PYExpected: Attempts return ok=False. After 5th failure lockout.lockout_until becomes non-zero (15 min). Attempt 6 continues to deny with same lockout info; no hard lock yet.
python - <<'PY'
from services.security import pin_gate, keystore
phrase = keystore.generate_recovery_phrase()
keystore.set_phrase(phrase)
print("reset_fail", pin_gate.reset_with_recovery("wrong phrase", "222222"))
print("reset_ok", pin_gate.reset_with_recovery(phrase, "123456"))
PYExpected: First result ok=False with recovery error; second ok=True and message "PIN reset.".
python -m apps.launcher.main --mode standard --pin 123456 --probe --ask "Summarize Client A trust highlights" --index Data/index.jsonExpected: PIN accepted. followed by Standard audit with adapters detected; probe outputs DNS: BLOCKED (ok) and SOCKET: BLOCKED (ok); answer provides bullets plus Samples citations.
python -m apps.launcher.main --mode hardened --pin 123456 --probe --ask "List liquidity and distribution targets" --index Data/index.jsonExpected: Hardened audit mentions outbound + DNS blocked and limited privileges; probe still blocked; Data/tmp/ exists and env vars TMP, TEMP, TMPDIR point inside repo.
python - <<'PY'
import os
print(os.environ.get("TMP"))
print(os.environ.get("TEMP"))
print(os.path.isdir(os.environ.get("TMP")))
PYExpected: Printed paths under Data/tmp/ and directory exists.
python - <<'PY'
from services.security import net_guard
net_guard.wipe_temp_sandbox()
print("sandbox_reset", net_guard._tmp_root)
PYExpected: Sandbox directory removed; _tmp_root prints None; follow-up check shows Data/tmp/ regenerated clean by next guard run.
python -m apps.launcher.main --mode paranoid --pin 123456 --probeExpected: Audit prints Mode: Paranoid — Adapters detected; please disable Wi-Fi/unplug Ethernet. and process exits before host alias or voice audits. Re-run with adapters physically disabled to confirm pass (optional).
python - <<'PY'
from services.preflight.audit import audit_voice
print(audit_voice(True).msg)
print(audit_voice(False).msg)
PYExpected: Messages match apps/ui/voice_script.md: "Voice Mode enabled. Hold space to speak." then "Voice Mode disabled."
Re-use Standard/Hardened launcher runs above to confirm answers follow docs/prompt_templates.md patterns (plan → answer → sources) and require explicit "Sources" request before speaking citations.
python -m apps.launcher.main --mode standard --pin 123456 --ingest Samples --client client-a --dest HOST_LOCALExpected: Launcher reports checksum verification before ingest starts, queues a job, and writes ledger entries noting chunk counts. Data/ingest_jobs/job-*.json shows storage_mode + OCR availability, and Data/ingested_registry.json records manifest + job_id for client-a.
python -m apps.launcher.main --mode standard --pin 123456 --ingest Samples --client client-a --dest STICK_ENCRYPTED --confirm-set-source SamplesExpected: Source validation runs, HOST_LOCAL chunks are encrypted via configured provider, and ledger output includes the provider audit line. Registry updates storage_mode to STICK_ENCRYPTED with encrypted index path and manifest reference. Failure to load crypto provider aborts with a clear error.
- Device remains air-gapped; adapters stay ON for Standard/Hardened streaming checks and OFF for Paranoid validation.
- Default LLM profile targeted for Day-3 (
offline-balanced-q4) and model assets staged underApp/models/llm/; wrapper tooling lives incore/llm/. - SHA256 manifests prepared beneath
packaging/checksums/(one JSON manifest +.sha256files). Keep WindowsGet-FileHashavailable for spot checks. - Web UI static bundle rebuilt (including
apps/webui/static/app.js) and SSE streaming flag enabled by Day-3 deliverable.
python -m core.llm.wrap --list-profilesExpected: Table lists offline-balanced-q4 with footprint metadata and marks it (default).
python -m core.llm.wrap --run --profile offline-balanced-q4 --prompt "Summarize Client A trust highlights."Expected: Wrapper streams tokens to stdout without network calls; exit code 0 when binaries/models present. On missing assets, returns actionable error referencing App/bin/llama/ and App/models/llm/ paths.
Get-ChildItem packaging/checksums/*.sha256 | ForEach-Object { Get-Content $_ }Expected: Manifests list SHA256 for each Day-3 artifact (LLM binaries, GGUF models, web assets).
python - <<'PY'
import json, subprocess, pathlib
manifest = json.load(open('packaging/checksums/manifest.json', 'r', encoding='utf-8'))
for rel_path, expected in manifest.items():
path = pathlib.Path(rel_path)
result = subprocess.run(['powershell', '-NoLogo', '-Command', f"Get-FileHash -Algorithm SHA256 '{path}'"], capture_output=True, text=True)
hash_line = next((line for line in result.stdout.splitlines() if line.strip().startswith('SHA256')), '')
actual = hash_line.split(':', 1)[-1].strip()
print(rel_path, actual == expected)
PYExpected: Every entry prints True. Any mismatch blocks acceptance until corrected.
python -m apps.launcher.main --mode standard --pin 123456 --probe --ui standard --ask "List open questions for Client A"Expected: Hardened-style audits for Standard mode (DNS/SOCKET blocked) then Loopback Web UI available at http://127.0.0.1:<port>. Browser opens automatically. In the UI, the answer renders incrementally (streaming chunks) before citations appear—verifiable in browser dev tools Network tab (/stream SSE).
python -m apps.launcher.main --mode hardened --pin 123456 --probe --ui enhanced --ask "Outline checksum policy for Day 3"Expected: Hardened audit includes temp sandbox verification (Temp sandbox — verified). UI loads in enhanced (large text) view with the same streaming behaviour as Standard. Guard prints continue to show DNS/socket blocked.
python -m apps.launcher.main --mode paranoid --pin 123456 --probe --ask "Confirm Paranoid fallback behaviour"Expected: Paranoid audit refuses to launch UI (UI server disabled in Paranoid mode.) while CLI answer prints plan + bullets and cites Sources on demand. No browser window opens. Capture console transcript and checksum verification logs for the acceptance bundle.