From 4d7d8bf42e2924722534b06409675443cca46275 Mon Sep 17 00:00:00 2001
From: Justin Soderberg <723679+sodejm@users.noreply.github.com>
Date: Tue, 13 Oct 2026 20:56:02 -0400
Subject: [PATCH 1/4] docs: correct source setup order and prerequisites
---
README.md | 13 +++++++++----
docs/tutorials/offline-gedcom-merge.md | 20 ++++++++++++--------
2 files changed, 21 insertions(+), 12 deletions(-)
diff --git a/README.md b/README.md
index af79ba48..6a5837b3 100644
--- a/README.md
+++ b/README.md
@@ -86,14 +86,19 @@ and [interactive-console guide](https://github.com/sodejm/AncestryLLM/blob/main/
### Work from source
-A source checkout requires a system-supplied Python 3.12 through 3.14. After
-following the
-[verified uv bootstrap guide](https://github.com/sodejm/AncestryLLM/blob/main/docs/security/verified-uv-bootstrap.md),
-run:
+A source checkout requires a system-supplied Python 3.12 through 3.14. First,
+clone the repository and enter its root:
```console
git clone https://github.com/sodejm/AncestryLLM.git
cd AncestryLLM
+```
+
+From that directory, follow the authentication and verification prerequisites in
+the [verified uv bootstrap guide](https://github.com/sodejm/AncestryLLM/blob/main/docs/security/verified-uv-bootstrap.md),
+then create and test the environment:
+
+```console
make setup
make test
```
diff --git a/docs/tutorials/offline-gedcom-merge.md b/docs/tutorials/offline-gedcom-merge.md
index 0327108e..47361691 100644
--- a/docs/tutorials/offline-gedcom-merge.md
+++ b/docs/tutorials/offline-gedcom-merge.md
@@ -21,7 +21,7 @@ data directories inside that run directory.
## Prerequisites
-- A checkout of this repository and Python 3.12 or newer.
+- A checkout of this repository and a system-supplied Python 3.12 through 3.14.
- A shell in the repository root.
- A disposable output parent such as `./ancestryllm-tutorial-output`. Do not
use a directory containing real genealogy data, a RootsMagic database, a
@@ -33,15 +33,18 @@ not open a database.
## 1. Create the supported environment
-Create the project environment once:
+From the repository root, follow the authentication and verification
+prerequisites in the [verified uv bootstrap guide](../security/verified-uv-bootstrap.md).
+Then create the project environment:
```console
make setup
```
-If dependency installation cannot use your configured package index, stop
-here. The tutorial's merge itself is offline, but initial package installation
-is a separate setup operation and can contact that configured index.
+If bootstrap verification or dependency installation fails, stop here and use
+the bootstrap guide's recovery steps. Bootstrap verification contacts GitHub,
+and dependency installation can contact your configured package index. These
+setup operations are separate from the network-free merge below.
## 2. Run the fictional merge
@@ -88,9 +91,10 @@ evidence.
## Recovery and cleanup
-- If `make setup` fails, repair the Python or package-index problem and rerun
- it before using `--skip-install`; do not point `ANCESTRYLLM_PYTHON` at an
- unverified interpreter.
+- If `make setup` fails, follow the bootstrap guide to resolve the Python,
+ authentication, verification, or package-index problem. Rerun setup before
+ using `--skip-install`; do not point `ANCESTRYLLM_PYTHON` at an unverified
+ interpreter.
- If the merge reports an error, keep the printed error and inspect the
fictional input named there. A rejected merge invocation publishes neither
its GEDCOM nor its report. Correct only a disposable copy, then rerun the
From 67ef16ffa8d0c178816da48ebed6e2d39eda8ea8 Mon Sep 17 00:00:00 2001
From: Justin Soderberg <723679+sodejm@users.noreply.github.com>
Date: Tue, 13 Oct 2026 21:04:15 -0400
Subject: [PATCH 2/4] docs: separate supported desktop onboarding from source
previews
Put task navigation and setup first while retaining detailed security contracts in the desktop guide. Update metadata and documentation assertions for the supported installer and fictional preview distinction.
Documentation-only change: application behavior, architecture, and threat-model boundaries are unchanged; no failing application behavior test applies. The documentation regression suite passes all 296 tests.
---
desktop/README.md | 138 +++++++++---------
docs/DOCS_AUTHORING.md | 2 +-
docs/Home.md | 133 +++++++----------
docs/_Sidebar.md | 13 +-
docs/_data/page_metadata.json | 2 +-
docs/explanation/DESKTOP_SHELL.md | 30 +++-
docs/tutorials/desktop-first-run.md | 57 +++++---
tests/test_desktop_learning_path_docs.py | 2 +-
...est_documentation_architecture_contract.py | 15 +-
9 files changed, 205 insertions(+), 187 deletions(-)
diff --git a/desktop/README.md b/desktop/README.md
index d81fd5e1..f4188511 100644
--- a/desktop/README.md
+++ b/desktop/README.md
@@ -1,7 +1,77 @@
# AncestryLLM desktop shell
This directory contains the UI-only Electron adapter and the packaged
-control-sidecar supervisor. It intentionally implements no genealogy domain
+control-sidecar supervisor.
+
+The supported 0.6.0 product surface is a one-time local welcome on Home, a temporary Home-based welcome review, Diagnostics, a sanitized capability summary, and local visual Settings only. It has no genealogy, files, jobs, chat, providers, cloud accounts, or updater controls. See the [desktop shell guide](../docs/explanation/DESKTOP_SHELL.md) for first-run behavior, supported targets, manual installation, unsigned-artifact limits, and recovery guidance.
+
+## Reproducible setup and gates
+
+From the repository root, use Node `26.5.0` (see `.node-version`), Corepack, and the repository-pinned pnpm `11.9.0`:
+
+```sh
+corepack enable
+corepack prepare pnpm@11.9.0 --activate
+make desktop-install
+make desktop-check
+make desktop-e2e
+make desktop-security
+pnpm --dir desktop test:accessibility
+pnpm --dir desktop test:visual
+```
+
+`desktop-install` performs the frozen-lockfile install, explicitly rebuilds the
+locked Electron package, and fails with a stable error if its platform runtime
+is still absent. The explicit rebuild makes setup fail closed even when a
+shared pnpm store contains stale build-script state. Electron 41.10.6 remains
+exactly pinned. The frozen lockfile scopes reviewed security replacements to
+the affected installer and test-tool dependency paths, including the
+Electron-maintained `@electron-internal/extract-zip` 1.0.5 fork; no runtime
+patch is required for the current Electron installer. WebdriverIO uses Mocha
+11.8.0 so its Chokidar 4 watcher retains Mocha's supported glob handling. The
+unused optional `@electron/get` legacy proxy agent is removed because it has
+no patched release. Installation and packaging fail explicitly when
+`ELECTRON_GET_USE_PROXY` is nonempty instead of silently ignoring that requested
+legacy behavior.
+
+`desktop-check` runs lint, separated main/preload/renderer type checks, unit
+tests, the presentation-boundary contract, and a source-map-free build
+inspection. `desktop-e2e` builds the production renderer and launches it in
+Electron with a deterministic fictional mock bridge; it is not an installer
+or literal packaged-executable test. `test:accessibility` scans every shell
+route in light, dark, and high-contrast modes with the exact locked `axe-core`
+version in real Chromium. Linux CI launches this source scan through
+`xvfb-run --auto-servernum` after verifying the installed Chromium SUID sandbox
+is a regular root-owned file with mode `4755`; WebdriverIO retains its automatic
+Xvfb fallback, and the Electron sandbox stays enabled. `test:visual` checks the minimum
+720-by-560 window at 200% zoom for horizontal clipping. Neither command
+replaces the manual screen-reader review in the
+[desktop shell guide](../docs/explanation/DESKTOP_SHELL.md).
+`desktop-security` runs the high-severity dependency audit, source secret scan,
+produces `desktop/sbom.cdx.json` (ignored by Git), builds an unpacked directory
+package after verifying the native sidecar resource, and inspects the resulting
+`app.asar`, eight packaged Electron fuses, and supported ASAR-integrity
+metadata. Local and ordinary CI builds remain unsigned verification inputs.
+Full production/trusted signing is deferred until v1.0.0: project-produced
+`0.x` release installers and annotated release tags must be unsigned. The tag
+release uses `electron-builder.release.yml` only after exact-head gates pass;
+it builds the four manual-installer rows documented in the
+[release runbook](../docs/RELEASING.md), then binds their declared signing mode,
+checksums, SBOMs, evidence, and provenance before publication. No updater feed,
+background update, staged rollout, or automatic rollback is configured.
+
+For a fictional development-only component review, run:
+
+```sh
+pnpm --dir desktop dev:gallery
+```
+
+The production build verifier rejects gallery copy and fixtures, embedded
+remote assets, and remote network endpoints.
+
+## Source-level contracts
+
+This adapter intentionally implements no genealogy domain
behavior and does not access files, databases, provider credentials, the
network, or operating-system services from the renderer. The versioned
`window.ancestry` bridge retains the six 0.5 control methods for application
@@ -25,7 +95,7 @@ renderer **Chat** destination over those fixed contracts. The combined surface
adds no generic request channel, renderer network access, tool surface, file or
database authority, genealogy operation, or persistent conversation store.
-The supported 0.6.0 product surface is a one-time local welcome on Home, a temporary Home-based welcome review, Diagnostics, a sanitized capability summary, and local visual Settings only. It has no genealogy, files, jobs, chat, providers, cloud accounts, or updater controls. See the [desktop shell guide](../docs/explanation/DESKTOP_SHELL.md) for first-run behavior, supported targets, manual installation, unsigned-artifact limits, and recovery guidance.
+
Source-level gated Issue #106 adds the reusable, responsive presentation shell for the
0.6 desktop work. Its `AppRoute`, `NavigationItem`, `CapabilityGate`,
@@ -84,70 +154,6 @@ Issue #103 is a source-level gated security foundation, not a supported 0.6 doma
The persisted schema contains only color scheme, reduced-motion choice, onboarding completion, schema version, and optimistic revision. `onboardingCompleted` is internal workflow state, not a Settings control. Continue persists that flag through the existing bridge, and a new application process skips the welcome only after a fresh valid snapshot reports completion. Conflicts, unavailable or malformed responses, and corrupt or unsupported storage fail closed and do not silently unlock or overwrite the file. Writes are validated, serialized, and atomically replace the file. Missing or supported legacy data receives safe defaults. Provider configuration, accounts, file grants, genealogy data, prompts, payloads, and secrets are never preference fields.
-## Reproducible setup and gates
-
-Use Node `26.5.0` (see `.node-version`), Corepack, and the repository-pinned pnpm `11.9.0`:
-
-```sh
-corepack enable
-corepack prepare pnpm@11.9.0 --activate
-make desktop-install
-make desktop-check
-make desktop-e2e
-make desktop-security
-pnpm --dir desktop test:accessibility
-pnpm --dir desktop test:visual
-```
-
-`desktop-install` performs the frozen-lockfile install, explicitly rebuilds the
-locked Electron package, and fails with a stable error if its platform runtime
-is still absent. The explicit rebuild makes setup fail closed even when a
-shared pnpm store contains stale build-script state. Electron 41.10.6 remains
-exactly pinned. The frozen lockfile scopes reviewed security replacements to
-the affected installer and test-tool dependency paths, including the
-Electron-maintained `@electron-internal/extract-zip` 1.0.5 fork; no runtime
-patch is required for the current Electron installer. WebdriverIO uses Mocha
-11.8.0 so its Chokidar 4 watcher retains Mocha's supported glob handling. The
-unused optional `@electron/get` legacy proxy agent is removed because it has
-no patched release. Installation and packaging fail explicitly when
-`ELECTRON_GET_USE_PROXY` is nonempty instead of silently ignoring that requested
-legacy behavior.
-
-`desktop-check` runs lint, separated main/preload/renderer type checks, unit
-tests, the presentation-boundary contract, and a source-map-free build
-inspection. `desktop-e2e` builds the production renderer and launches it in
-Electron with a deterministic fictional mock bridge; it is not an installer
-or literal packaged-executable test. `test:accessibility` scans every shell
-route in light, dark, and high-contrast modes with the exact locked `axe-core`
-version in real Chromium. Linux CI launches this source scan through
-`xvfb-run --auto-servernum` after verifying the installed Chromium SUID sandbox
-is a regular root-owned file with mode `4755`; WebdriverIO retains its automatic
-Xvfb fallback, and the Electron sandbox stays enabled. `test:visual` checks the minimum
-720-by-560 window at 200% zoom for horizontal clipping. Neither command
-replaces the manual screen-reader review in the
-[desktop shell guide](../docs/explanation/DESKTOP_SHELL.md).
-`desktop-security` runs the high-severity dependency audit, source secret scan,
-produces `desktop/sbom.cdx.json` (ignored by Git), builds an unpacked directory
-package after verifying the native sidecar resource, and inspects the resulting
-`app.asar`, eight packaged Electron fuses, and supported ASAR-integrity
-metadata. Local and ordinary CI builds remain unsigned verification inputs.
-Full production/trusted signing is deferred until v1.0.0: project-produced
-`0.x` release installers and annotated release tags must be unsigned. The tag
-release uses `electron-builder.release.yml` only after exact-head gates pass;
-it builds the four manual-installer rows documented in the
-[release runbook](../docs/RELEASING.md), then binds their declared signing mode,
-checksums, SBOMs, evidence, and provenance before publication. No updater feed,
-background update, staged rollout, or automatic rollback is configured.
-
-For a fictional development-only component review, run:
-
-```sh
-pnpm --dir desktop dev:gallery
-```
-
-The production build verifier rejects gallery copy and fixtures, embedded
-remote assets, and remote network endpoints.
-
## Architecture
The renderer has browser-only TypeScript types and imports. Its design-system
diff --git a/docs/DOCS_AUTHORING.md b/docs/DOCS_AUTHORING.md
index 75017fbc..f72751d4 100644
--- a/docs/DOCS_AUTHORING.md
+++ b/docs/DOCS_AUTHORING.md
@@ -315,7 +315,7 @@ briefs for the matching metadata-sidecar entries, not YAML front matter.
| `CORE_CONTRACTS_BASELINE.md` | Supporting/control: baseline record | `docs/CORE_CONTRACTS_BASELINE.md` | Retain | Maintainers | Implemented baseline | Core contracts | Audit the contract baseline | core contracts baseline; architecture baseline | Core contracts baseline | Records the established core-contract baseline. | Retain basename; no redirect needed |
| `reference/DEPENDENCY_MAINTENANCE.md` | Reference | `docs/reference/DEPENDENCY_MAINTENANCE.md` | Moved in #261 with git mv | Contributors and dependency maintainers | Implemented policy | Dependency maintenance | Update or audit dependency profiles | dependency groups; lockfile maintenance | Dependency maintenance | Describes purpose-specific groups, lock updates, and clean-environment verification. | Wiki basename retained; Pages route moved to the classified path and the prior route retired to avoid duplicate canonical sources |
| `DEPLOYMENT.md` | Supporting/control: release operation | `docs/DEPLOYMENT.md` | Retain | Release maintainers | Released bounded desktop publication controls and macOS arm64 runtime-tool management; domain expansion planned | Desktop release | Prepare bounded shell publication | desktop deployment; packaged desktop | Desktop deployment guide | Describes installer publication controls and app-owned macOS arm64 runtime-tool management for the released bounded desktop shell, not a hosted application or domain-capability rollout. | Retain for the released bounded shell |
-| `tutorials/desktop-first-run.md` | Tutorial | `docs/tutorials/desktop-first-run.md` | Create in #262; retain basename | New desktop users | Implemented v0.6 source learning path | Desktop experience | Complete a safe desktop first run | desktop first run; provider none desktop | Desktop first run | Reaches a verified network-free Home state with fictional local data and supported next steps. | Retain unique basename; validated in flat Wiki namespace |
+| `tutorials/desktop-first-run.md` | Tutorial | `docs/tutorials/desktop-first-run.md` | Create in #262; retain basename | New desktop users | Supported bounded 0.6.0 installer; separate development preview | Desktop experience | Complete a safe desktop first run | desktop first run; provider none desktop | Desktop first run | Reaches a network-free Home state in the supported installer; separates fictional illustrations and development previews. | Retain unique basename; validated in flat Wiki namespace |
| `how-to/desktop-diagnostics.md` | How-to guide | `docs/how-to/desktop-diagnostics.md` | Create in #262; retain basename | Desktop users | Implemented v0.6 source guidance | Desktop diagnostics | Recover from a degraded desktop launch | desktop diagnostics; retry desktop service | Recover with desktop diagnostics | Interprets sanitized startup components, stable codes, and bounded recovery actions. | Retain unique basename; validated in flat Wiki namespace |
| `how-to/desktop-file-access.md` | How-to guide | `docs/how-to/desktop-file-access.md` | Create in #262; retain basename | Desktop users | Implemented v0.6 source guidance | File grants | Grant bounded file access safely | desktop file access; opaque file grant | Grant desktop file access | Explains scoped opaque grants, immutable RootsMagic inputs, and loss-minimal GEDCOM handling. | Retain unique basename; validated in flat Wiki namespace |
| `how-to/desktop-gedcom-intake.md` | How-to guide | `docs/how-to/desktop-gedcom-intake.md` | Create in #115; retain basename | Desktop users and maintainers | Source-level GEDCOM intake; packaged release gates pending | GEDCOM intake | Inspect local sources and choose roots | desktop GEDCOM intake; validation findings; root selection | Inspect desktop GEDCOM sources | Inspects local GEDCOM sources, reviews bounded findings, and chooses roots in the source-level desktop workspace. | Retain unique basename; validated in flat Wiki namespace |
diff --git a/docs/Home.md b/docs/Home.md
index 6f0eddd2..88fe5e2c 100644
--- a/docs/Home.md
+++ b/docs/Home.md
@@ -1,80 +1,23 @@
# AncestryLLM documentation
-AncestryLLM is a local-first command-line tool for genealogy research. It
-combines deterministic RootsMagic and GEDCOM workflows with optional,
-explicitly selected LLM providers.
-
-The canonical source is this `docs/` directory. It is published to the
-[AncestryLLM documentation site](https://sodejm.github.io/AncestryLLM/) and the
-[GitHub Wiki](https://github.com/sodejm/AncestryLLM/wiki); the Wiki remains
-available, but neither published view is an independent documentation source.
-
-## Current product surfaces
-
-The CLI, interactive REPL, and released bounded Electron desktop control shell
-are the implemented product surfaces. The shell supports Home, Diagnostics,
-Settings, and capability onboarding.
-
-The CLI and REPL use the same command specification, transport-neutral
-executor, application DTOs, and genealogy services.
-
-- Start with the [CLI reference](reference/CLI.md) for one-shot commands.
-- Start with the [interactive console guide](CONSOLE.md) for the prompt-toolkit
- and Rich REPL.
-
-All user-selected files are governed by the shared
-[bounded file-ingress policy](reference/FILE_INGRESS.md), including byte and record
-budgets, race detection, output alias rejection, and transactional publication.
-
-The released bounded Electron desktop control shell uses the authenticated
-health/capability sidecar. The 0.6.0 source also includes explicitly bounded
-file-grant, provider-configuration, presentation-only **Tasks** adapters, a
-source-level synchronous transient-chat API, and a transient **Chat**
-destination over a Main-owned private stream. That chat boundary requires an
-exact stored profile and model plus current policy and compatible consent,
-keeps bounded content only in memory, grants no tools or domain authority,
-renders model Markdown through a closed allowlist, and keeps external-link
-confirmation in Electron Main. Desktop-domain capabilities such
-as target-matched packaged and adversarial chat evidence, genealogy/domain task
-admission or execution, direct artifact access, cloud accounts, and updater
-flows remain planned or incomplete. The current desktop records distinguish
-the supported packaged control surface from source-level gated adapters and
-the verification needed for later expansion; they
-are not a current journey for excluded domain capabilities.
-
-The accepted deployment architecture now has a source-level profile control
-plane: Local Desktop is the safe default, while Connect Remote and advanced
-Host Remote remain explicit unavailable intents. The bounded desktop shell
-also has reviewed macOS arm64 controls for acquiring and managing app-owned
-Colima, Lima, Docker Engine, and Compose tools. Those controls do not ship or
-activate an AncestryLLM application container or a remote runtime; the local
-CLI, REPL, and bounded desktop shell remain the only product surfaces.
-
-## v0.6 desktop learning path
-
-Start with the local, provider-none Home state, then use
-[Desktop shell](explanation/DESKTOP_SHELL.md) to understand the bounded
-control surface and its sanitized recovery path. Continue with the
-[interactive console guide](CONSOLE.md) for genealogy commands, and use the
-[CLI reference](reference/CLI.md) when a one-shot command is more appropriate.
-These surfaces share application contracts, but the desktop shell does not
-silently grant provider, network, filesystem, or genealogy authority.
-
-
+AncestryLLM is a local-first genealogy tool with one-shot commands, an
+interactive console, and a bounded desktop control shell. Choose a task below.
+The desktop supports local setup and diagnostics; use the CLI or console for
+genealogy workflows.
## Tutorials
-Learn a complete, safe workflow with fictional data:
+Follow a complete workflow:
-- [Desktop first run](tutorials/desktop-first-run.md) — reach a verified,
- network-free Home state and choose the next supported surface
+- [Desktop first run](tutorials/desktop-first-run.md) — reach a network-free
+ Home state in the supported 0.6.0 installer and choose the next supported surface
- [Merge fictional GEDCOM records offline](tutorials/offline-gedcom-merge.md)
— produce a rooted GEDCOM 5.5.5 file and quality report with `provider=none`
and no network calls.
## How-to guides
-Task-oriented guidance for common goals:
+Complete a specific task or recover from a problem:
- [Run an offline GEDCOM merge](how-to/run-an-offline-gedcom-merge.md) — merge
the public fictional fixtures, verify the results, and recover from failure
@@ -82,6 +25,17 @@ Task-oriented guidance for common goals:
— inspect the implemented prompt-toolkit/Rich REPL safely
- [Recover with desktop diagnostics](how-to/desktop-diagnostics.md) — interpret
sanitized startup state and retry the private desktop service
+- [Interactive console guide](CONSOLE.md) — start and use the REPL
+- [Encrypted backup and recovery](ENCRYPTED_BACKUPS.md) — create and restore backups
+- [First-run storage diagnostics](SETUP_DIAGNOSTICS.md) — troubleshoot setup
+- [Release runbook](RELEASING.md) — prepare and publish a release
+
+### Desktop source-level guides
+
+These guides cover gated adapters in source. They are outside the supported
+0.6.0 installer claim and require target-matched packaged and security evidence
+before support can expand. A fictional development preview is not that evidence.
+
- [Grant desktop file access](how-to/desktop-file-access.md) — understand
scoped opaque grants and the immutable-input boundary
- [Configure a desktop provider and consent](how-to/desktop-provider-consent.md)
@@ -90,14 +44,37 @@ Task-oriented guidance for common goals:
backend-owned progress and cancellation safe points
- [Use transient desktop chat](how-to/desktop-chat.md) — work with the bounded,
unsaved advisory conversation surface
-- [Interactive console guide](CONSOLE.md) — start and use the REPL
-- [Encrypted backup and recovery](ENCRYPTED_BACKUPS.md) — create and restore backups
-- [First-run storage diagnostics](SETUP_DIAGNOSTICS.md) — troubleshoot setup
-- [Release runbook](RELEASING.md) — prepare and publish a release
-The established root paths for the last four guides remain published while
-release packaging and contract consumers use them. Their inventory records the
-later `git mv` cutover that will update those consumers together.
+## v0.6 desktop learning path
+
+Start with the local, provider-none Home state, then use
+[Desktop shell](explanation/DESKTOP_SHELL.md) to understand the bounded
+control surface and its sanitized recovery path. Continue with the
+[interactive console guide](CONSOLE.md) for genealogy commands, and use the
+[CLI reference](reference/CLI.md) when a one-shot command is more appropriate.
+These surfaces share application contracts, but the desktop shell does not
+silently grant provider, network, filesystem, or genealogy authority.
+
+
+
+## Current product surfaces
+
+The CLI, interactive REPL, and released bounded Electron desktop control shell
+are the implemented product surfaces. The shell supports Home, Diagnostics,
+Settings, and capability onboarding. Desktop-domain capabilities remain
+planned or gated; see the [desktop shell guide](explanation/DESKTOP_SHELL.md)
+for the supported boundary and source-level contracts.
+
+The CLI and REPL use the same command specification, transport-neutral
+executor, application DTOs, and genealogy services. User-selected files follow
+the shared [bounded file-ingress policy](reference/FILE_INGRESS.md), including
+byte and record budgets, race detection, output alias rejection, and
+transactional publication.
+
+The [deployment guide](DEPLOYMENT.md) covers the reviewed macOS arm64
+runtime-tool controls. They do not activate an AncestryLLM application
+container or a remote runtime; Local Desktop remains the only available
+deployment choice.
## Reference
@@ -134,6 +111,7 @@ Concepts, rationale, and design context:
## Supporting records and publishing
+- [Published documentation](https://sodejm.github.io/AncestryLLM/) — browse the canonical guides on GitHub Pages
- [Wiki synchronization](WIKI_SYNC.md) — reproduce the publishing step locally
- [Wiki operations and recovery](WIKI_OPERATIONS.md) — dispatch, verify, rollback
- [Security response checklist](SECURITY_RESPONSE.md)
@@ -149,14 +127,3 @@ Concepts, rationale, and design context:
- [Provider framework evaluation ADR](ADR-0024-provider-framework-evaluation.md) — recorded provider choice
- [Data-flow threat model and control matrix](THREAT_MODEL.md) — security governance
- [Release evidence index](release-evidence/README.md) — retained verification artifacts
-
-## Documentation links
-
-Documentation links use relative Markdown filenames (for example,
-`[Console guide](CONSOLE.md)`). This keeps links valid from this `docs/`
-directory in the repository. The Pages build rewrites local links only in its
-generated staging directory, from `.md` targets to site paths. Wiki
-synchronization rewrites the same local targets to extensionless Wiki page
-links. The canonical source remains unchanged.
-
-Use the sidebar to navigate the complete published documentation set.
diff --git a/docs/_Sidebar.md b/docs/_Sidebar.md
index 03bc1ccc..fcff8a12 100644
--- a/docs/_Sidebar.md
+++ b/docs/_Sidebar.md
@@ -14,15 +14,20 @@
- [Run an offline GEDCOM merge](how-to/run-an-offline-gedcom-merge.md)
- [Explore commands in the interactive console](how-to/explore-the-interactive-console.md)
- [Recover with desktop diagnostics](how-to/desktop-diagnostics.md)
-- [Grant desktop file access](how-to/desktop-file-access.md)
-- [Configure a desktop provider and consent](how-to/desktop-provider-consent.md)
-- [Monitor and cancel desktop tasks](how-to/desktop-tasks.md)
-- [Use transient desktop chat](how-to/desktop-chat.md)
- [Interactive console guide](CONSOLE.md)
- [Encrypted backup and recovery](ENCRYPTED_BACKUPS.md)
- [First-run storage diagnostics](SETUP_DIAGNOSTICS.md)
- [Release runbook](RELEASING.md)
+### Desktop source-level guides
+
+Gated source adapters; outside the supported 0.6.0 installer claim.
+
+- [Grant desktop file access](how-to/desktop-file-access.md)
+- [Configure a desktop provider and consent](how-to/desktop-provider-consent.md)
+- [Monitor and cancel desktop tasks](how-to/desktop-tasks.md)
+- [Use transient desktop chat](how-to/desktop-chat.md)
+
### Reference
- [Desktop reference](reference/DESKTOP.md)
diff --git a/docs/_data/page_metadata.json b/docs/_data/page_metadata.json
index c6e15d4d..435e1a64 100644
--- a/docs/_data/page_metadata.json
+++ b/docs/_data/page_metadata.json
@@ -123,7 +123,7 @@
},
"tutorials/desktop-first-run.md": {
"title": "Desktop first run — AncestryLLM",
- "description": "A safe first journey through the v0.6 desktop source using fictional local state, provider none, and bounded recovery."
+ "description": "Reach the supported 0.6.0 desktop Home with provider none and bounded recovery. Fictional development previews have a separate procedure."
},
"how-to/desktop-diagnostics.md": {
"title": "Recover with desktop diagnostics — AncestryLLM",
diff --git a/docs/explanation/DESKTOP_SHELL.md b/docs/explanation/DESKTOP_SHELL.md
index 68c5a864..a60ec403 100644
--- a/docs/explanation/DESKTOP_SHELL.md
+++ b/docs/explanation/DESKTOP_SHELL.md
@@ -12,12 +12,12 @@ operations outside the sandboxed renderer, turns user-selected files into
opaque grants, and lets backend-owned cancellation finish at a declared safe
point.
-For a source-level v0.6 learning path, start with
-[Desktop first run](../tutorials/desktop-first-run.md), use the focused
-[desktop how-to guides](../Home.md#how-to-guides), and keep the
+For the supported 0.6.0 installer, start with
+[Desktop first run](../tutorials/desktop-first-run.md) and keep the
[desktop reference](../reference/DESKTOP.md) open for exact states and stable
-codes. These pages describe the current source contracts; they do not expand
-the supported 0.6.0 installer claim below.
+codes. The separately marked
+[desktop source-level guides](../Home.md#desktop-source-level-guides) describe
+gated adapters; they do not expand the supported installer claim below.
## Supported surface
@@ -34,6 +34,24 @@ The supported desktop destinations are deliberately small:

+### Source-level gates
+
+The released bounded Electron desktop control shell uses the authenticated
+health/capability sidecar. The 0.6.0 source also includes explicitly bounded
+file-grant, provider-configuration, presentation-only **Tasks** adapters, a
+source-level synchronous transient-chat API, and a transient **Chat**
+destination over a Main-owned private stream. That chat boundary requires an
+exact stored profile and model plus current policy and compatible consent,
+keeps bounded content only in memory, grants no tools or domain authority,
+renders model Markdown through a closed allowlist, and keeps external-link
+confirmation in Electron Main. Desktop-domain capabilities such
+as target-matched packaged and adversarial chat evidence, genealogy/domain task
+admission or execution, direct artifact access, cloud accounts, and updater
+flows remain planned or incomplete. The current desktop records distinguish
+the supported packaged control surface from source-level gated adapters and
+the verification needed for later expansion; they
+are not a current journey for excluded domain capabilities.
+
The 0.6.0 source from Issue #109 adds a **Tasks** destination to present
backend-owned work. It remains outside the supported 0.6.0 installer claim.
@@ -89,7 +107,7 @@ shipping renderer.
## First run and revisit
-The `0.6.0` source-level gated first launch opens a bounded welcome on **Home**
+The `0.6.0` first launch opens a bounded welcome on **Home**
and presents three explicit deployment intents:
- **Local Desktop (Recommended)** is the only available choice. It uses the
diff --git a/docs/tutorials/desktop-first-run.md b/docs/tutorials/desktop-first-run.md
index 12d566d8..b11d8460 100644
--- a/docs/tutorials/desktop-first-run.md
+++ b/docs/tutorials/desktop-first-run.md
@@ -1,25 +1,25 @@
# Desktop first run
-This tutorial takes you from the v0.6 desktop welcome screen to a safe,
-meaningful local Home state. It uses the checked-in fictional presentation
-state, keeps `provider=none`, and makes no network request. Do not substitute a
-real family tree, credential, prompt, response, database, backup, or log while
-following it.
-
-> The 0.6 desktop source includes the learning path described here. A released
-> 0.5 installer exposes only its bounded Home, Diagnostics, Settings, and
-> onboarding control surface. Treat a development build as verification input,
-> not as a supported release.
+This tutorial covers the supported 0.6.0 desktop installer: Home, Diagnostics,
+local visual Settings, and onboarding. You will reach a local Home state with
+`provider=none` and no network request. Tasks, Chat, provider configuration,
+and file-grant adapters remain source-level gates outside this installer claim.
## Before you begin
-Use a supported, target-matched desktop build. The desktop is local-first: its
+Install and verify a supported, target-matched 0.6.0 build using
+[Installation and updates](../explanation/DESKTOP_SHELL.md#installation-and-updates).
+The desktop is local-first: its
private sidecar is a **Local control channel**, not a public or LAN API. You do
not need an account, provider, API key, genealogy file, or cloud consent for
this tutorial.
-The screenshots use deterministic fictional fixtures. They contain no local
-paths, secrets, genealogy records, prompts, responses, or provider payloads.
+The screenshots illustrate the steps with deterministic fictional fixtures.
+Your installed application reports its own sanitized local startup state.
+The illustrations contain no local paths, secrets, genealogy records, prompts,
+responses, or provider payloads. Do not load real genealogy data or credentials
+to reproduce them. For fixture previews, use the separate development procedure
+at the end of this page.
## 1. Choose the local desktop
@@ -57,7 +57,8 @@ On Home, confirm the following cards are present:
- **Application** identifies the desktop build.
- **Offline posture** reports the local-first boundary.
-- **Startup state** reports **Ready** for this tutorial.
+- **Startup state** reports **Ready** after healthy startup checks. If it does
+ not, follow the diagnostics recovery in step 2.
- **Capabilities** contains only sanitized capability metadata.

@@ -70,9 +71,8 @@ needed to reach this result.
## 4. Explore without granting authority
Use the primary navigation to visit **Diagnostics** and **Settings**, then
-return to **Home**. The v0.6 source also exposes bounded **Tasks** and **Chat**
-destinations; merely visiting either one does not start work, select a provider,
-or disclose data.
+return to **Home**. Visiting these destinations does not select a provider,
+start genealogy work, or disclose data.
Press Ctrl+K on Windows or Linux, or
Command+K on macOS, to open **Go to a workspace**. Type a
@@ -88,8 +88,8 @@ does not reset settings or change the saved onboarding preference. Choose
## Result and next steps
-You now have a provider-none, network-free desktop Home state using only
-fictional presentation data. Continue according to your goal:
+After healthy startup checks, you have a provider-none, network-free desktop
+Home state without loading genealogy data. Continue according to your goal:
- Use [Recover with desktop diagnostics](../how-to/desktop-diagnostics.md) if
startup is degraded.
@@ -102,3 +102,22 @@ fictional presentation data. Continue according to your goal:
The CLI and interactive console own the supported genealogy workflows. The
desktop shell does not silently gain file, provider, network, or genealogy
authority by sharing their application contracts.
+
+## Optional: preview fictional development fixtures
+
+For source development, follow the
+[desktop setup and gates](https://github.com/sodejm/AncestryLLM/blob/main/desktop/README.md#reproducible-setup-and-gates),
+then run this command from the repository root:
+
+```sh
+pnpm --dir desktop dev:gallery
+```
+
+The gallery uses fictional presentation fixtures. It does not verify an
+installed application's startup state or establish support for a release.
+Keep real family trees, credentials, prompts, responses, databases, backups,
+and logs out of this preview. The production build excludes gallery fixtures.
+
+The [desktop source-level guides](../Home.md#desktop-source-level-guides)
+describe the gated file, provider, Tasks, and Chat contracts. A development
+preview does not replace their target-matched packaged and security evidence.
diff --git a/tests/test_desktop_learning_path_docs.py b/tests/test_desktop_learning_path_docs.py
index 7038135d..66d3698f 100644
--- a/tests/test_desktop_learning_path_docs.py
+++ b/tests/test_desktop_learning_path_docs.py
@@ -52,7 +52,7 @@ def test_desktop_learning_path_pages_are_published_and_discoverable() -> None:
def test_first_run_tutorial_reaches_a_safe_meaningful_result() -> None:
- """The tutorial uses fictional local state and offers supported next steps."""
+ """The tutorial reaches local Home and distinguishes fictional illustrations."""
tutorial = _normalized("tutorials/desktop-first-run.md")
for contract in (
diff --git a/tests/test_documentation_architecture_contract.py b/tests/test_documentation_architecture_contract.py
index aba9da72..ca54eb90 100644
--- a/tests/test_documentation_architecture_contract.py
+++ b/tests/test_documentation_architecture_contract.py
@@ -143,15 +143,18 @@ def test_navigation_separates_reader_modes_from_supporting_material() -> None:
assert "The CLI and REPL use the same command specification" in home
assert "All surfaces use the same command specification" not in home
assert "Desktop-domain capabilities" in home_text
- assert "presentation-only **Tasks** adapters" in home_text
- assert "source-level synchronous transient-chat API" in home_text
- assert "transient **Chat** destination over a Main-owned private stream" in home_text
- assert "renders model Markdown through a closed allowlist" in home_text
- assert "external-link confirmation in Electron Main" in home_text
+ desktop_text = " ".join(
+ (DOCS_DIRECTORY / "explanation/DESKTOP_SHELL.md").read_text(encoding="utf-8").split()
+ )
+ assert "presentation-only **Tasks** adapters" in desktop_text
+ assert "source-level synchronous transient-chat API" in desktop_text
+ assert "transient **Chat** destination over a Main-owned private stream" in desktop_text
+ assert "renders model Markdown through a closed allowlist" in desktop_text
+ assert "external-link confirmation in Electron Main" in desktop_text
assert (
"target-matched packaged and adversarial chat evidence, genealogy/domain task "
"admission or execution, direct artifact access, cloud accounts, and updater flows"
- in home_text
+ in desktop_text
)
for page in ("Home.md", "_Sidebar.md"):
navigation = (DOCS_DIRECTORY / page).read_text(encoding="utf-8")
From ce29d2e918b6ac09ba671bcf0dd4879b1cd6efe6 Mon Sep 17 00:00:00 2001
From: Justin Soderberg <723679+sodejm@users.noreply.github.com>
Date: Tue, 13 Oct 2026 21:04:26 -0400
Subject: [PATCH 3/4] docs: clarify exact-target review and file classification
rules
Present the authoritative Codex review procedure as ordered steps and explicit delivery stops. State that every unclassified tracked path fails the documentation inventory, including non-comment formats.
Preserve review identity, revision, resolution, and security invariants. Documentation-only clarification; implementation and architecture are unchanged. Relevant documentation regression tests pass.
---
CONTRIBUTING.md | 77 +++++++++++++++++++++++---------------
docs/CODE_DOCUMENTATION.md | 11 +++---
2 files changed, 52 insertions(+), 36 deletions(-)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 21ce2aa6..fc552f6d 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -93,37 +93,52 @@ follow-up.
### Codex pull-request review
-Use the repository-local
-[`code-review` skill](.agents/skills/code-review/SKILL.md) only after GitHub
-confirms that the pull request is non-draft. Before invoking it, the trusted
-delivery driver records the base branch and recorded base SHA, then loads the
-applicable repository guidance and skill from that commit rather than the
-untrusted pull-request head. It requests Codex review for one immutable target
-comprising the base branch, base SHA, merge-base SHA, and head SHA; reuses only
-a successful result from the expected Codex integration identity that is tied
-to the exact trusted review-request comment and target; and trusts a
-`BASE_BRANCH@BASE_SHA..HEAD_SHA` duplicate-prevention marker only when it was
-posted by the authenticated workflow actor. Before every review-related write,
-the live values must still match that target. Draft, changed, unknown, or
-unrefreshable state fails closed, and the workflow never marks a pull request
-ready on a human's behalf.
-
-The skill preserves the repository's Codex-only policy: it does not request a
-second review provider or hand implementation to another coding agent. It
-revalidates every exact-target Codex finding, including one already marked
-resolved, and deduplicates findings by root cause. It treats resolution status
-as untrusted input: verify who resolved it and why, then verify the exact-target
-evidence before honoring a prior resolution. A prior resolution is honored only
-when the authenticated delivery actor made it after a supported tested fix or an
-appropriate human or private-security decision authorizes the disposition.
-Supported findings are resolved only after a tested fix; ambiguous,
-unsupported, stale, or security-sensitive findings remain open until the
-appropriate human decision or private process authorizes resolution. A terminal
-Codex result ends only its review stream; polling continues until both the
-Codex result and required checks are terminal, followed by a final thread
-refresh, or until the five-minute deadline. An explicitly unsuccessful Codex
-result or non-successful required check, including a failure or cancellation,
-blocks delivery.
+The repository-local
+[`code-review` skill](.agents/skills/code-review/SKILL.md) is authoritative for
+this procedure. Use it only after GitHub confirms that the pull request is
+non-draft.
+
+Throughout this procedure, refresh the live base branch, base SHA, merge-base
+SHA, and head SHA before every review-related write. Confirm that they still
+match the immutable target. The workflow never marks a pull request ready on
+a human's behalf.
+
+1. **Establish the trusted target.** The trusted delivery driver records the
+ base branch and base SHA, then loads the applicable repository guidance and
+ skill from the recorded base SHA rather than from the untrusted pull-request head.
+ Record one immutable review target comprising the base branch, base SHA,
+ merge-base SHA, and head SHA.
+2. **Request or reuse the exact-target review.** Follow the repository's
+ Codex-only policy: do not request a second review provider or hand
+ implementation to another coding agent. Reuse a result only when it is
+ successful, comes from the expected Codex integration identity, and is tied
+ to the exact trusted review-request comment and immutable target. Trust a
+ `BASE_BRANCH@BASE_SHA..HEAD_SHA` duplicate-prevention marker only when the
+ authenticated workflow actor posted it.
+3. **Reconcile every finding.** Revalidate every exact-target Codex finding, including
+ one already marked resolved, and deduplicate findings by root cause. Treat
+ resolution status as untrusted input: verify who resolved it and why, then
+ verify the exact-target evidence. Honor a prior
+ resolution only when the authenticated delivery actor made it after a
+ supported tested fix, or when an appropriate human or private-security
+ decision authorizes the disposition. Resolve a supported finding only after
+ a tested fix.
+4. **Wait for the complete result.** A terminal Codex result ends only the
+ review stream. Continue polling until the Codex result and all required
+ checks are terminal, then perform a final thread refresh. Stop polling at
+ the five-minute deadline if that complete result has not arrived.
+
+Stop the review and block delivery when any of these conditions applies:
+
+- The pull request is draft, the immutable target changed, or any required
+ state is unknown or cannot be refreshed.
+- A finding is ambiguous, unsupported, stale, or security-sensitive and the
+ appropriate human decision or private process has not authorized its
+ resolution.
+- Codex reports an explicitly unsuccessful result.
+- Any non-successful required check, including one that fails or is cancelled.
+- The five-minute deadline expires before Codex, the required checks, and the
+ final thread refresh provide a complete exact-target result.
## Test-driven development
diff --git a/docs/CODE_DOCUMENTATION.md b/docs/CODE_DOCUMENTATION.md
index 2d605654..a216ed1b 100644
--- a/docs/CODE_DOCUMENTATION.md
+++ b/docs/CODE_DOCUMENTATION.md
@@ -20,9 +20,9 @@ links to or summarises the applicable contract without redefining it.
## File classification
-Every Git-tracked file belongs to exactly one classification. Unknown extensions in
-comment-capable categories fail the inventory check. The `check_code_documentation.py`
-script enforces this at every CI run.
+Every Git-tracked file belongs to exactly one classification. Any unclassified tracked
+path fails the inventory check, regardless of its extension or whether its format permits
+comments. The `check_code_documentation.py` script enforces this at every CI run.
| Classification | Description | Examples |
|---|---|---|
@@ -38,8 +38,9 @@ script enforces this at every CI run.
### Non-comment formats
-Files whose formats do not safely permit comments (JSON, plist/XML property lists) are
-classified as `non-comment-format` and excluded from file-level documentation requirements.
+Files whose formats do not safely permit comments (JSON, plist/XML property lists) must be
+explicitly classified as `non-comment-format`, mapped in `NON_COMMENT_FORMAT_MAP`, and are
+then excluded from file-level documentation requirements.
This also applies to the three `containers/compose*.yaml` manifests: despite their suffix,
they intentionally remain strict JSON-compatible YAML so duplicate keys and non-JSON YAML
constructs fail closed. Their semantics must be explained in an adjacent authoritative
From d4663d76b66cbb9ff946d854d825b08ed84a9445 Mon Sep 17 00:00:00 2001
From: Justin Soderberg <723679+sodejm@users.noreply.github.com>
Date: Tue, 13 Oct 2026 21:04:37 -0400
Subject: [PATCH 4/4] docs: make release readiness commands reproducible
Document the required dispatch inputs, capture the returned run URL, and verify workflow identity, candidate SHA, completion, and downloaded evidence before continuing. Use the repository virtual environment for release recovery verification.
Preserve lifecycle audit and release provenance requirements. Shell examples pass bash syntax checks and match the workflow and publication contracts. Documentation-only; no workflow was dispatched and no application behavior changed.
---
docs/RELEASING.md | 92 ++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 88 insertions(+), 4 deletions(-)
diff --git a/docs/RELEASING.md b/docs/RELEASING.md
index ffe6626f..8510d71f 100644
--- a/docs/RELEASING.md
+++ b/docs/RELEASING.md
@@ -367,9 +367,93 @@ self-approval; do not make that change during the one-maintainer release.
each dependency in the selected iteration is closed and verified. Closed
historical dependencies outside that iteration do not need to be added to
the release Project.
-6. Run `Release readiness` with the exact `main` commit and semantic version,
- and affirm the branch/worktree lifecycle audit input, backed by the
- documented reachability, unique-commit, cleanup, and preservation record.
+6. Dispatch `Release readiness` from `main` with the exact candidate commit,
+ semantic version, and completed lifecycle audit. Set all three workflow
+ inputs explicitly: `commit_sha`, `version`, and
+ `lifecycle_cleanup_confirmed=true`. This branch/worktree lifecycle audit input
+ attests that the
+ reachability, unique-commit, cleanup, and preservation record required by
+ step 2 is complete.
+
+ Run these commands only after steps 1 through 5 are complete. They capture
+ the run URL returned by GitHub CLI instead of guessing which recent run to
+ inspect. Stop if GitHub CLI does not return one unambiguous run URL.
+
+ ```bash
+ set -euo pipefail
+
+ repository="$(gh repo view --json nameWithOwner --jq .nameWithOwner)"
+ git fetch --no-tags origin main
+ test -z "$(git status --short)"
+ release_commit="$(git rev-parse origin/main)"
+ test "$(git rev-parse HEAD)" = "$release_commit"
+ release_version="$(jq -er '.release' .github/release-config.json)"
+
+ .venv/bin/python scripts/verify_release_configuration.py \
+ --config .github/release-config.json \
+ --version "$release_version"
+
+ readiness_dispatch_output="$(
+ gh workflow run release-readiness.yml \
+ --repo "$repository" \
+ --ref main \
+ --raw-field "commit_sha=$release_commit" \
+ --raw-field "version=$release_version" \
+ --raw-field lifecycle_cleanup_confirmed=true
+ )"
+ readiness_url="$(
+ sed -nE \
+ 's#.*(https://[^[:space:]]+/actions/runs/[0-9]+).*#\1#p' \
+ <<<"$readiness_dispatch_output" | sort -u
+ )"
+ if [[ -z "$readiness_url" || "$readiness_url" == *$'\n'* ]]; then
+ echo "Release readiness did not return one unambiguous run URL:" >&2
+ echo "$readiness_dispatch_output" >&2
+ exit 1
+ fi
+ readiness_run="${readiness_url##*/}"
+ ```
+
+ Bind the recorded run ID to the expected workflow and commit before waiting
+ for it. After it succeeds, download the named evidence artifact into a new
+ temporary directory and verify the same version, commit, and gate statuses
+ that the publication workflow consumes. Continue in the same Bash shell so
+ the recorded repository, commit, version, URL, and run ID remain available.
+
+ ```bash
+ release_readiness_workflow_id="$(
+ gh api "repos/$repository/actions/workflows/release-readiness.yml" --jq .id
+ )"
+ readiness_json="$(gh api "repos/$repository/actions/runs/$readiness_run")"
+ test "$(jq -r '.workflow_id' <<<"$readiness_json")" = \
+ "$release_readiness_workflow_id"
+ test "$(jq -r '.event' <<<"$readiness_json")" = workflow_dispatch
+ test "$(jq -r '.head_sha' <<<"$readiness_json")" = "$release_commit"
+ test "$(jq -r '.html_url' <<<"$readiness_json")" = "$readiness_url"
+
+ gh run watch "$readiness_run" --repo "$repository" --exit-status
+
+ readiness_json="$(gh api "repos/$repository/actions/runs/$readiness_run")"
+ test "$(jq -r '.status' <<<"$readiness_json")" = completed
+ test "$(jq -r '.conclusion' <<<"$readiness_json")" = success
+ test "$(jq -r '.head_sha' <<<"$readiness_json")" = "$release_commit"
+
+ readiness_evidence="$(mktemp -d)"
+ gh run download "$readiness_run" \
+ --repo "$repository" \
+ --name release-evidence \
+ --dir "$readiness_evidence"
+ test "$(jq -r '.release' "$readiness_evidence/gates.json")" = \
+ "$release_version"
+ test "$(jq -r '.commit' "$readiness_evidence/gates.json")" = \
+ "$release_commit"
+ test "$(jq -r '[.gates[].status == "verified"] | all' \
+ "$readiness_evidence/gates.json")" = true
+ grep -F -- "- Version: \`$release_version\`" \
+ "$readiness_evidence/release-evidence.md"
+ grep -F -- "- Commit: \`$release_commit\`" \
+ "$readiness_evidence/release-evidence.md"
+ ```
7. Confirm the successful exact-head `Desktop sidecar` aggregate is for the
same commit and contains all six unpublished native-package rows. This is
an input to the installer gate, not release-installer evidence by itself.
@@ -606,7 +690,7 @@ artifact from that run and the draft assets into separate directories, then
require:
```bash
-python scripts/verify_release_assets.py \
+.venv/bin/python scripts/verify_release_assets.py \
--expected /path/to/release-distributions \
--actual /path/to/draft-download
```