Operations and incremental assimilation
Create .secrets/artifact_token and .secrets/neo4j_auth with owner-only permissions, then copy them into Docker named secret volumes with scripts/prepare_compose_secrets.py. Docker Desktop’s local file-secret bind preserves host mode 0600, which the non-root service users cannot read; the named-volume copy stays inside Docker, is mounted read-only, and is mode 0444 there. Bind ports only to loopback. Ollama runs natively on macOS; Compose does not run Ollama. Keep model caches outside iCloud.
Configuration precedence is: validated CLI flags, environment variables, .env, then checked-in defaults. Secrets originate in owner-only host files, are copied into Docker-internal read-only volumes, and are never accepted from source notes or logged. The minimum environment is recorded in .env.example; production-like runs must record a redacted settings snapshot in the run manifest. LM Studio is needed only for embeddings; lms server status is the preflight check before indexing.
The host Codex CLI is the only distillation generator. Because this installation uses the OpenAI provider, sending private excerpts is an explicit data-egress decision. distill_file fails closed unless DEADWIRE_ALLOW_CODEX_EGRESS=1 is set after the account data policy is approved. A synthetic Codex smoke test must resolve gpt-5.6-luna before private excerpts are processed; if it fails, retain the error in the run manifest and stop. LM Studio chat completions are not an approved fallback. LM Studio may be started separately for batched embedding requests.
The version matrix for this handoff is Python 3.12, Swift 6.3.3, Docker Compose v5.5.1, Neo4j Community 2025.09.0-community (sha256:e2f0369a88cb3a846a6578bf73dfea38343f06b59d6f7b96117f762247726c6d for arm64), the artifact image’s pinned Python arm64 base (sha256:79082fdf411b897d64983893f44e8e1908e21cade2fc5a794d4f46de76c85275), LM Studio embeddings on host port 1234, Codex CLI gpt-5.6-luna, BGE-small-en-v1.5, and BGE-reranker-v2-m3. Luna must record the embedding model identifier, Codex CLI version, and immutable model revisions in evaluation output.
The artifact image was built successfully on the Apple Silicon host from the pinned base digest on 2026-09-10. A full Compose startup additionally requires local secret files under .secrets/ and the two external Docker secret volumes created by scripts/prepare_compose_secrets.py; do not commit those files or substitute credentials from source notes.
Build the native OCR adapter on macOS with swiftc native/DeadwireOCR/main.swift -framework Vision -framework ImageIO -o .deadwire/deadwire-ocr. It accepts a rendered page image and emits schema-versioned JSON with text, normalized bounding boxes, and recognition confidence. PDF rendering and page selection remain the Python extraction adapter’s responsibility; this boundary keeps Apple APIs out of the domain layer.
mkdir -p .secrets
openssl rand -hex 32 > .secrets/artifact_token
printf 'neo4j/%s\n' "$(openssl rand -base64 32)" > .secrets/neo4j_auth
chmod 600 .secrets/*
docker compose build artifacts
uv run python scripts/prepare_compose_secrets.py
docker compose config
docker compose up -d
docker compose ps
deadwire assimilate excludes Deadwire, generated curriculum/output folders, archives, caches, hidden files, unsupported media, and iCloud placeholders. It records every path and hash, then only runs invalidated stages. A stable hash with a new path reuses artifacts; a changed hash creates a new revision.
Stages are discovered → extracting → extracted → proposing → proposed → review → approved|rejected, with failed and retry count. A lock permits one writer. Recovery resumes from the last committed stage; partial files are quarantined. Publishing uses expected-content hashes and creates a conflict record if a human edit arrived first.
Distillation is resumable with scripts/distill_queue.py. The wrapper runs a bounded distill_batch.py subprocess, caps model attempts per batch, skips quarantined chunks by default so untouched work continues, records one JSON object per batch in ignored queue-progress.jsonl, and stops only when a batch attempts zero chunks. Pass --retry-failed for a deliberate retry pass. This makes an overnight or manually resumed run observable without placing private source text in logs. It never promotes a draft or treats a failed batch as learner evidence.
Back up canonical iCloud files using iCloud’s own versioning. Back up Docker volumes with a stopped database and docker run --rm -v deadwire_neo4j_data:/data -v "$PWD/backups:/backup" alpine tar czf /backup/neo4j.tar.gz -C /data .; restore only after validating the archive and stopping the service. Graph and artifacts can always be discarded and rebuilt from canonical notes and source files.