diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..c8293f5
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,7 @@
+node_modules
+.git
+evidence
+reports
+**/dist
+**/*.tsbuildinfo
+*.sqlite*
diff --git a/.env.example b/.env.example
index 33273a5..68f76a2 100644
--- a/.env.example
+++ b/.env.example
@@ -7,7 +7,5 @@ ALD_DATABASE_PATH=./evidence/ald.sqlite
ALD_LOG_LEVEL=info
ALD_BASE_NETWORK=base-sepolia
-# Paths and endpoints are intentionally blank.
-ALD_KEY_DIR=
-ALD_BASE_RPC_URL=
-ALD_ANCHOR_KEY_FILE=
+# Secret values and secret file paths are injected only by `si fort run`.
+# They are intentionally absent from this file.
diff --git a/.github/workflows/book-integrity.yml b/.github/workflows/book-integrity.yml
index cd4e388..34d60aa 100644
--- a/.github/workflows/book-integrity.yml
+++ b/.github/workflows/book-integrity.yml
@@ -1,47 +1,77 @@
-name: Research book integrity
+name: Consolidated integrity suite
on:
pull_request:
- paths:
- - RESEARCH.md
- - research-book.html
- - book/**
- - scripts/build-research-book.mjs
- - scripts/research-book-entry.js
- - package.json
- - package-lock.json
- - vitest.config.ts
push:
branches:
- main
- paths:
- - RESEARCH.md
- - research-book.html
- - book/**
- - scripts/build-research-book.mjs
- - scripts/research-book-entry.js
- - package.json
- - package-lock.json
- - vitest.config.ts
permissions:
contents: read
jobs:
- verify-book:
+ consolidated-suite:
runs-on: ubuntu-latest
steps:
- name: Check out repository
- uses: actions/checkout@v4
+ uses: actions/checkout@v7
- - name: Set up Node.js
- uses: actions/setup-node@v4
+ - name: Set up Homebrew
+ uses: Homebrew/actions/setup-homebrew@49d03f1bf5d455a413dfbdf99e6718054a4cd975
+
+ - name: Install Node.js and pnpm with Homebrew
+ run: |
+ brew install node@24 pnpm
+ echo "$(brew --prefix node@24)/bin" >> "$GITHUB_PATH"
+
+ - name: Install dependencies
+ run: pnpm install --frozen-lockfile
+
+ - name: Audit dependency graph
+ run: |
+ mkdir -p artifacts
+ pnpm audit --audit-level=high --json > artifacts/pnpm-audit.json
+
+ - name: Run consolidated suite with timing
+ run: |
+ mkdir -p artifacts
+ /usr/bin/time -v pnpm run check:ci 2> artifacts/consolidated-runtime.txt
+
+ - name: Upload test and runtime evidence
+ if: always()
+ uses: actions/upload-artifact@v7
with:
- node-version: 22.13.0
- cache: npm
+ name: consolidated-suite-evidence
+ path: artifacts/
+ retention-days: 30
+
+ mode-r:
+ runs-on: ubuntu-latest
+ needs: consolidated-suite
+ steps:
+ - name: Check out repository
+ uses: actions/checkout@v7
+
+ - name: Set up Homebrew
+ uses: Homebrew/actions/setup-homebrew@49d03f1bf5d455a413dfbdf99e6718054a4cd975
+
+ - name: Install Node.js and pnpm with Homebrew
+ run: |
+ brew install node@24 pnpm
+ echo "$(brew --prefix node@24)/bin" >> "$GITHUB_PATH"
- name: Install dependencies
- run: npm ci
+ run: pnpm install --frozen-lockfile
+
+ - name: Run real-container Mode R suite with timing
+ run: |
+ mkdir -p artifacts
+ /usr/bin/time -v pnpm run test:mode-r 2> artifacts/mode-r-runtime.txt
- - name: Verify manuscript and book assets
- run: npm test
+ - name: Upload Mode R runtime evidence
+ if: always()
+ uses: actions/upload-artifact@v7
+ with:
+ name: mode-r-suite-evidence
+ path: artifacts/
+ retention-days: 30
diff --git a/.gitignore b/.gitignore
index 84bdd39..fb2ceec 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
node_modules/
dist/
coverage/
+.artifacts/
*.tsbuildinfo
.env
.env.*
diff --git a/BACKLOG.md b/BACKLOG.md
index 2d7a53d..cf94471 100644
--- a/BACKLOG.md
+++ b/BACKLOG.md
@@ -23,21 +23,21 @@ This backlog translates `SPECIFICATION.md`, `EXPERIMENT-NOTEBOOK.md`, and `LEDGE
## 1. Document Status
-- **Status:** Implementation active. ALD-001 through ALD-007 are complete; ALD-008 is the next critical-path item.
+- **Status:** Implementation active, with 254 of 258 acceptance criteria verified. The verifiable core and Prototype Mode pipeline are joined by tested Phase E foundations for alternate carriers and affect, versioned carrier-leakage and semantic-leakage qualification, matched recurrent scratch-RL/self-supervised baselines with witnessed provenance and frozen evaluation, recorded per-Baby random policy initialization, frozen/hybrid adapter foundations, independently verified derived-run lineage, fail-closed scenario quarantine and audited observation-hygiene blocking, observation red-teaming, process and container training isolation, enumerated side-channel mitigations and active attacks, build-guarded response envelopes and claim labels, witness-committed analysis attachments, exact-export verification reports, prospectively bound confirmatory pre-registration, protected background scheduling, hash-linked deviation records, a vanilla Research Console with read-only replay, delayed human audit-ledger interpretation, telemetry, snapshot/restore, failure handling, retention enforcement, held-out scenario splits, fixed-schedule curriculum execution, verifier-bound live causal probes, recoverable bounded repair turns, a research-only three-role E40 encoding harness with an enforced production-crypto boundary, executable readiness gates covering all 19 experiments, dependency-integrity enforcement, reproducible E03 design and registration artifacts, a fail-closed research preflight, a real open-weight frozen-model qualification, and hosted consolidated CI/Mode R evidence. The prospective campaign is governed by the simulation-only profile; public-chain acceptance items remain capability work rather than campaign prerequisites. The acceptance checkboxes below remain authoritative for that optional capability, upstream required-check enforcement, and independent operator restore validation.
- **Source of truth precedence:** `SPECIFICATION.md` governs implementation; `LEDGER-INTEGRITY-DESIGN.md` governs ledger, checkpoint, Merkle, and anchoring mechanics; `EXPERIMENT-NOTEBOOK.md` governs experiment pre-registration and results; `CONCEPT-IDEA.md` preserves research rationale. This backlog is derived from those documents and introduces no new normative requirements.
- **Scope of this backlog:** software and process engineering work required to stand up the system described in `SPECIFICATION.md` and to make every experiment in `EXPERIMENT-NOTEBOOK.md` §7–§8 executable. It does **not** include running the experiments themselves, interpreting results, or drafting findings — those are research-execution activities tracked in the notebook, not software backlog items.
-- **Numbering:** Epics use stable IDs `EPIC-01`…`EPIC-15`. Individual backlog items use stable IDs `ALD-001`…`ALD-080`. IDs are assigned in dependency order: every item's `Depends on` list only ever references a **lower**-numbered ALD ID. IDs are permanent once assigned and must not be reused or renumbered by future edits; new work gets the next unused ID appended at the end of its epic's range or a new epic.
+- **Numbering:** Epics use stable IDs `EPIC-01`…`EPIC-16`. Individual backlog items use stable IDs `ALD-001`…`ALD-086`. IDs are assigned in dependency order: every item's `Depends on` list only ever references a **lower**-numbered ALD ID. IDs are permanent once assigned and must not be reused or renumbered by future edits; new work gets the next unused ID appended at the end of its epic's range or a new epic.
## 2. Planning Assumptions
-- **Runtime and language:** Node.js with TypeScript, consistent with the DTSF ecosystem this project builds on. Package management is npm, using npm workspaces for a monorepo layout (no Yarn/pnpm).
+- **Runtime and language:** Node.js with TypeScript, consistent with the DTSF ecosystem this project builds on. Package management uses pnpm workspaces with a frozen lockfile.
- **Evidence store:** SQLite in WAL (write-ahead log) mode is the authoritative local evidence store, per `LEDGER-INTEGRITY-DESIGN.md` [§18. Recommended Initial Decision](LEDGER-INTEGRITY-DESIGN.md#18-recommended-initial-decision). No external database is introduced.
-- **Anchoring chain:** Base Sepolia (testnet) is the first and default anchoring target. Mainnet anchoring is a separate, later, explicitly opt-in capability — never the default.
+- **Anchoring profile:** deterministic simulation is the default execution class and emulates Base Sepolia semantics without currency. Real Base Sepolia and mainnet anchoring are optional capabilities outside the approved campaign; mainnet remains separately opt-in.
- **Model default:** `scratch-rl` is the primary scientific baseline. A local open-weight `frozen-llm` is the orchestration-validation default; `self-supervised` is the initial reward-free comparison. `no-learning` and `hybrid` are explicit controls/variants.
- **Isolation:** Research-Grade Mode (Mode R) runs learner processes in separate containers/processes with no shared mutable state beyond the Gateway and ledger, per `SPECIFICATION.md` [§5.2 Research-Grade Mode (Mode R)](SPECIFICATION.md#52-research-grade-mode-mode-r).
- **On-chain privacy:** no private, raw-observation, or model-internal data is ever placed in an on-chain anchoring payload — only checkpoint root hashes and minimal metadata, per `SPECIFICATION.md` [§13.6 Privacy Controls](SPECIFICATION.md#136-privacy-controls) and `LEDGER-INTEGRITY-DESIGN.md` [§12. Privacy](LEDGER-INTEGRITY-DESIGN.md#12-privacy).
-- **No invented dates or staffing:** this backlog contains no calendar dates, durations, or headcount figures. Milestones are ordinal (`M0`…`M5`); the execution plan uses ordinal iterations (`Iteration 1`…`Iteration 4`, "Iteration 5+"). Sequencing is expressed purely through dependencies.
-- **Repository today:** documentation-only. Every "implement X" item below is net-new work; none of it exists in the repository yet, so no item's acceptance criteria assume pre-existing code beyond what an earlier, lower-numbered ALD item established.
+- **No invented dates or staffing:** this backlog contains no calendar dates, durations, or headcount figures. Milestones are ordinal (`M0`…`M6`); the execution plan uses ordinal iterations (`Iteration 1`…`Iteration 4`, "Iteration 5+"). Sequencing is expressed purely through dependencies.
+- **Repository today:** a pnpm-workspaces TypeScript monorepo with the packages listed in README.md; each item's acceptance criteria assume only what earlier, lower-numbered ALD items established.
- **Diplomacy-table reuse:** the repository's existing UX components (e.g., from a prior Diplomacy-style project) may be reused only within the boundaries `SPECIFICATION.md` [§16.2](SPECIFICATION.md#162-diplomacy-table-reuse-boundaries) defines; this is treated as a constraint, not an invitation to reuse everything available.
## 3. Priority Definitions
@@ -126,7 +126,12 @@ Milestones are ordinal and gate-based, not date-based. Each milestone's exit gat
- **Entry gate:** M4 exit met.
- **Exit gate:** Gate G5 (`ALD-077`) passes, `ALD-078` CI is green on the full consolidated suite, and `ALD-080` release/publication mapping is complete. Corresponds to `LEDGER-INTEGRITY-DESIGN.md` [Phase 3: Public Anchoring](LEDGER-INTEGRITY-DESIGN.md#phase-3-public-anchoring).
-**Critical path across milestones:** M0 → M1 → M2 → M3 → M4 → M5 is a strict chain — each milestone's epics depend on the previous milestone's evidence/lifecycle foundations. Within M2–M4, epics not named in the critical-path narrative (§10) can proceed in parallel once their own dependencies clear; see §10 for the detailed item-level view.
+### M6 — Research-Execution Readiness
+- **Epics in scope:** EPIC-16 (`ALD-081`–`086`).
+- **Entry gate:** the locally executable M5 software checks are green; external authority gates remain explicitly open rather than simulated.
+- **Exit gate:** dependency integrity is enforced, E03's design and registration artifacts reproduce, research preflight fails closed, a real open-weight frozen model completes both roles, and project-status drift is blocked by the consolidated check.
+
+**Critical path across milestones:** M0 → M1 → M2 → M3 → M4 → M5 → M6 is a strict chain — each milestone's epics depend on the previous milestone's evidence/lifecycle foundations. Within M2–M4, epics not named in the critical-path narrative (§10) can proceed in parallel once their own dependencies clear; see §10 for the detailed item-level view.
## 9. Epic Overview
@@ -147,6 +152,7 @@ Milestones are ordinal and gate-based, not date-based. Each milestone's exit gat
| EPIC-13 | Security, Red-Team, and Cryptography Track | ALD-067–070 | EPIC-06, EPIC-07, EPIC-10 | Red-team suites green; crypto novelty/security separation policy enforced |
| EPIC-14 | Experiment Pre-Registration and E00–E50 Readiness Gates | ALD-071–077 | EPIC-05, EPIC-06, EPIC-08, EPIC-13 | Gates G1–G5 all pass; all 19 experiments have a readiness record |
| EPIC-15 | CI/Test Suites, Documentation, Operations, and Release | ALD-078–080 | all prior epics | CI green on consolidated suite; docs and release/publication mapping complete |
+| EPIC-16 | Research-Execution Readiness | ALD-081–086 | EPIC-14, EPIC-15 | Reproducible design/registration, fail-closed preflight, real-model qualification, and status-drift enforcement pass |
## 10. Dependency and Critical Path View
@@ -224,7 +230,7 @@ dependencies are complete.
- **Workstream F (Audit and Recovery):** `ALD-058`, `ALD-059`, `ALD-060`, sequenced after lifecycle, evidence, and Mode R dependencies.
- **Exit state:** baby-a/baby-b/nursery routes live with authorization and standardized error shape; observation hygiene, sanitization, and seeded scenario determinism operational; Base Sepolia anchoring confirmed; Gate G1 (E00–E03 readiness) achievable.
-**Iteration 5+ (not detailed further here, no dates implied):** continues with the remaining branches — generative carrier and affect protocols (`ALD-031`–033), remaining adapter tracks (`ALD-046`–047), Mode R isolation and telemetry/audit/retention (EPIC-10, EPIC-11), the dashboard (EPIC-12), remaining security/crypto items (`ALD-069`–070), Gates G2–G5 (`ALD-074`–077), and CI/documentation/release (EPIC-15) — in the dependency order fixed by their IDs.
+**Iteration 5+ (not detailed further here, no dates implied):** continues with the remaining branches — generative carrier and affect protocols (`ALD-031`–033), remaining adapter tracks (`ALD-046`–047), Mode R isolation and telemetry/audit/retention (EPIC-10, EPIC-11), the dashboard (EPIC-12), remaining security/crypto items (`ALD-069`–070), Gates G2–G5 (`ALD-074`–077), CI/documentation/release (EPIC-15), and research-execution readiness (EPIC-16) — in the dependency order fixed by their IDs.
## 12. Backlog Items by Epic
@@ -234,13 +240,13 @@ Each item lists: Priority, Size, Classification (MVP / Research-Grade / Later-Re
**Goal:** stand up the monorepo, shared types, configuration convention, and twin pack skeletons so every later epic has a place to put code. **Depends on:** none. **Acceptance gate:** the monorepo installs and builds with zero source packages beyond skeletons, and a skeleton twin pack responds on its unprefixed route.
-#### ALD-001 — npm workspaces monorepo bootstrap
+#### ALD-001 — pnpm workspaces monorepo bootstrap
- **Priority:** P0 · **Size:** M · **Class:** MVP · **Depends on:** none
- **Spec refs:** `SPECIFICATION.md` [§4.1 Components](SPECIFICATION.md#41-components)
-- **Scope:** Initialize root `package.json` with `workspaces` for `packages/*` and `twins/*`; set up shared TypeScript config, lint/format config, and a root build script (`tsc --build` across project references).
+- **Scope:** Initialize a root pnpm workspace for `packages/*` and `twins/packs/*`; set up shared TypeScript config, lint/format config, and a root build script (`tsc --build` across project references).
- **Acceptance criteria:**
- - [x] `npm install` at the repo root succeeds with zero workspace packages beyond the initial skeletons.
- - [x] `npm run build` (project references) compiles with zero errors.
+ - [x] `pnpm install --frozen-lockfile` at the repo root succeeds.
+ - [x] `pnpm run build` (project references) compiles with zero errors.
- [x] A new package can be added under `packages/*` and is automatically picked up by the workspace without editing the root `package.json`.
#### ALD-002 — Shared `@ald/types` schema package
@@ -306,36 +312,36 @@ Each item lists: Priority, Size, Classification (MVP / Research-Grade / Later-Re
- **Spec refs:** `LEDGER-INTEGRITY-DESIGN.md` [§4. Canonical Ledger Event](LEDGER-INTEGRITY-DESIGN.md#4-canonical-ledger-event), [§6. Binding Ledgers to Communication](LEDGER-INTEGRITY-DESIGN.md#6-binding-ledgers-to-communication)
- **Scope:** Implement independent previous-hash chains for Baby A ledger, Baby B ledger, and channel transcript, plus optional affect/audit chains, with the cross-event bindings required by LEDGER §6.
- **Acceptance criteria:**
- - [ ] Each stored event's previous hash matches the immediately preceding event in the same run and event domain, with sequence starting at `1`.
- - [ ] Mutating, deleting, inserting, or reordering an event in any primary chain is detected by a chain-walk validator.
- - [ ] Sender intention, channel event, receiver delivery receipt, and receiver interpretation carry the exact cross-hashes required by LEDGER §6 and SPECIFICATION §11.5.
+ - [x] Each stored event's previous hash matches the immediately preceding event in the same run and event domain, with sequence starting at `1`.
+ - [x] Mutating, deleting, inserting, or reordering an event in any primary chain is detected by a chain-walk validator.
+ - [x] Sender intention, channel event, receiver delivery receipt, and receiver interpretation carry the exact cross-hashes required by LEDGER §6 and SPECIFICATION §11.5.
#### ALD-009 — Per-run event and witness key provisioning
- **Priority:** P0 · **Size:** M · **Class:** MVP · **Depends on:** ALD-008, ALD-003
- **Spec refs:** `LEDGER-INTEGRITY-DESIGN.md` [§11. Key Management](LEDGER-INTEGRITY-DESIGN.md#11-key-management)
- **Scope:** Provision isolated per-run Ed25519 keys for Baby A ledger, Baby B ledger, channel transcript, optional affect events, generated audit-ledger events, and Nursery checkpoint witness; expose domain-bound signing RPCs and store only public keys in the run manifest.
- **Acceptance criteria:**
- - [ ] Every committed event and checkpoint has a signature verifiable by the public key registered for exactly its domain.
- - [ ] Cross-domain signing attempts fail, including Baby A attempting to sign Baby B or channel content.
- - [ ] Private keys are absent from SQLite, logs, model context, and evidence bundles; per-run rotation produces distinct public keys.
+ - [x] Every committed event and checkpoint has a signature verifiable by the public key registered for exactly its domain.
+ - [x] Cross-domain signing attempts fail, including Baby A attempting to sign Baby B or channel content.
+ - [x] Private keys are absent from SQLite, logs, model context, and evidence bundles; per-run rotation produces distinct public keys.
#### ALD-010 — Evidence Writer and atomic turn transaction
- **Priority:** P0 · **Size:** L · **Class:** MVP · **Depends on:** ALD-005, ALD-008, ALD-009
- **Spec refs:** `SPECIFICATION.md` [§8.2 Atomic Ledger+Message Transaction](SPECIFICATION.md#82-atomic-ledgermessage-transaction)
- **Scope:** Implement the single Evidence Writer service from SPECIFICATION §4/§8: authenticate Gateway requests, assign sequences, build canonical events, obtain domain-bound signatures from `ALD-009`, and commit the sender ledger plus channel event in one SQLite transaction.
- **Acceptance criteria:**
- - [ ] A signing or insert failure at any point results in zero sender-ledger and channel rows committed.
- - [ ] A successful `TurnCommitRequest` commits both signed rows atomically and returns their entry hashes before delivery.
- - [ ] Module boundaries and database permissions prevent every other component, including Gateway and Controller, from writing event tables directly.
+ - [x] A signing or insert failure at any point results in zero sender-ledger and channel rows committed.
+ - [x] A successful `TurnCommitRequest` commits both signed rows atomically and returns their entry hashes before delivery.
+ - [x] Module boundaries and database permissions prevent every other component, including Gateway and Controller, from writing event tables directly.
#### ALD-011 — WAL durability and crash-safety tests
- **Priority:** P0 · **Size:** M · **Class:** MVP · **Depends on:** ALD-005, ALD-010
- **Spec refs:** `LEDGER-INTEGRITY-DESIGN.md` [§3. Authoritative Local Store](LEDGER-INTEGRITY-DESIGN.md#3-authoritative-local-store), [§15. Recovery and Fork Handling](LEDGER-INTEGRITY-DESIGN.md#15-recovery-and-fork-handling)
- **Scope:** Build a test harness that kills the process mid-write (simulated crash) and verifies the WAL recovers to a consistent last-committed state on restart, with no torn or partial ledger events.
- **Acceptance criteria:**
- - [ ] Simulated crash during an in-flight `ALD-010` transaction leaves the database with either the pre-transaction or post-transaction state, never a partial one, on restart.
- - [ ] The chain-walk validator from `ALD-008` reports zero integrity violations after each crash-recovery test run.
- - [ ] The test suite runs at least 20 randomized crash-point trials in CI (once `ALD-078` exists) without a single torn-write failure.
+ - [x] Simulated crash during an in-flight `ALD-010` transaction leaves the database with either the pre-transaction or post-transaction state, never a partial one, on restart.
+ - [x] The chain-walk validator from `ALD-008` reports zero integrity violations after each crash-recovery test run.
+ - [x] The test suite runs at least 20 randomized crash-point trials in CI (once `ALD-078` exists) without a single torn-write failure.
### EPIC-03 — Merkle Checkpoints and Verifier CLI (Phase 1)
@@ -346,54 +352,54 @@ Each item lists: Priority, Size, Classification (MVP / Research-Grade / Later-Re
- **Spec refs:** `LEDGER-INTEGRITY-DESIGN.md` [§7. Ordered Merkle Checkpoints](LEDGER-INTEGRITY-DESIGN.md#7-ordered-merkle-checkpoints)
- **Scope:** Implement RFC 6962-style ordered Merkle trees for all present primary and auxiliary event domains, producing roots, inclusion proofs, and prefix-consistency proofs between checkpoint sizes.
- **Acceptance criteria:**
- - [ ] Given a fixed ordered set of event hashes, the builder produces a deterministic, reproducible root hash.
- - [ ] An inclusion proof for any leaf verifies correctly against the root using only the proof and the leaf hash.
- - [ ] Valid extension checkpoints produce a consistency proof, while reordering, deletion, insertion, or a non-prefix tree fails consistency verification.
+ - [x] Given a fixed ordered set of event hashes, the builder produces a deterministic, reproducible root hash.
+ - [x] An inclusion proof for any leaf verifies correctly against the root using only the proof and the leaf hash.
+ - [x] Valid extension checkpoints produce a consistency proof, while reordering, deletion, insertion, or a non-prefix tree fails consistency verification.
#### ALD-013 — Checkpoint manifest generation
- **Priority:** P0 · **Size:** M · **Class:** MVP · **Depends on:** ALD-009, ALD-012, ALD-002
- **Spec refs:** `LEDGER-INTEGRITY-DESIGN.md` [§8. Checkpoint Manifest](LEDGER-INTEGRITY-DESIGN.md#8-checkpoint-manifest), `SPECIFICATION.md` [§11.7 Checkpoint Manifest Reference](SPECIFICATION.md#117-checkpoint-manifest-reference)
- **Scope:** Generate the complete checkpoint manifest with required Baby A/B/channel roots, present auxiliary roots, tree sizes, last hashes, prior-checkpoint hash, run/config/prompt hashes, then obtain the Nursery witness signature from `ALD-009`.
- **Acceptance criteria:**
- - [ ] A generated manifest validates against the authoritative schema and includes every event tree present in the Evidence Store.
- - [ ] Each manifest references the immediately prior checkpoint hash and carries a valid Nursery witness signature.
- - [ ] Every tree size/root exactly matches `ALD-012`, and a missing or extra tree causes checkpoint generation to fail.
+ - [x] A generated manifest validates against the authoritative schema and includes every event tree present in the Evidence Store.
+ - [x] Each manifest references the immediately prior checkpoint hash and carries a valid Nursery witness signature.
+ - [x] Every tree size/root exactly matches `ALD-012`, and a missing or extra tree causes checkpoint generation to fail.
#### ALD-014 — Checkpoint frequency scheduler
- **Priority:** P1 · **Size:** S · **Class:** MVP · **Depends on:** ALD-013
- **Spec refs:** `LEDGER-INTEGRITY-DESIGN.md` [§9. Checkpoint Frequency](LEDGER-INTEGRITY-DESIGN.md#9-checkpoint-frequency)
- **Scope:** Implement the scheduler that triggers checkpoint generation according to the frequency policy in §9 (event-count and/or time-based trigger, as specified).
- **Acceptance criteria:**
- - [ ] A checkpoint is generated automatically once the configured trigger threshold from §9 is reached.
- - [ ] No two checkpoints overlap in event range.
- - [ ] The scheduler is a background timer with the crash-protection convention (registered under the process's `uncaughtException`/`unhandledRejection` handlers) so a scheduling failure logs rather than crashes the server.
+ - [x] A checkpoint is generated automatically once the configured trigger threshold from §9 is reached.
+ - [x] No two checkpoints overlap in event range.
+ - [x] The scheduler is a background timer with the crash-protection convention (registered under the process's `uncaughtException`/`unhandledRejection` handlers) so a scheduling failure logs rather than crashes the server.
#### ALD-015 — Independent verifier CLI
- **Priority:** P0 · **Size:** L · **Class:** MVP · **Depends on:** ALD-012, ALD-013, ALD-009
- **Spec refs:** `LEDGER-INTEGRITY-DESIGN.md` [§14. Independent Verification](LEDGER-INTEGRITY-DESIGN.md#14-independent-verification)
- **Scope:** Build a standalone CLI with no runtime trust that validates canonical JSON, all event chains/cross-bindings, writer and witness signatures, Merkle roots, inclusion/consistency proofs, checkpoint chains, configuration hashes, forks, gaps, and unanchored tails. Chain-RPC verification is added by `ALD-021`.
- **Acceptance criteria:**
- - [ ] The CLI runs against an exported bundle with no network access and no shared process state with the server.
- - [ ] It accepts an unchanged local bundle and rejects every non-chain mutation case in LEDGER §17 with the correct machine-readable failure location.
- - [ ] It distinguishes chain, signature, inclusion, consistency, checkpoint, fork/gap, and unanchored-tail results.
+ - [x] The CLI runs against an exported bundle with no network access and no shared process state with the server.
+ - [x] It accepts an unchanged local bundle and rejects every non-chain mutation case in LEDGER §17 with the correct machine-readable failure location.
+ - [x] It distinguishes chain, signature, inclusion, consistency, checkpoint, fork/gap, and unanchored-tail results.
#### ALD-016 — Evidence bundle export
- **Priority:** P0 · **Size:** M · **Class:** MVP · **Depends on:** ALD-013, ALD-005
- **Spec refs:** `LEDGER-INTEGRITY-DESIGN.md` [§13. Evidence Bundle](LEDGER-INTEGRITY-DESIGN.md#13-evidence-bundle)
- **Scope:** Implement an export command that packages a run's ledger events, checkpoint manifests, signatures, and (once available) anchor receipts into a portable bundle format per §13.
- **Acceptance criteria:**
- - [ ] The exported bundle contains every event, manifest, and signature needed for `ALD-015` to verify it with no other input.
- - [ ] Exporting the same run twice without intervening writes produces byte-identical bundles.
- - [ ] The bundle format is documented with a schema so a third party could write their own verifier.
+ - [x] The exported bundle contains every event, manifest, and signature needed for `ALD-015` to verify it with no other input.
+ - [x] Exporting the same run twice without intervening writes produces byte-identical bundles.
+ - [x] The bundle format is documented with a schema so a third party could write their own verifier.
#### ALD-017 — Verification report schema and generator
- **Priority:** P1 · **Size:** S · **Class:** MVP · **Depends on:** ALD-015
- **Spec refs:** `SPECIFICATION.md` [§11.10 Verification Report](SPECIFICATION.md#1110-verification-report)
- **Scope:** Formalize the CLI's pass/fail output into the Verification Report structure defined in §11.10 and persist generated reports alongside the bundle they describe.
- **Acceptance criteria:**
- - [ ] Every verifier CLI run (`ALD-015`) produces a report conforming to the `ALD-002` schema for Verification Report.
- - [ ] A failing verification produces a report with machine-readable failure codes, not just free text.
- - [ ] Reports are timestamped and reference the exact bundle export they were generated from.
+ - [x] Every verifier CLI run (`ALD-015`) produces a report conforming to the `ALD-002` schema for Verification Report.
+ - [x] A failing verification produces a report with machine-readable failure codes, not just free text.
+ - [x] Reports are timestamped and reference the exact bundle export they were generated from.
### EPIC-04 — Base Sepolia and Mainnet Anchoring (Phases 2–3)
@@ -404,18 +410,18 @@ Each item lists: Priority, Size, Classification (MVP / Research-Grade / Later-Re
- **Spec refs:** `SPECIFICATION.md` [§11.8 Anchor Receipt Reference](SPECIFICATION.md#118-anchor-receipt-reference), `LEDGER-INTEGRITY-DESIGN.md` [§10. Base and L1 Anchoring](LEDGER-INTEGRITY-DESIGN.md#10-base-and-l1-anchoring)
- **Scope:** Define and persist the Anchor Receipt structure (checkpoint reference, chain ID, transaction hash, block number, confirmation status) linked one-to-one with a checkpoint manifest.
- **Acceptance criteria:**
- - [ ] A stored Anchor Receipt validates against the `ALD-002` schema and always references an existing checkpoint manifest (`ALD-013`).
- - [ ] Only a checkpoint root hash and minimal metadata are ever stored as the on-chain payload field — no raw observation or model data.
- - [ ] Querying receipts by checkpoint ID returns at most one receipt per chain per checkpoint.
+ - [x] A stored Anchor Receipt validates against the `ALD-002` schema and always references an existing checkpoint manifest (`ALD-013`).
+ - [x] Only a checkpoint root hash and minimal metadata are ever stored as the on-chain payload field — no raw observation or model data.
+ - [x] Querying receipts by checkpoint ID returns at most one receipt per chain per checkpoint.
#### ALD-019 — Anchoring signer key management
- **Priority:** P0 · **Size:** M · **Class:** MVP · **Depends on:** ALD-003, ALD-009
- **Spec refs:** `LEDGER-INTEGRITY-DESIGN.md` [§11. Key Management](LEDGER-INTEGRITY-DESIGN.md#11-key-management)
- **Scope:** Provision a distinct on-chain signing key (separate from the event-signing key in `ALD-009`) per the §11 key-management convention, with its own storage/rotation path.
- **Acceptance criteria:**
- - [ ] The anchoring key is stored separately from the event-signing key and neither can be derived from the other.
- - [ ] A key-rotation procedure exists and is exercised by a test that anchors before and after rotation without breaking prior receipts' validity.
- - [ ] The anchoring private key is never logged, telemetered, or included in any evidence bundle.
+ - [x] The anchoring key is stored separately from the event-signing key and neither can be derived from the other.
+ - [x] A key-rotation procedure exists and is exercised by a test that anchors before and after rotation without breaking prior receipts' validity.
+ - [x] The anchoring private key is never logged, telemetered, or included in any evidence bundle.
#### ALD-020 — Base Sepolia anchoring client
- **Priority:** P1 · **Size:** L · **Class:** MVP · **Depends on:** ALD-018, ALD-019
@@ -423,26 +429,26 @@ Each item lists: Priority, Size, Classification (MVP / Research-Grade / Later-Re
- **Scope:** Implement the client that submits a checkpoint root hash to Base Sepolia and records the resulting transaction as an Anchor Receipt (`ALD-018`), with Base Sepolia as the unconditional default target.
- **Acceptance criteria:**
- [ ] A submitted checkpoint root is independently observable on a public Base Sepolia block explorer.
- - [ ] The default configuration anchors to Base Sepolia with no additional opt-in required.
- - [ ] The submitted on-chain payload contains only the root hash and minimal required metadata, matching `ALD-018`'s privacy criterion.
+ - [x] The default configuration anchors to Base Sepolia with no additional opt-in required.
+ - [x] The submitted on-chain payload contains only the root hash and minimal required metadata, matching `ALD-018`'s privacy criterion.
#### ALD-021 — Anchor confirmation and retry/backoff
- **Priority:** P1 · **Size:** M · **Class:** MVP · **Depends on:** ALD-015, ALD-020
- **Spec refs:** `LEDGER-INTEGRITY-DESIGN.md` [§10. Base and L1 Anchoring](LEDGER-INTEGRITY-DESIGN.md#10-base-and-l1-anchoring)
- **Scope:** Implement finality polling and retry/backoff, then extend the independent verifier to retrieve the transaction through an independently configured RPC, validate chain ID/calldata/receipt/block inclusion, and compare the anchored checkpoint to the final local prefix.
- **Acceptance criteria:**
- - [ ] A receipt is marked `confirmed` only after reaching the configured confirmation depth.
- - [ ] Transient RPC failure retries without duplicate submission; wrong-chain, failed, or nonexistent transactions fail verification.
- - [ ] The verifier reports any event tail after the final anchored checkpoint and independently reproduces the anchored checkpoint hash.
+ - [x] A receipt is marked `confirmed` only after reaching the configured confirmation depth.
+ - [x] Transient RPC failure retries without duplicate submission; wrong-chain, failed, or nonexistent transactions fail verification.
+ - [x] The verifier reports any event tail after the final anchored checkpoint and independently reproduces the anchored checkpoint hash.
#### ALD-022 — Mainnet anchoring policy switch
- **Priority:** P2 · **Size:** M · **Class:** Later-Research · **Depends on:** ALD-020, ALD-021, ALD-003
- **Spec refs:** `SPECIFICATION.md` [§13.4 Base Sepolia / Mainnet Anchoring Policy](SPECIFICATION.md#134-base-sepolia--mainnet-anchoring-policy)
- **Scope:** Add an explicit, separately-configured mainnet anchoring path reusing the Sepolia client's logic with a different chain configuration, gated behind a distinct opt-in flag that defaults to off.
- **Acceptance criteria:**
- - [ ] With no explicit opt-in set, the system never submits any transaction to mainnet, confirmed by a test that asserts zero mainnet RPC calls under default config.
+ - [x] With no explicit opt-in set, the system never submits any transaction to mainnet, confirmed by a test that asserts zero mainnet RPC calls under default config.
- [ ] Enabling the opt-in flag and providing mainnet-specific key/config anchors successfully to mainnet in a manual/staging test.
- - [ ] Switching the opt-in flag off again immediately reverts all anchoring to Base Sepolia with no code change required.
+ - [x] Switching the opt-in flag off again immediately reverts all anchoring to Base Sepolia with no code change required.
### EPIC-05 — Run and Turn Lifecycle State Machine
@@ -453,54 +459,54 @@ Each item lists: Priority, Size, Classification (MVP / Research-Grade / Later-Re
- **Spec refs:** `SPECIFICATION.md` [§11.1 Run Configuration](SPECIFICATION.md#111-run-configuration)
- **Scope:** Implement validation for the Run Configuration schema (`ALD-002`), rejecting configs missing required fields (model track, protocol channel selection, mode) before a run can be created.
- **Acceptance criteria:**
- - [ ] Missing fields and incompatible track/learning-signal, oracle/experiment, or carrier-specific combinations are rejected with field-specific errors.
- - [ ] Valid root and derived configs cover every model, deployment, communication, carrier, affect, and interaction mode; lineage fields are all-or-none.
- - [ ] Validated canonical configs are persisted, hashable, and retrievable by run ID.
+ - [x] Missing fields and incompatible track/learning-signal, oracle/experiment, or carrier-specific combinations are rejected with field-specific errors.
+ - [x] Valid root and derived configs cover every model, deployment, communication, carrier, affect, and interaction mode; lineage fields are all-or-none.
+ - [x] Validated canonical configs are persisted, hashable, and retrievable by run ID.
#### ALD-024 — Run state machine
- **Priority:** P0 · **Size:** L · **Class:** MVP · **Depends on:** ALD-023
- **Spec refs:** `SPECIFICATION.md` [§7.1 Run States](SPECIFICATION.md#71-run-states), [§7.2 State Transition Table](SPECIFICATION.md#72-state-transition-table)
- **Scope:** Implement the full run-state machine exactly as the §7.2 transition table specifies, rejecting any transition not listed in the table.
- **Acceptance criteria:**
- - [ ] Every transition listed in §7.2 is implemented and unit-tested.
- - [ ] Every transition **not** listed in §7.2 is rejected with an explicit "invalid transition" error, verified by an exhaustive test over all state pairs.
- - [ ] The current state of any run is queryable and matches the last successfully applied transition.
+ - [x] Every transition listed in §7.2 is implemented and unit-tested.
+ - [x] Every transition **not** listed in §7.2 is rejected with an explicit "invalid transition" error, verified by an exhaustive test over all state pairs.
+ - [x] The current state of any run is queryable and matches the last successfully applied transition.
#### ALD-025 — Turn phase orchestrator
- **Priority:** P0 · **Size:** L · **Class:** MVP · **Depends on:** ALD-024, ALD-010
- **Spec refs:** `SPECIFICATION.md` [§8.1 Turn Phases](SPECIFICATION.md#81-turn-phases), [§8.3 Turn Timing and Budgets](SPECIFICATION.md#83-turn-timing-and-budgets)
- **Scope:** Implement the turn-phase sequencing (observation → proposal → validation → commit, per §8.1) driving the `ALD-010` atomic transaction wrapper at the commit phase, enforcing the timing budgets from §8.3.
- **Acceptance criteria:**
- - [ ] Every phase in §8.1 executes in the documented order for a successful turn.
- - [ ] A turn exceeding the §8.3 timing budget is terminated and recorded as a timeout, not left hanging.
- - [ ] The commit phase always goes through the `ALD-010` atomic wrapper — no direct ledger writes bypass it.
+ - [x] Every phase in §8.1 executes in the documented order for a successful turn.
+ - [x] A turn exceeding the §8.3 timing budget is terminated and recorded as a timeout, not left hanging.
+ - [x] The commit phase always goes through the `ALD-010` atomic wrapper — no direct ledger writes bypass it.
#### ALD-026 — Pause/abort handling
- **Priority:** P0 · **Size:** S · **Class:** MVP · **Depends on:** ALD-024
- **Spec refs:** `SPECIFICATION.md` [§7.3 Pause/Abort/Recovery/Fork Behavior](SPECIFICATION.md#73-pause-abort-recovery-fork-behavior)
- **Scope:** Implement pause and abort operations that transition a run to the corresponding §7.1 states, ensuring an in-flight turn either completes its atomic commit or is fully rolled back before the pause/abort takes effect.
- **Acceptance criteria:**
- - [ ] Pausing a run mid-turn either lets the current turn's atomic commit finish or fully rolls it back — never a partial commit.
- - [ ] An `aborted-sealed` run is terminal and can never accept another turn or be reopened.
- - [ ] Pause/abort/resume operations are recorded through the audited intervention path and produce required checkpoints.
+ - [x] Pausing a run mid-turn either lets the current turn's atomic commit finish or fully rolls it back — never a partial commit.
+ - [x] An `aborted-sealed` run is terminal and can never accept another turn or be reopened.
+ - [x] Pause/abort/resume operations are recorded through the audited intervention path and produce required checkpoints.
#### ALD-027 — Crash recovery and integrity-fork detection
- **Priority:** P0 · **Size:** M · **Class:** MVP · **Depends on:** ALD-011, ALD-025
- **Spec refs:** `SPECIFICATION.md` [§7.3 Pause/Abort/Recovery/Fork Behavior](SPECIFICATION.md#73-pause-abort-recovery-fork-behavior), `LEDGER-INTEGRITY-DESIGN.md` [§15. Recovery and Fork Handling](LEDGER-INTEGRITY-DESIGN.md#15-recovery-and-fork-handling)
- **Scope:** Reconstruct run/turn state from the last consistent evidence prefix after restart, and detect duplicate `(runId, domain, sequence)` entries with mismatched hashes both during writes and recovery.
- **Acceptance criteria:**
- - [ ] After a simulated crash mid-turn, restart reconstructs the run's state to exactly the last atomically committed turn, with no phantom in-progress turn.
- - [ ] A mismatched duplicate sequence preserves both artifacts, transitions the run to `forked-invalid`, halts writes, and requires research-integrity review.
- - [ ] Recovery appends an explicit recovery event at the next unused sequence and matches the state independently derived by `ALD-015`.
+ - [x] After a simulated crash mid-turn, restart reconstructs the run's state to exactly the last atomically committed turn, with no phantom in-progress turn.
+ - [x] A mismatched duplicate sequence preserves both artifacts, transitions the run to `forked-invalid`, halts writes, and requires research-integrity review.
+ - [x] Recovery appends an explicit recovery event at the next unused sequence and matches the state independently derived by `ALD-015`.
#### ALD-028 — Derived-run branching and lineage
- **Priority:** P1 · **Size:** M · **Class:** Research-Grade · **Depends on:** ALD-024, ALD-016
- **Spec refs:** `SPECIFICATION.md` [§7.4 Derived Runs and Lineage](SPECIFICATION.md#74-derived-runs-and-lineage)
- **Scope:** Implement a new derived run from a specific parent checkpoint, with optional per-Baby replacement policy/adapter, independent event sequences starting at `1`, and immutable parent references.
- **Acceptance criteria:**
- - [ ] A child run records `parentRunId`, `derivedFromCheckpointHash`, and both initial policy refs in config and its first initialization event.
- - [ ] Child sequences restart at `1`, and writes never modify parent evidence or reopen a terminal parent.
- - [ ] `ALD-016` exports lineage references and `ALD-015` verifies them against the immutable parent bundle.
+ - [x] A child run records `parentRunId`, `derivedFromCheckpointHash`, and both initial policy refs in config and its first initialization event.
+ - [x] Child sequences restart at `1`, and writes never modify parent evidence or reopen a terminal parent.
+ - [x] `ALD-016` exports lineage references and `ALD-015` verifies them against the immutable parent bundle.
### EPIC-06 — Symbol Gateway and Communication Protocols
@@ -511,72 +517,72 @@ Each item lists: Priority, Size, Classification (MVP / Research-Grade / Later-Re
- **Spec refs:** `SPECIFICATION.md` [§9. Communication Protocols](SPECIFICATION.md#9-communication-protocols)
- **Scope:** Implement the single mediation point for every inter-agent artifact, registered protocol dispatch, and all six §9.6 communication-control conditions, including seeded substitutions and oracle-only-for-E03 enforcement.
- **Acceptance criteria:**
- - [ ] Every artifact passes through the Gateway; direct Baby-to-Baby routes fail in an instrumented integration test.
- - [ ] `normal`, `disabled`, `constant`, seeded `random`, seeded `shuffled`, and E03-only `oracle` conditions produce their exact §9.6 behavior with no code changes.
- - [ ] Every accepted, rejected, or control-substituted turn records the Baby-proposal hash when present and exact delivered-artifact hash through `ALD-035`.
+ - [x] Every artifact passes through the Gateway; direct Baby-to-Baby routes fail in an instrumented integration test.
+ - [x] `normal`, `disabled`, `constant`, seeded `random`, seeded `shuffled`, and E03-only `oracle` conditions produce their exact §9.6 behavior with no code changes.
+ - [x] Every accepted, rejected, or control-substituted turn records the Baby-proposal hash when present and exact delivered-artifact hash through `ALD-035`.
#### ALD-030 — Fixed-token protocol
- **Priority:** P0 · **Size:** M · **Class:** MVP · **Depends on:** ALD-029
- **Spec refs:** `SPECIFICATION.md` [§9.1 Fixed Token Protocol](SPECIFICATION.md#91-fixed-token-protocol)
- **Scope:** Implement the fixed-token vocabulary channel: a closed, enumerable token set, with the Gateway validating every emitted token against the registered vocabulary.
- **Acceptance criteria:**
- - [ ] Emitting a token in the registered vocabulary is accepted and forwarded.
- - [ ] Emitting any token, string, or byte sequence not in the registered vocabulary is rejected, not silently coerced to the nearest valid token.
- - [ ] The vocabulary is configurable per run without a code change.
+ - [x] Emitting a token in the registered vocabulary is accepted and forwarded.
+ - [x] Emitting any token, string, or byte sequence not in the registered vocabulary is rejected, not silently coerced to the nearest valid token.
+ - [x] The vocabulary is configurable per run without a code change.
#### ALD-031 — Alternate neutral carrier protocols
- **Priority:** P2 · **Size:** L · **Class:** Later-Research · **Depends on:** ALD-029
- **Spec refs:** `SPECIFICATION.md` [§9.2 Alternate Neutral Carrier Protocols](SPECIFICATION.md#92-alternate-neutral-carrier-protocols)
- **Scope:** Implement §9.2's `fixed-glyph`, `generative-bitmap`, `generative-canvas`, and `generative-tone` carrier modules with frozen neutral grammars, hard bounds, RFC 8785 canonicalization, and carrier-qualified content-addressed `markHash` generation.
- **Acceptance criteria:**
- - [ ] Each alternate carrier accepts a valid bounded artifact and reproduces the same carrier-qualified `markHash`.
- - [ ] Out-of-range glyph IDs, bitmap sizes, stroke values, tone bins, text/color fields, and semantic tags are rejected with specific reasons.
- - [ ] Every carrier contributes accept/reject vectors to `ALD-036`, and exactly one carrier family is available in a run.
+ - [x] Each alternate carrier accepts a valid bounded artifact and reproduces the same carrier-qualified `markHash`.
+ - [x] Out-of-range glyph IDs, bitmap sizes, stroke values, tone bins, text/color fields, and semantic tags are rejected with specific reasons.
+ - [x] Every carrier contributes accept/reject vectors to `ALD-036`, and exactly one carrier family is available in a run.
#### ALD-032 — Alternate-carrier leakage evaluation
- **Priority:** P1 · **Size:** M · **Class:** Research-Grade · **Depends on:** ALD-031
- **Spec refs:** `SPECIFICATION.md` [§9.2 Alternate Neutral Carrier Protocols](SPECIFICATION.md#92-alternate-neutral-carrier-protocols), [§15.3 Evaluation Baselines and Statistics](SPECIFICATION.md#153-evaluation-baselines-and-statistics)
- **Scope:** Add offline evaluation hooks for measuring whether alternate-carrier artifacts reproduce recognizable human-language forms or encode task/referent information through unintended glyph, bitmap, stroke, or tone features. The evaluator reports evidence and claim-boundary impact; it does not silently rewrite accepted artifacts.
- **Acceptance criteria:**
- - [ ] The evaluator records mark-level leakage metrics and the exact analysis version in the run evidence bundle.
- - [ ] Pre-registered recognizable-glyph and unintended-feature probes produce explicit pass, fail, or inconclusive results without altering the original canvas artifact.
- - [ ] A failed leakage evaluation blocks an ungrounded-language claim while preserving the run as valid negative or integrity evidence.
+ - [x] The evaluator records mark-level leakage metrics and the exact analysis version in the run evidence bundle.
+ - [x] Pre-registered recognizable-glyph and unintended-feature probes produce explicit pass, fail, or inconclusive results without altering the original canvas artifact.
+ - [x] A failed leakage evaluation blocks an ungrounded-language claim while preserving the run as valid negative or integrity evidence.
#### ALD-033 — Six-display affect protocol
- **Priority:** P2 · **Size:** M · **Class:** Later-Research · **Depends on:** ALD-029
- **Spec refs:** `SPECIFICATION.md` [§9.3 Six-Display Affect Protocol](SPECIFICATION.md#93-six-display-affect-protocol)
- **Scope:** Implement declared, permuted, opaque, and derived six-display modes plus emergent-affect routing through the selected alternate carrier. In derived mode, the Gateway maps adapter measurements; the Baby cannot choose a display.
- **Acceptance criteria:**
- - [ ] Declared/permuted/opaque modes emit only A1-A6, while any other display or out-of-window submission is rejected.
- - [ ] Derived mode disables `submit_affect`, records the private measurement, and applies the pre-registered Gateway mapping; emergent mode records a carrier Channel Event rather than an Affect Event.
- - [ ] Affect schemas and every mode's accept/reject vectors extend `ALD-036`, including normalized timing/envelope behavior.
+ - [x] Declared/permuted/opaque modes emit only A1-A6, while any other display or out-of-window submission is rejected.
+ - [x] Derived mode disables `submit_affect`, records the private measurement, and applies the pre-registered Gateway mapping; emergent mode records a carrier Channel Event rather than an Affect Event.
+ - [x] Affect schemas and every mode's accept/reject vectors extend `ALD-036`, including normalized timing/envelope behavior.
#### ALD-034 — Channel violation detection and rejection behavior
- **Priority:** P0 · **Size:** M · **Class:** MVP · **Depends on:** ALD-029, ALD-030
- **Spec refs:** `SPECIFICATION.md` [§9.4 Rejection Behavior and Channel Violation Handling](SPECIFICATION.md#94-rejection-behavior-and-channel-violation-handling)
- **Scope:** Implement the protocol-independent rejection framework used by every Gateway module: consistent error shape, append-only `channel.rejected` events containing only a rejected-payload hash, rejection counters, and automatic pause after the configured consecutive-rejection ceiling. Fixed-token handling is the first registered module; later canvas and affect modules reuse this framework.
- **Acceptance criteria:**
- - [ ] A fixed-token violation produces the standard rejection shape and an append-only `channel.rejected` event with reason code and payload hash but no raw rejected content.
- - [ ] Five consecutive rejections by default trigger an automatic pause and `safety-trigger` audit entry.
- - [ ] A protocol-module contract test proves canvas and affect handlers can register later without changing the rejection event shape or pause policy.
+ - [x] A fixed-token violation produces the standard rejection shape and an append-only `channel.rejected` event with reason code and payload hash but no raw rejected content.
+ - [x] Five consecutive rejections by default trigger an automatic pause and `safety-trigger` audit entry.
+ - [x] A protocol-module contract test proves canvas and affect handlers can register later without changing the rejection event shape or pause policy.
#### ALD-035 — Turn envelope, channel event, and ledger draft schemas
- **Priority:** P0 · **Size:** S · **Class:** MVP · **Depends on:** ALD-002, ALD-029
- **Spec refs:** `SPECIFICATION.md` [§11.3 Turn and Ledger Proposal Envelopes](SPECIFICATION.md#113-turn-and-ledger-proposal-envelopes), [§11.5 Channel Event](SPECIFICATION.md#115-channel-event)
- **Scope:** Implement and validate Agent Action Proposal, Turn Proposal Envelope, Ledger Draft Envelope, Affect State Measurement, and fully signed Channel Event schemas, wired into Gateway and Evidence Writer boundaries.
- **Acceptance criteria:**
- - [ ] Every Gateway proposal includes one required private intention draft and rejects Baby-supplied run/turn/sender/hash metadata.
- - [ ] Every accepted/rejected event contains the sender-ledger binding, delivery receipt, previous channel hash, entry hash, and channel-writer signature required by §11.5.
- - [ ] Interpretation drafts require the delivered channel hash, and all schema failures use the standard Gateway error shape.
+ - [x] Every Gateway proposal includes one required private intention draft and rejects Baby-supplied run/turn/sender/hash metadata.
+ - [x] Every accepted/rejected event contains the sender-ledger binding, delivery receipt, previous channel hash, entry hash, and channel-writer signature required by §11.5.
+ - [x] Interpretation drafts require the delivered channel hash, and all schema failures use the standard Gateway error shape.
#### ALD-036 — Gateway/protocol conformance test suite
- **Priority:** P0 · **Size:** M · **Class:** MVP · **Depends on:** ALD-030, ALD-034, ALD-035
- **Spec refs:** `SPECIFICATION.md` [§9. Communication Protocols](SPECIFICATION.md#9-communication-protocols), [§17.2 Test Strategy](SPECIFICATION.md#172-test-strategy)
- **Scope:** Build an extensible automated conformance suite for registered Gateway protocols, rejection behavior, and schema validation, runnable independently of any learner adapter. The fixed-token module is the MVP gate; `ALD-031` and `ALD-033` must add canvas and affect vectors before those modules are declared done.
- **Acceptance criteria:**
- - [ ] The MVP suite exercises fixed-token acceptance/rejection, all six communication controls, dual proposal/delivery hashing, consecutive-rejection pause, and schema failures.
- - [ ] The suite runs against a mocked/stub learner, with no dependency on any specific `ALD-044`–047 adapter.
- - [ ] A protocol registration test requires every enabled module to contribute accept/reject vectors; the consolidated suite is the gate referenced by EPIC-06 and `ALD-078`.
+ - [x] The MVP suite exercises fixed-token acceptance/rejection, all six communication controls, dual proposal/delivery hashing, consecutive-rejection pause, and schema failures.
+ - [x] The suite runs against a mocked/stub learner, with no dependency on any specific `ALD-044`–047 adapter.
+ - [x] A protocol registration test requires every enabled module to contribute accept/reject vectors; the consolidated suite is the gate referenced by EPIC-06 and `ALD-078`.
### EPIC-07 — Observation Hygiene, Scenario Engine, and Deterministic Services
@@ -587,45 +593,45 @@ Each item lists: Priority, Size, Classification (MVP / Research-Grade / Later-Re
- **Spec refs:** `SPECIFICATION.md` [§11.2 Observation](SPECIFICATION.md#112-observation)
- **Scope:** Implement the Observation builder that assembles exactly the fields §11.2 defines for a given turn, from world/scenario state, with no additional fields leaking in.
- **Acceptance criteria:**
- - [ ] A built Observation validates against the `ALD-002` schema and contains no field not listed in §11.2.
- - [ ] Two observations built from identical underlying state are byte-identical after canonicalization (reusing `ALD-006`'s approach).
- - [ ] The builder is the only code path producing Observations delivered to learners.
+ - [x] A built Observation validates against the `ALD-002` schema and contains no field not listed in §11.2.
+ - [x] Two observations built from identical underlying state are byte-identical after canonicalization (reusing `ALD-006`'s approach).
+ - [x] The builder is the only code path producing Observations delivered to learners.
#### ALD-038 — Observation hygiene filter
- **Priority:** P0 · **Size:** M · **Class:** Research-Grade · **Depends on:** ALD-037
- **Spec refs:** `SPECIFICATION.md` [§10.1 Observation Hygiene](SPECIFICATION.md#101-observation-hygiene)
- **Scope:** Implement the filter that strips or blocks any observation content prohibited by §10.1 (e.g., internal identifiers, other agent's private state, out-of-scenario metadata) before delivery.
- **Acceptance criteria:**
- - [ ] Every prohibited field category listed in §10.1 is demonstrated blocked using a test observation deliberately constructed to contain it.
- - [ ] The filter runs on every Observation before it reaches the Gateway/learner boundary, with no bypass path.
- - [ ] A blocked field produces an audit-logged event (feeding `ALD-059`), not a silent drop.
+ - [x] Every prohibited field category listed in §10.1 is demonstrated blocked using a test observation deliberately constructed to contain it.
+ - [x] The filter runs on every Observation before it reaches the Gateway/learner boundary, with no bypass path.
+ - [x] A blocked field produces an audit-logged event (feeding `ALD-059`), not a silent drop.
#### ALD-039 — OCR detection and scenario-bundle quarantine
- **Priority:** P0 · **Size:** M · **Class:** Research-Grade · **Depends on:** ALD-037
- **Spec refs:** `SPECIFICATION.md` [§10.2 Prompt Injection Controls](SPECIFICATION.md#102-prompt-injection-controls)
- **Scope:** Scan every scene and asset for OCR-visible text before scenario registration. Any detected glyph or text causes the complete bundle to fail observation hygiene and enter quarantine; prohibited text is never sanitized and passed through.
- **Acceptance criteria:**
- - [ ] A bundle containing OCR-detected text, caption metadata, semantic filenames, or human-readable labels cannot be referenced by a run.
- - [ ] Text-free controls pass while pre-registered adversarial image/text fixtures are quarantined before any adapter receives them.
- - [ ] Quarantine events retain artifact hashes and reason codes without exposing raw injection text in Baby-visible or public logs.
+ - [x] A bundle containing OCR-detected text, caption metadata, semantic filenames, or human-readable labels cannot be referenced by a run.
+ - [x] Text-free controls pass while pre-registered adversarial image/text fixtures are quarantined before any adapter receives them.
+ - [x] Quarantine events retain artifact hashes and reason codes without exposing raw injection text in Baby-visible or public logs.
#### ALD-040 — Side-channel elimination in transport layer
- **Priority:** P0 · **Size:** M · **Class:** Research-Grade · **Depends on:** ALD-029, ALD-037
- **Spec refs:** `SPECIFICATION.md` [§10.3 Side Channel Controls](SPECIFICATION.md#103-side-channel-controls)
- **Scope:** Audit and close the transport-level side channels named in §10.3 (e.g., timing channels, response-size channels, error-message channels) in the Gateway and Observation delivery path.
- **Acceptance criteria:**
- - [ ] Each side-channel category named in §10.3 has a corresponding mitigation implemented (e.g., constant-shape error responses, timing normalization where specified).
- - [ ] A test harness measuring the relevant channel (e.g., response latency variance) confirms the mitigation is effective within the tolerance §10.3 implies.
- - [ ] This item's test harness is reused (not duplicated) by the red-team suite in `ALD-067`.
+ - [x] Each side-channel category named in §10.3 has a corresponding mitigation implemented (e.g., constant-shape error responses, timing normalization where specified).
+ - [x] A test harness measuring the relevant channel (e.g., response latency variance) confirms the mitigation is effective within the tolerance §10.3 implies.
+ - [x] This item's test harness is reused (not duplicated) by the red-team suite in `ALD-067`.
#### ALD-041 — Deterministic scenario/task engine
- **Priority:** P1 · **Size:** L · **Class:** MVP · **Depends on:** ALD-023, ALD-037
- **Spec refs:** `SPECIFICATION.md` [§9.5 Interaction and Utility Profiles](SPECIFICATION.md#95-interaction-and-utility-profiles), [§15.3 Evaluation Baselines and Statistics](SPECIFICATION.md#153-evaluation-baselines-and-statistics), [§17.3 Phased Delivery](SPECIFICATION.md#173-phased-delivery)
- **Scope:** Implement the scenario/task generator that deterministically produces scenario states, private observations, utility matrices, reservation values, and zones of possible agreement from run configuration and seed for all five §9.5 interaction profiles.
- **Acceptance criteria:**
- - [ ] Two runs with the same seed and interaction mode produce byte-identical scenarios, private facts, utilities, and task sequences.
- - [ ] Every §9.5 interaction profile produces its required utility relationship, including a provably empty zone of possible agreement for `no-agreement-control`.
- - [ ] The engine's output feeds `ALD-037`'s Observation builder with no intermediate non-deterministic step.
+ - [x] Two runs with the same seed and interaction mode produce byte-identical scenarios, private facts, utilities, and task sequences.
+ - [x] Every §9.5 interaction profile produces its required utility relationship, including a provably empty zone of possible agreement for `no-agreement-control`.
+ - [x] The engine's output feeds `ALD-037`'s Observation builder with no intermediate non-deterministic step.
### EPIC-08 — Learner Contracts and Model Adapters
@@ -636,54 +642,54 @@ Each item lists: Priority, Size, Classification (MVP / Research-Grade / Later-Re
- **Spec refs:** `SPECIFICATION.md` [§6.2 Learner Adapter Interface](SPECIFICATION.md#62-learner-adapter-interface)
- **Scope:** Define the shared TypeScript interface every model track must implement (receive Observation, return Agent Action Proposal, lifecycle hooks) exactly matching §6.2, and provide the deterministic/fixed `no-learning` reference adapter used for chance controls.
- **Acceptance criteria:**
- - [ ] The interface implements every §6.2 method, including `receive(DeliveredChannelArtifact)` returning a `LedgerDraftEnvelope`.
- - [ ] The `no-learning` reference adapter is selectable, performs no policy update, and passes the contract-conformance test.
- - [ ] The interface is the only integration point the turn orchestrator (`ALD-025`) uses to reach a learner.
+ - [x] The interface implements every §6.2 method, including `receive(DeliveredChannelArtifact)` returning a `LedgerDraftEnvelope`.
+ - [x] The `no-learning` reference adapter is selectable, performs no policy update, and passes the contract-conformance test.
+ - [x] The interface is the only integration point the turn orchestrator (`ALD-025`) uses to reach a learner.
#### ALD-043 — Learner contract versioning, lint, and tool-only enforcement
- **Priority:** P0 · **Size:** L · **Class:** Research-Grade · **Depends on:** ALD-042
- **Spec refs:** `SPECIFICATION.md` [§6.3 Tool-Only Interaction Contract](SPECIFICATION.md#63-tool-only-interaction-contract), [§6.4 Learner Contract Versioning](SPECIFICATION.md#64-learner-contract-versioning)
- **Scope:** Implement immutable versioned learner-contract files, CI lint that rejects semantic examples/sample exchanges/banned patterns, prompt-bundle hashing, and runtime enforcement that every adapter acts only through the declared tools and Gateway.
- **Acceptance criteria:**
- - [ ] A contract containing a symbol-meaning example, sample exchange, or prohibited side-channel instruction fails CI and cannot be referenced by a run.
- - [ ] Referenced contract versions are immutable and their prompt-bundle hashes appear in run evidence.
- - [ ] The no-learning reference and all four adapter tracks are blocked and audited when attempting any state write or output outside the §6.3 tool surface.
+ - [x] A contract containing a symbol-meaning example, sample exchange, or prohibited side-channel instruction fails CI and cannot be referenced by a run.
+ - [x] Referenced contract versions are immutable and their prompt-bundle hashes appear in run evidence.
+ - [x] The no-learning reference and all four adapter tracks are blocked and audited when attempting any state write or output outside the §6.3 tool surface.
#### ALD-044 — Frozen-LLM adapter with local open-weight default
- **Priority:** P0 · **Size:** L · **Class:** MVP · **Depends on:** ALD-042, ALD-043
- **Spec refs:** `SPECIFICATION.md` [§6.7 Model Recommendations (Defaults)](SPECIFICATION.md#67-model-recommendations-defaults), [§6.1 Track Definitions](SPECIFICATION.md#61-track-definitions)
- **Scope:** Implement the `frozen-llm` adapter using a locally deployable 3B–8B open-weight instruction model by default, with frozen weights, separate private memory, constrained tool calls, and no network access.
- **Acceptance criteria:**
- - [ ] The `frozen-llm` track is selectable via `ALD-023` run configuration and records the exact model and weight hashes.
- - [ ] A full turn (observation → proposal → Gateway validation → commit) completes end-to-end using this adapter.
- - [ ] The adapter exposes no weight-update path and passes the `ALD-036` Gateway conformance suite.
+ - [x] The `frozen-llm` track is selectable via `ALD-023` run configuration and records the exact model and weight hashes.
+ - [x] A full turn (observation → proposal → Gateway validation → commit) completes end-to-end using this adapter.
+ - [x] The adapter exposes no weight-update path and passes the `ALD-036` Gateway conformance suite.
#### ALD-045 — From-scratch RL learner track
- **Priority:** P1 · **Size:** L · **Class:** MVP · **Depends on:** ALD-042, ALD-043
- **Spec refs:** `SPECIFICATION.md` [§6.1 Track Definitions](SPECIFICATION.md#61-track-definitions), `EXPERIMENT-NOTEBOOK.md` [E11 — From-Scratch RL Naming Game](EXPERIMENT-NOTEBOOK.md#e11-from-scratch-rl-naming-game)
- **Scope:** Implement the `scratch-rl` GRU/LSTM actor-critic adapter with independent PPO-style updates, random initialization, private buffers, and policy checkpoint output.
- **Acceptance criteria:**
- - [ ] The track starts from randomly initialized parameters whose initial hash is recorded in the evidence bundle.
- - [ ] A full turn and minimal reward-to-parameter-update cycle complete end-to-end in both pre-registered extrinsic-reward and intrinsic-motivation modes.
- - [ ] Policy updates use only the Baby's private buffers and emit a verifiable policy checkpoint reference.
+ - [x] The track starts from randomly initialized parameters whose initial hash is recorded in the evidence bundle.
+ - [x] A full turn and minimal reward-to-parameter-update cycle complete end-to-end in both pre-registered extrinsic-reward and intrinsic-motivation modes.
+ - [x] Policy updates use only the Baby's private buffers and emit a verifiable policy checkpoint reference.
#### ALD-046 — Self-supervised ungrounded learner track
- **Priority:** P1 · **Size:** L · **Class:** Later-Research · **Depends on:** ALD-042, ALD-043
- **Spec refs:** `SPECIFICATION.md` [§6.1 Track Definitions](SPECIFICATION.md#61-track-definitions), `EXPERIMENT-NOTEBOOK.md` [E12 — Self-Supervised Ungrounded Baseline](EXPERIMENT-NOTEBOOK.md#e12-self-supervised-ungrounded-baseline)
- **Scope:** Implement the `self-supervised` adapter with the same recurrent backbone as `scratch-rl` where feasible, using a pre-registered predictive or contrastive loss and no scalar reward.
- **Acceptance criteria:**
- - [ ] The track is selectable, starts from recorded random initialization, and rejects any scalar reward supplied to its update path.
- - [ ] A full turn and minimal predictive/contrastive update complete end-to-end.
- - [ ] The evidence bundle records the loss definition and proves that outcome labels are not included in the self-supervised update batch.
+ - [x] The track is selectable, starts from recorded random initialization, and rejects any scalar reward supplied to its update path.
+ - [x] A full turn and minimal predictive/contrastive update complete end-to-end.
+ - [x] The evidence bundle records the loss definition and proves that outcome labels are not included in the self-supervised update batch.
#### ALD-047 — Hybrid learner track
- **Priority:** P1 · **Size:** L · **Class:** Later-Research · **Depends on:** ALD-042, ALD-043
- **Spec refs:** `SPECIFICATION.md` [§6.1 Track Definitions](SPECIFICATION.md#61-track-definitions), [§6.5 Semantic-Leakage Test Battery](SPECIFICATION.md#65-semantic-leakage-test-battery)
- **Scope:** Implement the `hybrid` adapter using a from-scratch sensory encoder, recurrent world model, and randomly initialized communication policy, with optional frozen low-level visual features only after semantic-leakage qualification.
- **Acceptance criteria:**
- - [ ] The track is selectable and records the provenance and hashes of every sensory, world-model, and communication component.
- - [ ] A full turn and minimal policy update complete end-to-end through the shared interface.
- - [ ] Any text-aligned frozen feature automatically weakens the run's claim classification; strict ungrounded classification requires `ALD-057` to pass.
+ - [x] The track is selectable and records the provenance and hashes of every sensory, world-model, and communication component.
+ - [x] A full turn and minimal policy update complete end-to-end through the shared interface.
+ - [x] Any text-aligned frozen feature automatically weakens the run's claim classification; strict ungrounded classification requires `ALD-057` to pass.
### EPIC-09 — DTSF Twin Packs, API Surface, and Authorization
@@ -694,45 +700,45 @@ Each item lists: Priority, Size, Classification (MVP / Research-Grade / Later-Re
- **Spec refs:** `SPECIFICATION.md` [§12.4 Baby Twin Routes (baby-a, baby-b)](SPECIFICATION.md#124-baby-twin-routes-baby-a-baby-b)
- **Scope:** Replace the `ALD-004` skeleton routes with full implementations of every route listed in §12.4, wired to the Gateway (`ALD-029`) and a selected learner adapter (`ALD-042`-conformant).
- **Acceptance criteria:**
- - [ ] Every route in §12.4, including Gateway-only `/deliver`, exists on both `baby-a` and `baby-b`, all unprefixed.
- - [ ] Each route's behavior matches its documented purpose in §12.4 (verified by an integration test per route).
- - [ ] A full run using these twin packs completes at least one turn end-to-end through the Gateway.
+ - [x] Every route in §12.4, including Gateway-only `/deliver`, exists on both `baby-a` and `baby-b`, all unprefixed.
+ - [x] Each route's behavior matches its documented purpose in §12.4 (verified by an integration test per route).
+ - [x] A full run using these twin packs completes at least one turn end-to-end through the Gateway.
#### ALD-049 — Nursery controller twin pack
- **Priority:** P0 · **Size:** L · **Class:** MVP · **Depends on:** ALD-024, ALD-048
- **Spec refs:** `SPECIFICATION.md` [§12.5 Nursery Controller Routes (nursery)](SPECIFICATION.md#125-nursery-controller-routes-nursery)
- **Scope:** Implement the nursery controller's routes for creating/starting/pausing/aborting runs and creating derived runs, driving the `ALD-024` state machine and `ALD-028` lineage service while orchestrating both Baby twins.
- **Acceptance criteria:**
- - [ ] Every route in §12.5 exists, unprefixed, and drives the correct `ALD-024` state transition.
- - [ ] Creating a run via nursery correctly provisions both `baby-a` and `baby-b` instances.
- - [ ] Pausing/aborting and derived-run creation use the same state/lineage services as direct internal calls, with no divergent logic path or reopening of terminal parents.
+ - [x] Every route in §12.5 exists, unprefixed, and drives the correct `ALD-024` state transition.
+ - [x] Creating a run via nursery correctly provisions both `baby-a` and `baby-b` instances.
+ - [x] Pausing/aborting and derived-run creation use the same state/lineage services as direct internal calls, with no divergent logic path or reopening of terminal parents.
#### ALD-050 — Evidence and verification routes on nursery
- **Priority:** P0 · **Size:** M · **Class:** MVP · **Depends on:** ALD-016, ALD-049
- **Spec refs:** `SPECIFICATION.md` [§12.6 Evidence and Verification Routes (nursery)](SPECIFICATION.md#126-evidence-and-verification-routes-nursery)
- **Scope:** Implement the nursery routes for triggering evidence bundle export (`ALD-016`) and retrieving verification reports (`ALD-017`), per §12.6.
- **Acceptance criteria:**
- - [ ] Every route in §12.6 exists, unprefixed, and returns data conforming to the `ALD-002` schemas involved.
- - [ ] Triggering an export via this route produces a bundle identical to calling `ALD-016`'s export function directly.
- - [ ] Unauthorized callers (per `ALD-051`) cannot reach these routes.
+ - [x] Every route in §12.6 exists, unprefixed, and returns data conforming to the `ALD-002` schemas involved.
+ - [x] Triggering an export via this route produces a bundle identical to calling `ALD-016`'s export function directly.
+ - [x] Unauthorized callers (per `ALD-051`) cannot reach these routes.
#### ALD-051 — Authorization roles and route guards
- **Priority:** P0 · **Size:** M · **Class:** MVP · **Depends on:** ALD-048, ALD-049, ALD-050
- **Spec refs:** `SPECIFICATION.md` [§12.2 Authorization Roles](SPECIFICATION.md#122-authorization-roles)
- **Scope:** Implement the role model and route guards from §12.2 across all twin routes, denying access to any role not explicitly permitted for a given route.
- **Acceptance criteria:**
- - [ ] Every role defined in §12.2 is enforced on every route that names a restriction.
- - [ ] Missing/invalid credentials return `401 UNAUTHENTICATED`; valid identities with insufficient roles return `403 FORBIDDEN`.
- - [ ] A test matrix of (role × route) confirms allow/deny matches §12.2 exactly.
+ - [x] Every role defined in §12.2 is enforced on every route that names a restriction.
+ - [x] Missing/invalid credentials return `401 UNAUTHENTICATED`; valid identities with insufficient roles return `403 FORBIDDEN`.
+ - [x] A test matrix of (role × route) confirms allow/deny matches §12.2 exactly.
#### ALD-052 — Response and error shape standardization
- **Priority:** P1 · **Size:** S · **Class:** MVP · **Depends on:** ALD-048, ALD-049, ALD-050
- **Spec refs:** `SPECIFICATION.md` [§12.3 Response and Error Shape](SPECIFICATION.md#123-response-and-error-shape)
- **Scope:** Apply the standardized success/error response envelope from §12.3 to every route across all three twin packs.
- **Acceptance criteria:**
- - [ ] Every success response across all routes matches the §12.3 success envelope.
- - [ ] Every error response across all routes matches the §12.3 error envelope, including the ones from `ALD-034`'s channel violations.
- - [ ] A lint/test rule fails the build if a new route is added without conforming to the envelope.
+ - [x] Every success response across all routes matches the §12.3 success envelope.
+ - [x] Every error response across all routes matches the §12.3 error envelope, including the ones from `ALD-034`'s channel violations.
+ - [x] A lint/test rule fails the build if a new route is added without conforming to the envelope.
### EPIC-10 — Mode R Isolation and Claim-Boundary Controls
@@ -743,45 +749,45 @@ Each item lists: Priority, Size, Classification (MVP / Research-Grade / Later-Re
- **Spec refs:** `SPECIFICATION.md` [§5.1 Prototype Mode (Mode P)](SPECIFICATION.md#51-prototype-mode-mode-p), [§5.2 Research-Grade Mode (Mode R)](SPECIFICATION.md#52-research-grade-mode-mode-r), [§5.3 Mode Comparison Table](SPECIFICATION.md#53-mode-comparison-table)
- **Scope:** Implement the configuration switch selecting Mode P or Mode R for a run, wiring each mode's distinct behaviors from §5.3 (e.g., isolation strictness, claim labeling) into the nursery run-creation path.
- **Acceptance criteria:**
- - [ ] A run created under Mode P and one under Mode R differ exactly along the dimensions listed in §5.3 — no undocumented behavioral difference.
- - [ ] The mode is immutable for the lifetime of a run once created (cannot be switched mid-run).
- - [ ] The active mode is recorded in the Run Configuration and visible in every exported evidence bundle.
+ - [x] A run created under Mode P and one under Mode R differ exactly along the dimensions listed in §5.3 — no undocumented behavioral difference.
+ - [x] The mode is immutable for the lifetime of a run once created (cannot be switched mid-run).
+ - [x] The active mode is recorded in the Run Configuration and visible in every exported evidence bundle.
#### ALD-054 — Claim-boundary enforcement
- **Priority:** P0 · **Size:** M · **Class:** Research-Grade · **Depends on:** ALD-053
- **Spec refs:** `SPECIFICATION.md` [§5.4 Claim Boundary Statements](SPECIFICATION.md#54-claim-boundary-statements)
- **Scope:** Implement automated checks that block any dashboard/report/export from asserting a Mode-R-only claim (e.g., "isolation-verified") about a run that actually executed in Mode P.
- **Acceptance criteria:**
- - [ ] Every claim statement listed in §5.4 is machine-checked against the run's actual recorded mode before being allowed to render/export.
- - [ ] A Mode P run attempting to surface a Mode-R-only claim label is blocked with a specific error, not silently downgraded.
- - [ ] The check is exercised by an automated test for every claim statement in §5.4, not spot-checked manually.
+ - [x] Every claim statement listed in §5.4 is machine-checked against the run's actual recorded mode before being allowed to render/export.
+ - [x] A Mode P run attempting to surface a Mode-R-only claim label is blocked with a specific error, not silently downgraded.
+ - [x] The check is exercised by an automated test for every claim statement in §5.4, not spot-checked manually.
#### ALD-055 — Separate-container isolation for Mode R
- **Priority:** P1 · **Size:** L · **Class:** Research-Grade · **Depends on:** ALD-053
- **Spec refs:** `SPECIFICATION.md` [§5.2 Research-Grade Mode (Mode R)](SPECIFICATION.md#52-research-grade-mode-mode-r)
- **Scope:** Run each learner adapter in Mode R in its own container/process with no shared mutable memory, communicating only through the Gateway and evidence store.
- **Acceptance criteria:**
- - [ ] In Mode R, `baby-a` and `baby-b` learner processes run in distinct OS processes/containers, verified by distinct process IDs / container IDs.
- - [ ] No in-memory object reference is shared between the two learner containers (verified by an isolation test attempting cross-container object access and observing failure).
- - [ ] Killing one learner container does not corrupt or crash the other, or the Gateway/evidence store.
+ - [x] In Mode R, `baby-a` and `baby-b` learner processes run in distinct OS processes/containers, verified by distinct process IDs / container IDs.
+ - [x] No in-memory object reference is shared between the two learner containers (verified by an isolation test attempting cross-container object access and observing failure).
+ - [x] Killing one learner container does not corrupt or crash the other, or the Gateway/evidence store.
#### ALD-056 — Training isolation guarantees
- **Priority:** P0 · **Size:** M · **Class:** Research-Grade · **Depends on:** ALD-055, ALD-045, ALD-046, ALD-047
- **Spec refs:** `SPECIFICATION.md` [§10.4 Training Isolation](SPECIFICATION.md#104-training-isolation)
- **Scope:** Verify and enforce that every trainable learner's update process (`scratch-rl`, `self-supervised`, and `hybrid`) cannot access the other agent's private state, replay data, gradients, optimizer, or parameters.
- **Acceptance criteria:**
- - [ ] Each trainable learner's update step reads only from its own adapter's local buffers, never from the counterpart process.
- - [ ] An isolation test that attempts to smuggle counterpart-agent internal state into a training update fails to do so, confirmed by the test.
- - [ ] Training isolation is verified specifically under Mode R container separation (`ALD-055`), not just asserted for Mode P.
+ - [x] Each trainable learner's update step reads only from its own adapter's local buffers, never from the counterpart process.
+ - [x] An isolation test that attempts to smuggle counterpart-agent internal state into a training update fails to do so, confirmed by the test.
+ - [x] Training isolation is verified specifically under Mode R container separation (`ALD-055`), not just asserted for Mode P.
#### ALD-057 — Semantic-leakage test battery automation
- **Priority:** P1 · **Size:** M · **Class:** Research-Grade · **Depends on:** ALD-038, ALD-044, ALD-045, ALD-046, ALD-047
- **Spec refs:** `SPECIFICATION.md` [§6.5 Semantic Leakage Test Battery](SPECIFICATION.md#65-semantic-leakage-test-battery)
- **Scope:** Implement the full §6.5 adapter test battery: tokenizer/vocabulary audit, frozen-feature linear probe against label-shuffled controls, and vision-language encoder classification, with claim-boundary results persisted in run evidence.
- **Acceptance criteria:**
- - [ ] Every test in §6.5 runs against `scratch-rl`, `self-supervised`, and strict `hybrid`; frozen-LLM and no-learning runs are explicitly classified rather than incorrectly presented as ungrounded.
- - [ ] Linear-probe evaluation uses the pre-registered 95% label-shuffled confidence-interval rule.
- - [ ] Battery results are attached to the run's evidence record so a reviewer can see leakage-test outcomes per run.
+ - [x] Every test in §6.5 runs against `scratch-rl`, `self-supervised`, and strict `hybrid`; frozen-LLM and no-learning runs are explicitly classified rather than incorrectly presented as ungrounded.
+ - [x] Linear-probe evaluation uses the pre-registered 95% label-shuffled confidence-interval rule.
+ - [x] Battery results are attached to the run's evidence record so a reviewer can see leakage-test outcomes per run.
### EPIC-11 — Telemetry, Audit, Snapshot/Recovery, and Retention
@@ -792,45 +798,45 @@ Each item lists: Priority, Size, Classification (MVP / Research-Grade / Later-Re
- **Spec refs:** `SPECIFICATION.md` [§14.1 Telemetry](SPECIFICATION.md#141-telemetry)
- **Scope:** Implement the telemetry pipeline capturing per-request/per-turn metrics (method, path, status, duration) named in §14.1, persisted for dashboard consumption.
- **Acceptance criteria:**
- - [ ] Every API request across all twin routes produces a telemetry record with the fields §14.1 requires.
- - [ ] Telemetry recording failures never block or fail the underlying request (verified by fault-injection test on the telemetry sink).
- - [ ] Telemetry data is queryable by run ID and by time range.
+ - [x] Every API request across all twin routes produces a telemetry record with the fields §14.1 requires.
+ - [x] Telemetry recording failures never block or fail the underlying request (verified by fault-injection test on the telemetry sink).
+ - [x] Telemetry data is queryable by run ID and by time range.
#### ALD-059 — Audit, intervention, and safety-event logging
- **Priority:** P0 · **Size:** L · **Class:** Research-Grade · **Depends on:** ALD-013, ALD-024, ALD-053
- **Spec refs:** `SPECIFICATION.md` [§14.2 Audit Logging](SPECIFICATION.md#142-audit-logging)
- **Scope:** Implement append-only audit records for human views, operator interventions, and safety triggers. Pause/resume/abort/annotate actions must use this path, record actor/reason, and request the mandatory checkpoint; unplanned interventions also create a notebook deviation reference.
- **Acceptance criteria:**
- - [ ] Every §14.2 human view/intervention and §14.5 safety trigger produces an append-only audit record with authenticated actor and machine-readable reason.
- - [ ] Each intervention produces a signed checkpoint, and any unplanned intervention links to an append-only notebook deviation record.
- - [ ] Audit and intervention logs plus checkpoint references are included in every evidence bundle, not only Mode R.
+ - [x] Every §14.2 human view/intervention and §14.5 safety trigger produces an append-only audit record with authenticated actor and machine-readable reason.
+ - [x] Each intervention produces a signed checkpoint, and any unplanned intervention links to an append-only notebook deviation record.
+ - [x] Audit and intervention logs plus checkpoint references are included in every evidence bundle, not only Mode R.
#### ALD-060 — Snapshot and restore mechanism
- **Priority:** P1 · **Size:** L · **Class:** MVP · **Depends on:** ALD-005, ALD-011
- **Spec refs:** `SPECIFICATION.md` [§14.4 Snapshot and Restore](SPECIFICATION.md#144-snapshot-and-restore)
- **Scope:** Implement periodic and on-demand snapshotting of all runtime state to serialized files, and a restore path that reconstructs state from the latest snapshot on startup, per §14.4.
- **Acceptance criteria:**
- - [ ] A manual "take snapshot now" action produces a snapshot file set that a restore can consume.
- - [ ] Restarting the server after a snapshot automatically restores to that snapshot's state (`autoRestore()`-equivalent behavior).
- - [ ] A restored run's evidence-store state matches, byte-for-byte in the chain-walk sense (`ALD-008`), the state at the moment the snapshot was taken.
+ - [x] A manual "take snapshot now" action produces a snapshot file set that a restore can consume.
+ - [x] Restarting the server after a snapshot automatically restores to that snapshot's state (`autoRestore()`-equivalent behavior).
+ - [x] A restored run's evidence-store state matches, byte-for-byte in the chain-walk sense (`ALD-008`), the state at the moment the snapshot was taken.
#### ALD-061 — Failure handling policy implementation
- **Priority:** P0 · **Size:** M · **Class:** MVP · **Depends on:** ALD-011, ALD-021
- **Spec refs:** `SPECIFICATION.md` [§14.5 Failure Handling](SPECIFICATION.md#145-failure-handling)
- **Scope:** Implement the documented failure-handling policy for each named failure mode in §14.5 (evidence-store failure, anchoring failure, learner adapter crash), including registering `process.on('uncaughtException')` and `process.on('unhandledRejection')` handlers so background tasks (checkpoint scheduler, anchoring retries) log rather than crash the server.
- **Acceptance criteria:**
- - [ ] Every failure mode named in §14.5 has an implemented, tested handling path.
- - [ ] An unhandled rejection thrown from a background task (e.g., a failed anchor confirmation poll) is caught, logged, and does not crash the server process, confirmed by a fault-injection test.
- - [ ] The failure-handling behavior for anchoring failures reuses `ALD-021`'s retry/backoff rather than a separate ad hoc mechanism.
+ - [x] Every failure mode named in §14.5 has an implemented, tested handling path.
+ - [x] An unhandled rejection thrown from a background task (e.g., a failed anchor confirmation poll) is caught, logged, and does not crash the server process, confirmed by a fault-injection test.
+ - [x] The failure-handling behavior for anchoring failures reuses `ALD-021`'s retry/backoff rather than a separate ad hoc mechanism.
#### ALD-062 — Retention policy enforcement job
- **Priority:** P1 · **Size:** S · **Class:** MVP · **Depends on:** ALD-005, ALD-016
- **Spec refs:** `SPECIFICATION.md` [§14.6 Retention Policy](SPECIFICATION.md#146-retention-policy)
- **Scope:** Purge bulk payload files only for non-public development/qualification runs that are not Base-mainnet anchored and exceed `prototypeRetentionDays`; preserve append-only database events, audit/intervention logs, manifests, receipts, and run index metadata.
- **Acceptance criteria:**
- - [ ] Only eligible non-public, non-mainnet run-bundle payloads are purged; public or mainnet-anchored bundles are retained indefinitely.
- - [ ] `run_metadata`, ledger/channel/audit/intervention rows, checkpoint manifests, and anchor receipts remain queryable after purge.
- - [ ] The job's actions are themselves audit-logged (`ALD-059`).
+ - [x] Only eligible non-public, non-mainnet run-bundle payloads are purged; public or mainnet-anchored bundles are retained indefinitely.
+ - [x] `run_metadata`, ledger/channel/audit/intervention rows, checkpoint manifests, and anchor receipts remain queryable after purge.
+ - [x] The job's actions are themselves audit-logged (`ALD-059`).
### EPIC-12 — Dashboard / Research Console and UX
@@ -841,36 +847,36 @@ Each item lists: Priority, Size, Classification (MVP / Research-Grade / Later-Re
- **Spec refs:** `SPECIFICATION.md` [§16.1 Dashboard and Research Console](SPECIFICATION.md#161-dashboard-and-research-console)
- **Scope:** Build the vanilla-JS Research Console with run/pre-registration status, separated Baby perspectives, public transcript, read-only audit-ledger comparison, checkpoint/anchor/verification state, telemetry, and operator-gated lifecycle controls.
- **Acceptance criteria:**
- - [ ] The console displays live run/pre-registration state, public transcript, telemetry, verification, checkpoint, and anchor data from authoritative routes.
- - [ ] Baby A/B observations and audit ledgers render in clearly separated read-only panels, and operator controls are role-gated and audited.
- - [ ] The console is a self-contained vanilla HTML/CSS/JS page with no frontend framework, build tool, or client-side side-channel route.
+ - [x] The console displays live run/pre-registration state, public transcript, telemetry, verification, checkpoint, and anchor data from authoritative routes.
+ - [x] Baby A/B observations and audit ledgers render in clearly separated read-only panels, and operator controls are role-gated and audited.
+ - [x] The console is a self-contained vanilla HTML/CSS/JS page with no frontend framework, build tool, or client-side side-channel route.
#### ALD-064 — Human audit-ledger Interpreter
- **Priority:** P1 · **Size:** M · **Class:** Research-Grade · **Depends on:** ALD-005, ALD-016, ALD-042
- **Spec refs:** `SPECIFICATION.md` [§13.6 Privacy Controls](SPECIFICATION.md#136-privacy-controls)
- **Scope:** Implement delayed/batched conversion of agent-native ledger state into separately signed, append-only `audit_ledger_entries`, labeled `source: generated-analysis`, with no Baby-readable route or feedback path.
- **Acceptance criteria:**
- - [ ] Every generated interpretation references source native events and is explicitly labeled external analysis.
- - [ ] Baby identities cannot read audit-ledger entries, while authorized researchers and the verifier can.
- - [ ] Audit entries are included in their checkpoint auxiliary tree and exported evidence without modifying native ledger events.
+ - [x] Every generated interpretation references source native events and is explicitly labeled external analysis.
+ - [x] Baby identities cannot read audit-ledger entries, while authorized researchers and the verifier can.
+ - [x] Audit entries are included in their checkpoint auxiliary tree and exported evidence without modifying native ledger events.
#### ALD-065 — Prohibited UX pattern review checklist
- **Priority:** P1 · **Size:** S · **Class:** MVP · **Depends on:** ALD-063
- **Spec refs:** `SPECIFICATION.md` [§16.2 Diplomacy Table Reuse Boundaries](SPECIFICATION.md#162-diplomacy-table-reuse-boundaries), [§16.3 Prohibited UX Patterns](SPECIFICATION.md#163-prohibited-ux-patterns)
- **Scope:** Audit every reused Diplomacy-style component and run a checklist against all prohibited side-channel, misleading-claim, caucus, coalition, and direct-relay patterns.
- **Acceptance criteria:**
- - [ ] Every reused component is listed with its permitted §16.2 mapping, and no Diplomacy game logic or side-channel route is imported.
- - [ ] Any failing item blocks `ALD-063` from being marked `Done` until resolved.
- - [ ] Every §16.3 prohibition has a pass/fail result, and the checklist reruns after material dashboard changes.
+ - [x] Every reused component is listed with its permitted §16.2 mapping, and no Diplomacy game logic or side-channel route is imported.
+ - [x] Any failing item blocks `ALD-063` from being marked `Done` until resolved.
+ - [x] Every §16.3 prohibition has a pass/fail result, and the checklist reruns after material dashboard changes.
#### ALD-066 — Automated replay fidelity and viewer
- **Priority:** P1 · **Size:** L · **Class:** Research-Grade · **Depends on:** ALD-041, ALD-063
- **Spec refs:** `SPECIFICATION.md` [§14.3 Reproducibility and Replay Fidelity](SPECIFICATION.md#143-reproducibility-and-replay-fidelity)
- **Scope:** Implement scenario replay and deterministic execution `replayDigest` generation/verification per §14.3, then expose the results in a read-only dashboard viewer.
- **Acceptance criteria:**
- - [ ] Same-seed scenario replay reproduces scenario/observation hashes; wrong-seed replay fails automatically.
- - [ ] Deterministic adapters reproduce the §14.3 replay digest, while nondeterministic adapters are explicitly `not-applicable` and pass recorded-decision playback only.
- - [ ] The viewer displays machine results and remains read-only; it cannot alter evidence or override a failure.
+ - [x] Same-seed scenario replay reproduces scenario/observation hashes; wrong-seed replay fails automatically.
+ - [x] Deterministic adapters reproduce the §14.3 replay digest, while nondeterministic adapters are explicitly `not-applicable` and pass recorded-decision playback only.
+ - [x] The viewer displays machine results and remains read-only; it cannot alter evidence or override a failure.
### EPIC-13 — Security, Red-Team, and Cryptography Track
@@ -881,36 +887,36 @@ Each item lists: Priority, Size, Classification (MVP / Research-Grade / Later-Re
- **Spec refs:** `SPECIFICATION.md` [§10.3 Side Channel Controls](SPECIFICATION.md#103-side-channel-controls), `EXPERIMENT-NOTEBOOK.md` [E01 — Channel Isolation and Side-Channel Red-Team](EXPERIMENT-NOTEBOOK.md#e01-channel-isolation-and-side-channel-red-team)
- **Scope:** Build an adversarial test harness that actively attempts to exploit each side channel `ALD-040` claims to have closed, reusing its measurement tooling, sufficient to support `E01`.
- **Acceptance criteria:**
- - [ ] The harness includes at least one active exploit attempt per side-channel category named in §10.3.
- - [ ] Every exploit attempt fails to extract cross-agent information, confirmed by an automated pass/fail check, not manual judgment.
- - [ ] The harness runs under both Mode P and Mode R (`ALD-053`) so `E01`'s isolation comparison is possible.
+ - [x] The harness includes at least one active exploit attempt per side-channel category named in §10.3.
+ - [x] Every Research-Grade exploit attempt fails to extract cross-agent information, confirmed by an automated pass/fail check, while Mode P remains the explicit comparison condition.
+ - [x] The harness runs under both Mode P and Mode R (`ALD-053`) so `E01`'s isolation comparison is possible.
#### ALD-068 — Observation-text and quarantine-bypass red-team suite
- **Priority:** P0 · **Size:** M · **Class:** Research-Grade · **Depends on:** ALD-039
- **Spec refs:** `SPECIFICATION.md` [§10.2 Prompt Injection Controls](SPECIFICATION.md#102-prompt-injection-controls), `EXPERIMENT-NOTEBOOK.md` [E02 — Observation and Metadata Leakage Audit](EXPERIMENT-NOTEBOOK.md#e02-observation-and-metadata-leakage-audit)
- **Scope:** Build adversarial scenario bundles that hide text in pixels, metadata, filenames, alternate encodings, and malformed assets, attempting to bypass `ALD-039` and reach a Baby observation.
- **Acceptance criteria:**
- - [ ] The suite includes direct text, low-contrast/OCR-evasion fixtures, metadata labels, semantic filenames, and malformed-image cases.
- - [ ] Every positive fixture is quarantined and zero raw text reaches an adapter context; negative text-free controls remain loadable.
- - [ ] Results are exported as hashed evidence linked from the E02 Experiment Record, not misrepresented as the Experiment Record itself.
+ - [x] The suite includes direct text, low-contrast/OCR-evasion fixtures, metadata labels, semantic filenames, and malformed-image cases.
+ - [x] Every positive fixture is quarantined and zero raw text reaches an adapter context; negative text-free controls remain loadable.
+ - [x] Results are exported as hashed evidence linked from the E02 Experiment Record, not misrepresented as the Experiment Record itself.
#### ALD-069 — Ephemeral encoding and adversarial cryptography research harness
- **Priority:** P2 · **Size:** L · **Class:** Later-Research · **Depends on:** ALD-031, ALD-057
- **Spec refs:** `SPECIFICATION.md` [§18. Experiment Variable Registry](SPECIFICATION.md#18-experiment-variable-registry), `EXPERIMENT-NOTEBOOK.md` [E40 — Ephemeral Encoding and Adversarial Cryptography](EXPERIMENT-NOTEBOOK.md#e40-ephemeral-encoding-and-adversarial-cryptography)
- **Scope:** Build the research harness needed for `E40` — instrumentation to let two learners develop and test ephemeral, session-specific encodings over the generative carrier channel (`ALD-031`), with a third-party eavesdropper role able to attempt decoding.
- **Acceptance criteria:**
- - [ ] The harness supports at least three roles in a single run: two communicating learners and one eavesdropper observer.
- - [ ] The harness logs every encoding scheme change as a distinct, timestamped event so `E40` can measure encoding lifetime.
- - [ ] The harness itself makes no claim about cryptographic security — it only provides the measurement/instrumentation `E40`'s research execution needs; a passing harness build is not a security claim.
+ - [x] The harness supports at least three roles in a single run: two communicating learners and one eavesdropper observer.
+ - [x] The harness logs every encoding scheme change as a distinct, timestamped event so `E40` can measure encoding lifetime.
+ - [x] The harness itself makes no claim about cryptographic security — it only provides the measurement/instrumentation `E40`'s research execution needs; a passing harness build is not a security claim.
#### ALD-070 — Cryptographic novelty-vs-security separation policy
- **Priority:** P0 · **Size:** S · **Class:** Later-Research · **Depends on:** ALD-009, ALD-019
- **Spec refs:** `SPECIFICATION.md` [§19. Deferred Decisions and ADRs](SPECIFICATION.md#19-deferred-decisions-and-adrs)
- **Scope:** Document and enforce, via a documented review gate, that any learner-invented "encoding" or "cipher" from `ALD-069`'s research (or any other emergent scheme) is never substituted for the production signing/hashing mechanisms in `ALD-009`/`ALD-019` — novelty in a research harness must never be mistaken for or promoted to a security mechanism.
- **Acceptance criteria:**
- - [ ] A written policy statement exists distinguishing "research-harness encoding" from "production cryptographic signing," citing `ALD-009` and `ALD-019` as the only production mechanisms.
- - [ ] A code-level check (e.g., module boundary or lint rule) prevents any `ALD-069`-harness-derived code from being imported into the `ALD-009`/`ALD-019` signing modules.
- - [ ] This policy is included in the documentation set (`ALD-079`) and referenced by `E40`'s readiness gate (`ALD-077`).
+ - [x] A written policy statement exists distinguishing "research-harness encoding" from "production cryptographic signing," citing `ALD-009` and `ALD-019` as the only production mechanisms.
+ - [x] A code-level check (e.g., module boundary or lint rule) prevents any `ALD-069`-harness-derived code from being imported into the `ALD-009`/`ALD-019` signing modules.
+ - [x] This policy is included in the documentation set (`ALD-079`) and referenced by `E40`'s readiness gate (`ALD-077`).
### EPIC-14 — Experiment Pre-Registration and E00–E50 Readiness Gates
@@ -921,63 +927,63 @@ Each item lists: Priority, Size, Classification (MVP / Research-Grade / Later-Re
- **Spec refs:** `SPECIFICATION.md` [§15.1 Pre-Registration Binding](SPECIFICATION.md#151-pre-registration-binding), `EXPERIMENT-NOTEBOOK.md` [§4. Study Metadata](EXPERIMENT-NOTEBOOK.md#4-study-metadata)
- **Scope:** Bind a notebook experiment and sealed hypothesis/parameters to RunConfig, create append-only versioned Experiment Records, and export `experiment-record.json` with disposition/checkpoint/anchor/verifier/deviation references.
- **Acceptance criteria:**
- - [ ] A confirmatory run cannot start without a bound experiment ID, protocol commit, external registration URL, canonical pre-registration hash, and matching pre-run anchor receipt.
- - [ ] Pre-registration creates Experiment Record version `1`; later disposition/evidence changes append higher versions without updating prior rows.
- - [ ] Every evidence bundle contains the latest record plus its version history and references resolvable by an independent reviewer.
+ - [x] A confirmatory run cannot start without a bound experiment ID, protocol commit, complete repository-native or external registration, canonical pre-registration hash, and matching pre-run commitment receipt whose simulated/public class matches the run configuration.
+ - [x] Pre-registration creates Experiment Record version `1`; later disposition/evidence changes append higher versions without updating prior rows.
+ - [x] Every evidence bundle contains the latest record plus its version history and references resolvable by an independent reviewer.
#### ALD-072 — Intervention test suite and baseline/statistics scaffold
- **Priority:** P1 · **Size:** L · **Class:** MVP · **Depends on:** ALD-041, ALD-071
- **Spec refs:** `SPECIFICATION.md` [§15.2 Intervention Test Suite](SPECIFICATION.md#152-intervention-test-suite), [§15.3 Evaluation Baselines and Statistics](SPECIFICATION.md#153-evaluation-baselines-and-statistics)
- **Scope:** Build the software scaffold (not the scientific analysis itself) that lets a pre-registered intervention be applied to a deterministic scenario run (`ALD-041`) and that computes the baseline statistics named in §15.3 over run output.
- **Acceptance criteria:**
- - [ ] An intervention defined in a pre-registration reference (`ALD-071`) can be toggled on/off for a run via configuration, with no code change per intervention.
- - [ ] The scaffold computes every baseline statistic named in §15.3 over a completed run's evidence.
- - [ ] The scaffold's output is a data structure ready for a researcher's downstream analysis — it does not itself draw or store scientific conclusions.
+ - [x] An intervention defined in a pre-registration reference (`ALD-071`) can be toggled on/off for a run via configuration, with no code change per intervention.
+ - [x] The scaffold computes every baseline statistic named in §15.3 over a completed run's evidence.
+ - [x] The scaffold's output is a data structure ready for a researcher's downstream analysis — it does not itself draw or store scientific conclusions.
#### ALD-073 — Gate G1: Integrity and isolation readiness (E00–E03)
- **Priority:** P0 · **Size:** S · **Class:** MVP · **Depends on:** ALD-015, ALD-021, ALD-029, ALD-035, ALD-036, ALD-041, ALD-042, ALD-067, ALD-068, ALD-071, ALD-072
- **Spec refs:** `SPECIFICATION.md` [§17.4 Traceability to E00–E50](SPECIFICATION.md#174-traceability-to-e00-e50), `EXPERIMENT-NOTEBOOK.md` [E00](EXPERIMENT-NOTEBOOK.md#e00-ledger-integrity-and-base-anchoring), [E01](EXPERIMENT-NOTEBOOK.md#e01-channel-isolation-and-side-channel-red-team), [E02](EXPERIMENT-NOTEBOOK.md#e02-observation-and-metadata-leakage-audit), [E03](EXPERIMENT-NOTEBOOK.md#e03-chance-no-communication-and-random-message-controls)
- **Scope:** Define and check the readiness gate confirming the software capability required for `E00`–`E03` exists and passes its own conformance checks — the gate asserts *capability is ready to run the experiment*, not that the experiment has been run or what it found.
- **Acceptance criteria:**
- - [ ] `E00` readiness: the verifier accepts an unchanged anchored bundle and rejects all 14 mutation/anchor cases in LEDGER §17, including wrong-chain anchors and unanchored tails.
- - [ ] `E01`/`E02` readiness: `ALD-067`/`ALD-068` red-team suites are green.
- - [ ] `E03` readiness: `ALD-029`/`ALD-036` run all six controls with dual-hash evidence, while `ALD-041`/`ALD-042`/`ALD-072` provide deterministic scenarios, no-learning behavior, confidence intervals, and effect sizes.
+ - [x] `E00` readiness: the verifier accepts an unchanged anchored bundle and rejects all 14 mutation/anchor cases in LEDGER §17, including wrong-chain anchors and unanchored tails.
+ - [x] `E01`/`E02` readiness: `ALD-067`/`ALD-068` red-team suites are green.
+ - [x] `E03` readiness: `ALD-029`/`ALD-036` run all six controls with dual-hash evidence, while `ALD-041`/`ALD-042`/`ALD-072` provide deterministic scenarios, no-learning behavior, confidence intervals, and effect sizes.
#### ALD-074 — Gate G2: Model-track and protocol readiness (E10–E16)
- **Priority:** P1 · **Size:** S · **Class:** MVP · **Depends on:** ALD-031, ALD-032, ALD-036, ALD-042, ALD-044, ALD-045, ALD-046, ALD-047, ALD-056, ALD-057, ALD-064, ALD-072
- **Spec refs:** `SPECIFICATION.md` [§17.4 Traceability to E00–E50](SPECIFICATION.md#174-traceability-to-e00-e50), `EXPERIMENT-NOTEBOOK.md` [E10](EXPERIMENT-NOTEBOOK.md#e10-frozen-pretrained-llm-protocol-baseline), [E11](EXPERIMENT-NOTEBOOK.md#e11-from-scratch-rl-naming-game), [E12](EXPERIMENT-NOTEBOOK.md#e12-self-supervised-ungrounded-baseline), [E13](EXPERIMENT-NOTEBOOK.md#e13-no-predefined-symbol-library), [E14](EXPERIMENT-NOTEBOOK.md#e14-turn-taking-role-reversal-and-repair), [E15](EXPERIMENT-NOTEBOOK.md#e15-composition-and-held-out-generalization), [E16](EXPERIMENT-NOTEBOOK.md#e16-causal-listening-and-ledger-validity)
- **Scope:** Define and check the readiness gate confirming every model track and protocol capability that `E10`–`E16` require exists and passes conformance, across all seven experiments in this range.
- **Acceptance criteria:**
- - [ ] `E10`/`E11`/`E12` readiness: `ALD-044`/`ALD-045`/`ALD-046` complete full turns; ungrounded tracks pass training isolation and semantic-leakage qualification.
- - [ ] `E13` readiness: all `ALD-031` alternate carriers pass conformance and `ALD-032` leakage evaluation can compare all five notebook carrier conditions.
- - [ ] `E14`/`E15`/`E16` readiness: `ALD-072` supports role reversal, held-out splits, and causal interventions, and `ALD-064` produces separately labeled human audit interpretations.
+ - [x] `E10`/`E11`/`E12` readiness: `ALD-044`/`ALD-045`/`ALD-046` complete full turns; ungrounded tracks pass training isolation and semantic-leakage qualification.
+ - [x] `E13` readiness: all `ALD-031` alternate carriers pass conformance and `ALD-032` leakage evaluation can compare all five notebook carrier conditions.
+ - [x] `E14`/`E15`/`E16` readiness: `ALD-072` supports role reversal, held-out splits, and causal interventions, and `ALD-064` produces separately labeled human audit interpretations.
#### ALD-075 — Gate G3: Affect and learning-comparison readiness (E20–E22)
- **Priority:** P1 · **Size:** S · **Class:** MVP · **Depends on:** ALD-023, ALD-033, ALD-042, ALD-044, ALD-045, ALD-046, ALD-072
- **Spec refs:** `SPECIFICATION.md` [§17.4 Traceability to E00–E50](SPECIFICATION.md#174-traceability-to-e00-e50), `EXPERIMENT-NOTEBOOK.md` [E20](EXPERIMENT-NOTEBOOK.md#e20-constrained-affect-channel-study), [E21](EXPERIMENT-NOTEBOOK.md#e21-rl-versus-non-rl-learning-comparison), [E22](EXPERIMENT-NOTEBOOK.md#e22-developmental-plasticity-and-curriculum)
- **Scope:** Define and check the readiness gate confirming the six-display affect channel and the RL/non-RL comparison capability required for `E20`–`E22` exist and pass conformance.
- **Acceptance criteria:**
- - [ ] `E20` readiness: `ALD-033` affect protocol independently passes conformance with all six displays exercised.
- - [ ] `E21` readiness: no-learning (`ALD-042`), frozen-LLM (`ALD-044`), extrinsic/intrinsic scratch-RL (`ALD-045`), and self-supervised (`ALD-046`) modes run under the same scenario configuration.
- - [ ] `E22` readiness: `ALD-072`'s scaffold supports a staged/curriculum sequence of interventions within a single run.
+ - [x] `E20` readiness: `ALD-033` affect protocol independently passes conformance with all six displays exercised.
+ - [x] `E21` readiness: no-learning (`ALD-042`), frozen-LLM (`ALD-044`), extrinsic/intrinsic scratch-RL (`ALD-045`), and self-supervised (`ALD-046`) modes run under the same scenario configuration.
+ - [x] `E22` readiness: `ALD-072`'s scaffold supports a staged/curriculum sequence of interventions within a single run.
#### ALD-076 — Gate G4: Transfer and negotiation-scenario readiness (E30–E32)
- **Priority:** P2 · **Size:** S · **Class:** Later-Research · **Depends on:** ALD-028, ALD-041, ALD-072
- **Spec refs:** `SPECIFICATION.md` [§17.4 Traceability to E00–E50](SPECIFICATION.md#174-traceability-to-e00-e50), `EXPERIMENT-NOTEBOOK.md` [E30](EXPERIMENT-NOTEBOOK.md#e30-partner-replacement-and-zero-shot-transfer), [E31](EXPERIMENT-NOTEBOOK.md#e31-longitudinal-drift-and-stability), [E32](EXPERIMENT-NOTEBOOK.md#e32-cooperative-signaling-versus-negotiation)
- **Scope:** Define and check the readiness gate confirming derived-run support, deterministic long-run analysis, and the Scenario Engine's aligned/private/semi-cooperative/conflicting utility configurations are sufficient for partner-replacement, longitudinal, and negotiation experiments.
- **Acceptance criteria:**
- - [ ] `E30` readiness: `ALD-028` derived-run support can substitute a new learner adapter in the child run without altering the parent.
- - [ ] `E31` readiness: `ALD-072`'s baseline/statistics scaffold can compare metrics across a long sequence of turns/checkpoints for drift analysis.
- - [ ] `E32` readiness: `ALD-041` produces each pre-registered cooperative and negotiation utility condition from configuration without a code change.
+ - [x] `E30` readiness: `ALD-028` derived-run support can substitute a new learner adapter in the child run without altering the parent.
+ - [x] `E31` readiness: `ALD-072`'s baseline/statistics scaffold can compare metrics across a long sequence of turns/checkpoints for drift analysis.
+ - [x] `E32` readiness: `ALD-041` produces each pre-registered cooperative and negotiation utility condition from configuration without a code change.
#### ALD-077 — Gate G5: Cryptography-research and replication readiness (E40, E50)
- **Priority:** P2 · **Size:** S · **Class:** Later-Research · **Depends on:** ALD-069, ALD-070, ALD-028, ALD-072
- **Spec refs:** `SPECIFICATION.md` [§17.4 Traceability to E00–E50](SPECIFICATION.md#174-traceability-to-e00-e50), `EXPERIMENT-NOTEBOOK.md` [E40](EXPERIMENT-NOTEBOOK.md#e40-ephemeral-encoding-and-adversarial-cryptography), [E50](EXPERIMENT-NOTEBOOK.md#e50-multi-seed-replication-and-study-closeout), [§12. Publication Checklist](EXPERIMENT-NOTEBOOK.md#12-publication-checklist)
- **Scope:** Define and check the readiness gate confirming the cryptography research harness and its safety-separation policy are in place for `E40`, and that multi-seed replication tooling is ready for `E50`.
- **Acceptance criteria:**
- - [ ] `E40` readiness: `ALD-069` harness and `ALD-070` separation policy both pass their own acceptance criteria.
- - [ ] `E50` readiness: `ALD-028` derived-run support and `ALD-072`'s scaffold together launch the same pre-registered configuration across independent seeds and aggregate baseline statistics.
- - [ ] This gate's checklist cross-references the `EXPERIMENT-NOTEBOOK.md` [§12. Publication Checklist](EXPERIMENT-NOTEBOOK.md#12-publication-checklist) items that are software-verifiable, without asserting any of the checklist's research-judgment items are satisfied.
+ - [x] `E40` readiness: `ALD-069` harness and `ALD-070` separation policy both pass their own acceptance criteria.
+ - [x] `E50` readiness: `ALD-028` derived-run support and `ALD-072`'s scaffold together launch the same pre-registered configuration across independent seeds and aggregate baseline statistics.
+ - [x] This gate's checklist cross-references the `EXPERIMENT-NOTEBOOK.md` [§12. Publication Checklist](EXPERIMENT-NOTEBOOK.md#12-publication-checklist) items that are software-verifiable, without asserting any of the checklist's research-judgment items are satisfied.
### EPIC-15 — CI/Test Suites, Documentation, Operations, and Release
@@ -989,16 +995,16 @@ Each item lists: Priority, Size, Classification (MVP / Research-Grade / Later-Re
- **Scope:** Stand up a CI pipeline running, on every change: the crash-safety suite (`ALD-011`), the Gateway conformance suite (`ALD-036`), the semantic-leakage battery (`ALD-057`), and both red-team suites (`ALD-067`/`068`), plus every other item's own acceptance tests referenced elsewhere in this backlog.
- **Acceptance criteria:**
- [ ] CI runs on every proposed change and blocks merge on any failing suite.
- - [ ] The consolidated suite includes at least one test per `Done` item's acceptance criteria at the time CI is stood up.
- - [ ] CI run time and flakiness are tracked; a flaky test is quarantined with a tracked follow-up, not silently ignored.
+ - [x] The consolidated suite includes at least one test per `Done` item's acceptance criteria at the time CI is stood up.
+ - [x] CI run time and flakiness are tracked; a flaky test is quarantined with a tracked follow-up, not silently ignored.
#### ALD-079 — Architecture/API/operations documentation set
- **Priority:** P1 · **Size:** M · **Class:** MVP · **Depends on:** ALD-048, ALD-049, ALD-050, ALD-055, ALD-060
- **Spec refs:** `SPECIFICATION.md` [§1.5 Relationship to Companion Documents](SPECIFICATION.md#15-relationship-to-companion-documents)
- **Scope:** Write the documentation set covering: architecture overview, full API reference (all routes from EPIC-09), Mode R operational runbook (container isolation, `ALD-055`), and the snapshot/restore/recovery runbook (`ALD-060`).
- **Acceptance criteria:**
- - [ ] Every route implemented in EPIC-09 has a corresponding API reference entry with request/response shape.
- - [ ] The Mode R runbook lets an operator who has not read the source code stand up an isolated run following the documented steps alone.
+ - [x] Every route implemented in EPIC-09 has a corresponding API reference entry with request/response shape.
+ - [x] The Mode R runbook lets an operator who has not read the source code stand up an isolated run following the documented steps alone.
- [ ] The snapshot/restore runbook is validated by having someone other than the implementer follow it to perform a real restore.
#### ALD-080 — Release process and publication-checklist mapping
@@ -1006,9 +1012,67 @@ Each item lists: Priority, Size, Classification (MVP / Research-Grade / Later-Re
- **Spec refs:** `EXPERIMENT-NOTEBOOK.md` [§12. Publication Checklist](EXPERIMENT-NOTEBOOK.md#12-publication-checklist)
- **Scope:** Define the release process for the software (versioning, tagging, changelog) and produce a mapping from each `EXPERIMENT-NOTEBOOK.md` §12 publication-checklist item to the specific backlog item(s)/gate(s) that make it achievable, without claiming any research-judgment checklist item as satisfied by software alone.
- **Acceptance criteria:**
- - [ ] A documented release process exists (version scheme, changelog convention, tagging) consistent with §1's normative-language conventions.
- - [ ] Every software-verifiable item in the §12 publication checklist is mapped to at least one `ALD-XXX` ID or Gate (`ALD-073`–`077`).
- - [ ] The mapping explicitly flags which §12 checklist items are research-judgment calls outside this backlog's scope (e.g., "results support the stated hypothesis"), rather than silently omitting them.
+ - [x] A documented release process exists (version scheme, changelog convention, tagging) consistent with §1's normative-language conventions.
+ - [x] Every software-verifiable item in the §12 publication checklist is mapped to at least one `ALD-XXX` ID or Gate (`ALD-073`–`077`).
+ - [x] The mapping explicitly flags which §12 checklist items are research-judgment calls outside this backlog's scope (e.g., "results support the stated hypothesis"), rather than silently omitting them.
+
+### EPIC-16 — Research-Execution Readiness
+
+**Goal:** turn the completed software foundation into a reproducible, fail-closed operator path for research preparation without representing qualification as empirical evidence. **Depends on:** EPIC-14 and EPIC-15. **Acceptance gate:** E03 design and registration artifacts reproduce, the preflight blocks incomplete confirmatory bindings, a real open-weight model completes the frozen track, and the consolidated check rejects public-status drift.
+
+#### ALD-081 — Dependency-integrity enforcement
+- **Priority:** P0 · **Size:** S · **Class:** Research-Grade · **Depends on:** ALD-078
+- **Spec refs:** `SPECIFICATION.md` [§17.2 Test Strategy](SPECIFICATION.md#172-test-strategy)
+- **Scope:** Make high/critical dependency advisories a blocking local and hosted check while retaining a machine-readable audit artifact for review.
+- **Acceptance criteria:**
+ - [x] A clean frozen-lockfile install followed by `pnpm audit --audit-level=high` exits zero.
+ - [x] Hosted consolidated CI retains the audit JSON even when another check fails.
+ - [x] Required native dependency install scripts are explicitly allowlisted by exact package version.
+
+#### ALD-082 — Reproducible E03 design simulation and seed manifest
+- **Priority:** P0 · **Size:** M · **Class:** Research-Grade · **Depends on:** ALD-072
+- **Spec refs:** `RESEARCH.md` [Appendix D.7](RESEARCH.md#d7-sensitivity-and-power)
+- **Scope:** Replace prose-only E03 power calculations with a deterministic Monte Carlo implementation and derived primary/reserve seed manifest.
+- **Acceptance criteria:**
+ - [x] A fixed seed reproduces byte-identical 30,000-replicate design output.
+ - [x] Every registered SD/sample-size row has a lower 95% Monte Carlo bound at or above the 90% power floor.
+ - [x] The committed seed manifest deterministically derives separate scenario, random-control, and shuffled-control seeds without exposing realized confirmatory outcomes.
+
+#### ALD-083 — Canonical E03 registration compiler
+- **Priority:** P0 · **Size:** M · **Class:** Research-Grade · **Depends on:** ALD-071, ALD-082
+- **Spec refs:** `SPECIFICATION.md` [§7.1 Pre-Registration Binding](SPECIFICATION.md#71-pre-registration-binding), `RESEARCH.md` [Appendix D](RESEARCH.md#appendix-d-pre-registered-e03-protocol)
+- **Scope:** Compile E03's registered parameter template, its canonical domain-separated hash, complete seed allocation, and per-condition run-config templates into one validated artifact.
+- **Acceptance criteria:**
+ - [x] The compiler output validates as a `PreRegistrationArtifact` and is byte-identical on repeat.
+ - [x] Run IDs, realized random seeds, execution bindings, and the pre-registration hash are excluded from the hashed parameter template.
+ - [x] Every primary and reserve condition configuration carries the same exact pre-registration hash.
+
+#### ALD-084 — Fail-closed research preflight
+- **Priority:** P0 · **Size:** M · **Class:** Research-Grade · **Depends on:** ALD-071, ALD-083
+- **Spec refs:** `SPECIFICATION.md` [§7.1 Pre-Registration Binding](SPECIFICATION.md#71-pre-registration-binding), [§7.2 Experiment Record](SPECIFICATION.md#72-experiment-record)
+- **Scope:** Check the immutable software, configuration, isolation, seed, registration, and pre-run commitment bindings before confirmatory collection and report every blocker together.
+- **Acceptance criteria:**
+ - [x] Human and JSON outputs independently check Mode R, learning isolation, artifact class, hashes, immutable ancestral commits, seed count, complete registration, and confirmed matching pre-run commitment.
+ - [x] A missing repository-native/external registration, mismatched binding, or absent/incorrect commitment blocks confirmatory readiness.
+ - [x] A passing preflight explicitly does not claim public-chain verification or scientific validity.
+
+#### ALD-085 — Real open-weight frozen-model qualification
+- **Priority:** P1 · **Size:** M · **Class:** Research-Grade · **Depends on:** ALD-044, ALD-054, ALD-081
+- **Spec refs:** `SPECIFICATION.md` [§6.7 Frozen Pretrained LLM Track](SPECIFICATION.md#67-frozen-pretrained-llm-track), [§10.3 Research-Grade Isolation Threat Model](SPECIFICATION.md#103-research-grade-isolation-threat-model)
+- **Scope:** Exercise the frozen-LLM adapter against a public local model through the loopback-only OpenAI-compatible client and retain privacy-minimized exact provenance.
+- **Acceptance criteria:**
+ - [x] The report binds the exact weight-file hash, inference-runtime archive hash, model identity, quantization, software commit, and seed hash.
+ - [x] At least two episodes exercise intention and interpretation in both Baby roles with tool-only conformance and no policy updates.
+ - [x] The committed report is labeled non-confirmatory and omits prompts, observations, raw output, candidate references, and private ledger content.
+
+#### ALD-086 — Project-status drift enforcement
+- **Priority:** P1 · **Size:** S · **Class:** MVP · **Depends on:** ALD-080, ALD-081, ALD-082, ALD-083, ALD-084, ALD-085
+- **Spec refs:** `SPECIFICATION.md` [§1.5 Relationship to Companion Documents](SPECIFICATION.md#15-relationship-to-companion-documents)
+- **Scope:** Fail the consolidated check when package versions, backlog totals, completion-plan state, README status, or manuscript engineering status disagree.
+- **Acceptance criteria:**
+ - [x] The checker derives acceptance totals from backlog checkboxes rather than accepting a manually supplied number.
+ - [x] Root package/lock versions and the public README/manuscript engineering snapshot must match exactly.
+ - [x] Both local and hosted consolidated checks run the drift checker before build and tests.
## 13. Experiment Readiness Gate Mapping
@@ -1069,10 +1133,11 @@ Every top-level `SPECIFICATION.md` section maps to at least one backlog item. Se
These are working decisions this backlog encodes. Where a decision is not yet made in the source documents, it is marked accordingly rather than invented.
-- **Runtime/language:** Node.js + TypeScript, npm workspaces monorepo (ALD-001). No calendar dates or staffing levels are assumed anywhere in this backlog; all sequencing is dependency-based.
+- **Runtime/language:** Node.js + TypeScript, pnpm workspaces monorepo (ALD-001). No calendar dates or staffing levels are assumed anywhere in this backlog; all sequencing is dependency-based.
- **Evidence store:** SQLite in WAL mode is the sole authoritative local store (ALD-005), per `LEDGER-INTEGRITY-DESIGN.md` [§18. Recommended Initial Decision](LEDGER-INTEGRITY-DESIGN.md#18-recommended-initial-decision). No external database is introduced by this backlog.
- **Anchoring:** Base Sepolia is the default and only unconditional anchoring target (ALD-020); mainnet anchoring exists only as an explicit, separately-configured opt-in (ALD-022), never a default.
- **Model default:** `scratch-rl` (ALD-045) is the primary scientific baseline; the local open-weight `frozen-llm` adapter (ALD-044) is the orchestration-validation default. `no-learning` (ALD-042), `self-supervised` (ALD-046), and `hybrid` (ALD-047) are explicit selections.
+- **Recurrent scientific baseline.** `gru-actor-critic-v1` uses a 16-unit GRU, separate sender/receiver/value heads, Xavier initialization, Adam at `0.003`, four PPO-style epochs, clip `0.2`, value coefficient `0.5`, and gradient-norm cap `1`. Scratch RL and self-supervision serialize the same parameter/optimizer/checkpoint shape; the reward-free track replaces the actor/value objective with partner-message predictive cross-entropy and cannot read scalar reward or outcome labels. Tabular REINFORCE and positional count models remain explicit reference controls rather than the scientific default.
- **Isolation:** Mode R uses separate containers/processes per learner with no shared mutable state (ALD-055); Mode P has no such isolation guarantee and must never be labeled with a Mode-R-only claim (ALD-054).
- **On-chain privacy:** only checkpoint root hashes and minimal metadata are ever placed on-chain (ALD-018, ALD-020); no raw observation, model, or private data is anchored, per `SPECIFICATION.md` [§13.6](SPECIFICATION.md#136-privacy-controls) and `LEDGER-INTEGRITY-DESIGN.md` [§12](LEDGER-INTEGRITY-DESIGN.md#12-privacy).
- **Research vs. software boundary:** this backlog treats every `E00`–`E50` experiment as something the software must make *executable*, never as a task this backlog itself completes. EPIC-14's gates check capability readiness only (§13 of this document is explicit about this).
@@ -1080,11 +1145,34 @@ These are working decisions this backlog encodes. Where a decision is not yet ma
- **Sizing/priority are relative, not calendar-based:** S/M/L reflect complexity, not effort-days; P0/P1/P2 reflect blast radius on integrity/critical-path/research-readiness, not business value.
- **Open/undecided (not invented here):** the specific open-weight frozen-LLM model, exact retention durations for §14.6, and exact confirmation-depth thresholds for §13.4 are left to be filled in when their owning item (ALD-044, ALD-062, ALD-021 respectively) is picked up, using whatever value the source documents specify at that time — this backlog does not invent them.
+### Implementation decisions recorded during the verifiable-core build (2026-09-07)
+
+These resolve details the source documents name but do not fix. Each is implemented, tested, and referenced from code comments.
+
+- **Hash domains.** LEDGER-INTEGRITY-DESIGN.md and SPECIFICATION.md name six domain separators; the implementation defines the remaining ones in `packages/types/src/domains.ts` (`HASH_DOMAINS`): channel event, affect event and measurement, audit-ledger entry, intervention event and causal probe, turn record, Baby proposal, rejected payload, run config/id/manifest, pre-registration, scenario bundle/state, observation, action, outcome, prompt bundle, policy checkpoint, carrier-form inventory, glyph bundle, retention log, failure message, runtime snapshot, encoding scheme, nonce commitment, and PRNG seed. All follow `SHA-256(domain || 0x00 || payload)`; only Merkle interior nodes use `0x01`.
+- **Turn-record stream.** SPEC §14.3 needs per-turn hashes for the replay digest, so the Evidence Store carries an implementation-defined `turns` stream (`turn_records`, migration v2), witness-signed and committed as the auxiliary checkpoint tree `turns`. `intervention_log` stays hash-chained but unsigned and is exported without a checkpoint tree (LEDGER §8 auxiliary trees require a writer key).
+- **Checkpoint manifest `reason`.** LEDGER §8's manifest is illustrative; the implementation adds a `reason` enum recording the LEDGER §9 trigger so intervention checkpoints are verifiable.
+- **Empty trees.** A stream with no events is committed as `treeSize 0`, `EMPTY_MERKLE_ROOT`, `lastEntryHash = GENESIS_HASH`; a size-0 auxiliary tree is omitted from `auxiliaryTrees` and a verifier reads the omission as the empty tree (docs/evidence-bundle-format.md §6). A single-leaf Merkle root is the leaf hash (leaves are already domain-hashed).
+- **Ledger draft `evidenceRefs`.** Non-empty `evidenceRefs` on a draft are merged into `content.evidenceRefs` of the committed event (LEDGER §4 example shape).
+- **Communication controls.** `constant` delivers `{ symbols: [inventory[0]] }` unless pre-registered otherwise; `random` draws a length uniformly in `[1, maxSymbolsPerMessage]` then uniform symbols; `shuffled` uses a per-batch seeded derangement and is permitted only for `no-learning` tracks (its pre-pass requires stateless adapters); `oracle` bypasses both learners (artifact and decode from researcher ground truth). Timeouts and other payload-less rejections hash canonical `null`.
+- **Anchor receipts.** `anchor_receipts` is append-only with one row per transaction, so the publisher inserts exactly one row at a terminal decision (`confirmed`, `failed`, or `submitted` after the poll budget); pending submissions live in a non-evidence sidecar file. `safe-tag` finality is an interim 32-confirmation proxy (ADR-05). Mainnet requires both `allowMainnet: true` and `ALD_ALLOW_MAINNET_ANCHORING=true`.
+- **Experiment records.** Version 1 is written at run creation with `disposition: invalid` (SPEC §7.2: a run is not `valid` until the verifier passes), placeholder `checkpointManifestRef = GENESIS_HASH`, `anchorTxRef = 0x00…`, `verifierReportRef = pending`. Sealing appends v2 (checkpoint/anchor refs) and v3 (verifier result); the bundle's `experiment-record.json` is rewritten after v3.
+- **Unanchorable prototype runs.** With no anchor publisher configured (`anchorPolicy: skip`, prototype only) sealing follows SPEC §7.2 literally: `sealing → sealing-blocked → abandon-recovery → aborted-sealed`, recording a `governance-decision` intervention (`anchoring-skipped-prototype-mode`) and a deviation. Such runs are never `valid`.
+- **Verifier local-integrity mode.** `--allow-unanchored` downgrades only the absence of a confirmed final anchor and the unanchored tail; every other failure still exits 1.
+- **Adapter failures.** SPEC §14.5: one retry, then forfeit the turn (null action, turn record written), append a `safety-trigger` intervention, and pause. `evaluating` has no `pause` row in §7.2, so a trigger there records `pause-not-available` and continues (spec gap flagged).
+- **Run configuration.** Optional `evaluationTurns` (runtime default 200) fixes the evaluation-phase budget; `symbolInventorySize`/`maxSymbolsPerMessage` are valid only for `fixed-token` and `maxStrokes` only for `generative-canvas`.
+- **Learner contracts.** Files carry a `` header exempt from the banned-pattern lint; `promptBundleHash` is the canonical hash of `{ track: text }`.
+- **Signer boundary.** Public-study per-run seeds are encrypted in `safe` and
+ materialized only through `si fort` files mode. The Nursery accepts a mode-0600
+ regular file with an exact run-id map and never mounts it into either learner;
+ runId grammar remains `^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$`.
+- **Twin routes (Mode P).** Roles arrive as `x-ald-role` + `x-ald-service-token`; default dev tokens `dev-` exist only for prototype mode. `POST /reset` returns 501 until the runtime exposes adapter re-initialization. `GET /runs` is added as a read-only convenience implied by the session routes.
+
## 16. Appendix: ID Index
| ID | Title | Epic |
|---|---|---|
-| ALD-001 | npm workspaces monorepo bootstrap | EPIC-01 |
+| ALD-001 | pnpm workspaces monorepo bootstrap | EPIC-01 |
| ALD-002 | Shared `@ald/types` schema package | EPIC-01 |
| ALD-003 | Environment, configuration, and secrets convention | EPIC-01 |
| ALD-004 | DTSF twin pack scaffolding (baby-a, baby-b, nursery) | EPIC-01 |
@@ -1164,3 +1252,9 @@ These are working decisions this backlog encodes. Where a decision is not yet ma
| ALD-078 | CI pipeline and consolidated test suite | EPIC-15 |
| ALD-079 | Architecture/API/operations documentation set | EPIC-15 |
| ALD-080 | Release process and publication-checklist mapping | EPIC-15 |
+| ALD-081 | Dependency-integrity enforcement | EPIC-16 |
+| ALD-082 | Reproducible E03 design simulation and seed manifest | EPIC-16 |
+| ALD-083 | Canonical E03 registration compiler | EPIC-16 |
+| ALD-084 | Fail-closed research preflight | EPIC-16 |
+| ALD-085 | Real open-weight frozen-model qualification | EPIC-16 |
+| ALD-086 | Project-status drift enforcement | EPIC-16 |
diff --git a/CONFIGURATION.md b/CONFIGURATION.md
index 0adb06f..1e56f20 100644
--- a/CONFIGURATION.md
+++ b/CONFIGURATION.md
@@ -1,8 +1,9 @@
# Configuration
Runtime configuration is loaded through `@ald/config`. Environment variables contain
-only operational values and paths. Private key material and API tokens must never be
-stored directly in environment files committed to this repository.
+only non-secret operational values or short-lived file paths materialized by `si fort`.
+Private key material, signer seeds, RPC credentials, and API tokens must never be
+stored directly in environment variables or repository files.
## Variables
@@ -13,32 +14,50 @@ stored directly in environment files committed to this repository.
| `ALD_DEPLOYMENT_MODE` | `prototype` or `research-grade` | `prototype` | No |
| `ALD_EVIDENCE_DIR` | Path | `./evidence` | No |
| `ALD_DATABASE_PATH` | Path | `/ald.sqlite` | No |
-| `ALD_KEY_DIR` | Path | `/keys` | Yes in research-grade mode |
+| `ALD_RUN_SIGNER_SEEDS_JSON_FILE` | Fort-materialized path | None | Yes in research-grade mode |
| `ALD_LOG_LEVEL` | `debug`, `info`, `warn`, or `error` | `info` | No |
+| `ALD_ANCHOR_CLASS` | `simulated` or `public-chain` | `simulated` | No |
| `ALD_BASE_NETWORK` | `base-sepolia` or `base-mainnet` | `base-sepolia` | No |
-| `ALD_BASE_RPC_URL` | URL | None | Required only when anchoring is enabled |
-| `ALD_ANCHOR_KEY_FILE` | Path | None | Required only when anchoring is enabled |
+| `ALD_BASE_RPC_URL_FILE` | Fort-materialized path | None | Required only for an amended `public-chain` profile |
+| `ALD_ANCHOR_KEY_FILE` | Fort-materialized path | None | Required only for an amended `public-chain` profile |
+| `ALD_ALLOW_MAINNET_ANCHORING` | `true` or unset | unset | Must be `true` (together with an explicit publisher opt-in) before any Base mainnet transaction is submitted |
## Secret Handling
-- Store private keys in files outside the repository and provide only their paths.
+- Store all secret values only in the encrypted `safe` repository and access them
+ through `si fort`; do not create ad-hoc secret files.
- Do not commit `.env` files. The repository ignores `.env` and `.env.*`.
-- Use a dedicated, low-balance anchor wallet.
-- Run `npm run scan:secrets` before committing.
-- Research-grade mode fails fast unless `ALD_KEY_DIR` is explicitly configured.
+- The approved research `RunConfig` defaults to `anchorClass: "simulated"` and uses
+ no wallet, RPC credential, faucet, token, or fee.
+- If a future amendment permits `anchorClass: "public-chain"`, use a dedicated,
+ low-balance anchor wallet and independent verification endpoint.
+- Run `pnpm run scan:secrets` before committing.
+- Research-grade mode fails fast unless Fort materializes
+ `ALD_RUN_SIGNER_SEEDS_JSON_FILE` in files mode.
+- Mainnet anchoring is double opt-in: the anchor publisher must be constructed with `allowMainnet: true` and `ALD_ALLOW_MAINNET_ANCHORING=true` must be set. The current governance policy separately prohibits all public-chain research transactions.
+- The signer material is a versioned JSON envelope containing an exact run-id map
+ and all six Ed25519 signer domains. The Nursery reads its mode-0600 regular file
+ once; the path is then removed from the child environment. Learner containers
+ never receive the path or file mount. Seeds never enter the evidence store or a
+ bundle.
## Examples
Prototype defaults require no environment variables:
```powershell
-npm run build
+pnpm run build
```
-Research-grade mode requires an explicit isolated key directory:
+Research-grade Mode R uses Fort file materialization:
-```powershell
-$env:ALD_DEPLOYMENT_MODE = 'research-grade'
-$env:ALD_KEY_DIR = 'C:\ald-secrets\keys'
-npm run build
+```sh
+si fort run --repo agentic-language-development --env dev \
+ --keys ALD_RUN_SIGNER_SEEDS_JSON --mode files -- \
+ pnpm run test:mode-r-study
```
+
+The encrypted value must authorize each exact study run id. The qualification
+command can run without credentials using ephemeral in-memory signers, but that
+path is explicitly non-confirmatory. Simulated funding removes the wallet/RPC
+dependency; it does not remove the persistent per-run signer or registration gates.
diff --git a/EXPERIMENT-NOTEBOOK.md b/EXPERIMENT-NOTEBOOK.md
index 796781b..dee9c37 100644
--- a/EXPERIMENT-NOTEBOOK.md
+++ b/EXPERIMENT-NOTEBOOK.md
@@ -2,7 +2,7 @@
> **Document type:** Research protocol and results notebook
>
-> **Status:** Ready for pre-registration; no experiments completed
+> **Status:** Design draft; not registration-ready; no experiments completed
>
> **Companion documents:**
> [CONCEPT-IDEA.md](CONCEPT-IDEA.md) and
@@ -61,18 +61,18 @@ permits otherwise.
| Field | Value |
|---|---|
| Study title | Agentic Language Development Nursery Lab |
-| Study version | `TBD` |
-| Principal investigator | `TBD` |
-| Research team | `TBD` |
+| Study version | `0.1.81` prospective design snapshot |
+| Principal investigator | project-operator role |
+| Research team | research-operator, integrity-verifier, and data-steward roles |
| Repository | `Ethical-Tech-CoLab/agentic-language-development` |
| DTSF version / commit | `TBD` |
| Evidence verifier version | `TBD` |
-| Base anchor network | Base Sepolia for qualification; Base mainnet for public studies |
-| Public anchor address / contract | `TBD` |
+| Commitment profile | deterministic simulation of Base Sepolia semantics; no public transaction |
+| Public anchor address / contract | Not applicable under `ALD-GOV-2026-09-12-01` |
| Study start date | `TBD` |
| Study end date | `TBD` |
-| Ethics or governance review | `TBD` |
-| Data-retention policy | `TBD` |
+| Ethics or governance review | `ALD-GOV-2026-09-12-01`: synthetic-only, no human participants or human-coded outcomes |
+| Data-retention policy | Eligible research evidence indefinite; development bulk payloads 30 days; immutable metadata retained |
## 5. Default Experimental Invariants
@@ -89,9 +89,19 @@ Unless an experiment explicitly varies one of these, hold it constant:
[LEDGER-INTEGRITY-DESIGN.md](LEDGER-INTEGRITY-DESIGN.md);
- the affect channel is disabled unless explicitly under study;
- experiment schedules and seeds are fixed before the run;
+- software-qualification, blinded-pilot, confirmatory, and replication seeds use
+ disjoint SHA-256 domains; paired conditions share only their scenario seed;
+- pilot outcomes select only the predeclared seed-count prefix and never enter a
+ confirmatory or replication estimate;
- held-out evaluation runs with learning disabled;
- no production secrets or personal data appear in any experiment.
+The exact derivation, tuning limit, candidate N grid, ordered reserves, per-condition
+allocations, and current zero-spend local resource ceiling are frozen in
+[`protocols/seed-and-resource-allocation.v1.json`](protocols/seed-and-resource-allocation.v1.json).
+The generated ledger contains design commitments only; it is not evidence that any
+pilot or study seed has run.
+
## 6. Standard Run Record
Copy this block into the experiment's result section for every run.
@@ -174,8 +184,8 @@ E01 Channel isolation ---- E02 Observation leakage
| ID | Experiment | Depends on | Status | Result |
|---|---|---|---|---|
-| E00 | Ledger integrity and Base anchoring | None | Not started | — |
-| E01 | Channel isolation and side-channel red team | E00 | Not started | — |
+| E00 | Ledger integrity and simulated commitment | None | Qualified (software) | V2/v4 failures preserved; v5 passed |
+| E01 | Channel isolation and side-channel red team | E00 | In progress | V1 registered topology suite passed; explicit attempt corpus/evidence binding remains |
| E02 | Observation and metadata leakage audit | E00 | Not started | — |
| E03 | Chance, no-communication, and random-message controls | E01, E02 | Not started | — |
| E10 | Frozen pretrained-LLM protocol baseline | E03 | Not started | — |
@@ -196,9 +206,9 @@ E01 Channel isolation ---- E02 Observation leakage
---
-## E00. Ledger Integrity and Base Anchoring
+## E00. Ledger Integrity and Simulated Commitment
-**Status:** Not started
+**Status:** Completed—v5 prospectively registered software qualification passed
**Purpose:** Qualify the evidence system before collecting behavioral data.
@@ -207,34 +217,35 @@ pre-registered mutation of a committed ledger or transcript.
### Preparation
-- [ ] Implement local hash chains and Ed25519 signatures.
-- [ ] Implement ordered Merkle checkpoints.
-- [ ] Implement standalone verifier.
-- [ ] Configure Base Sepolia anchor wallet.
-- [ ] Pre-register checkpoint frequency and finality rule.
-- [ ] Seal protocol commit and configuration hashes.
+- [x] Implement local hash chains and Ed25519 signatures.
+- [x] Implement ordered Merkle checkpoints.
+- [x] Implement standalone verifier.
+- [x] Bind `anchorClass: "simulated"` and configure the deterministic transport.
+- [x] Pre-register checkpoint frequency and finality rule.
+- [x] Seal protocol commit and configuration hashes.
### Procedure
-- [ ] Create a synthetic run with at least 100 events in each Baby ledger.
-- [ ] Produce at least three checkpoints.
-- [ ] Anchor each checkpoint to Base Sepolia.
-- [ ] Verify the unchanged bundle through an independent RPC provider.
-- [ ] Modify one event payload and verify rejection.
-- [ ] Delete a middle event and verify rejection.
-- [ ] Insert an event and verify rejection.
-- [ ] Reorder two events and verify rejection.
-- [ ] Replace a signature and verify rejection.
-- [ ] Modify a Merkle proof and verify rejection.
-- [ ] Present a checkpoint from the wrong chain and verify rejection.
-- [ ] Add an unanchored tail and verify that it is reported.
-- [ ] Restore from checkpoint and append new events without reusing a sequence number.
+- [x] Create a synthetic run with at least 100 events in each Baby ledger.
+- [x] Produce at least three checkpoints.
+- [x] Commit each checkpoint through the deterministic simulation transport.
+- [x] Verify the unchanged bundle through both independent verifier implementations.
+- [x] Relabel a simulated receipt as public-chain evidence and verify rejection.
+- [x] Modify one event payload and verify rejection.
+- [x] Delete a middle event and verify rejection.
+- [x] Insert an event and verify rejection.
+- [x] Reorder two events and verify rejection.
+- [x] Replace a signature and verify rejection.
+- [x] Modify a Merkle proof and verify rejection.
+- [x] Present a checkpoint from the wrong chain and verify rejection.
+- [x] Add an unanchored tail and verify that it is reported.
+- [x] Restore from checkpoint and append new events without reusing a sequence number.
### Acceptance Criteria
- unchanged evidence passes;
- every mutation case fails verification;
-- the final checkpoint hash matches Base calldata or the anchor event;
+- the final checkpoint hash matches the simulated-chain calldata or anchor event;
- restart produces a consistent extension proof;
- no private ledger content appears on-chain.
@@ -242,23 +253,56 @@ pre-registered mutation of a committed ledger or transcript.
| Metric | Planned | Observed |
|---|---:|---:|
-| Valid bundle accepted | 100% | `TBD` |
-| Mutation cases detected | 100% | `TBD` |
-| Anchor receipts verified | 100% | `TBD` |
-| Private content found on-chain | 0 | `TBD` |
-
-- [ ] Integrity acceptance criteria met
-- [ ] Evidence review complete
-- [ ] Base anchor verified
-- [ ] Result committed
-
-**Result summary:** `Not run`
+| Valid bundle accepted | 100% | v5: 5/5 accepted by both verifiers |
+| Mutation cases detected | 100% | v5: 55/55 rejected by both verifiers |
+| Simulated anchor receipts verified | 100% | v5: 5/5 slots anchored with checkpoint-hash payloads |
+| Private content found in simulated commitments | 0 | v5: 0/5 slots had a non-hash commitment payload |
+
+- [x] Integrity acceptance criteria met
+- [x] Evidence review complete
+- [x] Simulated commitment verified
+- [x] Result committed
+
+**Result summary:** v2 slot 1 stopped at the first dual-verifier disagreement. Slots
+2-5 were not attempted and slot 1 will not be rerun into success. The Rust auditor
+did not inspect inclusion-proof files; the failed receipt is retained at
+`reports/research/e00-integrity-qualification-attempt-1.json`. V3 was superseded
+without execution after a source-binding cycle was found. V4 binds the frozen
+scientific protocol, records exact implementation identity at execution, and uses a
+fresh seed domain before any further attempt.
+
+The v4 packet is immutable at commit
+`60cc54da47fc0ad8b49dfddc418e7839c8d9d409`, and its matching deterministic
+in-memory-chain commitment is confirmed before outcome execution. This establishes
+prospective local byte binding, not an independently witnessed timestamp or public
+chain transaction.
+
+V4 then completed all five registered slots. Both verifiers accepted all five
+unchanged bundles and rejected 50/55 registered mutation instances. The TypeScript
+verifier rejected all five simulated-to-public-chain relabels, while the Rust
+auditor accepted them. The complete failure receipt is retained at
+`reports/research/e00-integrity-qualification-attempt-2.json`, all five unchanged
+signed bundles remain under `evidence/qualification/e00-v4/`, and no v4 seed will be
+rerun into success. V5 binds the repaired anchor-class comparison and a fresh seed
+domain before another attempt. Its immutable packet is registered at commit
+`8cef99cb07daf130c38f93968e5ba24845af49e3` and has a matching confirmed
+deterministic simulated commitment before execution.
+
+V5 executed once on exact clean commit
+`6a3faa8e85cb9f7a9fe7847445897c6e98ee56cb`. Both independent implementations
+accepted all five unchanged bundles and rejected all 55 registered mutation
+instances. Each slot contains 100 events in each Baby ledger and four checkpoints;
+all commitment payloads are 32-byte hashes. First-party recovery and post-restore
+extension tests passed. The receipt is
+`reports/research/e00-integrity-qualification-receipt.json`, and the five retained
+bundles are under `evidence/qualification/e00-v5/`. This qualifies E00 software only;
+it is not evidence for emergent communication or any other behavioral hypothesis.
---
## E01. Channel Isolation and Side-Channel Red Team
-**Status:** Not started
+**Status:** In progress—v1 registered topology qualification passed; B15 remains
**Depends on:** E00
@@ -295,17 +339,33 @@ recorded.
| Test category | Attempts | Blocked | Evidence verified |
|---|---:|---:|---:|
-| Human language | `TBD` | `TBD` | `TBD` |
-| Unicode / emoji | `TBD` | `TBD` | `TBD` |
-| Timing / retries | `TBD` | `TBD` | `TBD` |
-| Tools / storage / network | `TBD` | `TBD` | `TBD` |
-| Error behavior | `TBD` | `TBD` | `TBD` |
-
-- [ ] Isolation criteria met
-- [ ] Residual risks documented
-- [ ] Result committed
-
-**Result summary:** `Not run`
+| Registered category decisions | 60 | 60 | Receipt-verified |
+| Recipient-visible Gateway/transport observations | 500 | 500 within registered bounds | Receipt-verified aggregates |
+| Host capability decisions | 25 | 25 | Receipt-verified aggregates |
+| Detector-positive checks | 20 | 20 detected | Receipt-verified aggregates |
+| Explicit notebook content/path variants | Complete enumerated corpus | Not yet run | B15 open |
+
+- [ ] Isolation criteria met across the complete notebook corpus
+- [x] Residual risks documented
+- [x] V1 bounded qualification result committed
+
+**Result summary:** V1 ran once on exact clean commit
+`8d3a9f67257ad8c53bc5438926ff8dc23743ed0d` after repository registration and a
+matching deterministic simulated pre-run commitment. Five independently recreated
+two-container slots passed all 60 category decisions, 500 Gateway/transport
+observations, 25 host-capability decisions, and 20 detector-positive checks with no
+external spend or public-chain transaction. The tracked receipt is
+`reports/research/e01-isolation-qualification-receipt.json`; five detailed slot
+records remain under `evidence/qualification/e01-v1/`.
+
+The internal review does not mark E01 complete. V1 groups schema-equivalent carrier
+content and does not separately exercise every notebook variant, including each
+human-language, Unicode, URL/code, whitespace, cache, vector-store, replay-buffer,
+and snapshot path. Its host and transport observations are preserved in the receipt
+but are not individual signed ledger events. B15 requires a prospective amendment
+with the full enumerated corpus and attempt-level verified evidence. V1 therefore
+supports only its registered topology/category claim and is not an agent-language
+finding.
---
@@ -371,6 +431,10 @@ messages are randomized, or receiver access to messages is shuffled.
A numerically complete worked registration for this experiment is provided in
[RESEARCH.md Appendix D](RESEARCH.md#appendix-d-worked-preregistration-example-e03-controls).
+Its D05 amendment uses seed-level primary tests, treats high-rate seeds as mandatory
+leakage-review triggers rather than an uncalibrated count rejection, and is backed by
+the independent bounded simulation in
+[`docs/statistical-validation-and-power.md`](docs/statistical-validation-and-power.md).
### Conditions
@@ -680,7 +744,8 @@ compositional reuse.
hypotheses predict those effects.
**Hypothesis:** Substituting, masking, or reordering a form changes receiver behavior
-in the direction predicted by the corresponding ledger.
+in the direction predicted by the corresponding ledger, and pre-outcome ledger
+predictions add held-out predictive value beyond non-ledger comparators.
### Procedure
@@ -691,6 +756,11 @@ in the direction predicted by the corresponding ledger.
- [ ] Reorder multi-part messages.
- [ ] Replay identical observations with counterfactual messages.
- [ ] Compare native ledger predictions with human audit interpretations.
+- [ ] Fit transcript-only, task-history, policy-state, random, and majority prediction
+ baselines without access to private ledger content.
+- [ ] Select the strongest eligible baseline using validation data only, then compare
+ its preregistered proper prediction score with the frozen ledger predictor on
+ untouched intervention cases.
- [ ] Record positive signaling and positive listening separately.
- [ ] For the primary H2 contrast, compare ledger-consistent substitutions with
shuffled-control messages in scratch-RL/extrinsic/fixed-token runs using a
@@ -702,7 +772,8 @@ in the direction predicted by the corresponding ledger.
- normal messages outperform constant and shuffled controls;
- receiver actions change under message intervention;
-- ledger predictions exceed the pre-registered chance baseline;
+- pre-outcome ledger predictions improve the registered proper score beyond the
+ validation-selected non-ledger baseline by the registered practical threshold;
- external audit interpretations are labeled separately from agent-native state.
### Results
@@ -714,6 +785,7 @@ in the direction predicted by the corresponding ledger.
| Positive listening | — | — | — | `TBD` |
| Intervention effect size | — | — | — | `TBD` |
| Native ledger agreement | — | — | — | `TBD` |
+| Ledger proper-score increment | — | — | — | `TBD` |
| Human audit-ledger agreement | — | — | — | `TBD` |
- [ ] Causal listening demonstrated
@@ -759,12 +831,15 @@ but can leak referent information unless strictly constrained.
after stratifying by binary success/failure outcome, using a Miller-Madow
bias-corrected discrete estimator and within-outcome permutation null.
- [ ] For each seed, subtract the mean of 1,000 within-outcome permutations from the
- observed Miller-Madow estimate; test whether the seed-bootstrap one-sided 95%
- upper bound on this excess CMI is below 0.02 bits.
+ observed Miller-Madow estimate; test whether the seed-level Student-t one-sided
+ 95% upper bound on this excess CMI is below 0.02 bits. Report the percentile
+ seed-bootstrap upper bound as sensitivity analysis only.
- [ ] Before registration, simulate the complete estimator at the registered
windows-per-seed count and require at least 90% probability that the null-case
upper bound falls below 0.02 bits; otherwise increase windows or seeds without
widening the bound.
+- [ ] Use a blinded pilot to verify that seed-level excess-CMI standard deviation is
+ at most 0.04 bits; otherwise increase the seed count before unblinding outcomes.
- [ ] Red-team the affect channel as a covert alphabet.
### Results
diff --git a/LEDGER-INTEGRITY-DESIGN.md b/LEDGER-INTEGRITY-DESIGN.md
index 89290a2..8bf780d 100644
--- a/LEDGER-INTEGRITY-DESIGN.md
+++ b/LEDGER-INTEGRITY-DESIGN.md
@@ -81,7 +81,9 @@ Recommended tables:
- `channel_events`;
- `checkpoint_manifests`;
- `anchor_receipts`;
-- `run_metadata`.
+- `run_metadata`;
+- `analysis_attachments` (canonical analysis bytes plus the descriptor bound to
+ an `analysis-attached` intervention event).
Enable WAL mode and serialize writes through one evidence-writer service. Database
permissions and triggers should reject `UPDATE` and `DELETE` operations on event
@@ -296,28 +298,34 @@ Create a checkpoint:
- at run initialization;
- every 64 accepted ledger events or five minutes, whichever occurs first;
- immediately before and after a policy checkpoint;
+- immediately after a delayed human audit-interpreter batch (`analysis`);
- after a BabySitter or human intervention;
- when the run is paused;
- when the run ends or is aborted.
The exact frequency is a protocol parameter recorded before the run. A lower interval
-reduces the unanchored rewrite window but increases anchoring cost.
+reduces the uncommitted rewrite window but increases commitment and storage overhead.
-## 10. Base and L1 Anchoring
+## 10. Simulated Commitments and Optional Public Anchoring
-### Development
+### Approved Research Profile
-Use Base Sepolia to test transaction construction, failure recovery, receipt capture,
-and verification without spending mainnet funds.
+Use the deterministic in-memory transport for development, qualification, pilot,
+confirmatory, and replication runs. It exercises transaction construction, failure
+recovery, receipt capture, and verification with non-monetary test units. Every run,
+pending record, and receipt binds `anchorClass: "simulated"`; the verifier rejects a
+class mismatch. These receipts are not public timestamps or economic finality.
-### Public Research Runs
+### Optional Public-Chain Capability
-Use Base mainnet for routine checkpoint anchoring. Only the 32-byte checkpoint hash
-and minimal routing metadata should be public.
+Base Sepolia and Base mainnet transports remain optional capabilities outside the
+approved research profile. Any activation requires a prospective governance and
+spending amendment. Only the 32-byte checkpoint hash and minimal routing metadata
+should be public.
The simplest viable anchor is a zero-value transaction from the project anchor wallet
to a designated project address with the checkpoint hash in transaction calldata.
-The evidence bundle records:
+For either receipt class, the evidence bundle records:
- chain ID;
- transaction hash;
@@ -351,8 +359,8 @@ root and anchor that root to Ethereum L1. For example:
- daily during an active study;
- before publishing a paper or dataset release.
-Base anchoring is sufficient for the initial implementation. L1 anchoring is an
-additional trust and archival choice, not a prerequisite for every turn.
+Public anchoring is not a prerequisite for the approved campaign. L1 anchoring is an
+additional future trust and archival choice.
## 11. Key Management
@@ -479,15 +487,16 @@ Failure evidence is part of the research record.
- checkpoint consistency proofs;
- signed checkpoint manifests.
-### Phase 2: Testnet Anchoring
+### Phase 2: Simulated Anchoring and Optional Testnet Capability
-- Base Sepolia publisher;
+- deterministic in-memory publisher and explicitly classified receipts;
+- optional Base Sepolia publisher;
- receipt capture;
- independent RPC verification;
- retry and nonce management;
- deliberate failure tests.
-### Phase 3: Public Anchoring
+### Phase 3: Optional Public Anchoring
- Base mainnet anchor wallet;
- published anchor address or minimal contract;
@@ -511,6 +520,7 @@ verifier rejects:
- false inclusion proof;
- inconsistent checkpoint prefix;
- modified run configuration;
+- simulated/public receipt-class relabeling;
- anchor transaction on the wrong chain;
- failed or nonexistent anchor transaction;
- unanchored final ledger tail.
@@ -520,8 +530,9 @@ checkpoint hash.
## 18. Recommended Initial Decision
-Implement Phase 0 and Phase 1 first. Add Base Sepolia anchoring immediately after the
-local verifier is stable. Move to Base mainnet only for declared public research runs.
+Implement Phase 0 and Phase 1 first. Use deterministic simulated anchoring after the
+local verifier is stable. Keep Base Sepolia and Base mainnet disabled unless a later
+prospective amendment explicitly authorizes public-chain operation.
This design is simple enough for an initial Node.js implementation using SQLite,
`node:crypto`, canonical JSON, and a small Base transaction publisher. It provides
diff --git a/README.md b/README.md
index ab5f619..a6ab2d1 100644
--- a/README.md
+++ b/README.md
@@ -95,13 +95,118 @@ channel constraints, and reward conditions were used.
## Project Status
-This repository is in the **foundation implementation phase**. The npm/TypeScript
-workspace, shared runtime schemas, typed configuration loader, secret scan, and three
-DTSF-compatible twin-pack skeletons, SQLite WAL evidence schema, RFC 8785 canonical
-serialization, and ledger event validators are implemented. The next critical-path
-work is independent ledger/channel hash chaining (ALD-008 onward).
-
-No experiment results are claimed yet.
+**Engineering snapshot:** v0.1.97 · 254/258 backlog acceptance criteria verified.
+
+The repository's locally executable **verifiable core and research-execution
+readiness path are complete**. The evidence integrity spine, communication MVP,
+Mode R isolation, experiment-readiness scaffolds, and operator preflight are
+implemented and tested:
+
+- `@ald/hashing`, `@ald/merkle`, `@ald/evidence`: domain-separated hashing, RFC 8785
+ canonical JSON, per-run Ed25519 signers and key store, hash-chain validation, RFC
+ 6962 ordered Merkle trees with inclusion and consistency proofs, and the single
+ atomic SQLite Evidence Writer with fork detection, recovery, bundle export, and
+ analysis attachments atomically bound to witness-committed intervention events.
+- `@ald/checkpoint`, `@ald/anchor`, `@ald/verifier`: signed checkpoint manifests and
+ proof files, the Base-shaped anchor publisher (deterministic simulation by default;
+ optional viem public-chain transport outside the approved campaign), and the standalone
+ `ald-verify` CLI that re-derives
+ every hash, signature, root, proof, binding, and anchor from a bundle alone.
+ A separate read-only Rust auditor independently rebuilds canonical event hashes,
+ signatures, Merkle prefixes, checkpoint chains, receipt bindings, and attachment
+ hashes; `pnpm run challenge:integrity` compares both implementations against a
+ fresh real export and deliberate mutations.
+- `@ald/lifecycle`, `@ald/scenario`, `@ald/gateway`, `@ald/learners`,
+ `@ald/orchestrator`, `@ald/analysis`: the SPEC §7 run state machine; deterministic
+ scenarios, hygiene, and a fail-closed run-registration quarantine gate; fixed-token, glyph, bitmap, canvas,
+ tone, and six-display affect protocols; no-learning and all four trainable/runtime
+ tracks; an explicitly selected 16-unit GRU actor-critic with PPO-style updates for
+ scratch RL; the same 4,049-parameter GRU core with reward-free predictive
+ cross-entropy for self-supervision; tabular/count models retained as named
+ qualification controls; frozen-LLM and hybrid adapter conformance foundations; the
+ carrier analysis module provides grammar-valid bitmap, translation-tolerant canvas,
+ and graded tone distances plus deterministic held-out nearest-prototype scoring,
+ explicitly bounded to a handcrafted-distance diagnostic rather than learned
+ perceptual generalization; the
+ independently seeded policies and witness-committed initial hashes;
+ independently verified derived-run lineage against immutable parent exports;
+ Nursery's end-to-end SPEC §8 turn cycle; a delayed, source-bound human audit
+ interpreter whose generated entries are separately signed and checkpointed; and
+ pre-registered analysis primitives, including immutable mark-level leakage
+ probes across all five carrier conditions with an evidence-preserving claim gate;
+ and an E16 runtime seam that commits validation-selected baseline and native-ledger
+ predictions after delivery but before receiver action, checkpoints that chronology,
+ then source-binds post-outcome scores as per-turn analysis attachments. The immutable
+ run configuration binds the comparator-selection commitment and native
+ prediction-function version, limits eligibility to accepted evaluation
+ deliveries, and includes fail-closed restart checks.
+- `@ald/isolation`, `@ald/ops`, `@ald/interventions`, `@ald/redteam`: fixed-frame
+ process transport, a two-container Mode R network-isolation gate, and learner-host confinement; API telemetry, snapshot/restore,
+ and failure supervision; configuration-driven, verifier-bound live causal probes
+ and bounded repair turns, plus held-out, curriculum, drift, and statistical
+ scaffolds; the committed observation-text and quarantine-bypass corpus; and
+ an active twelve-category side-channel red-team suite shared by Mode P and Mode R,
+ plus 28 generated-carrier dimension, metadata, raw-media, sample-rate, compression,
+ and container attacks through the real Gateway.
+ These are tested foundations, not a completed production Mode R deployment or
+ a scientific result. `pnpm run test:mode-r` builds the locked-down learner image,
+ denies Baby-to-Baby routes on separate internal networks, checks host capability
+ denial and normalized timing, then kills one learner and verifies the other survives.
+ `pnpm run test:mode-r-study` additionally drives every learner track through the
+ actual controller, Gateway, SQLite writer, checkpoint, deterministic simulated commitment,
+ exporter, and verifier. Its explicit simulated receipt remains software evidence,
+ not a public-chain transaction or research result. Persistent study signers are
+ accepted only from `si fort` files-mode materialization mounted into the Nursery;
+ neither learner receives that mount or its path.
+- `@ald/crypto-research`: an E40 research-only, three-role instrumentation harness
+ that records hash-chained ephemeral scheme changes and Eve recovery attempts over
+ synthetic messages. A repository lint boundary prevents it from entering the
+ production hashing or anchoring packages; it never reports cryptographic security.
+- DTSF twin packs for `baby-a`, `baby-b`, and `nursery` expose the SPEC §12 routes
+ with role guards in Prototype Mode; audit-ledger reads return only the separate
+ generated-analysis stream and reject Baby service identities.
+
+The qualification harness (`scripts/run-qualification.mjs`) executes E03-style
+chance controls and an E11-style naming game through the real pipeline and writes a
+report under `reports/qualification/`. Those runs are **non-confirmatory software
+qualification in Prototype Mode**: not pre-registered, not anchored, and never
+research findings.
+
+The committed E03 design simulation and seed manifest make the manuscript's
+power rule reproducible; the registration compiler produces canonical hashed
+artifacts and all primary/reserve run templates; and the research preflight
+blocks confirmatory execution until its immutable software, isolation, external
+registration, and confirmed pre-run simulated-commitment bindings agree.
+
+The frozen-LLM operator path also completed a real two-episode qualification
+against Qwen3-4B Q4_K_M through Homebrew llama.cpp 0.4.0. The retained
+[`reports/qualification/frozen-model-qwen3-4b-q4-k-m.json`](reports/qualification/frozen-model-qwen3-4b-q4-k-m.json)
+binds the exact model weights, resolved executable and bottle, software commit,
+live server configuration, separate role processes, clean-process replay,
+tool-only calls, and frozen-weight/private-memory semantics while omitting prompts
+and private output. The 7.5-GiB validation host required non-overlapping role
+processes and a 300-second qualification ceiling, so this is bounded software
+evidence rather than a production-capacity or empirical finding.
+
+The E01/E02 software-readiness outputs have a hashed attachment path linked from
+the append-only Experiment Record and independently checked against their evidence
+event and committed prefix. The approved prospective research profile uses no real
+funds or public-chain transactions; those remain optional capability tests outside
+the study. Repository-native preregistration and deterministic simulated commitments
+are the sole experiment activation path. Hosted enforcement, a restore performed by
+a second human, and third-party registration remain optional evidence-strengthening
+activities and are never claimed unless actually completed. The retention job is implemented
+and covered against real exported bundles and evidence-store rows.
+
+The [external-prerequisite handoff](docs/external-prerequisite-handoff.md) and its
+machine-readable ledger make O01–O06 auditable without recording secrets or personal
+identity. The ledger is ready at 1/1 applicable prerequisite: O01 is verified, while
+O02-O06 are non-applicable to local synthetic execution under the zero-spend,
+repository-native policy. A read-only upstream observation remains as historical
+evidence that hosted required-check enforcement is not demonstrated, not as an
+experiment blocker.
+
+No experiment results are claimed.
The complete rationale, literature review, experimental ideas, risks, and open
decisions are in [CONCEPT-IDEA.md](CONCEPT-IDEA.md).
@@ -116,6 +221,15 @@ decisions are in [CONCEPT-IDEA.md](CONCEPT-IDEA.md).
| [SPECIFICATION.md](SPECIFICATION.md) | Normative architecture, protocols, schemas, APIs, isolation controls, lifecycle, and acceptance criteria |
| [BACKLOG.md](BACKLOG.md) | Milestones, critical path, epics, dependency-ordered stories, readiness gates, and requirement coverage |
| [RESEARCH.md](RESEARCH.md) | Pre-results academic manuscript, research questions, methods, literature review, analysis plan, source verification, and arXiv preparation checklist |
+| [CONFIGURATION.md](CONFIGURATION.md) | Runtime environment variables, key-store layout, and secret handling |
+| [docs/external-prerequisite-handoff.md](docs/external-prerequisite-handoff.md) | Exact privacy-safe evidence and activation checks for O01–O06 |
+| [docs/simulation-funded-research-profile.md](docs/simulation-funded-research-profile.md) | Approved zero-spend campaign boundary and the distinction between simulated funds and real observations |
+| [docs/evidence-bundle-format.md](docs/evidence-bundle-format.md) | Byte-level evidence bundle contract shared by the exporter, checkpoint service, and verifier |
+| [docs/cryptographic-separation-policy.md](docs/cryptographic-separation-policy.md) | Mandatory boundary between E40 research encodings and production hashing/signing/anchoring |
+| [reports/README.md](reports/README.md) | What the qualification reports are and are not |
+| [Research validation report](reports/research/research-validation-report.md) | Living evidence-class, validation, experiment, and claim-readiness report |
+| [Source-lineage register](reports/research/source-lineage-register.md) | Requirement origins and later normative amendments without personal attribution |
+| [Requirement conformance matrix](docs/requirement-conformance-matrix.md) | Provisional mapping from every backlog criterion and normative MUST-bearing line to executable evidence |
## Research Book
@@ -131,7 +245,7 @@ generated PDF as a download.
Regenerate the book after changing the manuscript:
```powershell
-npm run book:research
+pnpm run book:research
```
The page rasterizer requires Node.js 22.13 or newer; generated book assets do not
@@ -143,6 +257,46 @@ are committed so GitHub Pages needs no server, CDN, or runtime PDF renderer.
The notebook is ready for pre-registration. No experiment results are claimed yet.
+## Running the Platform Locally
+
+```bash
+pnpm install --frozen-lockfile
+pnpm run check
+```
+
+`pnpm run check` runs every source/contract/boundary/readiness/status lint, builds
+every workspace, runs the complete test suite, scans for committed secrets, and
+blocks on high/critical dependency advisories.
+
+Reproduce the E03 design inputs, compile the default 75-primary/8-reserve
+registration, and run the fail-closed preflight with:
+
+```bash
+pnpm run design:e03
+pnpm run registration:e03 --out evidence/preregistration/e03-v1-draft.json
+pnpm run preflight:research \
+ --registration evidence/preregistration/e03-v1-draft.json \
+ --binding /absolute/path/repository-registration-and-commitment-binding.json
+```
+
+The preflight fails until the packet exists unchanged in an ancestral Git commit and
+a confirmed matching pre-run simulated commitment is supplied in the binding.
+
+Run the Prototype Mode qualification harness and verify a bundle independently:
+
+```bash
+pnpm run build && node scripts/run-qualification.mjs
+```
+
+```bash
+node packages/verifier/bin/ald-verify.js evidence/qualification//bundles/runs/ --allow-unanchored
+```
+
+Databases and bundles are written under `evidence/`, which is ignored by git; reports
+are written under `reports/qualification/`. The approved profile needs no funded
+wallet: runs use the deterministic in-memory transport, carry
+`anchorClass: "simulated"`, and fail verification if that class is altered.
+
## Responsible Research
All learned-cipher experiments should use synthetic, non-sensitive messages. Novel or
diff --git a/RESEARCH.md b/RESEARCH.md
index 221f64e..fd1a236 100644
--- a/RESEARCH.md
+++ b/RESEARCH.md
@@ -8,13 +8,15 @@
>
> **Prepared:** September 2, 2026
>
+> **Engineering snapshot:** v0.1.97 · 254/258 backlog acceptance criteria verified.
+>
> **Proposed arXiv category:** `cs.MA` (primary), with possible cross-listing to
> `cs.AI` and `cs.CL`
>
-> **Authors:** Ethical Tech CoLab; individual author order, affiliations, ORCID
-> identifiers, and corresponding author to be finalized before submission
+> **Authors:** Anonymous working draft; author order, affiliations, ORCID identifiers,
+> and corresponding author are omitted until the authorized submission stage
>
-> **Repository:**
+> **Artifact:** Anonymous review artifact to be prepared only after release approval
>
> **Empirical status:** No Nursery Lab experiment has been reported as completed in
> this manuscript. Sections 10 and 11 distinguish implemented infrastructure from
@@ -39,9 +41,11 @@ reinforcement learning, intrinsic-motivation learning, self-supervised learning,
hybrid models, and no-learning controls under common scenario, channel, evidence, and
evaluation interfaces. Each agent is specified to maintain an independent chronological ledger of its own
intentions and interpretations. The framework specifies append-only, hash-chained,
-signed ledger and channel records, ordered Merkle checkpoints, and periodic
-public-chain checkpoint anchoring. These mechanisms are not yet fully implemented and
-do not prove that an agent's interpretation is truthful; they are designed to preserve
+signed ledger and channel records, ordered Merkle checkpoints, and deterministic
+simulated commitments. The local integrity, checkpoint, verifier, and commitment
+paths are implemented and tested under a zero-external-spend profile. Optional
+public-chain transport remains outside the approved campaign and its claims. These
+mechanisms do not prove that an agent's interpretation is truthful; they are designed to preserve
what was recorded and make later alteration detectable. Causal message interventions, held-out generalization, partner
replacement, leakage tests, and control-channel conditions are therefore required in
addition to task success.
@@ -72,7 +76,10 @@ Assistance in Formulating Research Questions* guidance [47]:
- AI-suggested connections are treated as exploratory until supported;
- the influence and limitations of AI assistance are disclosed;
- source verification state and journal credibility are recorded in Appendix A;
-- a separate critical-review pass is required before publication.
+- a separate critical-review pass is required before publication; the current
+ internal pass is recorded in
+ [reports/research/research-critical-review.md](reports/research/research-critical-review.md)
+ and does not count as independent review.
In this draft, source retrieval and the first verification pass were performed by an
AI assistant using web, scholarly-index, and metadata tools, followed by separate AI
@@ -227,10 +234,10 @@ pre-registrations. The following hypotheses define the current direction:
| H1 | Normal communication will outperform disabled, constant, random, and shuffled controls on held-out tasks. | Control performance equals or exceeds normal communication after correction. |
| H2 | In E16's scratch-RL, extrinsic-reward, fixed-token condition, a ledger-consistent substitution will increase the probability of the ledger-predicted receiver action relative to shuffled-control messages. | The hierarchical substitution-versus-shuffle contrast is zero or negative. |
| H3 | At equal model capacity, training episodes, and update/compute budget, the planned 32-symbol/4-token condition will produce higher held-out compositional generalization than the 128-symbol/8-token condition. | The planned contrast is zero or favors the higher-bandwidth condition. |
-| H4 | Ledger-predicted intervention directions will exceed a pre-registered chance baseline. | Ledger agreement is at chance or fails out-of-sample. |
+| H4 | On untouched intervention cases, pre-outcome ledger predictions will improve a pre-registered proper prediction score beyond the strongest eligible transcript-only, task-history, policy-state, random, and majority baseline. | The ledger fails to exceed the strongest eligible non-ledger baseline by the registered practical threshold. |
| H5 | A blank bounded carrier will support repeated forms, but will converge more slowly than a fixed symbol inventory. | No stable forms emerge, or blank-carrier convergence is not slower. |
| H6a | The declared six-display affect condition will reduce median turns to successful repair relative to no affect. | Repair time is equal or longer under affect. |
-| H6b | Under fixed windows and cardinality, permutation-calibrated excess conditional mutual information between affect and referent will remain below the pre-registered 0.02-bit practical-leakage bound. | The seed-bootstrap upper-bound test cannot rule out excess leakage of 0.02 bits or more. |
+| H6b | Under fixed windows and cardinality, permutation-calibrated excess conditional mutual information between affect and referent will remain below the pre-registered 0.02-bit practical-leakage bound. | The seed-level one-sided Student-t upper-bound test cannot rule out excess leakage of 0.02 bits or more. |
| H7 | Fixed dyads will show greater partner-replacement degradation than learners trained with pre-registered partner variation. | Degradation for fixed dyads is no greater than degradation after partner-varied training. |
| H8 | Partially conflicting utility will reduce message informativeness and increase strategic ambiguity relative to aligned utility. | Informativeness and ambiguity do not change in the predicted direction. |
@@ -658,6 +665,23 @@ Researcher ground truth may contain semantic labels; learner observations may no
Observations use opaque numeric arrays, pixels, or separately qualified hybrid
features. Images containing OCR-detectable text are quarantined before a run.
+The initial numeric referential design contains 16 two-attribute combinations. The
+four equal-attribute diagonal combinations are the locked compositional test targets;
+the remaining 12 combinations are the shared semantic support for training and
+in-distribution validation. Training and validation use independent PRNG domains,
+and no held-out type may occur in either split as a target or distractor. Validation
+is learning-off and may be used for tuning and baseline selection. The held-out split
+is learning-off and is accessed once after those choices freeze. The broader
+`evaluation` split remains an engineering and software-qualification surface and is
+not interchangeable with the confirmatory held-out test.
+
+The versioned split, duplicate rules, matched budget dimensions, and boundaries
+between within-architecture causal contrasts and cross-architecture descriptive
+benchmarks are frozen in
+[`protocols/scenario-split-and-model-comparison.v1.json`](protocols/scenario-split-and-model-comparison.v1.json)
+and explained in
+[`docs/scenario-splits-and-model-comparisons.md`](docs/scenario-splits-and-model-comparisons.md).
+
### 6.5 Communication Conditions
For the baseline fixed-token carrier, each run declares a random inventory such as
@@ -754,7 +778,7 @@ criteria are satisfied.
1. held-out task success relative to E03 controls;
2. positive listening under message intervention;
-3. ledger-predicted intervention agreement;
+3. ledger incremental predictive value on untouched interventions;
4. held-out compositional generalization.
**Secondary outcomes**
@@ -782,7 +806,12 @@ distributions to change while the receiver observation is held fixed.
**Ledger agreement:** the direction of an observed intervention effect matches the
direction predicted from the learner's ledger before intervention outcomes are
-revealed.
+revealed. This is a descriptive calibration measure, not H4's confirmatory estimand.
+
+**Ledger incremental value:** held-out improvement in a pre-registered proper
+prediction score over the strongest eligible transcript-only, task-history,
+policy-state, random, and majority baseline. Predictions are committed before the
+intervention outcome is generated.
**Compositional generalization:** reusable subparts support above-control success on
pre-registered unseen combinations with learning disabled.
@@ -796,15 +825,20 @@ equal-weight eight-partner-training degradation.
### 7.3 Statistical Plan
-The final analysis plan will be frozen before confirmatory runs.
-
-- Alpha is `0.05` for each experiment's primary family.
-- Holm-Bonferroni correction is applied across primary metrics within an experiment.
-- The confirmatory study family is restricted to H1-H8, including H6a and H6b.
- Hierarchical gatekeeping tests qualification first, then core emergence, then later
- affect/transfer/negotiation hypotheses; a blocked family is reported descriptively.
- Exploratory analyses use false-discovery-rate reporting and remain labeled
- exploratory.
+The common analysis and multiplicity rules are frozen in
+[`protocols/statistical-analysis-and-power.v1.json`](protocols/statistical-analysis-and-power.v1.json).
+Experiment-specific raw-scale practical margins and seed allocations will be frozen
+after disjoint pilots and before confirmatory runs.
+
+- The confirmatory study family contains nine members: H1, H2, H3, H4, H5, H6a,
+ H6b, H7, and H8. One pre-registered p-value is formed per member and Holm correction
+ is applied globally at family-wise alpha 0.05. Multi-component directional members
+ use the maximum component p-value and require every registered direction and
+ practical threshold.
+- E00-E03 and experiment-specific checks are validity gates, not sources of reusable
+ alpha. A failed or missing gate produces `not-tested`, not a favorable or
+ unfavorable p-value. Exploratory analyses use false-discovery-rate reporting and
+ remain labeled exploratory.
- Effect sizes and confidence or credible intervals are reported with every
significance test.
- Binary task outcomes are modeled at the run/seed level, with episodes treated as
@@ -827,12 +861,50 @@ Before empirical submission, simulation-based power analysis will determine the
required number of independent seeds for each primary contrast; the larger value
governs.
+Independent base-R validation agrees with the production special functions and
+seed-level tests, demonstrates calibrated boundary behavior, and shows why pooled
+episode inference is prohibited. The complete E03 numeric decision has a lower 95%
+Monte Carlo power bound above 0.90 in all four planned variance rows. A nine-member
+Holm sensitivity shows that 75 seeds is not generally sufficient: at standardized
+effect 0.40, all-member power is 0.6752 at N=75 and 0.9068 at N=100. These values are
+design evidence rather than universal sample sizes; D07 applies the registered
+member-specific rule. Full methods and Monte Carlo intervals are in
+[`docs/statistical-validation-and-power.md`](docs/statistical-validation-and-power.md).
+
Claims that a control is "at chance" or that leakage is absent use equivalence or
upper-bound tests, not failure to reject a difference. Each pre-registration must
state the smallest effect of interest, the equivalence margin, and power to rule out
that margin. The worked E03 design in Appendix D uses a +/-0.05 success-rate margin;
H6b uses a 0.02-bit conditional-mutual-information bound.
+The outcome-blind causal-ledger and leakage rules are frozen in
+[`protocols/causal-ledger-and-leakage.v1.json`](protocols/causal-ledger-and-leakage.v1.json).
+For E02, at least 200 untouched test rows are required and the one-sided 95%
+Wilson upper bound on linear-probe accuracy advantage over the held-out majority
+baseline must be at most 0.10. The identical probe and split must detect an injected
+one-hot target feature with a lower advantage bound of at least 0.20. For E20, 75
+eligible seeds and 1,000 windows per seed are required before a decision; the primary
+bound is seed-level Student-t and the percentile bootstrap is sensitivity-only.
+Allowed and forbidden information sets and detector-positive controls are explicit
+for E01, E02, E13, and E20. Intended normalized carrier form is communication, not a
+side channel.
+
+Seed and resource allocation is frozen in
+[`protocols/seed-and-resource-allocation.v1.json`](protocols/seed-and-resource-allocation.v1.json).
+Qualification, blinded-pilot, confirmatory, and replication stages use disjoint
+SHA-256 domains; paired conditions share scenario seeds but not learner, Gateway, or
+analysis seeds. A 20-slot blinded pilot selects the smallest shared candidate N whose
+complete nine-member Holm-family simulation has a lower 95% Monte Carlo power bound
+of at least 0.90. N=100 is a planning value, not a selected result.
+
+A fresh 260-turn recurrent-carrier benchmark took 37.58 seconds and wrote 25.53 MB.
+At that measured uncompressed rate, maximum materialized pools including replication
+project to 9,171 bundles, 9.36 million turns, 855.9 GiB, and 375.7 single-core hours.
+The present local ceiling is 72 CPU-hours, 25 GiB, one frozen-model process, and zero
+external spend. It supports bounded qualification and pilots, not the full campaign;
+confirmatory registration requires an exact selected prefix and an approved execution
+resource plan.
+
Run exclusions are limited to pre-specified integrity or protocol failures. Each
condition receives a fixed ordered list of primary and reserve seeds before outcomes
are observed. An invalid primary seed may be replaced only by the next reserve seed;
@@ -863,17 +935,21 @@ Qualitative analysis is secondary and will examine:
- abrupt convention changes;
- negotiation-era semantic shifts.
-Human coders will use a pre-registered codebook and, where feasible, blinded
-independent coding. Generated audit interpretations will not be treated as ground
-truth.
+The approved initial campaign uses no human-coded outcome. Qualitative labels are
+generated by registered deterministic analysis and are not treated as ground truth.
+Any later human-coding proposal requires a prospective protocol and governance
+amendment before collection.
---
## 8. Evidence Integrity and Reproducibility
-> **Design status:** This section describes required evidence behavior. Hash-chain
-> writing, signatures, Merkle checkpoints, anchoring, and the independent verifier are
-> not yet complete; see Section 10.
+> **Implementation status:** Local hash-chain writing, domain-separated signatures,
+> ordered-Merkle checkpoints and proofs, anchor publisher transports, evidence export,
+> and the standalone verifier are implemented and covered by software tests. The
+> approved campaign uses deterministic simulated receipts and no real funds; no
+> public-chain receipt is claimed, and the historical research
+> corpus remains unregistered and unanchored; see Section 10.
### 8.1 Append-Only Evidence
@@ -893,15 +969,18 @@ Ordered Merkle trees are specified to provide:
Signed checkpoint manifests will bind the event roots to run configuration, learner
contract, software commit, and previous checkpoint.
-### 8.3 External Anchoring
+### 8.3 Simulated Commitments and Optional External Anchoring
-Development qualification is specified to use Base Sepolia. Declared public studies may anchor
-checkpoint hashes to Base mainnet. Only hashes and minimal routing metadata are
-on-chain. Private observations, messages, ledgers, prompts, identities, and keys
-remain off-chain.
+The prospective campaign uses a deterministic in-memory transport, a non-monetary
+simulated balance, and receipts labeled `anchorClass: "simulated"`. Base Sepolia and
+Base mainnet remain optional software capabilities outside the approved study. A
+future public-chain activation would require a new prospective amendment; only hashes
+and minimal routing metadata could be placed on-chain.
-The anchor proves that a committed prefix existed no later than a chain block and
-that disclosed content matches the commitment. It does not prove:
+The simulated commitment proves that the executed bundle consumed a specific
+committed prefix and that disclosed content matches it. Together with the external
+registration timestamp and immutable Git commit, it preserves prospective order. It
+does not prove public availability, decentralized persistence, economic finality, or:
- an event was true;
- no event was omitted before commitment;
@@ -925,7 +1004,7 @@ The standalone verifier is specified to check:
- cross-bindings among intention, message, delivery, interpretation, and outcome;
- Merkle roots, inclusion proofs, and consistency proofs;
- checkpoint chains and witness signatures;
-- public-chain transaction, chain ID, block inclusion, and finality;
+- receipt class, transaction-shaped identifier, chain identity, block inclusion, and finality semantics;
- forks, gaps, and unanchored tails.
Any integrity failure prevents a run from receiving a valid disposition.
@@ -933,8 +1012,9 @@ Any integrity failure prevents a run from receiving a valid disposition.
Here, **independent verifier** means software that recomputes evidence from an exported
bundle without trusting the live runtime, database, or private keys. For a
publication-facing claim, at least one verification execution must additionally be
-performed by a person who did not operate the original run, using an independently
-configured chain RPC. External replication remains stronger than either form.
+performed by a person who did not operate the original run, using the independent
+offline verifier. An independent RPC is additionally required only for a future
+public-chain receipt. External replication remains stronger than either form.
### 8.5 Replay
@@ -1014,30 +1094,84 @@ as separate fields.
## 10. Current Implementation Status
-As of September 2, 2026, the repository records ALD-001 through ALD-007 as complete.
-This is engineering status, not an empirical result.
+**Engineering snapshot:** v0.1.97 · 254/258 backlog acceptance criteria verified.
+
+As of September 12, 2026, 82 of 86 backlog items satisfy all of their acceptance
+criteria. This is engineering status, not an empirical result.
Implemented:
-- npm/TypeScript workspaces;
-- runtime-validated shared schemas;
-- typed configuration and secret scanning;
-- DTSF-compatible Learner A, Learner B, and Nursery twin-pack scaffolds;
-- SQLite WAL evidence schema and append-only triggers;
-- RFC 8785 canonical serialization;
-- ledger event-type validators;
-- automated lint, build, test, dependency-audit, and clean-clone checks.
-
-Not yet implemented or empirically executed:
-
-- full hash-chain writing and signatures;
-- atomic evidence writer;
-- Merkle checkpoints and independent verifier;
-- Base anchoring;
-- complete gateway and scenario engine;
-- model adapters and training;
-- Research-Grade isolation;
-- experiments E00-E50.
+- hash-chained, signed SQLite evidence; ordered Merkle checkpoints; exact bundle
+ export; and an independent verifier;
+- a frozen local audit-cost protocol and receipt covering five immutable
+ qualification bundles, with ordinary-log, signed-stream, integrity-structure,
+ policy-state, and complete-bundle storage separated; descriptive offline verifier
+ timing and the prior six-case mutation challenge are reported without claiming a
+ public anchor or an empirical result;
+- an E16 comparator pipeline that fits all five eligible non-ledger predictors on a
+ validation-fit fold, selects by Brier score on a disjoint validation-selection
+ fold, refits and hash-locks the selected model, commits baseline and native-ledger
+ predictions before accepting test outcomes, and keeps the oracle diagnostic
+ ineligible for selection; exact synthetic qualification passed five comparator and
+ seven negative-control paths; the production runtime now invokes an injected
+ outcome-blind native predictor after Gateway delivery and before receiver action,
+ commits and checkpoints baseline/native predictions, derives the receiver choice
+ from its hash-bound turn record, and binds per-turn post-outcome scores; the hashed
+ run configuration commits the selection and prediction-function identities and
+ accepted-evaluation-delivery eligibility, and recovery refuses an absent or
+ mismatched provider; exact detached qualification passed 10 focused tests and the
+ full 1,808-test repository gate;
+- a general fail-closed registration-packet compiler requiring eleven exact binding
+ classes; the current all-experiment inventory resolves only the 19 protocol cards,
+ leaves 170 experiment-specific bindings open, and emits E00 and E01 registration hashes;
+- grammar-valid bitmap, translation-tolerant canvas, and graded tone distances with
+ deterministic nearest-prototype evaluation; this is a handcrafted E13 diagnostic,
+ not evidence that a learner learned the metric or generalized to novel forms; an
+ exact clean-candidate qualification covers three carriers and six rejection paths;
+- a Base-shaped commitment client with confirmation/recovery handling, explicit
+ simulated/public receipt classification, and mainnet gating; the verifier rejects
+ a simulated receipt relabeled as public-chain evidence;
+- an authenticated Fort boundary that stores the project signer envelope and unused
+ optional public-chain credentials only as encrypted Safe material; a four-track
+ files-mode Mode R run sealed and production-verified every bounded qualification
+ bundle; the zero-balance public address remains inactive and is not needed by the
+ simulation-funded campaign;
+- deterministic scenarios, the tool-only Gateway, all declared carrier controls,
+ five learner tracks, DTSF twin routes, and the complete turn lifecycle;
+- process/container Mode R isolation, training separation, active side-channel and
+ observation red teams, including a reusable 28-case generated-carrier structural
+ side-feature audit with accepted controls and fail-closed evidence readiness; the
+ exact candidate also passed the current two-container Mode R timing, fixed-envelope,
+ error-shape, host-denial, crash-survival, and three-track update checks; plus
+ telemetry, retention, snapshot/restore, and failure policy;
+- readiness gates for E00-E50, reproducible E03 design and seed artifacts, canonical
+ E03 registration compilation, and a fail-closed confirmatory preflight;
+- a privacy-minimized real-model software qualification of Qwen3-4B Q4_K_M through
+ llama.cpp, with exact model/runtime hashes and both role directions exercised; and
+- automated lint, build, test, dependency-audit, secret-scan, acceptance-coverage,
+ API-documentation, project-status, clean-clone, hosted CI, and Mode R checks.
+
+Not yet empirically executed or independently evidenced:
+
+- final-topology/pilot resource qualification; and
+- confirmatory experiments E00-E50 or any scientific results.
+
+The external-dependency ledger is ready at 1/1 applicable item: O01 is verified by
+the scoped synthetic-only governance decision, while O02-O06 are non-applicable to
+local execution. Public funding, public-chain transactions, hosted enforcement,
+second-person restoration, and third-party registration remain optional claim-
+strengthening activities. Their absence is disclosed and prohibits claims of public
+finality, hosted enforcement, independent restoration, or third-party registration;
+it does not answer or alter the agent-language estimands.
+
+The frozen local [data/claim inventory](docs/data-and-claim-inventory.md) resolves 125
+exported bundles across 19 collections by path and content hash. Forty-one have
+tracked bounded software-qualification support, 33 are historical qualification
+exports, and 51 are failed or superseded diagnostics. All 125 are excluded from
+empirical estimates. Seventy-seven recorded anchor confirmations are historical local
+fake-chain receipts; prospective receipts now bind an explicit class that the
+verifier refuses to relabel. Confirmed public-chain anchors, pilot bundles, confirmatory
+bundles, replication bundles, and research-included bundles are all zero.
The implementation backlog is maintained in [BACKLOG.md](BACKLOG.md), while normative
requirements are in [SPECIFICATION.md](SPECIFICATION.md).
@@ -1141,11 +1275,10 @@ database search with inclusion/exclusion criteria and dual-review screening.
### 14.1 Code
-Source code and planning artifacts are publicly available at:
-
-
+Source code and planning artifacts exist in the working repository. An anonymous
+review artifact and any public release URL will be prepared only after release
+approval. Every empirical paper revision will identify an immutable source commit.
-Every empirical paper revision will identify the exact Git commit used.
### 14.2 Protocols
@@ -1154,6 +1287,8 @@ Every empirical paper revision will identify the exact Git commit used.
- Ledger integrity: [LEDGER-INTEGRITY-DESIGN.md](LEDGER-INTEGRITY-DESIGN.md)
- Experiment protocols and results notebook:
[EXPERIMENT-NOTEBOOK.md](EXPERIMENT-NOTEBOOK.md)
+- Frozen question, estimand, and outcome-class cards:
+ [docs/research-protocol-cards.md](docs/research-protocol-cards.md)
- Engineering plan: [BACKLOG.md](BACKLOG.md)
### 14.3 Data
@@ -1170,12 +1305,14 @@ and analysis plan before execution. The run configuration stores the protocol co
and pre-registration hash. Changes create appended amendments rather than rewriting
the original record.
-No external registration record exists yet. Before the first confirmatory run, the
-team intends to create a dated OSF registration and anchor the same canonical
-`preRegistrationHash` before the run enters `running`. A Git commit in an
-author-controlled repository is retained as a development record but is not, by
-itself, treated as third-party preregistration. Appendix D supplies a numerically
-complete worked E03 registration for review.
+No complete experiment packet has yet been repository-registered. Before each
+confirmatory run, its canonical packet will be committed unchanged in a Git ancestor
+of the execution commit. Preflight will load those historical bytes, reproduce the
+`preRegistrationHash`, and require a matching deterministic simulated commitment
+before the run enters `running`. This establishes exact local identity, ancestry,
+ordering against later committed evidence, and tamper detection; it is not described
+as third-party registration or an independent timestamp. Appendix D supplies a
+numerically complete worked E03 registration for review.
---
@@ -1222,11 +1359,10 @@ Institutional and technical acknowledgements: **TBD before submission**.
### AI-Assistance Disclosure
-This working manuscript was developed with AI assistance in VS Code through the
-Copilot SDK. The AI assistant performed the initial source retrieval, opened the
-arXiv/ACL/PMLR/Crossref/publisher/standards pages summarized in Appendix A, organized
-the manuscript, summarized relevance, and conducted consistency checks. A separate AI
-research-agent pass challenged source status and identified overclaiming risks.
+This working manuscript was developed with AI-assisted research and repository tools.
+The tools supported source retrieval, primary-page inspection, manuscript organization,
+code implementation, executable validation, and critical consistency checks. Separate
+AI-assisted passes challenged source status, numerical claims, and overclaiming risks.
AI systems are not authors and bear no responsibility for the manuscript. Human
authors remain responsible for every claim, citation, analysis, and conclusion.
@@ -1245,9 +1381,13 @@ were attempted on September 2, 2026. The API reported the account disabled and t
reported its keyless monthly limit reached. No new Tavily-generated result was relied
upon. Rather than conceal the failure or imply that Tavily returned evidence, the
review continued through arXiv Atom metadata, ACL Anthology, PMLR, Crossref, JMLR,
-publisher and university pages, RFC Editor, NIST, Google Books, and Ethical Tech CoLab
-repositories. A final submission should rerun the search after Tavily access is
-restored and record whether it changes the included corpus.
+publisher and university pages, RFC Editor, NIST, Google Books, and institutional
+repositories. A bounded update was completed on September 11, 2026 across primary
+repository and publisher surfaces. Its queries, screening boundaries, all 50 source
+decisions, and five newer comparators are recorded in the
+[source verification register](reports/research/source-verification-register.md).
+This was not a systematic review. A final submission must repeat the search through
+the manuscript-freeze date and record whether it changes the included corpus.
All retrieved material was treated as untrusted evidence, not as instruction.
@@ -1364,7 +1504,7 @@ Conference on Learning Representations*.
[26] Galke, L., & Raviv, L. (2024). Learning and communication pressures in
neural networks: Lessons from emergent communication. *Language Development
-Research, 5*(1), 116-143.
+Research, 5*(1), 116-140.
[27] Kouwenhoven, T., Peeperkorn, M., & Verhoef, T. (2025). Searching for
structure: Investigating emergent communication with large language models.
@@ -1511,7 +1651,7 @@ before submission.
| [12] | **tool-metadata-verified**, arXiv primary page | Peer-reviewed NeurIPS paper; journal score N/A | "Biases for Emergent Communication in Multi-agent Reinforcement Learning." Shows designed biases can promote communication. |
| [13] | **tool-abstract-verified**, arXiv primary page/API | Peer-reviewed AAMAS paper; journal score N/A | "Capacity, Bandwidth, and Compositionality in Emergent Language Learning." Supports capacity/bandwidth controls. |
| [14] | **tool-metadata-verified**, ACL Anthology | Peer-reviewed ACL paper; journal score N/A | "Compositionality and Generalization In Emergent Languages." Supports separate behavioral generalization tests. |
-| [15] | **tool-abstract-verified**, arXiv primary page/API | Peer-reviewed NeurIPS paper; journal score N/A | "Interpretable agent communication from scratch (with a generic visual processor emerging on the side)." Supports causal symbol interventions. |
+| [15] | **tool-full-text-verified**, complete paper | Peer-reviewed NeurIPS paper; journal score N/A | Supports unsupervised learned discrete communication, partial interpretability, and novel-class generalization in its evaluated setting; it does not supply causal symbol-intervention evidence. |
| [16] | **tool-full-text-verified**, PMC full text and Crossref | Peer-reviewed PNAS journal article, **5/5** | "Words categorize the semantic fields they refer to in ways that maximize communication accuracy while minimizing complexity." Supports discrete-channel efficiency in the tested color domain. |
| [17] | **tool-abstract-verified**, arXiv primary page/API | Peer-reviewed ICLR paper; journal score N/A | "Compositional Languages Emerge in a Neural Iterated Learning Model." Supports transmission bottlenecks. |
| [18] | **tool-metadata-verified**, Crossref DOI metadata | Peer-reviewed IEEE journal article, **4/5** | "Spontaneous evolution of linguistic structure: an iterated learning model of the emergence of regularity and irregularity." Establishes computational iterated learning. |
@@ -1522,8 +1662,8 @@ before submission.
| [23] | **tool-metadata-verified**, ACL Anthology | Peer-reviewed EMNLP paper; journal score N/A | "Emergent Linguistic Phenomena in Multi-Agent Communication Games." Supports community contact and protocol convergence. |
| [24] | **tool-abstract-verified**, arXiv primary page/API and venue comment | Peer-reviewed NeurIPS paper; journal score N/A | "Emergent Communication: Generalization and Overfitting in Lewis Games." Used as supporting, not sole, evidence. |
| [25] | **tool-metadata-verified**, arXiv primary page | Peer-reviewed ICLR paper; journal score N/A | "On the role of population heterogeneity in emergent communication." Supports heterogeneity effects. |
-| [26] | **tool-metadata-verified**, official journal page | Peer-reviewed journal article, **3/5** | "Learning and communication pressures in neural networks: Lessons from emergent communication." A field review with a newer/variable-impact venue. |
-| [27] | **tool-metadata-verified**, ACL Anthology | Peer-reviewed COLING paper; journal score N/A | "Searching for Structure: Investigating Emergent Communication with Large Language Models." Direct pretrained-LLM comparison. |
+| [26] | **tool-full-text-verified**, complete official paper | Peer-reviewed journal article, **3/5** | Reviews communicative success, production effort, learnability, and other pressures; official pagination is 116–140. |
+| [27] | **tool-full-text-verified**, complete ACL Anthology paper | Peer-reviewed COLING paper; journal score N/A | Directly studies artificial-language learning and transmission with pretrained language models. |
| [28] | **tool-abstract-verified**, arXiv page and TMLR record metadata | Peer-reviewed TMLR journal article, **4/5** | "A Review of the Applications of Deep Learning-Based Emergent Communication." Used as a field synthesis, not primary experiment. |
| [29] | **tool-abstract-verified**, arXiv primary page/API | Peer-reviewed ICLR paper; journal score N/A | "Emergent Communication through Negotiation." Supports incentive-sensitive communication. |
| [30] | **tool-metadata-verified**, Crossref/JSTOR metadata; full page blocked | Peer-reviewed Econometrica journal article, **5/5** | "Strategic Information Transmission." Supplies cheap-talk theory. |
@@ -1545,8 +1685,8 @@ before submission.
| [46] | **tool-full-text-verified**, CoLab publication page | Institutional report, not peer-reviewed; **1/5** under the fixed journal rubric | "What Is Ethical AI?" Used for CoLab governance commitments, not independent empirical evidence. |
| [47] | **tool-full-text-verified**, CoLab publication and source repository | Institutional research guidance, not peer-reviewed; **1/5** | "AI-Powered Assistance in Formulating Research Questions." Supplies the source-verification and AI-disclosure method. |
| [48] | **tool-metadata-verified**, arXiv primary page | Preprint, not peer-reviewed; journal score N/A | "Learning to Protect Communications with Adversarial Neural Cryptography." Motivates an exploratory synthetic-message experiment only. |
-| [49] | **tool-metadata-verified**, ACL Anthology | Peer-reviewed EMNLP demo paper; journal score N/A | "EGG: a toolkit for research on Emergence of lanGuage in Games." Closest infrastructure comparator. |
-| [50] | **tool-abstract-verified**, PMLR primary page | Peer-reviewed ICML paper; journal score N/A | "\"Other-Play\" for Zero-Shot Coordination." Supports novel-partner evaluation and specialized-convention risk. |
+| [49] | **tool-full-text-verified**, complete ACL Anthology paper | Peer-reviewed EMNLP demo paper; journal score N/A | Closest infrastructure comparator: modular games, channels, optimization, analysis, and checkpoints. |
+| [50] | **tool-full-text-verified**, complete PMLR paper | Peer-reviewed ICML paper; journal score N/A | Supports independently trained novel-partner evaluation and specialized-convention risk. |
No source in the table was silently upgraded from preprint or workshop status to a
peer-reviewed main-track result.
@@ -1607,9 +1747,9 @@ not assigned a journal score because the fixed rubric is explicitly journal-base
- Registration target: OSF Registries.
- The canonical registration JSON, this manuscript commit, analysis-script commit,
and generated seed manifest will be registered before execution.
-- The same `preRegistrationHash` will be anchored to Base Sepolia before any run
- enters `running`.
-- No outcome will be inspected before registration and anchoring complete.
+- The same `preRegistrationHash` will be committed through the deterministic
+ simulation transport before any run enters `running`.
+- No outcome will be inspected before registration and commitment complete.
### D.2 Objective
@@ -1678,43 +1818,49 @@ The unit of analysis is the run/seed success proportion across 200 episodes.
normal no-learning, perform two one-sided one-sample tests on seed-level success
proportions against equivalence bounds 0.20 and 0.30. Equivalence requires both
one-sided tests to reject at the Holm-adjusted alpha.
-2. **Oracle adequacy:** The lower bound of the two-sided 95% bootstrap confidence
- interval for mean seed-level oracle success must exceed 0.90.
+2. **Oracle adequacy:** A one-sided seed-level t test and its 95% lower confidence
+ bound must exceed 0.90. A two-sided 95% seed-bootstrap interval is reported as a
+ sensitivity estimate.
3. **Oracle separation:** For each non-oracle condition, compute paired seed-level
- oracle-minus-control differences. The lower bound of the Holm-adjusted 95%
- confidence interval must exceed 0.60.
+ oracle-minus-control differences. One-sided t-test p-values above 0.60 receive
+ Holm correction across the five conditions. Conservative 99% Bonferroni lower
+ bounds and nominal paired seed-bootstrap intervals are reported.
No episode is analyzed as an independent run.
### D.7 Sensitivity and Power
Before final registration, a separate outcome-blind-for-confirmatory-use pilot of 20
-seeds per non-oracle condition will estimate the largest between-seed standard
-deviation. Pilot runs will not enter confirmatory estimates. The registered primary
+seeds per non-oracle condition will fit the beta-binomial model and estimate the
+largest latent between-seed standard deviation after accounting for 200-episode
+sampling. Pilot runs will not enter confirmatory estimates. The registered primary
seed count is selected by this fixed rule:
-| Largest pilot SD | Primary seeds per condition |
+| Largest latent pilot SD | Primary seeds per condition |
|---:|---:|
| <= 0.05 | 25 |
| > 0.05 and <= 0.10 | 75 |
-| > 0.10 and <= 0.15 | 150 |
+| > 0.10 and <= 0.15 | 155 |
| > 0.15 and <= 0.20 | 300 |
| > 0.20 | New simulation and amended registration required before collection |
-A 30,000-replicate Monte Carlo design check was run for this draft under a true
-seed-level mean of 0.25, between-seed standard deviation of 0.10, 200 binomial
-episodes per seed, and conservative per-test alpha of 0.01. Estimated equivalence-test
-power was 0.924 at 75 seeds per condition. Sensitivity checks produced approximately
-0.912 power at SD 0.05 with 25 seeds, 0.920 at SD 0.15 with 150 seeds, and 0.913 at
-SD 0.20 with 300 seeds. Before registration, the simulation code and output must be
-checked in and independently rerun. Failure to reproduce at least 90% power blocks
+The original 30,000-replicate normal sufficient-statistic calculation is retained as
+a single-control equivalence component check. It is not the registration-facing
+power claim. Independent base-R simulation instead draws a bounded latent seed
+probability from a beta distribution and then 200 binary episodes, applies all five
+Holm-adjusted control TOSTs, the oracle adequacy test, and all five Holm-adjusted
+paired separation tests. With 10,000 repetitions per row, full numeric-rule power
+was 0.9318, 0.9308, 0.9163, and 0.9552 for the four rows; lower 95% Monte Carlo bounds
+were 0.9267, 0.9257, 0.9107, and 0.9510. Exact output is committed in
+`reports/research/statistical-validation.tsv` and independently replayed by
+`pnpm audit:statistics:r`. Failure to reproduce a lower bound of at least 0.90 blocks
registration; it does not permit post-hoc widening of the margin.
Sensitivity analyses:
- Wilson intervals over pooled episodes are descriptive only;
-- a hierarchical Bernoulli model with seed random intercept is reported as a
- robustness check;
+- a hierarchical Bernoulli model with seed random intercept and percentile bootstrap
+ intervals are reported as sensitivity checks;
- invalid primary runs are treated as failures in a worst-case sensitivity analysis.
### D.8 Exclusions, Invalid Runs, and Replacement
@@ -1741,8 +1887,9 @@ E03 qualifies the downstream chance baseline only if:
- all five non-oracle conditions meet equivalence;
- oracle adequacy and separation criteria pass;
-- no non-oracle condition has more than 5% of its primary seeds with observed success
- of 0.35 or greater; every such seed is individually audited for leakage;
+- every non-oracle primary seed with observed success of 0.35 or greater receives an
+ individually resolved leakage audit; the count is diagnostic and is not an
+ uncalibrated statistical rejection rule;
- all included evidence bundles pass verification;
- no unplanned metadata or channel leakage is detected.
diff --git a/SPECIFICATION.md b/SPECIFICATION.md
index bf9e28c..8a0e363 100644
--- a/SPECIFICATION.md
+++ b/SPECIFICATION.md
@@ -460,6 +460,12 @@ subject only to the linting rule in §6.4.
| `scratch-rl` | GRU or LSTM actor-critic, independent PPO-style update per Baby |
| `self-supervised` | Same backbone as `scratch-rl`, predictive/contrastive loss in place of a scalar reward |
| `hybrid` | From-scratch encoder + small recurrent world model + randomly initialized communication head |
+
+Every trainable adapter exports its exact policy immediately after initialization.
+The Nursery writes that policy under `policies/-policy-initial.json`, records
+its domain-separated `initialPolicyHash` in a `runtime-attestation` event, and
+includes that event in checkpoint 0's intervention auxiliary tree before the first
+turn. Per-Baby private seeds produce independent scratch-RL initial parameters.
| BabySitter narration | MAY use a larger reasoning model for audit summaries only; MUST NOT feed its output back into either Baby during a run (CONCEPT-IDEA.md §20.7) |
## 7. Run Lifecycle and State Machine
@@ -672,6 +678,15 @@ separation pattern) so that a repeated form can be recognized without assigning
a meaning. No grammar supplies a semantic tag; each only bounds what can be
physically expressed (resolves Q5 jointly with §18's variable registry).
+Offline carrier-leakage analysis uses the hash-bound
+`carrierLeakageProbePlan` from `RunConfig`. For every accepted observation it
+rebuilds the carrier-qualified `markHash`, records reuse and a bounded structural
+feature signature, and evaluates the pre-registered recognizable-glyph rate and
+feature/referent mutual-information bounds. Each probe reports `pass`, `fail`, or
+`inconclusive`; the evaluator never rewrites an artifact. Any result other than
+`pass` blocks an ungrounded-language claim, but has no effect on evidence-integrity
+validity and remains publishable as negative or integrity evidence.
+
### 9.3 Six-Display Affect Protocol
Disabled by default (`affectMode: "none"`); enabling it selects one of the five
@@ -874,6 +889,7 @@ interface RunConfig {
evaluationSeeds: number; // default 5 qualification / 10 publication
checkpointEventInterval: number; // default 64 (LEDGER-INTEGRITY-DESIGN.md §9)
checkpointTimeIntervalMs: number; // default 300000
+ anchorClass: "simulated" | "public-chain";
anchorNetwork: "base-sepolia" | "base-mainnet";
finalityPolicy: string; // default "1-confirmation" or "safe-tag"
prototypeRetentionDays: number; // default 30
@@ -882,6 +898,7 @@ interface RunConfig {
protocolGitCommit: string;
preRegistrationHash: string;
randomSeed: string;
+ carrierLeakageProbePlan?: { recognizableGlyph: { enabled: boolean; maximumRecognizableRate: number }; intendedCarrierFeatureUse: { enabled: boolean; minimumObservations: number } };
}
```
@@ -1053,7 +1070,8 @@ interface AffectEvent {
### 11.7 Checkpoint Manifest (Reference)
Normative shape is LEDGER-INTEGRITY-DESIGN.md §8, including its optional named
-`auxiliaryTrees` map for `affect` and `audit` roots. Every run manifest MUST
+`auxiliaryTrees` map for `affect`, `audit`, `turns`, and witness-committed
+unsigned `intervention` roots. Every run manifest MUST
additionally be reachable from an `ExperimentRecord` (§11.9) via
`checkpointManifestRef`.
@@ -1079,6 +1097,7 @@ interface ExperimentRecord {
checkpointManifestRef: string; // final checkpoint hash
anchorTxRef: string; // Base transaction hash
verifierReportRef: string;
+ analysisAttachmentRefs?: string[]; // hashes in analysis/index.json
claimBoundaryStatement: string; // verbatim §5.1/§5.2 sentence
deviations: string[]; // pointers into EXPERIMENT-NOTEBOOK.md §9
}
@@ -1268,16 +1287,23 @@ LEDGER-INTEGRITY-DESIGN.md §4, §7, and §8 exactly, including for the new
and its own Merkle root, included in the checkpoint manifest as additional named
trees alongside `babyA`/`babyB`/`channel`).
-### 13.4 Base Sepolia / Mainnet Anchoring Policy
+### 13.4 Simulated and Optional Public-Chain Anchoring Policy
-Unchanged from LEDGER-INTEGRITY-DESIGN.md §10: Base Sepolia for development and
-qualification (E00); Base mainnet for declared public research runs; only the
-32-byte checkpoint hash and minimal routing metadata are ever public. Finality
-policy default: Sepolia — 1 confirmation for development iteration; mainnet — wait
-for the `safe` block tag (or equivalent finality/confirmation-depth policy the
-chosen RPC provider exposes) before a checkpoint is reported as anchored-final in
-the notebook (resolves part of Q28; provider-specific finality-tag naming is
-deferred, §19).
+The approved research profile is simulation-only. Every prospective campaign run
+MUST declare `anchorClass: "simulated"` and use the deterministic in-memory
+transport. Its Base-shaped network, transaction, block, and confirmation values are
+non-monetary test data and MUST NOT be described as public-chain publication,
+economic finality, or incurred cost. The exact `anchorClass` is bound into the run
+configuration, pending-submission record, anchor receipt, pre-registration binding,
+and verifier checks so a simulated receipt cannot be silently relabeled.
+
+Base Sepolia and Base mainnet remain optional transport capabilities inherited from
+LEDGER-INTEGRITY-DESIGN.md §10. Any real-chain operation MUST instead declare
+`anchorClass: "public-chain"`; only the 32-byte checkpoint hash and minimal routing
+metadata may be public. Public-chain operation is outside the currently approved
+research profile and requires a new prospective governance amendment. If amended,
+Sepolia waits for at least one confirmation and mainnet waits for the `safe` block
+tag or an equivalent provider-specific policy before reporting anchored-final.
### 13.5 Key Management
@@ -1300,7 +1326,13 @@ architecture MUST NOT expose any Baby-reachable API for reading
`audit_ledger_entries`, enforced by the same role model as §12.2 (only
`researcher-viewer`/`researcher-operator`/`verifier-service` may read it). Every
generated interpretation is labeled `source: "generated-analysis"` and MUST NOT be
-represented, in any report, as the Baby's own explanation.
+represented, in any report, as the Baby's own explanation. The reference
+implementation validates every `sourceEntryHash` against the named Baby's signed
+native stream, waits until at least one later turn is fully complete, validates the
+whole submitted batch before its first append, and creates an `analysis` checkpoint
+after the batch. The Interpreter has no adapter or Gateway dependency, so no
+generated interpretation can be delivered back to a Baby as observation, outcome,
+message, or ledger feedback.
## 14. Telemetry, Audit, Reproducibility, Snapshot/Restore, Failure Handling, Retention
@@ -1400,11 +1432,17 @@ A run MAY NOT enter `preregistered` (§7.1) until:
LEDGER-INTEGRITY-DESIGN.md).
For a confirmatory or publication-facing run, the canonical pre-registration
-artifact MUST also be registered with an external timestamping/registration service
-(OSF Registries is the default) and its `preRegistrationHash` MUST be anchored before
-the run enters `running`. The external registration URL and pre-run anchor receipt
-are included in the run manifest. Qualification-only development runs MAY use a
-Base-Sepolia pre-run anchor without OSF, but MUST be labeled non-confirmatory.
+artifact MUST be committed unchanged in the repository before outcome collection.
+Its binding records the packet path, canonical hash, commit, and commit time; the
+registration commit MUST be ancestral to the execution commit, and preflight MUST
+load the artifact bytes from that commit and reproduce the registered hash. The same
+`preRegistrationHash` MUST be committed before the run enters `running`. Under the
+approved simulation-only profile, that receipt MUST declare
+`anchorClass: "simulated"`; the deterministic receipt proves exact local consumption
+and tamper detection. An external registration or archival timestamp MAY be added
+as an independently hosted enhancement but is not required for local synthetic
+execution. Repository-native registration does not prove an independent timestamp,
+third-party custody, decentralized persistence, or economic finality.
The run's `ExperimentRecord.disposition` and the matching EXPERIMENT-NOTEBOOK.md
run record MUST agree; the Verifier's `VerificationReport` is authoritative for
@@ -1467,6 +1505,9 @@ NOT change the third field. Learned encodings MUST NOT be imported into the prod
hashing, signing, anchoring, authentication, or key-management packages. This
formalizes Q17 and the `cipherThreatModel` variable in §18.
+The mandatory repository boundary and E40 review gate are specified in
+[`docs/cryptographic-separation-policy.md`](docs/cryptographic-separation-policy.md).
+
### 15.5 Traceability to Experiment Notebook
See §17.4 for the full E00-E50 traceability table. Every experiment section in
@@ -1608,7 +1649,8 @@ defaulted, pre-registerable configuration variable, not an open question:
| `maxConsecutiveRejections` | `5` | ≥ 1 | Q6 |
| `checkpointEventInterval` | `64` | ≥ 1 | Q28 |
| `checkpointTimeIntervalMs` | `300000` | ≥ 1000 | Q28 |
-| `anchorNetwork` | `base-sepolia` (dev), `base-mainnet` (public) | per LEDGER doc §10 | Q28 |
+| `anchorClass` | `simulated` | `simulated`, `public-chain` | approved simulation-funded profile; a public-chain value requires amendment |
+| `anchorNetwork` | `base-sepolia` (emulated by default), `base-mainnet` (optional capability) | per LEDGER doc §10 | Q28 |
| `finalityPolicy` | `1-confirmation` (Sepolia), `safe-tag` (mainnet) | provider-dependent | Q28 (partially deferred, §19) |
| `interactionMode` | `cooperative-signaling` | `cooperative-signaling`, `asymmetric-information`, `semi-cooperative-negotiation`, `conflicting-negotiation`, `no-agreement-control` | Q19 |
| `cipherThreatModel` | `post-run-disclosure` | `post-run-disclosure`, `external-observer-only`, `novelty-only` | Q16, Q18 |
diff --git a/book/__tests__/research-book.test.ts b/book/__tests__/research-book.test.ts
index 7d12372..799a348 100644
--- a/book/__tests__/research-book.test.ts
+++ b/book/__tests__/research-book.test.ts
@@ -31,7 +31,12 @@ describe('research page-turn book', () => {
expect(manifest.aspect).toBeCloseTo(0.7727, 4);
expect(manifest.sourceSha256).toBe(
createHash('sha256')
- .update(await readFile(join(root, 'RESEARCH.md'), 'utf8'))
+ .update(
+ (await readFile(join(root, 'RESEARCH.md'), 'utf8')).replace(
+ /\r\n?/gu,
+ '\n',
+ ),
+ )
.digest('hex'),
);
diff --git a/book/pages/manifest.json b/book/pages/manifest.json
index 26ee019..849936d 100644
--- a/book/pages/manifest.json
+++ b/book/pages/manifest.json
@@ -1,6 +1,6 @@
{
"generatedFrom": "research.pdf",
- "pageCount": 49,
+ "pageCount": 51,
"aspect": 0.7727,
"pages": [
"pages/p01.webp",
@@ -51,8 +51,10 @@
"pages/p46.webp",
"pages/p47.webp",
"pages/p48.webp",
- "pages/p49.webp"
+ "pages/p49.webp",
+ "pages/p50.webp",
+ "pages/p51.webp"
],
"source": "RESEARCH.md",
- "sourceSha256": "dd88ca6f47e1d57c482620da036247e9ef437764b6f53ebceef72ff8c9b2eae5"
+ "sourceSha256": "921d297032002868c729a97f5d871a6c3e8e203fd0fe683f5cc4517820d8f7c3"
}
diff --git a/book/pages/p01.webp b/book/pages/p01.webp
index 8f6ed61..0f180ca 100644
Binary files a/book/pages/p01.webp and b/book/pages/p01.webp differ
diff --git a/book/pages/p02.webp b/book/pages/p02.webp
index 49aee10..9213bbb 100644
Binary files a/book/pages/p02.webp and b/book/pages/p02.webp differ
diff --git a/book/pages/p03.webp b/book/pages/p03.webp
index 61ea938..f17b269 100644
Binary files a/book/pages/p03.webp and b/book/pages/p03.webp differ
diff --git a/book/pages/p04.webp b/book/pages/p04.webp
index d50ee6c..3d03dd2 100644
Binary files a/book/pages/p04.webp and b/book/pages/p04.webp differ
diff --git a/book/pages/p05.webp b/book/pages/p05.webp
index e44a6dc..b82ccc2 100644
Binary files a/book/pages/p05.webp and b/book/pages/p05.webp differ
diff --git a/book/pages/p06.webp b/book/pages/p06.webp
index 1c53d0b..d4a3418 100644
Binary files a/book/pages/p06.webp and b/book/pages/p06.webp differ
diff --git a/book/pages/p07.webp b/book/pages/p07.webp
index 7a312e4..b1665fb 100644
Binary files a/book/pages/p07.webp and b/book/pages/p07.webp differ
diff --git a/book/pages/p08.webp b/book/pages/p08.webp
index 2609492..99306d4 100644
Binary files a/book/pages/p08.webp and b/book/pages/p08.webp differ
diff --git a/book/pages/p09.webp b/book/pages/p09.webp
index 47f8303..cfba01e 100644
Binary files a/book/pages/p09.webp and b/book/pages/p09.webp differ
diff --git a/book/pages/p10.webp b/book/pages/p10.webp
index 1a3bf57..9410e6d 100644
Binary files a/book/pages/p10.webp and b/book/pages/p10.webp differ
diff --git a/book/pages/p11.webp b/book/pages/p11.webp
index 158cacc..19b5f87 100644
Binary files a/book/pages/p11.webp and b/book/pages/p11.webp differ
diff --git a/book/pages/p12.webp b/book/pages/p12.webp
index 7f11d66..a3536d1 100644
Binary files a/book/pages/p12.webp and b/book/pages/p12.webp differ
diff --git a/book/pages/p13.webp b/book/pages/p13.webp
index c9f7efd..875c9c6 100644
Binary files a/book/pages/p13.webp and b/book/pages/p13.webp differ
diff --git a/book/pages/p14.webp b/book/pages/p14.webp
index 47012ec..33e3248 100644
Binary files a/book/pages/p14.webp and b/book/pages/p14.webp differ
diff --git a/book/pages/p15.webp b/book/pages/p15.webp
index c09cbb4..393c065 100644
Binary files a/book/pages/p15.webp and b/book/pages/p15.webp differ
diff --git a/book/pages/p16.webp b/book/pages/p16.webp
index 1daa6fb..23568e9 100644
Binary files a/book/pages/p16.webp and b/book/pages/p16.webp differ
diff --git a/book/pages/p17.webp b/book/pages/p17.webp
index e0db6bd..52f1595 100644
Binary files a/book/pages/p17.webp and b/book/pages/p17.webp differ
diff --git a/book/pages/p18.webp b/book/pages/p18.webp
index e15982e..1a8caaf 100644
Binary files a/book/pages/p18.webp and b/book/pages/p18.webp differ
diff --git a/book/pages/p19.webp b/book/pages/p19.webp
index 3bf9e4f..2ecf26b 100644
Binary files a/book/pages/p19.webp and b/book/pages/p19.webp differ
diff --git a/book/pages/p20.webp b/book/pages/p20.webp
index 2be74ca..8be9808 100644
Binary files a/book/pages/p20.webp and b/book/pages/p20.webp differ
diff --git a/book/pages/p21.webp b/book/pages/p21.webp
index eb58948..0108598 100644
Binary files a/book/pages/p21.webp and b/book/pages/p21.webp differ
diff --git a/book/pages/p22.webp b/book/pages/p22.webp
index 98a3c34..d108b04 100644
Binary files a/book/pages/p22.webp and b/book/pages/p22.webp differ
diff --git a/book/pages/p23.webp b/book/pages/p23.webp
index dc66140..3a3c86e 100644
Binary files a/book/pages/p23.webp and b/book/pages/p23.webp differ
diff --git a/book/pages/p24.webp b/book/pages/p24.webp
index a368589..4feaa1b 100644
Binary files a/book/pages/p24.webp and b/book/pages/p24.webp differ
diff --git a/book/pages/p25.webp b/book/pages/p25.webp
index 9e0cc8e..3470858 100644
Binary files a/book/pages/p25.webp and b/book/pages/p25.webp differ
diff --git a/book/pages/p26.webp b/book/pages/p26.webp
index fe48d12..88045ab 100644
Binary files a/book/pages/p26.webp and b/book/pages/p26.webp differ
diff --git a/book/pages/p27.webp b/book/pages/p27.webp
index 1504ede..32f85be 100644
Binary files a/book/pages/p27.webp and b/book/pages/p27.webp differ
diff --git a/book/pages/p28.webp b/book/pages/p28.webp
index 07d22ad..d3659cd 100644
Binary files a/book/pages/p28.webp and b/book/pages/p28.webp differ
diff --git a/book/pages/p29.webp b/book/pages/p29.webp
index 16a8737..21928e1 100644
Binary files a/book/pages/p29.webp and b/book/pages/p29.webp differ
diff --git a/book/pages/p30.webp b/book/pages/p30.webp
index ba4283f..c0cb24f 100644
Binary files a/book/pages/p30.webp and b/book/pages/p30.webp differ
diff --git a/book/pages/p31.webp b/book/pages/p31.webp
index c7bbcc6..e0c535b 100644
Binary files a/book/pages/p31.webp and b/book/pages/p31.webp differ
diff --git a/book/pages/p32.webp b/book/pages/p32.webp
index 34b569d..e7c638b 100644
Binary files a/book/pages/p32.webp and b/book/pages/p32.webp differ
diff --git a/book/pages/p33.webp b/book/pages/p33.webp
index e852c7d..e1a5009 100644
Binary files a/book/pages/p33.webp and b/book/pages/p33.webp differ
diff --git a/book/pages/p34.webp b/book/pages/p34.webp
index 3373e91..26b7a4e 100644
Binary files a/book/pages/p34.webp and b/book/pages/p34.webp differ
diff --git a/book/pages/p35.webp b/book/pages/p35.webp
index 3c994f7..028da15 100644
Binary files a/book/pages/p35.webp and b/book/pages/p35.webp differ
diff --git a/book/pages/p36.webp b/book/pages/p36.webp
index c464d39..f86ae77 100644
Binary files a/book/pages/p36.webp and b/book/pages/p36.webp differ
diff --git a/book/pages/p37.webp b/book/pages/p37.webp
index b599880..44163bc 100644
Binary files a/book/pages/p37.webp and b/book/pages/p37.webp differ
diff --git a/book/pages/p38.webp b/book/pages/p38.webp
index 1342e28..1193606 100644
Binary files a/book/pages/p38.webp and b/book/pages/p38.webp differ
diff --git a/book/pages/p39.webp b/book/pages/p39.webp
index ac911be..67282ec 100644
Binary files a/book/pages/p39.webp and b/book/pages/p39.webp differ
diff --git a/book/pages/p40.webp b/book/pages/p40.webp
index 8190589..14afcbd 100644
Binary files a/book/pages/p40.webp and b/book/pages/p40.webp differ
diff --git a/book/pages/p41.webp b/book/pages/p41.webp
index 7ecb411..5837a4f 100644
Binary files a/book/pages/p41.webp and b/book/pages/p41.webp differ
diff --git a/book/pages/p42.webp b/book/pages/p42.webp
index 829e39c..4835def 100644
Binary files a/book/pages/p42.webp and b/book/pages/p42.webp differ
diff --git a/book/pages/p43.webp b/book/pages/p43.webp
index d4c9bf7..d905d57 100644
Binary files a/book/pages/p43.webp and b/book/pages/p43.webp differ
diff --git a/book/pages/p44.webp b/book/pages/p44.webp
index 083c84c..cf97a31 100644
Binary files a/book/pages/p44.webp and b/book/pages/p44.webp differ
diff --git a/book/pages/p45.webp b/book/pages/p45.webp
index b339ca2..ed45cd6 100644
Binary files a/book/pages/p45.webp and b/book/pages/p45.webp differ
diff --git a/book/pages/p46.webp b/book/pages/p46.webp
index 046069c..cc0b8c4 100644
Binary files a/book/pages/p46.webp and b/book/pages/p46.webp differ
diff --git a/book/pages/p47.webp b/book/pages/p47.webp
index 91ba774..c0ea2fa 100644
Binary files a/book/pages/p47.webp and b/book/pages/p47.webp differ
diff --git a/book/pages/p48.webp b/book/pages/p48.webp
index cfc6059..b21a458 100644
Binary files a/book/pages/p48.webp and b/book/pages/p48.webp differ
diff --git a/book/pages/p49.webp b/book/pages/p49.webp
index e823d75..e864611 100644
Binary files a/book/pages/p49.webp and b/book/pages/p49.webp differ
diff --git a/book/pages/p50.webp b/book/pages/p50.webp
new file mode 100644
index 0000000..3a48acb
Binary files /dev/null and b/book/pages/p50.webp differ
diff --git a/book/pages/p51.webp b/book/pages/p51.webp
new file mode 100644
index 0000000..e07de18
Binary files /dev/null and b/book/pages/p51.webp differ
diff --git a/book/research-print.html b/book/research-print.html
index c04b331..c76506d 100644
--- a/book/research-print.html
+++ b/book/research-print.html
@@ -50,7 +50,11 @@
p, li { orphans: 3; widows: 3; }
p { margin: 0 0 0.11in; }
ul, ol { margin: 0.04in 0 0.13in; padding-left: 0.24in; }
- li { margin: 0 0 0.035in; }
+ li {
+ margin: 0 0 0.035in;
+ break-inside: avoid;
+ page-break-inside: avoid;
+ }
blockquote {
margin: 0.13in 0;
padding: 0.11in 0.16in;
@@ -99,33 +103,21 @@
border-top: 0.5pt solid #c6d1df;
}
img { max-width: 100%; break-inside: avoid; }
- .running-footer {
- position: fixed;
- right: 0;
- bottom: -0.46in;
- left: 0;
- color: #778399;
- font-family: "Segoe UI", Arial, sans-serif;
- font-size: 7pt;
- text-align: center;
- }
-
Auditable Emergent Communication Between Isolated Artificial Agents
A Preregistrable Study Protocol for Comparing Learning, Grounding, and Protocol Formation
Document type: Working academic manuscript and pre-results study protocol
Status: Draft for research execution; not yet ready for arXiv submission
Prepared: September 2, 2026
+Engineering snapshot: v0.1.97 · 254/258 backlog acceptance criteria verified.
Proposed arXiv category: cs.MA (primary), with possible cross-listing to
cs.AI and cs.CL
-Authors: Ethical Tech CoLab; individual author order, affiliations, ORCID
-identifiers, and corresponding author to be finalized before submission
-Repository: https://github.com/Ethical-Tech-CoLab/agentic-language-development
+Authors: Anonymous working draft; author order, affiliations, ORCID identifiers,
+and corresponding author are omitted until the authorized submission stage
+Artifact: Anonymous review artifact to be prepared only after release approval
Empirical status: No Nursery Lab experiment has been reported as completed in
this manuscript. Sections 10 and 11 distinguish implemented infrastructure from
planned empirical work. No table contains an observed empirical result.
@@ -147,9 +139,11 @@ Abstract
hybrid models, and no-learning controls under common scenario, channel, evidence, and
evaluation interfaces. Each agent is specified to maintain an independent chronological ledger of its own
intentions and interpretations. The framework specifies append-only, hash-chained,
-signed ledger and channel records, ordered Merkle checkpoints, and periodic
-public-chain checkpoint anchoring. These mechanisms are not yet fully implemented and
-do not prove that an agent's interpretation is truthful; they are designed to preserve
+signed ledger and channel records, ordered Merkle checkpoints, and deterministic
+simulated commitments. The local integrity, checkpoint, verifier, and commitment
+paths are implemented and tested under a zero-external-spend profile. Optional
+public-chain transport remains outside the approved campaign and its claims. These
+mechanisms do not prove that an agent's interpretation is truthful; they are designed to preserve
what was recorded and make later alteration detectable. Causal message interventions, held-out generalization, partner
replacement, leakage tests, and control-channel conditions are therefore required in
addition to task success.
@@ -175,7 +169,10 @@ Research Integrity Notice
AI-suggested connections are treated as exploratory until supported;
the influence and limitations of AI assistance are disclosed;
source verification state and journal credibility are recorded in Appendix A;
-a separate critical-review pass is required before publication.
+a separate critical-review pass is required before publication; the current
+internal pass is recorded in
+reports/research/research-critical-review.md
+and does not count as independent review.
In this draft, source retrieval and the first verification pass were performed by an
AI assistant using web, scholarly-index, and metadata tools, followed by separate AI
@@ -322,8 +319,8 @@
2.2 Confirmatory Hypotheses
| H4 |
-Ledger-predicted intervention directions will exceed a pre-registered chance baseline. |
-Ledger agreement is at chance or fails out-of-sample. |
+On untouched intervention cases, pre-outcome ledger predictions will improve a pre-registered proper prediction score beyond the strongest eligible transcript-only, task-history, policy-state, random, and majority baseline. |
+The ledger fails to exceed the strongest eligible non-ledger baseline by the registered practical threshold. |
| H5 |
@@ -338,7 +335,7 @@ 2.2 Confirmatory Hypotheses
| H6b |
Under fixed windows and cardinality, permutation-calibrated excess conditional mutual information between affect and referent will remain below the pre-registered 0.02-bit practical-leakage bound. |
-The seed-bootstrap upper-bound test cannot rule out excess leakage of 0.02 bits or more. |
+The seed-level one-sided Student-t upper-bound test cannot rule out excess leakage of 0.02 bits or more. |
| H7 |
@@ -742,6 +739,21 @@ 6.4 Scenario Families
Researcher ground truth may contain semantic labels; learner observations may not.
Observations use opaque numeric arrays, pixels, or separately qualified hybrid
features. Images containing OCR-detectable text are quarantined before a run.
+The initial numeric referential design contains 16 two-attribute combinations. The
+four equal-attribute diagonal combinations are the locked compositional test targets;
+the remaining 12 combinations are the shared semantic support for training and
+in-distribution validation. Training and validation use independent PRNG domains,
+and no held-out type may occur in either split as a target or distractor. Validation
+is learning-off and may be used for tuning and baseline selection. The held-out split
+is learning-off and is accessed once after those choices freeze. The broader
+evaluation split remains an engineering and software-qualification surface and is
+not interchangeable with the confirmatory held-out test.
+The versioned split, duplicate rules, matched budget dimensions, and boundaries
+between within-architecture causal contrasts and cross-architecture descriptive
+benchmarks are frozen in
+protocols/scenario-split-and-model-comparison.v1.json
+and explained in
+docs/scenario-splits-and-model-comparisons.md.
6.5 Communication Conditions
For the baseline fixed-token carrier, each run declares a random inventory such as
S01-S32 without assigned meaning. The gateway supports six control conditions:
@@ -847,7 +859,7 @@ 7.1 Outcome Hierarchy
- held-out task success relative to E03 controls;
- positive listening under message intervention;
-- ledger-predicted intervention agreement;
+- ledger incremental predictive value on untouched interventions;
- held-out compositional generalization.
Secondary outcomes
@@ -871,7 +883,11 @@ 7.2 Operational Definitions
distributions to change while the receiver observation is held fixed.
Ledger agreement: the direction of an observed intervention effect matches the
direction predicted from the learner's ledger before intervention outcomes are
-revealed.
+revealed. This is a descriptive calibration measure, not H4's confirmatory estimand.
+Ledger incremental value: held-out improvement in a pre-registered proper
+prediction score over the strongest eligible transcript-only, task-history,
+policy-state, random, and majority baseline. Predictions are committed before the
+intervention outcome is generated.
Compositional generalization: reusable subparts support above-control success on
pre-registered unseen combinations with learning disabled.
Leakage: information about hidden referent or task state is recoverable from a
@@ -880,15 +896,20 @@
7.2 Operational Definitions
the same training seed. The H7 estimand is fixed-dyad degradation minus the
equal-weight eight-partner-training degradation.
7.3 Statistical Plan
-The final analysis plan will be frozen before confirmatory runs.
+The common analysis and multiplicity rules are frozen in
+protocols/statistical-analysis-and-power.v1.json.
+Experiment-specific raw-scale practical margins and seed allocations will be frozen
+after disjoint pilots and before confirmatory runs.
-- Alpha is
0.05 for each experiment's primary family.
-- Holm-Bonferroni correction is applied across primary metrics within an experiment.
-- The confirmatory study family is restricted to H1-H8, including H6a and H6b.
-Hierarchical gatekeeping tests qualification first, then core emergence, then later
-affect/transfer/negotiation hypotheses; a blocked family is reported descriptively.
-Exploratory analyses use false-discovery-rate reporting and remain labeled
-exploratory.
+- The confirmatory study family contains nine members: H1, H2, H3, H4, H5, H6a,
+H6b, H7, and H8. One pre-registered p-value is formed per member and Holm correction
+is applied globally at family-wise alpha 0.05. Multi-component directional members
+use the maximum component p-value and require every registered direction and
+practical threshold.
+- E00-E03 and experiment-specific checks are validity gates, not sources of reusable
+alpha. A failed or missing gate produces
not-tested, not a favorable or
+unfavorable p-value. Exploratory analyses use false-discovery-rate reporting and
+remain labeled exploratory.
- Effect sizes and confidence or credible intervals are reported with every
significance test.
- Binary task outcomes are modeled at the run/seed level, with episodes treated as
@@ -910,11 +931,45 @@
7.3 Statistical Plan
Before empirical submission, simulation-based power analysis will determine the
required number of independent seeds for each primary contrast; the larger value
governs.
+Independent base-R validation agrees with the production special functions and
+seed-level tests, demonstrates calibrated boundary behavior, and shows why pooled
+episode inference is prohibited. The complete E03 numeric decision has a lower 95%
+Monte Carlo power bound above 0.90 in all four planned variance rows. A nine-member
+Holm sensitivity shows that 75 seeds is not generally sufficient: at standardized
+effect 0.40, all-member power is 0.6752 at N=75 and 0.9068 at N=100. These values are
+design evidence rather than universal sample sizes; D07 applies the registered
+member-specific rule. Full methods and Monte Carlo intervals are in
+docs/statistical-validation-and-power.md.
Claims that a control is "at chance" or that leakage is absent use equivalence or
upper-bound tests, not failure to reject a difference. Each pre-registration must
state the smallest effect of interest, the equivalence margin, and power to rule out
that margin. The worked E03 design in Appendix D uses a +/-0.05 success-rate margin;
H6b uses a 0.02-bit conditional-mutual-information bound.
+The outcome-blind causal-ledger and leakage rules are frozen in
+protocols/causal-ledger-and-leakage.v1.json.
+For E02, at least 200 untouched test rows are required and the one-sided 95%
+Wilson upper bound on linear-probe accuracy advantage over the held-out majority
+baseline must be at most 0.10. The identical probe and split must detect an injected
+one-hot target feature with a lower advantage bound of at least 0.20. For E20, 75
+eligible seeds and 1,000 windows per seed are required before a decision; the primary
+bound is seed-level Student-t and the percentile bootstrap is sensitivity-only.
+Allowed and forbidden information sets and detector-positive controls are explicit
+for E01, E02, E13, and E20. Intended normalized carrier form is communication, not a
+side channel.
+Seed and resource allocation is frozen in
+protocols/seed-and-resource-allocation.v1.json.
+Qualification, blinded-pilot, confirmatory, and replication stages use disjoint
+SHA-256 domains; paired conditions share scenario seeds but not learner, Gateway, or
+analysis seeds. A 20-slot blinded pilot selects the smallest shared candidate N whose
+complete nine-member Holm-family simulation has a lower 95% Monte Carlo power bound
+of at least 0.90. N=100 is a planning value, not a selected result.
+A fresh 260-turn recurrent-carrier benchmark took 37.58 seconds and wrote 25.53 MB.
+At that measured uncompressed rate, maximum materialized pools including replication
+project to 9,171 bundles, 9.36 million turns, 855.9 GiB, and 375.7 single-core hours.
+The present local ceiling is 72 CPU-hours, 25 GiB, one frozen-model process, and zero
+external spend. It supports bounded qualification and pilots, not the full campaign;
+confirmatory registration requires an exact selected prefix and an approved execution
+resource plan.
Run exclusions are limited to pre-specified integrity or protocol failures. Each
condition receives a fixed ordered list of primary and reserve seeds before outcomes
are observed. An invalid primary seed may be replaced only by the next reserve seed;
@@ -941,15 +996,19 @@
7.5 Qualitative Analysis
- abrupt convention changes;
- negotiation-era semantic shifts.
-Human coders will use a pre-registered codebook and, where feasible, blinded
-independent coding. Generated audit interpretations will not be treated as ground
-truth.
+The approved initial campaign uses no human-coded outcome. Qualitative labels are
+generated by registered deterministic analysis and are not treated as ground truth.
+Any later human-coding proposal requires a prospective protocol and governance
+amendment before collection.
8. Evidence Integrity and Reproducibility
-Design status: This section describes required evidence behavior. Hash-chain
-writing, signatures, Merkle checkpoints, anchoring, and the independent verifier are
-not yet complete; see Section 10.
+Implementation status: Local hash-chain writing, domain-separated signatures,
+ordered-Merkle checkpoints and proofs, anchor publisher transports, evidence export,
+and the standalone verifier are implemented and covered by software tests. The
+approved campaign uses deterministic simulated receipts and no real funds; no
+public-chain receipt is claimed, and the historical research
+corpus remains unregistered and unanchored; see Section 10.
8.1 Append-Only Evidence
The specified evidence system requires every learner ledger and channel transcript
@@ -965,13 +1024,16 @@
8.2 Checkpoints
Signed checkpoint manifests will bind the event roots to run configuration, learner
contract, software commit, and previous checkpoint.
-8.3 External Anchoring
-Development qualification is specified to use Base Sepolia. Declared public studies may anchor
-checkpoint hashes to Base mainnet. Only hashes and minimal routing metadata are
-on-chain. Private observations, messages, ledgers, prompts, identities, and keys
-remain off-chain.
-The anchor proves that a committed prefix existed no later than a chain block and
-that disclosed content matches the commitment. It does not prove:
+8.3 Simulated Commitments and Optional External Anchoring
+The prospective campaign uses a deterministic in-memory transport, a non-monetary
+simulated balance, and receipts labeled anchorClass: "simulated". Base Sepolia and
+Base mainnet remain optional software capabilities outside the approved study. A
+future public-chain activation would require a new prospective amendment; only hashes
+and minimal routing metadata could be placed on-chain.
+The simulated commitment proves that the executed bundle consumed a specific
+committed prefix and that disclosed content matches it. Together with the external
+registration timestamp and immutable Git commit, it preserves prospective order. It
+does not prove public availability, decentralized persistence, economic finality, or:
- an event was true;
- no event was omitted before commitment;
@@ -993,15 +1055,16 @@ 8.4 Independent Verification
- cross-bindings among intention, message, delivery, interpretation, and outcome;
- Merkle roots, inclusion proofs, and consistency proofs;
- checkpoint chains and witness signatures;
-- public-chain transaction, chain ID, block inclusion, and finality;
+- receipt class, transaction-shaped identifier, chain identity, block inclusion, and finality semantics;
- forks, gaps, and unanchored tails.
Any integrity failure prevents a run from receiving a valid disposition.
Here, independent verifier means software that recomputes evidence from an exported
bundle without trusting the live runtime, database, or private keys. For a
publication-facing claim, at least one verification execution must additionally be
-performed by a person who did not operate the original run, using an independently
-configured chain RPC. External replication remains stronger than either form.
+performed by a person who did not operate the original run, using the independent
+offline verifier. An independent RPC is additionally required only for a future
+public-chain receipt. External replication remains stronger than either form.
8.5 Replay
Scenario replay reconstructs scenario and observation hashes from the recorded seed.
Deterministic adapters additionally reconstruct a replay digest over scenario,
@@ -1065,30 +1128,81 @@
9.5 Dual-Use Concerns
as separate fields.
10. Current Implementation Status
-As of September 2, 2026, the repository records ALD-001 through ALD-007 as complete.
-This is engineering status, not an empirical result.
+Engineering snapshot: v0.1.97 · 254/258 backlog acceptance criteria verified.
+As of September 12, 2026, 82 of 86 backlog items satisfy all of their acceptance
+criteria. This is engineering status, not an empirical result.
Implemented:
-- npm/TypeScript workspaces;
-- runtime-validated shared schemas;
-- typed configuration and secret scanning;
-- DTSF-compatible Learner A, Learner B, and Nursery twin-pack scaffolds;
-- SQLite WAL evidence schema and append-only triggers;
-- RFC 8785 canonical serialization;
-- ledger event-type validators;
-- automated lint, build, test, dependency-audit, and clean-clone checks.
+- hash-chained, signed SQLite evidence; ordered Merkle checkpoints; exact bundle
+export; and an independent verifier;
+- a frozen local audit-cost protocol and receipt covering five immutable
+qualification bundles, with ordinary-log, signed-stream, integrity-structure,
+policy-state, and complete-bundle storage separated; descriptive offline verifier
+timing and the prior six-case mutation challenge are reported without claiming a
+public anchor or an empirical result;
+- an E16 comparator pipeline that fits all five eligible non-ledger predictors on a
+validation-fit fold, selects by Brier score on a disjoint validation-selection
+fold, refits and hash-locks the selected model, commits baseline and native-ledger
+predictions before accepting test outcomes, and keeps the oracle diagnostic
+ineligible for selection; exact synthetic qualification passed five comparator and
+seven negative-control paths; the production runtime now invokes an injected
+outcome-blind native predictor after Gateway delivery and before receiver action,
+commits and checkpoints baseline/native predictions, derives the receiver choice
+from its hash-bound turn record, and binds per-turn post-outcome scores; the hashed
+run configuration commits the selection and prediction-function identities and
+accepted-evaluation-delivery eligibility, and recovery refuses an absent or
+mismatched provider; exact detached qualification passed 10 focused tests and the
+full 1,808-test repository gate;
+- a general fail-closed registration-packet compiler requiring eleven exact binding
+classes; the current all-experiment inventory resolves only the 19 protocol cards,
+leaves 170 experiment-specific bindings open, and emits E00 and E01 registration hashes;
+- grammar-valid bitmap, translation-tolerant canvas, and graded tone distances with
+deterministic nearest-prototype evaluation; this is a handcrafted E13 diagnostic,
+not evidence that a learner learned the metric or generalized to novel forms; an
+exact clean-candidate qualification covers three carriers and six rejection paths;
+- a Base-shaped commitment client with confirmation/recovery handling, explicit
+simulated/public receipt classification, and mainnet gating; the verifier rejects
+a simulated receipt relabeled as public-chain evidence;
+- an authenticated Fort boundary that stores the project signer envelope and unused
+optional public-chain credentials only as encrypted Safe material; a four-track
+files-mode Mode R run sealed and production-verified every bounded qualification
+bundle; the zero-balance public address remains inactive and is not needed by the
+simulation-funded campaign;
+- deterministic scenarios, the tool-only Gateway, all declared carrier controls,
+five learner tracks, DTSF twin routes, and the complete turn lifecycle;
+- process/container Mode R isolation, training separation, active side-channel and
+observation red teams, including a reusable 28-case generated-carrier structural
+side-feature audit with accepted controls and fail-closed evidence readiness; the
+exact candidate also passed the current two-container Mode R timing, fixed-envelope,
+error-shape, host-denial, crash-survival, and three-track update checks; plus
+telemetry, retention, snapshot/restore, and failure policy;
+- readiness gates for E00-E50, reproducible E03 design and seed artifacts, canonical
+E03 registration compilation, and a fail-closed confirmatory preflight;
+- a privacy-minimized real-model software qualification of Qwen3-4B Q4_K_M through
+llama.cpp, with exact model/runtime hashes and both role directions exercised; and
+- automated lint, build, test, dependency-audit, secret-scan, acceptance-coverage,
+API-documentation, project-status, clean-clone, hosted CI, and Mode R checks.
-Not yet implemented or empirically executed:
+Not yet empirically executed or independently evidenced:
-- full hash-chain writing and signatures;
-- atomic evidence writer;
-- Merkle checkpoints and independent verifier;
-- Base anchoring;
-- complete gateway and scenario engine;
-- model adapters and training;
-- Research-Grade isolation;
-- experiments E00-E50.
+- final-topology/pilot resource qualification; and
+- confirmatory experiments E00-E50 or any scientific results.
+The external-dependency ledger is ready at 1/1 applicable item: O01 is verified by
+the scoped synthetic-only governance decision, while O02-O06 are non-applicable to
+local execution. Public funding, public-chain transactions, hosted enforcement,
+second-person restoration, and third-party registration remain optional claim-
+strengthening activities. Their absence is disclosed and prohibits claims of public
+finality, hosted enforcement, independent restoration, or third-party registration;
+it does not answer or alter the agent-language estimands.
+The frozen local data/claim inventory resolves 125
+exported bundles across 19 collections by path and content hash. Forty-one have
+tracked bounded software-qualification support, 33 are historical qualification
+exports, and 51 are failed or superseded diagnostics. All 125 are excluded from
+empirical estimates. Seventy-seven recorded anchor confirmations are historical local
+fake-chain receipts; prospective receipts now bind an explicit class that the
+verifier refuses to relabel. Confirmed public-chain anchors, pilot bundles, confirmatory
+bundles, replication bundles, and research-included bundles are all zero.
The implementation backlog is maintained in BACKLOG.md, while normative
requirements are in SPECIFICATION.md.
@@ -1173,9 +1287,9 @@ 13.6 Literature Search Limits
14. Reproducibility, Data, and Code Availability
14.1 Code
-Source code and planning artifacts are publicly available at:
-https://github.com/Ethical-Tech-CoLab/agentic-language-development
-Every empirical paper revision will identify the exact Git commit used.
+Source code and planning artifacts exist in the working repository. An anonymous
+review artifact and any public release URL will be prepared only after release
+approval. Every empirical paper revision will identify an immutable source commit.
14.2 Protocols
14.3 Data
@@ -1195,12 +1311,14 @@ 14.4 Pre-Registration
and analysis plan before execution. The run configuration stores the protocol commit
and pre-registration hash. Changes create appended amendments rather than rewriting
the original record.
-No external registration record exists yet. Before the first confirmatory run, the
-team intends to create a dated OSF registration and anchor the same canonical
-preRegistrationHash before the run enters running. A Git commit in an
-author-controlled repository is retained as a development record but is not, by
-itself, treated as third-party preregistration. Appendix D supplies a numerically
-complete worked E03 registration for review.
+No complete experiment packet has yet been repository-registered. Before each
+confirmatory run, its canonical packet will be committed unchanged in a Git ancestor
+of the execution commit. Preflight will load those historical bytes, reproduce the
+preRegistrationHash, and require a matching deterministic simulated commitment
+before the run enters running. This establishes exact local identity, ancestry,
+ordering against later committed evidence, and tamper detection; it is not described
+as third-party registration or an independent timestamp. Appendix D supplies a
+numerically complete worked E03 registration for review.
15. Conclusion
The literature no longer leaves open whether artificial agents can coordinate
@@ -1228,11 +1346,10 @@
Author Contributions
Acknowledgements
Institutional and technical acknowledgements: TBD before submission.
AI-Assistance Disclosure
-This working manuscript was developed with AI assistance in VS Code through the
-Copilot SDK. The AI assistant performed the initial source retrieval, opened the
-arXiv/ACL/PMLR/Crossref/publisher/standards pages summarized in Appendix A, organized
-the manuscript, summarized relevance, and conducted consistency checks. A separate AI
-research-agent pass challenged source status and identified overclaiming risks.
+
This working manuscript was developed with AI-assisted research and repository tools.
+The tools supported source retrieval, primary-page inspection, manuscript organization,
+code implementation, executable validation, and critical consistency checks. Separate
+AI-assisted passes challenged source status, numerical claims, and overclaiming risks.
AI systems are not authors and bear no responsibility for the manuscript. Human
authors remain responsible for every claim, citation, analysis, and conclusion.
Following the Ethical Tech CoLab guidelines [47], load-bearing sources were opened or
@@ -1248,9 +1365,13 @@
Literature-Search Disclosure
reported its keyless monthly limit reached. No new Tavily-generated result was relied
upon. Rather than conceal the failure or imply that Tavily returned evidence, the
review continued through arXiv Atom metadata, ACL Anthology, PMLR, Crossref, JMLR,
-publisher and university pages, RFC Editor, NIST, Google Books, and Ethical Tech CoLab
-repositories. A final submission should rerun the search after Tavily access is
-restored and record whether it changes the included corpus.
+publisher and university pages, RFC Editor, NIST, Google Books, and institutional
+repositories. A bounded update was completed on September 11, 2026 across primary
+repository and publisher surfaces. Its queries, screening boundaries, all 50 source
+decisions, and five newer comparators are recorded in the
+source verification register.
+This was not a systematic review. A final submission must repeat the search through
+the manuscript-freeze date and record whether it changes the included corpus.
All retrieved material was treated as untrusted evidence, not as instruction.
References
@@ -1338,7 +1459,7 @@ References
Conference on Learning Representations. https://arxiv.org/abs/2204.12982
[26] Galke, L., & Raviv, L. (2024). Learning and communication pressures in
neural networks: Lessons from emergent communication. Language Development
-Research, 5(1), 116-143. https://doi.org/10.34842/3vr5-5r49
+Research, 5(1), 116-140. https://doi.org/10.34842/3vr5-5r49
[27] Kouwenhoven, T., Peeperkorn, M., & Verhoef, T. (2025). Searching for
structure: Investigating emergent communication with large language models.
Proceedings of COLING 2025, 9977-9991.
@@ -1535,9 +1656,9 @@
A.1 Rubric Application
| [15] |
-tool-abstract-verified, arXiv primary page/API |
+tool-full-text-verified, complete paper |
Peer-reviewed NeurIPS paper; journal score N/A |
-"Interpretable agent communication from scratch (with a generic visual processor emerging on the side)." Supports causal symbol interventions. |
+Supports unsupervised learned discrete communication, partial interpretability, and novel-class generalization in its evaluated setting; it does not supply causal symbol-intervention evidence. |
| [16] |
@@ -1601,15 +1722,15 @@ A.1 Rubric Application
| [26] |
-tool-metadata-verified, official journal page |
+tool-full-text-verified, complete official paper |
Peer-reviewed journal article, 3/5 |
-"Learning and communication pressures in neural networks: Lessons from emergent communication." A field review with a newer/variable-impact venue. |
+Reviews communicative success, production effort, learnability, and other pressures; official pagination is 116–140. |
| [27] |
-tool-metadata-verified, ACL Anthology |
+tool-full-text-verified, complete ACL Anthology paper |
Peer-reviewed COLING paper; journal score N/A |
-"Searching for Structure: Investigating Emergent Communication with Large Language Models." Direct pretrained-LLM comparison. |
+Directly studies artificial-language learning and transmission with pretrained language models. |
| [28] |
@@ -1739,15 +1860,15 @@ A.1 Rubric Application
| [49] |
-tool-metadata-verified, ACL Anthology |
+tool-full-text-verified, complete ACL Anthology paper |
Peer-reviewed EMNLP demo paper; journal score N/A |
-"EGG: a toolkit for research on Emergence of lanGuage in Games." Closest infrastructure comparator. |
+Closest infrastructure comparator: modular games, channels, optimization, analysis, and checkpoints. |
| [50] |
-tool-abstract-verified, PMLR primary page |
+tool-full-text-verified, complete PMLR paper |
Peer-reviewed ICML paper; journal score N/A |
-""Other-Play" for Zero-Shot Coordination." Supports novel-partner evaluation and specialized-convention risk. |
+Supports independently trained novel-partner evaluation and specialized-convention risk. |
No source in the table was silently upgraded from preprint or workshop status to a
@@ -1828,9 +1949,9 @@
D.1 Registration and Integrity
Registration target: OSF Registries.
The canonical registration JSON, this manuscript commit, analysis-script commit,
and generated seed manifest will be registered before execution.
-The same preRegistrationHash will be anchored to Base Sepolia before any run
-enters running.
-No outcome will be inspected before registration and anchoring complete.
+The same preRegistrationHash will be committed through the deterministic
+simulation transport before any run enters running.
+No outcome will be inspected before registration and commitment complete.
D.2 Objective
Test whether a four-choice referential task can be solved above chance without
@@ -1942,22 +2063,25 @@
D.6 Primary Outcomes and Tests
normal no-learning, perform two one-sided one-sample tests on seed-level success
proportions against equivalence bounds 0.20 and 0.30. Equivalence requires both
one-sided tests to reject at the Holm-adjusted alpha.
-Oracle adequacy: The lower bound of the two-sided 95% bootstrap confidence
-interval for mean seed-level oracle success must exceed 0.90.
+Oracle adequacy: A one-sided seed-level t test and its 95% lower confidence
+bound must exceed 0.90. A two-sided 95% seed-bootstrap interval is reported as a
+sensitivity estimate.
Oracle separation: For each non-oracle condition, compute paired seed-level
-oracle-minus-control differences. The lower bound of the Holm-adjusted 95%
-confidence interval must exceed 0.60.
+oracle-minus-control differences. One-sided t-test p-values above 0.60 receive
+Holm correction across the five conditions. Conservative 99% Bonferroni lower
+bounds and nominal paired seed-bootstrap intervals are reported.
No episode is analyzed as an independent run.
D.7 Sensitivity and Power
Before final registration, a separate outcome-blind-for-confirmatory-use pilot of 20
-seeds per non-oracle condition will estimate the largest between-seed standard
-deviation. Pilot runs will not enter confirmatory estimates. The registered primary
+seeds per non-oracle condition will fit the beta-binomial model and estimate the
+largest latent between-seed standard deviation after accounting for 200-episode
+sampling. Pilot runs will not enter confirmatory estimates. The registered primary
seed count is selected by this fixed rule:
-| Largest pilot SD |
+Largest latent pilot SD |
Primary seeds per condition |
@@ -1971,7 +2095,7 @@ D.7 Sensitivity and Power
| > 0.10 and <= 0.15 |
-150 |
+155 |
| > 0.15 and <= 0.20 |
@@ -1982,19 +2106,22 @@ D.7 Sensitivity and Power
New simulation and amended registration required before collection |
-A 30,000-replicate Monte Carlo design check was run for this draft under a true
-seed-level mean of 0.25, between-seed standard deviation of 0.10, 200 binomial
-episodes per seed, and conservative per-test alpha of 0.01. Estimated equivalence-test
-power was 0.924 at 75 seeds per condition. Sensitivity checks produced approximately
-0.912 power at SD 0.05 with 25 seeds, 0.920 at SD 0.15 with 150 seeds, and 0.913 at
-SD 0.20 with 300 seeds. Before registration, the simulation code and output must be
-checked in and independently rerun. Failure to reproduce at least 90% power blocks
+
The original 30,000-replicate normal sufficient-statistic calculation is retained as
+a single-control equivalence component check. It is not the registration-facing
+power claim. Independent base-R simulation instead draws a bounded latent seed
+probability from a beta distribution and then 200 binary episodes, applies all five
+Holm-adjusted control TOSTs, the oracle adequacy test, and all five Holm-adjusted
+paired separation tests. With 10,000 repetitions per row, full numeric-rule power
+was 0.9318, 0.9308, 0.9163, and 0.9552 for the four rows; lower 95% Monte Carlo bounds
+were 0.9267, 0.9257, 0.9107, and 0.9510. Exact output is committed in
+reports/research/statistical-validation.tsv and independently replayed by
+pnpm audit:statistics:r. Failure to reproduce a lower bound of at least 0.90 blocks
registration; it does not permit post-hoc widening of the margin.
Sensitivity analyses:
- Wilson intervals over pooled episodes are descriptive only;
-- a hierarchical Bernoulli model with seed random intercept is reported as a
-robustness check;
+- a hierarchical Bernoulli model with seed random intercept and percentile bootstrap
+intervals are reported as sensitivity checks;
- invalid primary runs are treated as failures in a worst-case sensitivity analysis.
D.8 Exclusions, Invalid Runs, and Replacement
@@ -2017,8 +2144,9 @@ D.10 Decision Rule
- all five non-oracle conditions meet equivalence;
- oracle adequacy and separation criteria pass;
-- no non-oracle condition has more than 5% of its primary seeds with observed success
-of 0.35 or greater; every such seed is individually audited for leakage;
+- every non-oracle primary seed with observed success of 0.35 or greater receives an
+individually resolved leakage audit; the count is diagnostic and is not an
+uncalibrated statistical rejection rule;
- all included evidence bundles pass verification;
- no unplanned metadata or channel leakage is detected.
diff --git a/book/research.pdf b/book/research.pdf
index bcaed49..462f830 100644
Binary files a/book/research.pdf and b/book/research.pdf differ
diff --git a/book/vendor/research-book.js b/book/vendor/research-book.js
index 2386540..a110861 100644
--- a/book/vendor/research-book.js
+++ b/book/vendor/research-book.js
@@ -1,4 +1,4 @@
-var V=Object.create;var O=Object.defineProperty;var j=Object.getOwnPropertyDescriptor;var Z=Object.getOwnPropertyNames;var Y=Object.getPrototypeOf,K=Object.prototype.hasOwnProperty;var X=(a,p)=>()=>{try{return p||a((p={exports:{}}).exports,p),p.exports}catch(l){throw p=0,l}};var J=(a,p,l,c)=>{if(p&&typeof p=="object"||typeof p=="function")for(let m of Z(p))!K.call(a,m)&&m!==l&&O(a,m,{get:()=>p[m],enumerable:!(c=j(p,m))||c.enumerable});return a};var Q=(a,p,l)=>(l=a!=null?V(Y(a)):{},J(p||!a||!a.__esModule?O(l,"default",{value:a,enumerable:!0}):l,a));var G=X((E,_)=>{(function(a,p){typeof E=="object"&&typeof _<"u"?p(E):typeof define=="function"&&define.amd?define(["exports"],p):p((a=a||self).St={})})(E,(function(a){"use strict";class p{constructor(t,e){this.state={angle:0,area:[],position:{x:0,y:0},hardAngle:0,hardDrawingAngle:0},this.createdDensity=e,this.nowDrawingDensity=this.createdDensity,this.render=t}setDensity(t){this.createdDensity=t,this.nowDrawingDensity=t}setDrawingDensity(t){this.nowDrawingDensity=t}setPosition(t){this.state.position=t}setAngle(t){this.state.angle=t}setArea(t){this.state.area=t}setHardDrawingAngle(t){this.state.hardDrawingAngle=t}setHardAngle(t){this.state.hardAngle=t,this.state.hardDrawingAngle=t}setOrientation(t){this.orientation=t}getDrawingDensity(){return this.nowDrawingDensity}getDensity(){return this.createdDensity}getHardAngle(){return this.state.hardAngle}}class l extends p{constructor(t,e,i){super(t,i),this.image=null,this.isLoad=!1,this.loadingAngle=0,this.image=new Image,this.image.src=e}draw(t){let e=this.render.getContext(),i=this.render.convertToGlobal(this.state.position),s=this.render.getRect().pageWidth,n=this.render.getRect().height;e.save(),e.translate(i.x,i.y),e.beginPath();for(let o of this.state.area)o!==null&&(o=this.render.convertToGlobal(o),e.lineTo(o.x-i.x,o.y-i.y));e.rotate(this.state.angle),e.clip(),this.isLoad?e.drawImage(this.image,0,0,s,n):this.drawLoader(e,{x:0,y:0},s,n),e.restore()}simpleDraw(t){let e=this.render.getRect(),i=this.render.getContext(),s=e.pageWidth,n=e.height,o=t===1?e.left+e.pageWidth:e.left,h=e.top;this.isLoad?i.drawImage(this.image,o,h,s,n):this.drawLoader(i,{x:o,y:h},s,n)}drawLoader(t,e,i,s){t.beginPath(),t.strokeStyle="rgb(200, 200, 200)",t.fillStyle="rgb(255, 255, 255)",t.lineWidth=1,t.rect(e.x+1,e.y+1,i-1,s-1),t.stroke(),t.fill();let n={x:e.x+i/2,y:e.y+s/2};t.beginPath(),t.lineWidth=10,t.arc(n.x,n.y,20,this.loadingAngle,3*Math.PI/2+this.loadingAngle),t.stroke(),t.closePath(),this.loadingAngle+=.07,this.loadingAngle>=2*Math.PI&&(this.loadingAngle=0)}load(){this.isLoad||(this.image.onload=()=>{this.isLoad=!0})}newTemporaryCopy(){return this}getTemporaryCopy(){return this}hideTemporaryCopy(){}}class c{constructor(t,e){this.pages=[],this.currentPageIndex=0,this.currentSpreadIndex=0,this.landscapeSpread=[],this.portraitSpread=[],this.render=e,this.app=t,this.currentPageIndex=0,this.isShowCover=this.app.getSettings().showCover}destroy(){this.pages=[]}createSpread(){this.landscapeSpread=[],this.portraitSpread=[];for(let e=0;e=0&&t0?this.pages[e-1]:null}getFlippingPage(t){let e=this.currentSpreadIndex;if(this.render.getOrientation()==="portrait")return t===0?this.pages[e].newTemporaryCopy():this.pages[e-1];{let i=t===0?this.getSpread()[e+1]:this.getSpread()[e-1];return i.length===1||t===0?this.pages[i[0]]:this.pages[i[1]]}}getBottomPage(t){let e=this.currentSpreadIndex;if(this.render.getOrientation()==="portrait")return t===0?this.pages[e+1]:this.pages[e-1];{let i=t===0?this.getSpread()[e+1]:this.getSpread()[e-1];return i.length===1?this.pages[i[0]]:t===0?this.pages[i[1]]:this.pages[i[0]]}}showNext(){this.currentSpreadIndex0&&(this.currentSpreadIndex--,this.showSpread())}getCurrentPageIndex(){return this.currentPageIndex}show(t=null){if(t===null&&(t=this.currentPageIndex),t<0||t>=this.pages.length)return;let e=this.getSpreadIndexByPage(t);e!==null&&(this.currentSpreadIndex=e,this.showSpread())}getCurrentSpreadIndex(){return this.currentSpreadIndex}setCurrentSpreadIndex(t){if(!(t>=0&&t=t.left&&e.x<=t.width+t.left&&e.y>=t.top&&e.y<=t.top+t.height?e:null}static GetRotatedPoint(t,e,i){return{x:t.x*Math.cos(i)+t.y*Math.sin(i)+e.x,y:t.y*Math.cos(i)-t.x*Math.sin(i)+e.y}}static LimitPointToCircle(t,e,i){if(g.GetDistanceBetweenTwoPoint(t,i)<=e)return i;let s=t.x,n=t.y,o=i.x,h=i.y,d=Math.sqrt(Math.pow(e,2)*Math.pow(s-o,2)/(Math.pow(s-o,2)+Math.pow(n-h,2)))+s;i.x<0&&(d*=-1);let u=(d-s)*(n-h)/(s-o)+n;return s-o+n===0&&(u=e),{x:d,y:u}}static GetIntersectBetweenTwoSegment(t,e,i){return g.PointInRect(t,g.GetIntersectBeetwenTwoLine(e,i))}static GetIntersectBeetwenTwoLine(t,e){let i=t[0].y-t[1].y,s=e[0].y-e[1].y,n=t[1].x-t[0].x,o=e[1].x-e[0].x,h=t[0].x*t[1].y-t[1].x*t[0].y,d=e[0].x*e[1].y-e[1].x*e[0].y,u=i*d-s*h,x=n*d-o*h,T=-(h*o-d*n)/(i*o-s*n),L=-(i*d-s*h)/(i*o-s*n);if(isFinite(T)&&isFinite(L))return{x:T,y:L};if(Math.abs(u-x)<.1)throw new Error("Segment included");return null}static GetCordsFromTwoPoint(t,e){let i=Math.abs(t.x-e.x),s=Math.abs(t.y-e.y),n=Math.max(i,s),o=[t];function h(d,u,x,T,L){return u>d?d+L*(x/T):u()=>{try{return p||r((p={exports:{}}).exports,p),p.exports}catch(l){throw p=0,l}};var J=(r,p,l,c)=>{if(p&&typeof p=="object"||typeof p=="function")for(let w of j(p))!X.call(r,w)&&w!==l&&_(r,w,{get:()=>p[w],enumerable:!(c=Y(p,w))||c.enumerable});return r};var Q=(r,p,l)=>(l=r!=null?Z(V(r)):{},J(p||!r||!r.__esModule?_(l,"default",{value:r,enumerable:!0}):l,r));var G=K((A,O)=>{(function(r,p){typeof A=="object"&&typeof O<"u"?p(A):typeof define=="function"&&define.amd?define(["exports"],p):p((r=r||self).St={})})(A,(function(r){"use strict";class p{constructor(t,e){this.state={angle:0,area:[],position:{x:0,y:0},hardAngle:0,hardDrawingAngle:0},this.createdDensity=e,this.nowDrawingDensity=this.createdDensity,this.render=t}setDensity(t){this.createdDensity=t,this.nowDrawingDensity=t}setDrawingDensity(t){this.nowDrawingDensity=t}setPosition(t){this.state.position=t}setAngle(t){this.state.angle=t}setArea(t){this.state.area=t}setHardDrawingAngle(t){this.state.hardDrawingAngle=t}setHardAngle(t){this.state.hardAngle=t,this.state.hardDrawingAngle=t}setOrientation(t){this.orientation=t}getDrawingDensity(){return this.nowDrawingDensity}getDensity(){return this.createdDensity}getHardAngle(){return this.state.hardAngle}}class l extends p{constructor(t,e,i){super(t,i),this.image=null,this.isLoad=!1,this.loadingAngle=0,this.image=new Image,this.image.src=e}draw(t){let e=this.render.getContext(),i=this.render.convertToGlobal(this.state.position),s=this.render.getRect().pageWidth,n=this.render.getRect().height;e.save(),e.translate(i.x,i.y),e.beginPath();for(let o of this.state.area)o!==null&&(o=this.render.convertToGlobal(o),e.lineTo(o.x-i.x,o.y-i.y));e.rotate(this.state.angle),e.clip(),this.isLoad?e.drawImage(this.image,0,0,s,n):this.drawLoader(e,{x:0,y:0},s,n),e.restore()}simpleDraw(t){let e=this.render.getRect(),i=this.render.getContext(),s=e.pageWidth,n=e.height,o=t===1?e.left+e.pageWidth:e.left,h=e.top;this.isLoad?i.drawImage(this.image,o,h,s,n):this.drawLoader(i,{x:o,y:h},s,n)}drawLoader(t,e,i,s){t.beginPath(),t.strokeStyle="rgb(200, 200, 200)",t.fillStyle="rgb(255, 255, 255)",t.lineWidth=1,t.rect(e.x+1,e.y+1,i-1,s-1),t.stroke(),t.fill();let n={x:e.x+i/2,y:e.y+s/2};t.beginPath(),t.lineWidth=10,t.arc(n.x,n.y,20,this.loadingAngle,3*Math.PI/2+this.loadingAngle),t.stroke(),t.closePath(),this.loadingAngle+=.07,this.loadingAngle>=2*Math.PI&&(this.loadingAngle=0)}load(){this.isLoad||(this.image.onload=()=>{this.isLoad=!0})}newTemporaryCopy(){return this}getTemporaryCopy(){return this}hideTemporaryCopy(){}}class c{constructor(t,e){this.pages=[],this.currentPageIndex=0,this.currentSpreadIndex=0,this.landscapeSpread=[],this.portraitSpread=[],this.render=e,this.app=t,this.currentPageIndex=0,this.isShowCover=this.app.getSettings().showCover}destroy(){this.pages=[]}createSpread(){this.landscapeSpread=[],this.portraitSpread=[];for(let e=0;e=0&&t0?this.pages[e-1]:null}getFlippingPage(t){let e=this.currentSpreadIndex;if(this.render.getOrientation()==="portrait")return t===0?this.pages[e].newTemporaryCopy():this.pages[e-1];{let i=t===0?this.getSpread()[e+1]:this.getSpread()[e-1];return i.length===1||t===0?this.pages[i[0]]:this.pages[i[1]]}}getBottomPage(t){let e=this.currentSpreadIndex;if(this.render.getOrientation()==="portrait")return t===0?this.pages[e+1]:this.pages[e-1];{let i=t===0?this.getSpread()[e+1]:this.getSpread()[e-1];return i.length===1?this.pages[i[0]]:t===0?this.pages[i[1]]:this.pages[i[0]]}}showNext(){this.currentSpreadIndex0&&(this.currentSpreadIndex--,this.showSpread())}getCurrentPageIndex(){return this.currentPageIndex}show(t=null){if(t===null&&(t=this.currentPageIndex),t<0||t>=this.pages.length)return;let e=this.getSpreadIndexByPage(t);e!==null&&(this.currentSpreadIndex=e,this.showSpread())}getCurrentSpreadIndex(){return this.currentSpreadIndex}setCurrentSpreadIndex(t){if(!(t>=0&&t=t.left&&e.x<=t.width+t.left&&e.y>=t.top&&e.y<=t.top+t.height?e:null}static GetRotatedPoint(t,e,i){return{x:t.x*Math.cos(i)+t.y*Math.sin(i)+e.x,y:t.y*Math.cos(i)-t.x*Math.sin(i)+e.y}}static LimitPointToCircle(t,e,i){if(g.GetDistanceBetweenTwoPoint(t,i)<=e)return i;let s=t.x,n=t.y,o=i.x,h=i.y,d=Math.sqrt(Math.pow(e,2)*Math.pow(s-o,2)/(Math.pow(s-o,2)+Math.pow(n-h,2)))+s;i.x<0&&(d*=-1);let u=(d-s)*(n-h)/(s-o)+n;return s-o+n===0&&(u=e),{x:d,y:u}}static GetIntersectBetweenTwoSegment(t,e,i){return g.PointInRect(t,g.GetIntersectBeetwenTwoLine(e,i))}static GetIntersectBeetwenTwoLine(t,e){let i=t[0].y-t[1].y,s=e[0].y-e[1].y,n=t[1].x-t[0].x,o=e[1].x-e[0].x,h=t[0].x*t[1].y-t[1].x*t[0].y,d=e[0].x*e[1].y-e[1].x*e[0].y,u=i*d-s*h,x=n*d-o*h,C=-(h*o-d*n)/(i*o-s*n),L=-(i*d-s*h)/(i*o-s*n);if(isFinite(C)&&isFinite(L))return{x:C,y:L};if(Math.abs(u-x)<.1)throw new Error("Segment included");return null}static GetCordsFromTwoPoint(t,e){let i=Math.abs(t.x-e.x),s=Math.abs(t.y-e.y),n=Math.max(i,s),o=[t];function h(d,u,x,C,L){return u>d?d+L*(x/C):u=10&&t.push(this.sideIntersectPoint):this.corner==="top"&&t.push({x:this.pageWidth,y:this.pageHeight}),t.push(this.bottomIntersectPoint),t.push(this.topIntersectPoint),t}getAngle(){return this.direction===0?-this.angle:this.angle}getRect(){return this.rect}getPosition(){return this.position}getActiveCorner(){return this.direction===0?this.rect.topLeft:this.rect.topRight}getDirection(){return this.direction}getFlippingProgress(){return Math.abs((this.position.x-this.pageWidth)/(2*this.pageWidth)*100)}getCorner(){return this.corner}getBottomPagePosition(){return this.direction===1?{x:this.pageWidth,y:0}:{x:0,y:0}}getShadowStartPoint(){return this.corner==="top"?this.topIntersectPoint:this.sideIntersectPoint!==null?this.sideIntersectPoint:this.topIntersectPoint}getShadowAngle(){let t=g.GetAngleBetweenTwoLine(this.getSegmentToShadowLine(),[{x:0,y:0},{x:this.pageWidth,y:0}]);return this.direction===0?t:Math.PI-t}calcAngleAndPosition(t){let e=t;if(this.updateAngleAndGeometry(e),e=this.corner==="top"?this.checkPositionAtCenterLine(e,{x:0,y:0},{x:0,y:this.pageHeight}):this.checkPositionAtCenterLine(e,{x:0,y:this.pageHeight},{x:0,y:0}),Math.abs(e.x-this.pageWidth)<1&&Math.abs(e.y)<1)throw new Error("Point is too small");return e}updateAngleAndGeometry(t){this.angle=this.calculateAngle(t),this.rect=this.getPageRect(t)}calculateAngle(t){let e=this.pageWidth-t.x+1,i=this.corner==="bottom"?this.pageHeight-t.y:t.y,s=2*Math.acos(e/Math.sqrt(i*i+e*e));i<0&&(s=-s);let n=Math.PI-s;if(!isFinite(s)||n>=0&&n<.003)throw new Error("The G point is too small");return this.corner==="bottom"&&(s=-s),s}getPageRect(t){return this.corner==="top"?this.getRectFromBasePoint([{x:0,y:0},{x:this.pageWidth,y:0},{x:0,y:this.pageHeight},{x:this.pageWidth,y:this.pageHeight}],t):this.getRectFromBasePoint([{x:0,y:-this.pageHeight},{x:this.pageWidth,y:-this.pageHeight},{x:0,y:0},{x:this.pageWidth,y:0}],t)}getRectFromBasePoint(t,e){return{topLeft:this.getRotatedPoint(t[0],e),topRight:this.getRotatedPoint(t[1],e),bottomLeft:this.getRotatedPoint(t[2],e),bottomRight:this.getRotatedPoint(t[3],e)}}getRotatedPoint(t,e){return{x:t.x*Math.cos(this.angle)+t.y*Math.sin(this.angle)+e.x,y:t.y*Math.cos(this.angle)-t.x*Math.sin(this.angle)+e.y}}calculateIntersectPoint(t){let e={left:-1,top:-1,width:this.pageWidth+2,height:this.pageHeight+2};this.corner==="top"?(this.topIntersectPoint=g.GetIntersectBetweenTwoSegment(e,[t,this.rect.topRight],[{x:0,y:0},{x:this.pageWidth,y:0}]),this.sideIntersectPoint=g.GetIntersectBetweenTwoSegment(e,[t,this.rect.bottomLeft],[{x:this.pageWidth,y:0},{x:this.pageWidth,y:this.pageHeight}]),this.bottomIntersectPoint=g.GetIntersectBetweenTwoSegment(e,[this.rect.bottomLeft,this.rect.bottomRight],[{x:0,y:this.pageHeight},{x:this.pageWidth,y:this.pageHeight}])):(this.topIntersectPoint=g.GetIntersectBetweenTwoSegment(e,[this.rect.topLeft,this.rect.topRight],[{x:0,y:0},{x:this.pageWidth,y:0}]),this.sideIntersectPoint=g.GetIntersectBetweenTwoSegment(e,[t,this.rect.topLeft],[{x:this.pageWidth,y:0},{x:this.pageWidth,y:this.pageHeight}]),this.bottomIntersectPoint=g.GetIntersectBetweenTwoSegment(e,[this.rect.bottomLeft,this.rect.bottomRight],[{x:0,y:this.pageHeight},{x:this.pageWidth,y:this.pageHeight}]))}checkPositionAtCenterLine(t,e,i){let s=t,n=g.LimitPointToCircle(e,this.pageWidth,s);s!==n&&(s=n,this.updateAngleAndGeometry(s));let o=Math.sqrt(Math.pow(this.pageWidth,2)+Math.pow(this.pageHeight,2)),h=this.rect.bottomRight,d=this.rect.topLeft;if(this.corner==="bottom"&&(h=this.rect.topRight,d=this.rect.bottomLeft),h.x<=0){let u=g.LimitPointToCircle(i,o,d);u!==s&&(s=u,this.updateAngleAndGeometry(s))}return s}getSegmentToShadowLine(){let t=this.getShadowStartPoint();return[t,t!==this.sideIntersectPoint&&this.sideIntersectPoint!==null?this.sideIntersectPoint:this.bottomIntersectPoint]}}class b{constructor(t,e){this.flippingPage=null,this.bottomPage=null,this.calc=null,this.state="read",this.render=t,this.app=e}fold(t){this.setState("user_fold"),this.calc===null&&this.start(t),this.do(this.render.convertToPage(t))}flip(t){if(this.app.getSettings().disableFlipByClick&&!this.isPointOnCorners(t)||(this.calc!==null&&this.render.finishAnimation(),!this.start(t)))return;let e=this.getBoundsRect();this.setState("flipping");let i=e.height/10,s=this.calc.getCorner()==="bottom"?e.height-i:i,n=this.calc.getCorner()==="bottom"?e.height:0;this.calc.calc({x:e.pageWidth-i,y:s}),this.animateFlippingTo({x:e.pageWidth-i,y:s},{x:-e.pageWidth,y:n},!0)}start(t){this.reset();let e=this.render.convertToBook(t),i=this.getBoundsRect(),s=this.getDirectionByPoint(e),n=e.y>=i.height/2?"bottom":"top";if(!this.checkDirection(s))return!1;try{if(this.flippingPage=this.app.getPageCollection().getFlippingPage(s),this.bottomPage=this.app.getPageCollection().getBottomPage(s),this.render.getOrientation()==="landscape")if(s===1){let o=this.app.getPageCollection().nextBy(this.flippingPage);o!==null&&this.flippingPage.getDensity()!==o.getDensity()&&(this.flippingPage.setDrawingDensity("hard"),o.setDrawingDensity("hard"))}else{let o=this.app.getPageCollection().prevBy(this.flippingPage);o!==null&&this.flippingPage.getDensity()!==o.getDensity()&&(this.flippingPage.setDrawingDensity("hard"),o.setDrawingDensity("hard"))}return this.render.setDirection(s),this.calc=new P(s,n,i.pageWidth.toString(10),i.height.toString(10)),!0}catch{return!1}}do(t){if(this.calc!==null&&this.calc.calc(t)){let e=this.calc.getFlippingProgress();this.bottomPage.setArea(this.calc.getBottomClipArea()),this.bottomPage.setPosition(this.calc.getBottomPagePosition()),this.bottomPage.setAngle(0),this.bottomPage.setHardAngle(0),this.flippingPage.setArea(this.calc.getFlippingClipArea()),this.flippingPage.setPosition(this.calc.getActiveCorner()),this.flippingPage.setAngle(this.calc.getAngle()),this.calc.getDirection()===0?this.flippingPage.setHardAngle(90*(200-2*e)/100):this.flippingPage.setHardAngle(-90*(200-2*e)/100),this.render.setPageRect(this.calc.getRect()),this.render.setBottomPage(this.bottomPage),this.render.setFlippingPage(this.flippingPage),this.render.setShadowData(this.calc.getShadowStartPoint(),this.calc.getShadowAngle(),e,this.calc.getDirection())}}flipToPage(t,e){let i=this.app.getPageCollection().getCurrentSpreadIndex(),s=this.app.getPageCollection().getSpreadIndexByPage(t);try{s>i&&(this.app.getPageCollection().setCurrentSpreadIndex(s-1),this.flipNext(e)),sthis.do(d));let h=this.getAnimationDuration(n.length);this.render.startAnimation(o,h,()=>{this.calc&&(i&&(this.calc.getDirection()===1?this.app.turnToPrevPage():this.app.turnToNextPage()),s&&(this.render.setBottomPage(null),this.render.setFlippingPage(null),this.render.clearShadow(),this.setState("read"),this.reset()))})}getCalculation(){return this.calc}getState(){return this.state}setState(t){this.state!==t&&(this.app.updateState(t),this.state=t)}getDirectionByPoint(t){let e=this.getBoundsRect();if(this.render.getOrientation()==="portrait"){if(t.x-e.pageWidth<=e.width/5)return 1}else if(t.x=1e3?e:t/1e3*e}checkDirection(t){return t===0?this.app.getCurrentPageIndex()=1}reset(){this.calc=null,this.flippingPage=null,this.bottomPage=null}getBoundsRect(){return this.render.getRect()}checkState(...t){for(let e of t)if(this.state===e)return!0;return!1}isPointOnCorners(t){let e=this.getBoundsRect(),i=e.pageWidth,s=Math.sqrt(Math.pow(i,2)+Math.pow(e.height,2))/5,n=this.render.convertToBook(t);return n.x>0&&n.y>0&&n.xe.width-s)&&(n.ye.height-s)}}class v{constructor(t,e){this.leftPage=null,this.rightPage=null,this.flippingPage=null,this.bottomPage=null,this.direction=null,this.orientation=null,this.shadow=null,this.animation=null,this.pageRect=null,this.boundsRect=null,this.timer=0,this.safari=!1,this.setting=e,this.app=t;let i=new RegExp("Version\\/[\\d\\.]+.*Safari/");this.safari=i.exec(window.navigator.userAgent)!==null}render(t){if(this.animation!==null){let e=Math.round((t-this.animation.startedAt)/this.animation.durationFrame);e{this.render(e),requestAnimationFrame(t)};requestAnimationFrame(t)}startAnimation(t,e,i){this.finishAnimation(),this.animation={frames:t,duration:e,durationFrame:e/t.length,onAnimateEnd:i,startedAt:this.timer}}finishAnimation(){this.animation!==null&&(this.animation.frames[this.animation.frames.length-1](),this.animation.onAnimateEnd!==null&&this.animation.onAnimateEnd()),this.animation=null}update(){this.boundsRect=null;let t=this.calculateBoundsRect();this.orientation!==t&&(this.orientation=t,this.app.updateOrientation(t))}calculateBoundsRect(){let t="landscape",e=this.getBlockWidth(),i=e/2,s=this.getBlockHeight()/2,n=this.setting.width/this.setting.height,o=this.setting.width,h=this.setting.height,d=i-o;return this.setting.size==="stretch"?(e<2*this.setting.minWidth&&this.app.getSettings().usePortrait&&(t="portrait"),o=t==="portrait"?this.getBlockWidth():this.getBlockWidth()/2,o>this.setting.maxWidth&&(o=this.setting.maxWidth),h=o/n,h>this.getBlockHeight()&&(h=this.getBlockHeight(),o=h*n),d=t==="portrait"?i-o/2-o:i-o):e<2*o&&this.app.getSettings().usePortrait&&(t="portrait",d=i-o/2-o),this.boundsRect={left:d,top:s-h/2,width:2*o,height:h,pageWidth:o},t}setShadowData(t,e,i,s){if(!this.app.getSettings().drawShadow)return;let n=100*this.getSettings().maxShadowOpacity;this.shadow={pos:t,angle:e,width:3*this.getRect().pageWidth/4*i/100,opacity:(100-i)*n/100/100,direction:s,progress:2*i}}clearShadow(){this.shadow=null}getBlockWidth(){return this.app.getUI().getDistElement().offsetWidth}getBlockHeight(){return this.app.getUI().getDistElement().offsetHeight}getDirection(){return this.direction}getRect(){return this.boundsRect===null&&this.calculateBoundsRect(),this.boundsRect}getSettings(){return this.app.getSettings()}getOrientation(){return this.orientation}setPageRect(t){this.pageRect=t}setDirection(t){this.direction=t}setRightPage(t){t!==null&&t.setOrientation(1),this.rightPage=t}setLeftPage(t){t!==null&&t.setOrientation(0),this.leftPage=t}setBottomPage(t){t!==null&&t.setOrientation(this.direction===1?0:1),this.bottomPage=t}setFlippingPage(t){t!==null&&t.setOrientation(this.direction===0&&this.orientation!=="portrait"?0:1),this.flippingPage=t}convertToBook(t){let e=this.getRect();return{x:t.x-e.left,y:t.y-e.top}}isSafari(){return this.safari}convertToPage(t,e){e||(e=this.direction);let i=this.getRect();return{x:e===0?t.x-i.left-i.width/2:i.width/2-t.x+i.left,y:t.y-i.top}}convertToGlobal(t,e){if(e||(e=this.direction),t==null)return null;let i=this.getRect();return{x:e===0?t.x+i.left+i.width/2:i.width/2-t.x+i.left,y:t.y+i.top}}convertRectToGlobal(t,e){return e||(e=this.direction),{topLeft:this.convertToGlobal(t.topLeft,e),topRight:this.convertToGlobal(t.topRight,e),bottomLeft:this.convertToGlobal(t.bottomLeft,e),bottomRight:this.convertToGlobal(t.bottomRight,e)}}}class I extends v{constructor(t,e,i){super(t,e),this.canvas=i,this.ctx=i.getContext("2d")}getContext(){return this.ctx}reload(){}drawFrame(){this.clear(),this.orientation!=="portrait"&&this.leftPage!=null&&this.leftPage.simpleDraw(0),this.rightPage!=null&&this.rightPage.simpleDraw(1),this.bottomPage!=null&&this.bottomPage.draw(),this.drawBookShadow(),this.flippingPage!=null&&this.flippingPage.draw(),this.shadow!=null&&(this.drawOuterShadow(),this.drawInnerShadow());let t=this.getRect();this.orientation==="portrait"&&(this.ctx.beginPath(),this.ctx.rect(t.left+t.pageWidth,t.top,t.width,t.height),this.ctx.clip())}drawBookShadow(){let t=this.getRect();this.ctx.save(),this.ctx.beginPath();let e=t.width/20;this.ctx.rect(t.left,t.top,t.width,t.height);let i={x:t.left+t.width/2-e/2,y:0};this.ctx.translate(i.x,i.y);let s=this.ctx.createLinearGradient(0,0,e,0);s.addColorStop(0,"rgba(0, 0, 0, 0)"),s.addColorStop(.4,"rgba(0, 0, 0, 0.2)"),s.addColorStop(.49,"rgba(0, 0, 0, 0.1)"),s.addColorStop(.5,"rgba(0, 0, 0, 0.5)"),s.addColorStop(.51,"rgba(0, 0, 0, 0.4)"),s.addColorStop(1,"rgba(0, 0, 0, 0)"),this.ctx.clip(),this.ctx.fillStyle=s,this.ctx.fillRect(0,0,e,2*t.height),this.ctx.restore()}drawOuterShadow(){let t=this.getRect();this.ctx.save(),this.ctx.beginPath(),this.ctx.rect(t.left,t.top,t.width,t.height);let e=this.convertToGlobal({x:this.shadow.pos.x,y:this.shadow.pos.y});this.ctx.translate(e.x,e.y),this.ctx.rotate(Math.PI+this.shadow.angle+Math.PI/2);let i=this.ctx.createLinearGradient(0,0,this.shadow.width,0);this.shadow.direction===0?(this.ctx.translate(0,-100),i.addColorStop(0,"rgba(0, 0, 0, "+this.shadow.opacity+")"),i.addColorStop(1,"rgba(0, 0, 0, 0)")):(this.ctx.translate(-this.shadow.width,-100),i.addColorStop(0,"rgba(0, 0, 0, 0)"),i.addColorStop(1,"rgba(0, 0, 0, "+this.shadow.opacity+")")),this.ctx.clip(),this.ctx.fillStyle=i,this.ctx.fillRect(0,0,this.shadow.width,2*t.height),this.ctx.restore()}drawInnerShadow(){let t=this.getRect();this.ctx.save(),this.ctx.beginPath();let e=this.convertToGlobal({x:this.shadow.pos.x,y:this.shadow.pos.y}),i=this.convertRectToGlobal(this.pageRect);this.ctx.moveTo(i.topLeft.x,i.topLeft.y),this.ctx.lineTo(i.topRight.x,i.topRight.y),this.ctx.lineTo(i.bottomRight.x,i.bottomRight.y),this.ctx.lineTo(i.bottomLeft.x,i.bottomLeft.y),this.ctx.translate(e.x,e.y),this.ctx.rotate(Math.PI+this.shadow.angle+Math.PI/2);let s=3*this.shadow.width/4,n=this.ctx.createLinearGradient(0,0,s,0);this.shadow.direction===0?(this.ctx.translate(-s,-100),n.addColorStop(1,"rgba(0, 0, 0, "+this.shadow.opacity+")"),n.addColorStop(.9,"rgba(0, 0, 0, 0.05)"),n.addColorStop(.7,"rgba(0, 0, 0, "+this.shadow.opacity+")"),n.addColorStop(0,"rgba(0, 0, 0, 0)")):(this.ctx.translate(0,-100),n.addColorStop(0,"rgba(0, 0, 0, "+this.shadow.opacity+")"),n.addColorStop(.1,"rgba(0, 0, 0, 0.05)"),n.addColorStop(.3,"rgba(0, 0, 0, "+this.shadow.opacity+")"),n.addColorStop(1,"rgba(0, 0, 0, 0)")),this.ctx.clip(),this.ctx.fillStyle=n,this.ctx.fillRect(0,0,s,2*t.height),this.ctx.restore()}clear(){this.ctx.fillStyle="white",this.ctx.fillRect(0,0,this.canvas.width,this.canvas.height)}}class C{constructor(t,e,i){this.touchPoint=null,this.swipeTimeout=250,this.onResize=()=>{this.update()},this.onMouseDown=n=>{if(this.checkTarget(n.target)){let o=this.getMousePos(n.clientX,n.clientY);this.app.startUserTouch(o),n.preventDefault()}},this.onTouchStart=n=>{if(this.checkTarget(n.target)&&n.changedTouches.length>0){let o=n.changedTouches[0],h=this.getMousePos(o.clientX,o.clientY);this.touchPoint={point:h,time:Date.now()},setTimeout(()=>{this.touchPoint!==null&&this.app.startUserTouch(h)},this.swipeTimeout),this.app.getSettings().mobileScrollSupport||n.preventDefault()}},this.onMouseUp=n=>{let o=this.getMousePos(n.clientX,n.clientY);this.app.userStop(o)},this.onMouseMove=n=>{let o=this.getMousePos(n.clientX,n.clientY);this.app.userMove(o,!1)},this.onTouchMove=n=>{if(n.changedTouches.length>0){let o=n.changedTouches[0],h=this.getMousePos(o.clientX,o.clientY);this.app.getSettings().mobileScrollSupport?(this.touchPoint!==null&&(Math.abs(this.touchPoint.point.x-h.x)>10||this.app.getState()!=="read")&&n.cancelable&&this.app.userMove(h,!0),this.app.getState()!=="read"&&n.preventDefault()):this.app.userMove(h,!0)}},this.onTouchEnd=n=>{if(n.changedTouches.length>0){let o=n.changedTouches[0],h=this.getMousePos(o.clientX,o.clientY),d=!1;if(this.touchPoint!==null){let u=h.x-this.touchPoint.point.x,x=Math.abs(h.y-this.touchPoint.point.y);Math.abs(u)>this.swipeDistance&&x<2*this.swipeDistance&&Date.now()-this.touchPoint.time0?this.app.flipPrev(this.touchPoint.point.y'),this.wrapper=t.querySelector(".stf__wrapper"),this.app=e;let s=this.app.getSettings().usePortrait?1:2;t.style.minWidth=i.minWidth*s+"px",t.style.minHeight=i.minHeight+"px",i.size==="fixed"&&(t.style.minWidth=i.width*s+"px",t.style.minHeight=i.height+"px"),i.autoSize&&(t.style.width="100%",t.style.maxWidth=2*i.maxWidth+"px"),t.style.display="block",window.addEventListener("resize",this.onResize,!1),this.swipeDistance=i.swipeDistance}destroy(){this.app.getSettings().useMouseEvents&&this.removeHandlers(),this.distElement.remove(),this.wrapper.remove()}getDistElement(){return this.distElement}getWrapper(){return this.wrapper}setOrientationStyle(t){this.wrapper.classList.remove("--portrait","--landscape"),t==="portrait"?(this.app.getSettings().autoSize&&(this.wrapper.style.paddingBottom=this.app.getSettings().height/this.app.getSettings().width*100+"%"),this.wrapper.classList.add("--portrait")):(this.app.getSettings().autoSize&&(this.wrapper.style.paddingBottom=this.app.getSettings().height/(2*this.app.getSettings().width)*100+"%"),this.wrapper.classList.add("--landscape")),this.update()}removeHandlers(){window.removeEventListener("resize",this.onResize),this.distElement.removeEventListener("mousedown",this.onMouseDown),this.distElement.removeEventListener("touchstart",this.onTouchStart),window.removeEventListener("mousemove",this.onMouseMove),window.removeEventListener("touchmove",this.onTouchMove),window.removeEventListener("mouseup",this.onMouseUp),window.removeEventListener("touchend",this.onTouchEnd)}setHandlers(){window.addEventListener("resize",this.onResize,!1),this.app.getSettings().useMouseEvents&&(this.distElement.addEventListener("mousedown",this.onMouseDown),this.distElement.addEventListener("touchstart",this.onTouchStart),window.addEventListener("mousemove",this.onMouseMove),window.addEventListener("touchmove",this.onTouchMove,{passive:!this.app.getSettings().mobileScrollSupport}),window.addEventListener("mouseup",this.onMouseUp),window.addEventListener("touchend",this.onTouchEnd))}getMousePos(t,e){let i=this.distElement.getBoundingClientRect();return{x:t-i.left,y:e-i.top}}checkTarget(t){return!this.app.getSettings().clickEventForward||!["a","button"].includes(t.tagName.toLowerCase())}}class S extends C{constructor(t,e,i,s){super(t,e,i),this.wrapper.insertAdjacentHTML("afterbegin",''),this.distElement=t.querySelector(".stf__block"),this.items=s;for(let n of s)this.distElement.appendChild(n);this.setHandlers()}clear(){for(let t of this.items)this.parentElement.appendChild(t)}updateItems(t){this.removeHandlers(),this.distElement.innerHTML="";for(let e of t)this.distElement.appendChild(e);this.items=t,this.setHandlers()}update(){this.app.getRender().update()}}class k extends C{constructor(t,e,i){super(t,e,i),this.wrapper.innerHTML='',this.canvas=t.querySelectorAll("canvas")[0],this.distElement=this.canvas,this.resizeCanvas(),this.setHandlers()}resizeCanvas(){let t=getComputedStyle(this.canvas),e=parseInt(t.getPropertyValue("width"),10),i=parseInt(t.getPropertyValue("height"),10);this.canvas.width=e,this.canvas.height=i}getCanvas(){return this.canvas}update(){this.resizeCanvas(),this.app.getRender().update()}}class M extends v{constructor(t,e,i){super(t,e),this.outerShadow=null,this.innerShadow=null,this.hardShadow=null,this.hardInnerShadow=null,this.element=i,this.createShadows()}createShadows(){this.element.insertAdjacentHTML("beforeend",`
+ z-index: ${this.render.getSettings().startZIndex+1};`}getElement(){return this.element}load(){this.isLoad=!0}setOrientation(t){super.setOrientation(t),this.element.classList.remove("--left","--right"),this.element.classList.add(t===1?"--right":"--left")}setDrawingDensity(t){this.element.classList.remove("--soft","--hard"),this.element.classList.add("--"+t),super.setDrawingDensity(t)}}class f extends c{constructor(t,e,i,s){super(t,e),this.element=i,this.pagesElement=s}load(){for(let t of this.pagesElement){let e=new m(this.render,t,t.dataset.density==="hard"?"hard":"soft");e.load(),this.pages.push(e)}this.createSpread()}}class P{constructor(t,e,i,s){this.direction=t,this.corner=e,this.topIntersectPoint=null,this.sideIntersectPoint=null,this.bottomIntersectPoint=null,this.pageWidth=parseInt(i,10),this.pageHeight=parseInt(s,10)}calc(t){try{return this.position=this.calcAngleAndPosition(t),this.calculateIntersectPoint(this.position),!0}catch{return!1}}getFlippingClipArea(){let t=[],e=!1;return t.push(this.rect.topLeft),t.push(this.topIntersectPoint),this.sideIntersectPoint===null?e=!0:(t.push(this.sideIntersectPoint),this.bottomIntersectPoint===null&&(e=!1)),t.push(this.bottomIntersectPoint),(e||this.corner==="bottom")&&t.push(this.rect.bottomLeft),t}getBottomClipArea(){let t=[];return t.push(this.topIntersectPoint),this.corner==="top"?t.push({x:this.pageWidth,y:0}):(this.topIntersectPoint!==null&&t.push({x:this.pageWidth,y:0}),t.push({x:this.pageWidth,y:this.pageHeight})),this.sideIntersectPoint!==null?g.GetDistanceBetweenTwoPoint(this.sideIntersectPoint,this.topIntersectPoint)>=10&&t.push(this.sideIntersectPoint):this.corner==="top"&&t.push({x:this.pageWidth,y:this.pageHeight}),t.push(this.bottomIntersectPoint),t.push(this.topIntersectPoint),t}getAngle(){return this.direction===0?-this.angle:this.angle}getRect(){return this.rect}getPosition(){return this.position}getActiveCorner(){return this.direction===0?this.rect.topLeft:this.rect.topRight}getDirection(){return this.direction}getFlippingProgress(){return Math.abs((this.position.x-this.pageWidth)/(2*this.pageWidth)*100)}getCorner(){return this.corner}getBottomPagePosition(){return this.direction===1?{x:this.pageWidth,y:0}:{x:0,y:0}}getShadowStartPoint(){return this.corner==="top"?this.topIntersectPoint:this.sideIntersectPoint!==null?this.sideIntersectPoint:this.topIntersectPoint}getShadowAngle(){let t=g.GetAngleBetweenTwoLine(this.getSegmentToShadowLine(),[{x:0,y:0},{x:this.pageWidth,y:0}]);return this.direction===0?t:Math.PI-t}calcAngleAndPosition(t){let e=t;if(this.updateAngleAndGeometry(e),e=this.corner==="top"?this.checkPositionAtCenterLine(e,{x:0,y:0},{x:0,y:this.pageHeight}):this.checkPositionAtCenterLine(e,{x:0,y:this.pageHeight},{x:0,y:0}),Math.abs(e.x-this.pageWidth)<1&&Math.abs(e.y)<1)throw new Error("Point is too small");return e}updateAngleAndGeometry(t){this.angle=this.calculateAngle(t),this.rect=this.getPageRect(t)}calculateAngle(t){let e=this.pageWidth-t.x+1,i=this.corner==="bottom"?this.pageHeight-t.y:t.y,s=2*Math.acos(e/Math.sqrt(i*i+e*e));i<0&&(s=-s);let n=Math.PI-s;if(!isFinite(s)||n>=0&&n<.003)throw new Error("The G point is too small");return this.corner==="bottom"&&(s=-s),s}getPageRect(t){return this.corner==="top"?this.getRectFromBasePoint([{x:0,y:0},{x:this.pageWidth,y:0},{x:0,y:this.pageHeight},{x:this.pageWidth,y:this.pageHeight}],t):this.getRectFromBasePoint([{x:0,y:-this.pageHeight},{x:this.pageWidth,y:-this.pageHeight},{x:0,y:0},{x:this.pageWidth,y:0}],t)}getRectFromBasePoint(t,e){return{topLeft:this.getRotatedPoint(t[0],e),topRight:this.getRotatedPoint(t[1],e),bottomLeft:this.getRotatedPoint(t[2],e),bottomRight:this.getRotatedPoint(t[3],e)}}getRotatedPoint(t,e){return{x:t.x*Math.cos(this.angle)+t.y*Math.sin(this.angle)+e.x,y:t.y*Math.cos(this.angle)-t.x*Math.sin(this.angle)+e.y}}calculateIntersectPoint(t){let e={left:-1,top:-1,width:this.pageWidth+2,height:this.pageHeight+2};this.corner==="top"?(this.topIntersectPoint=g.GetIntersectBetweenTwoSegment(e,[t,this.rect.topRight],[{x:0,y:0},{x:this.pageWidth,y:0}]),this.sideIntersectPoint=g.GetIntersectBetweenTwoSegment(e,[t,this.rect.bottomLeft],[{x:this.pageWidth,y:0},{x:this.pageWidth,y:this.pageHeight}]),this.bottomIntersectPoint=g.GetIntersectBetweenTwoSegment(e,[this.rect.bottomLeft,this.rect.bottomRight],[{x:0,y:this.pageHeight},{x:this.pageWidth,y:this.pageHeight}])):(this.topIntersectPoint=g.GetIntersectBetweenTwoSegment(e,[this.rect.topLeft,this.rect.topRight],[{x:0,y:0},{x:this.pageWidth,y:0}]),this.sideIntersectPoint=g.GetIntersectBetweenTwoSegment(e,[t,this.rect.topLeft],[{x:this.pageWidth,y:0},{x:this.pageWidth,y:this.pageHeight}]),this.bottomIntersectPoint=g.GetIntersectBetweenTwoSegment(e,[this.rect.bottomLeft,this.rect.bottomRight],[{x:0,y:this.pageHeight},{x:this.pageWidth,y:this.pageHeight}]))}checkPositionAtCenterLine(t,e,i){let s=t,n=g.LimitPointToCircle(e,this.pageWidth,s);s!==n&&(s=n,this.updateAngleAndGeometry(s));let o=Math.sqrt(Math.pow(this.pageWidth,2)+Math.pow(this.pageHeight,2)),h=this.rect.bottomRight,d=this.rect.topLeft;if(this.corner==="bottom"&&(h=this.rect.topRight,d=this.rect.bottomLeft),h.x<=0){let u=g.LimitPointToCircle(i,o,d);u!==s&&(s=u,this.updateAngleAndGeometry(s))}return s}getSegmentToShadowLine(){let t=this.getShadowStartPoint();return[t,t!==this.sideIntersectPoint&&this.sideIntersectPoint!==null?this.sideIntersectPoint:this.bottomIntersectPoint]}}class S{constructor(t,e){this.flippingPage=null,this.bottomPage=null,this.calc=null,this.state="read",this.render=t,this.app=e}fold(t){this.setState("user_fold"),this.calc===null&&this.start(t),this.do(this.render.convertToPage(t))}flip(t){if(this.app.getSettings().disableFlipByClick&&!this.isPointOnCorners(t)||(this.calc!==null&&this.render.finishAnimation(),!this.start(t)))return;let e=this.getBoundsRect();this.setState("flipping");let i=e.height/10,s=this.calc.getCorner()==="bottom"?e.height-i:i,n=this.calc.getCorner()==="bottom"?e.height:0;this.calc.calc({x:e.pageWidth-i,y:s}),this.animateFlippingTo({x:e.pageWidth-i,y:s},{x:-e.pageWidth,y:n},!0)}start(t){this.reset();let e=this.render.convertToBook(t),i=this.getBoundsRect(),s=this.getDirectionByPoint(e),n=e.y>=i.height/2?"bottom":"top";if(!this.checkDirection(s))return!1;try{if(this.flippingPage=this.app.getPageCollection().getFlippingPage(s),this.bottomPage=this.app.getPageCollection().getBottomPage(s),this.render.getOrientation()==="landscape")if(s===1){let o=this.app.getPageCollection().nextBy(this.flippingPage);o!==null&&this.flippingPage.getDensity()!==o.getDensity()&&(this.flippingPage.setDrawingDensity("hard"),o.setDrawingDensity("hard"))}else{let o=this.app.getPageCollection().prevBy(this.flippingPage);o!==null&&this.flippingPage.getDensity()!==o.getDensity()&&(this.flippingPage.setDrawingDensity("hard"),o.setDrawingDensity("hard"))}return this.render.setDirection(s),this.calc=new P(s,n,i.pageWidth.toString(10),i.height.toString(10)),!0}catch{return!1}}do(t){if(this.calc!==null&&this.calc.calc(t)){let e=this.calc.getFlippingProgress();this.bottomPage.setArea(this.calc.getBottomClipArea()),this.bottomPage.setPosition(this.calc.getBottomPagePosition()),this.bottomPage.setAngle(0),this.bottomPage.setHardAngle(0),this.flippingPage.setArea(this.calc.getFlippingClipArea()),this.flippingPage.setPosition(this.calc.getActiveCorner()),this.flippingPage.setAngle(this.calc.getAngle()),this.calc.getDirection()===0?this.flippingPage.setHardAngle(90*(200-2*e)/100):this.flippingPage.setHardAngle(-90*(200-2*e)/100),this.render.setPageRect(this.calc.getRect()),this.render.setBottomPage(this.bottomPage),this.render.setFlippingPage(this.flippingPage),this.render.setShadowData(this.calc.getShadowStartPoint(),this.calc.getShadowAngle(),e,this.calc.getDirection())}}flipToPage(t,e){let i=this.app.getPageCollection().getCurrentSpreadIndex(),s=this.app.getPageCollection().getSpreadIndexByPage(t);try{s>i&&(this.app.getPageCollection().setCurrentSpreadIndex(s-1),this.flipNext(e)),sthis.do(d));let h=this.getAnimationDuration(n.length);this.render.startAnimation(o,h,()=>{this.calc&&(i&&(this.calc.getDirection()===1?this.app.turnToPrevPage():this.app.turnToNextPage()),s&&(this.render.setBottomPage(null),this.render.setFlippingPage(null),this.render.clearShadow(),this.setState("read"),this.reset()))})}getCalculation(){return this.calc}getState(){return this.state}setState(t){this.state!==t&&(this.app.updateState(t),this.state=t)}getDirectionByPoint(t){let e=this.getBoundsRect();if(this.render.getOrientation()==="portrait"){if(t.x-e.pageWidth<=e.width/5)return 1}else if(t.x=1e3?e:t/1e3*e}checkDirection(t){return t===0?this.app.getCurrentPageIndex()=1}reset(){this.calc=null,this.flippingPage=null,this.bottomPage=null}getBoundsRect(){return this.render.getRect()}checkState(...t){for(let e of t)if(this.state===e)return!0;return!1}isPointOnCorners(t){let e=this.getBoundsRect(),i=e.pageWidth,s=Math.sqrt(Math.pow(i,2)+Math.pow(e.height,2))/5,n=this.render.convertToBook(t);return n.x>0&&n.y>0&&n.xe.width-s)&&(n.ye.height-s)}}class v{constructor(t,e){this.leftPage=null,this.rightPage=null,this.flippingPage=null,this.bottomPage=null,this.direction=null,this.orientation=null,this.shadow=null,this.animation=null,this.pageRect=null,this.boundsRect=null,this.timer=0,this.safari=!1,this.setting=e,this.app=t;let i=new RegExp("Version\\/[\\d\\.]+.*Safari/");this.safari=i.exec(window.navigator.userAgent)!==null}render(t){if(this.animation!==null){let e=Math.round((t-this.animation.startedAt)/this.animation.durationFrame);e{this.render(e),requestAnimationFrame(t)};requestAnimationFrame(t)}startAnimation(t,e,i){this.finishAnimation(),this.animation={frames:t,duration:e,durationFrame:e/t.length,onAnimateEnd:i,startedAt:this.timer}}finishAnimation(){this.animation!==null&&(this.animation.frames[this.animation.frames.length-1](),this.animation.onAnimateEnd!==null&&this.animation.onAnimateEnd()),this.animation=null}update(){this.boundsRect=null;let t=this.calculateBoundsRect();this.orientation!==t&&(this.orientation=t,this.app.updateOrientation(t))}calculateBoundsRect(){let t="landscape",e=this.getBlockWidth(),i=e/2,s=this.getBlockHeight()/2,n=this.setting.width/this.setting.height,o=this.setting.width,h=this.setting.height,d=i-o;return this.setting.size==="stretch"?(e<2*this.setting.minWidth&&this.app.getSettings().usePortrait&&(t="portrait"),o=t==="portrait"?this.getBlockWidth():this.getBlockWidth()/2,o>this.setting.maxWidth&&(o=this.setting.maxWidth),h=o/n,h>this.getBlockHeight()&&(h=this.getBlockHeight(),o=h*n),d=t==="portrait"?i-o/2-o:i-o):e<2*o&&this.app.getSettings().usePortrait&&(t="portrait",d=i-o/2-o),this.boundsRect={left:d,top:s-h/2,width:2*o,height:h,pageWidth:o},t}setShadowData(t,e,i,s){if(!this.app.getSettings().drawShadow)return;let n=100*this.getSettings().maxShadowOpacity;this.shadow={pos:t,angle:e,width:3*this.getRect().pageWidth/4*i/100,opacity:(100-i)*n/100/100,direction:s,progress:2*i}}clearShadow(){this.shadow=null}getBlockWidth(){return this.app.getUI().getDistElement().offsetWidth}getBlockHeight(){return this.app.getUI().getDistElement().offsetHeight}getDirection(){return this.direction}getRect(){return this.boundsRect===null&&this.calculateBoundsRect(),this.boundsRect}getSettings(){return this.app.getSettings()}getOrientation(){return this.orientation}setPageRect(t){this.pageRect=t}setDirection(t){this.direction=t}setRightPage(t){t!==null&&t.setOrientation(1),this.rightPage=t}setLeftPage(t){t!==null&&t.setOrientation(0),this.leftPage=t}setBottomPage(t){t!==null&&t.setOrientation(this.direction===1?0:1),this.bottomPage=t}setFlippingPage(t){t!==null&&t.setOrientation(this.direction===0&&this.orientation!=="portrait"?0:1),this.flippingPage=t}convertToBook(t){let e=this.getRect();return{x:t.x-e.left,y:t.y-e.top}}isSafari(){return this.safari}convertToPage(t,e){e||(e=this.direction);let i=this.getRect();return{x:e===0?t.x-i.left-i.width/2:i.width/2-t.x+i.left,y:t.y-i.top}}convertToGlobal(t,e){if(e||(e=this.direction),t==null)return null;let i=this.getRect();return{x:e===0?t.x+i.left+i.width/2:i.width/2-t.x+i.left,y:t.y+i.top}}convertRectToGlobal(t,e){return e||(e=this.direction),{topLeft:this.convertToGlobal(t.topLeft,e),topRight:this.convertToGlobal(t.topRight,e),bottomLeft:this.convertToGlobal(t.bottomLeft,e),bottomRight:this.convertToGlobal(t.bottomRight,e)}}}class I extends v{constructor(t,e,i){super(t,e),this.canvas=i,this.ctx=i.getContext("2d")}getContext(){return this.ctx}reload(){}drawFrame(){this.clear(),this.orientation!=="portrait"&&this.leftPage!=null&&this.leftPage.simpleDraw(0),this.rightPage!=null&&this.rightPage.simpleDraw(1),this.bottomPage!=null&&this.bottomPage.draw(),this.drawBookShadow(),this.flippingPage!=null&&this.flippingPage.draw(),this.shadow!=null&&(this.drawOuterShadow(),this.drawInnerShadow());let t=this.getRect();this.orientation==="portrait"&&(this.ctx.beginPath(),this.ctx.rect(t.left+t.pageWidth,t.top,t.width,t.height),this.ctx.clip())}drawBookShadow(){let t=this.getRect();this.ctx.save(),this.ctx.beginPath();let e=t.width/20;this.ctx.rect(t.left,t.top,t.width,t.height);let i={x:t.left+t.width/2-e/2,y:0};this.ctx.translate(i.x,i.y);let s=this.ctx.createLinearGradient(0,0,e,0);s.addColorStop(0,"rgba(0, 0, 0, 0)"),s.addColorStop(.4,"rgba(0, 0, 0, 0.2)"),s.addColorStop(.49,"rgba(0, 0, 0, 0.1)"),s.addColorStop(.5,"rgba(0, 0, 0, 0.5)"),s.addColorStop(.51,"rgba(0, 0, 0, 0.4)"),s.addColorStop(1,"rgba(0, 0, 0, 0)"),this.ctx.clip(),this.ctx.fillStyle=s,this.ctx.fillRect(0,0,e,2*t.height),this.ctx.restore()}drawOuterShadow(){let t=this.getRect();this.ctx.save(),this.ctx.beginPath(),this.ctx.rect(t.left,t.top,t.width,t.height);let e=this.convertToGlobal({x:this.shadow.pos.x,y:this.shadow.pos.y});this.ctx.translate(e.x,e.y),this.ctx.rotate(Math.PI+this.shadow.angle+Math.PI/2);let i=this.ctx.createLinearGradient(0,0,this.shadow.width,0);this.shadow.direction===0?(this.ctx.translate(0,-100),i.addColorStop(0,"rgba(0, 0, 0, "+this.shadow.opacity+")"),i.addColorStop(1,"rgba(0, 0, 0, 0)")):(this.ctx.translate(-this.shadow.width,-100),i.addColorStop(0,"rgba(0, 0, 0, 0)"),i.addColorStop(1,"rgba(0, 0, 0, "+this.shadow.opacity+")")),this.ctx.clip(),this.ctx.fillStyle=i,this.ctx.fillRect(0,0,this.shadow.width,2*t.height),this.ctx.restore()}drawInnerShadow(){let t=this.getRect();this.ctx.save(),this.ctx.beginPath();let e=this.convertToGlobal({x:this.shadow.pos.x,y:this.shadow.pos.y}),i=this.convertRectToGlobal(this.pageRect);this.ctx.moveTo(i.topLeft.x,i.topLeft.y),this.ctx.lineTo(i.topRight.x,i.topRight.y),this.ctx.lineTo(i.bottomRight.x,i.bottomRight.y),this.ctx.lineTo(i.bottomLeft.x,i.bottomLeft.y),this.ctx.translate(e.x,e.y),this.ctx.rotate(Math.PI+this.shadow.angle+Math.PI/2);let s=3*this.shadow.width/4,n=this.ctx.createLinearGradient(0,0,s,0);this.shadow.direction===0?(this.ctx.translate(-s,-100),n.addColorStop(1,"rgba(0, 0, 0, "+this.shadow.opacity+")"),n.addColorStop(.9,"rgba(0, 0, 0, 0.05)"),n.addColorStop(.7,"rgba(0, 0, 0, "+this.shadow.opacity+")"),n.addColorStop(0,"rgba(0, 0, 0, 0)")):(this.ctx.translate(0,-100),n.addColorStop(0,"rgba(0, 0, 0, "+this.shadow.opacity+")"),n.addColorStop(.1,"rgba(0, 0, 0, 0.05)"),n.addColorStop(.3,"rgba(0, 0, 0, "+this.shadow.opacity+")"),n.addColorStop(1,"rgba(0, 0, 0, 0)")),this.ctx.clip(),this.ctx.fillStyle=n,this.ctx.fillRect(0,0,s,2*t.height),this.ctx.restore()}clear(){this.ctx.fillStyle="white",this.ctx.fillRect(0,0,this.canvas.width,this.canvas.height)}}class T{constructor(t,e,i){this.touchPoint=null,this.swipeTimeout=250,this.onResize=()=>{this.update()},this.onMouseDown=n=>{if(this.checkTarget(n.target)){let o=this.getMousePos(n.clientX,n.clientY);this.app.startUserTouch(o),n.preventDefault()}},this.onTouchStart=n=>{if(this.checkTarget(n.target)&&n.changedTouches.length>0){let o=n.changedTouches[0],h=this.getMousePos(o.clientX,o.clientY);this.touchPoint={point:h,time:Date.now()},setTimeout(()=>{this.touchPoint!==null&&this.app.startUserTouch(h)},this.swipeTimeout),this.app.getSettings().mobileScrollSupport||n.preventDefault()}},this.onMouseUp=n=>{let o=this.getMousePos(n.clientX,n.clientY);this.app.userStop(o)},this.onMouseMove=n=>{let o=this.getMousePos(n.clientX,n.clientY);this.app.userMove(o,!1)},this.onTouchMove=n=>{if(n.changedTouches.length>0){let o=n.changedTouches[0],h=this.getMousePos(o.clientX,o.clientY);this.app.getSettings().mobileScrollSupport?(this.touchPoint!==null&&(Math.abs(this.touchPoint.point.x-h.x)>10||this.app.getState()!=="read")&&n.cancelable&&this.app.userMove(h,!0),this.app.getState()!=="read"&&n.preventDefault()):this.app.userMove(h,!0)}},this.onTouchEnd=n=>{if(n.changedTouches.length>0){let o=n.changedTouches[0],h=this.getMousePos(o.clientX,o.clientY),d=!1;if(this.touchPoint!==null){let u=h.x-this.touchPoint.point.x,x=Math.abs(h.y-this.touchPoint.point.y);Math.abs(u)>this.swipeDistance&&x<2*this.swipeDistance&&Date.now()-this.touchPoint.time0?this.app.flipPrev(this.touchPoint.point.y'),this.wrapper=t.querySelector(".stf__wrapper"),this.app=e;let s=this.app.getSettings().usePortrait?1:2;t.style.minWidth=i.minWidth*s+"px",t.style.minHeight=i.minHeight+"px",i.size==="fixed"&&(t.style.minWidth=i.width*s+"px",t.style.minHeight=i.height+"px"),i.autoSize&&(t.style.width="100%",t.style.maxWidth=2*i.maxWidth+"px"),t.style.display="block",window.addEventListener("resize",this.onResize,!1),this.swipeDistance=i.swipeDistance}destroy(){this.app.getSettings().useMouseEvents&&this.removeHandlers(),this.distElement.remove(),this.wrapper.remove()}getDistElement(){return this.distElement}getWrapper(){return this.wrapper}setOrientationStyle(t){this.wrapper.classList.remove("--portrait","--landscape"),t==="portrait"?(this.app.getSettings().autoSize&&(this.wrapper.style.paddingBottom=this.app.getSettings().height/this.app.getSettings().width*100+"%"),this.wrapper.classList.add("--portrait")):(this.app.getSettings().autoSize&&(this.wrapper.style.paddingBottom=this.app.getSettings().height/(2*this.app.getSettings().width)*100+"%"),this.wrapper.classList.add("--landscape")),this.update()}removeHandlers(){window.removeEventListener("resize",this.onResize),this.distElement.removeEventListener("mousedown",this.onMouseDown),this.distElement.removeEventListener("touchstart",this.onTouchStart),window.removeEventListener("mousemove",this.onMouseMove),window.removeEventListener("touchmove",this.onTouchMove),window.removeEventListener("mouseup",this.onMouseUp),window.removeEventListener("touchend",this.onTouchEnd)}setHandlers(){window.addEventListener("resize",this.onResize,!1),this.app.getSettings().useMouseEvents&&(this.distElement.addEventListener("mousedown",this.onMouseDown),this.distElement.addEventListener("touchstart",this.onTouchStart),window.addEventListener("mousemove",this.onMouseMove),window.addEventListener("touchmove",this.onTouchMove,{passive:!this.app.getSettings().mobileScrollSupport}),window.addEventListener("mouseup",this.onMouseUp),window.addEventListener("touchend",this.onTouchEnd))}getMousePos(t,e){let i=this.distElement.getBoundingClientRect();return{x:t-i.left,y:e-i.top}}checkTarget(t){return!this.app.getSettings().clickEventForward||!["a","button"].includes(t.tagName.toLowerCase())}}class b extends T{constructor(t,e,i,s){super(t,e,i),this.wrapper.insertAdjacentHTML("afterbegin",''),this.distElement=t.querySelector(".stf__block"),this.items=s;for(let n of s)this.distElement.appendChild(n);this.setHandlers()}clear(){for(let t of this.items)this.parentElement.appendChild(t)}updateItems(t){this.removeHandlers(),this.distElement.innerHTML="";for(let e of t)this.distElement.appendChild(e);this.items=t,this.setHandlers()}update(){this.app.getRender().update()}}class D extends T{constructor(t,e,i){super(t,e,i),this.wrapper.innerHTML='',this.canvas=t.querySelectorAll("canvas")[0],this.distElement=this.canvas,this.resizeCanvas(),this.setHandlers()}resizeCanvas(){let t=getComputedStyle(this.canvas),e=parseInt(t.getPropertyValue("width"),10),i=parseInt(t.getPropertyValue("height"),10);this.canvas.width=e,this.canvas.height=i}getCanvas(){return this.canvas}update(){this.resizeCanvas(),this.app.getRender().update()}}class M extends v{constructor(t,e,i){super(t,e),this.outerShadow=null,this.innerShadow=null,this.hardShadow=null,this.hardInnerShadow=null,this.element=i,this.createShadows()}createShadows(){this.element.insertAdjacentHTML("beforeend",`
`),this.outerShadow=this.element.querySelector(".stf__outerShadow"),this.innerShadow=this.element.querySelector(".stf__innerShadow"),this.hardShadow=this.element.querySelector(".stf__hardShadow"),this.hardInnerShadow=this.element.querySelector(".stf__hardInnerShadow")}clearShadow(){super.clearShadow(),this.outerShadow.style.cssText="display: none",this.innerShadow.style.cssText="display: none",this.hardShadow.style.cssText="display: none",this.hardInnerShadow.style.cssText="display: none"}reload(){this.element.querySelector(".stf__outerShadow")||this.createShadows()}drawHardInnerShadow(){let t=this.getRect(),e=this.shadow.progress>100?200-this.shadow.progress:this.shadow.progress,i=(100-e)*(2.5*t.pageWidth)/100+20;i>t.pageWidth&&(i=t.pageWidth);let s=`
@@ -40,7 +40,7 @@ var V=Object.create;var O=Object.defineProperty;var j=Object.getOwnPropertyDescr
background: linear-gradient(to left, rgba(0, 0, 0, ${this.shadow.opacity}) 5%, rgba(0, 0, 0, 0) 100%);
left: ${t.left+t.width/2}px;
transform-origin: 0 0;
- `;i+=this.getDirection()===0&&this.shadow.progress>100||this.getDirection()===1&&this.shadow.progress<=100?"transform: translate3d(0, 0, 0) rotateY(180deg);":"transform: translate3d(0, 0, 0);",this.hardShadow.style.cssText=i}drawInnerShadow(){let t=this.getRect(),e=3*this.shadow.width/4,i=this.getDirection()===0?e:0,s=this.getDirection()===0?"to left":"to right",n=this.convertToGlobal(this.shadow.pos),o=this.shadow.angle+3*Math.PI/2,h=[this.pageRect.topLeft,this.pageRect.topRight,this.pageRect.bottomRight,this.pageRect.bottomLeft],d="polygon( ";for(let x of h){let T=this.getDirection()===1?{x:-x.x+this.shadow.pos.x,y:x.y-this.shadow.pos.y}:{x:x.x-this.shadow.pos.x,y:x.y-this.shadow.pos.y};T=g.GetRotatedPoint(T,{x:i,y:100},o),d+=T.x+"px "+T.y+"px, "}d=d.slice(0,-2),d+=")";let u=`
+ `;i+=this.getDirection()===0&&this.shadow.progress>100||this.getDirection()===1&&this.shadow.progress<=100?"transform: translate3d(0, 0, 0) rotateY(180deg);":"transform: translate3d(0, 0, 0);",this.hardShadow.style.cssText=i}drawInnerShadow(){let t=this.getRect(),e=3*this.shadow.width/4,i=this.getDirection()===0?e:0,s=this.getDirection()===0?"to left":"to right",n=this.convertToGlobal(this.shadow.pos),o=this.shadow.angle+3*Math.PI/2,h=[this.pageRect.topLeft,this.pageRect.topRight,this.pageRect.bottomRight,this.pageRect.bottomLeft],d="polygon( ";for(let x of h){let C=this.getDirection()===1?{x:-x.x+this.shadow.pos.x,y:x.y-this.shadow.pos.y}:{x:x.x-this.shadow.pos.x,y:x.y-this.shadow.pos.y};C=g.GetRotatedPoint(C,{x:i,y:100},o),d+=C.x+"px "+C.y+"px, "}d=d.slice(0,-2),d+=")";let u=`
display: block;
z-index: ${(this.getSettings().startZIndex+10).toString(10)};
width: ${e}px;
@@ -64,7 +64,7 @@ var V=Object.create;var O=Object.defineProperty;var j=Object.getOwnPropertyDescr
transform: translate3d(${e.x-s}px, ${e.y-100}px, 0) rotate(${i}rad);
clip-path: ${h};
-webkit-clip-path: ${h};
- `;this.outerShadow.style.cssText=d}drawLeftPage(){this.orientation!=="portrait"&&this.leftPage!==null&&(this.direction===1&&this.flippingPage!==null&&this.flippingPage.getDrawingDensity()==="hard"?(this.leftPage.getElement().style.zIndex=(this.getSettings().startZIndex+5).toString(10),this.leftPage.setHardDrawingAngle(180+this.flippingPage.getHardAngle()),this.leftPage.draw(this.flippingPage.getDrawingDensity())):this.leftPage.simpleDraw(0))}drawRightPage(){this.rightPage!==null&&(this.direction===0&&this.flippingPage!==null&&this.flippingPage.getDrawingDensity()==="hard"?(this.rightPage.getElement().style.zIndex=(this.getSettings().startZIndex+5).toString(10),this.rightPage.setHardDrawingAngle(180+this.flippingPage.getHardAngle()),this.rightPage.draw(this.flippingPage.getDrawingDensity())):this.rightPage.simpleDraw(1))}drawBottomPage(){if(this.bottomPage===null)return;let t=this.flippingPage!=null?this.flippingPage.getDrawingDensity():null;this.orientation==="portrait"&&this.direction===1||(this.bottomPage.getElement().style.zIndex=(this.getSettings().startZIndex+3).toString(10),this.bottomPage.draw(t))}drawFrame(){this.clear(),this.drawLeftPage(),this.drawRightPage(),this.drawBottomPage(),this.flippingPage!=null&&(this.flippingPage.getElement().style.zIndex=(this.getSettings().startZIndex+5).toString(10),this.flippingPage.draw()),this.shadow!=null&&this.flippingPage!==null&&(this.flippingPage.getDrawingDensity()==="soft"?(this.drawOuterShadow(),this.drawInnerShadow()):(this.drawHardOuterShadow(),this.drawHardInnerShadow()))}clear(){for(let t of this.app.getPageCollection().getPages())t!==this.leftPage&&t!==this.rightPage&&t!==this.flippingPage&&t!==this.bottomPage&&(t.getElement().style.cssText="display: none"),t.getTemporaryCopy()!==this.flippingPage&&t.hideTemporaryCopy()}update(){super.update(),this.rightPage!==null&&this.rightPage.setOrientation(1),this.leftPage!==null&&this.leftPage.setOrientation(0)}}class R{constructor(){this._default={startPage:0,size:"fixed",width:0,height:0,minWidth:0,maxWidth:0,minHeight:0,maxHeight:0,drawShadow:!0,flippingTime:1e3,usePortrait:!0,startZIndex:0,autoSize:!0,maxShadowOpacity:1,showCover:!1,mobileScrollSupport:!0,swipeDistance:30,clickEventForward:!0,useMouseEvents:!0,showPageCorners:!0,disableFlipByClick:!1}}getSettings(t){let e=this._default;if(Object.assign(e,t),e.size!=="stretch"&&e.size!=="fixed")throw new Error('Invalid size type. Available only "fixed" and "stretch" value');if(e.width<=0||e.height<=0)throw new Error("Invalid width or height");if(e.flippingTime<=0)throw new Error("Invalid flipping time");return e.size==="stretch"?(e.minWidth<=0&&(e.minWidth=100),e.maxWidth{this.ui.update(),this.trigger("init",this,{page:this.setting.startPage,mode:this.render.getOrientation()})},1)}loadFromHTML(r){this.ui=new S(this.block,this,this.setting,r),this.render=new M(this,this.setting,this.ui.getDistElement()),this.flipController=new b(this.render,this),this.pages=new f(this,this.render,this.ui.getDistElement(),r),this.pages.load(),this.render.start(),this.pages.show(this.setting.startPage),setTimeout(()=>{this.ui.update(),this.trigger("init",this,{page:this.setting.startPage,mode:this.render.getOrientation()})},1)}updateFromImages(r){let t=this.pages.getCurrentPageIndex();this.pages.destroy(),this.pages=new m(this,this.render,r),this.pages.load(),this.pages.show(t),this.trigger("update",this,{page:t,mode:this.render.getOrientation()})}updateFromHtml(r){let t=this.pages.getCurrentPageIndex();this.pages.destroy(),this.pages=new f(this,this.render,this.ui.getDistElement(),r),this.pages.load(),this.ui.updateItems(r),this.render.reload(),this.pages.show(t),this.trigger("update",this,{page:t,mode:this.render.getOrientation()})}clear(){this.pages.destroy(),this.ui.clear()}turnToPrevPage(){this.pages.showPrev()}turnToNextPage(){this.pages.showNext()}turnToPage(r){this.pages.show(r)}flipNext(r="top"){this.flipController.flipNext(r)}flipPrev(r="top"){this.flipController.flipPrev(r)}flip(r,t="top"){this.flipController.flipToPage(r,t)}updateState(r){this.trigger("changeState",this,r)}updatePageIndex(r){this.trigger("flip",this,r)}updateOrientation(r){this.ui.setOrientationStyle(r),this.update(),this.trigger("changeOrientation",this,r)}getPageCount(){return this.pages.getPageCount()}getCurrentPageIndex(){return this.pages.getCurrentPageIndex()}getPage(r){return this.pages.getPage(r)}getRender(){return this.render}getFlipController(){return this.flipController}getOrientation(){return this.render.getOrientation()}getBoundsRect(){return this.render.getRect()}getSettings(){return this.setting}getUI(){return this.ui}getState(){return this.flipController.getState()}getPageCollection(){return this.pages}startUserTouch(r){this.mousePosition=r,this.isUserTouch=!0,this.isUserMove=!1}userMove(r,t){this.isUserTouch||t||!this.setting.showPageCorners?this.isUserTouch&&g.GetDistanceBetweenTwoPoint(this.mousePosition,r)>5&&(this.isUserMove=!0,this.flipController.fold(r)):this.flipController.showCorner(r)}userStop(r,t=!1){this.isUserTouch&&(this.isUserTouch=!1,t||(this.isUserMove?this.flipController.stopMove():this.flipController.flip(r)))}},Object.defineProperty(a,"__esModule",{value:!0})}))});var A={startPage:0,singlePageBreakpoint:640,chromeHeight:150,chromeWidth:48,maxPageHeight:1100,flippingTime:700,drawShadow:!0,maxShadowOpacity:.4,keyboard:!0};function z(a,p){let l=p.chromeHeight??A.chromeHeight,c=p.chromeWidth??A.chromeWidth,m=Math.min(p.viewportHeight-l,p.maxPageHeight??A.maxPageHeight),g=p.viewportWidth-c,w=Math.max(m,120),f=w*a,P=p.single?f:f*2;if(P>g){let b=g/P;f*=b,w*=b}return{width:Math.round(f),height:Math.round(w)}}async function B(a,p){let l={...A,...p};if(!l.pages.length)throw new Error("mountFlipbook: `pages` is empty");let m=(await Promise.resolve().then(()=>Q(G(),1))).PageFlip,g=null,w=Math.min(Math.max(l.startPage,0),l.pages.length-1),f=!1,P=null,b=()=>{if(f)return;let S=l.singlePageBreakpoint>0&&window.matchMedia(`(max-width: ${l.singlePageBreakpoint}px)`).matches,{width:k,height:M}=z(l.aspect,{single:S,viewportWidth:window.innerWidth,viewportHeight:window.innerHeight,chromeWidth:l.chromeWidth,chromeHeight:l.chromeHeight,maxPageHeight:l.maxPageHeight});if(g=new m(a,{width:k,height:M,size:"fixed",showCover:!0,usePortrait:S,maxShadowOpacity:l.maxShadowOpacity,mobileScrollSupport:!0,flippingTime:l.flippingTime,drawShadow:l.drawShadow}),g.loadFromImages(l.pages.slice()),g.on("flip",R=>{w=R.data,l.onFlip?.(w)}),w>0)try{g.turnToPage(w)}catch{}l.onReady?.()},v=()=>{if(g){try{g.destroy()}catch{}g=null,a.innerHTML=""}},I=()=>{P&&clearTimeout(P),P=setTimeout(()=>{v(),b()},200)},C=S=>{S.key==="ArrowLeft"?g?.flipPrev():S.key==="ArrowRight"&&g?.flipNext()};return b(),window.addEventListener("resize",I),l.keyboard&&document.addEventListener("keydown",C),{next:()=>g?.flipNext(),prev:()=>g?.flipPrev(),goTo:S=>g?.turnToPage(S),currentPage:()=>w,pageCount:()=>l.pages.length,destroy:()=>{f||(f=!0,P&&clearTimeout(P),window.removeEventListener("resize",I),document.removeEventListener("keydown",C),v())}}}function y(a,p,l){let c=document.createElement(a);return p&&(c.className=p),l!=null&&(c.textContent=l),c}async function H(a){let p=a.container??document.body,l=a.pages.length,c=y("div",`rab-overlay${a.className?` ${a.className}`:""}`);c.setAttribute("role","dialog"),c.setAttribute("aria-modal","true"),c.setAttribute("aria-label",`${a.title??"Document"} \u2014 page view`);let m=y("div","rab-chrome");m.append(y("span","rab-title",a.title??""));let g=y("div","rab-actions"),w=y("span","rab-counter");if(g.append(w),a.pdfUrl){let n=y("a","rab-btn rab-download","Download PDF \u2197");n.href=a.pdfUrl,n.target="_blank",n.rel="noopener noreferrer",g.append(n)}let f=y("button","rab-btn","Close \u2715");f.type="button",f.setAttribute("aria-label","Close book view"),g.append(f),m.append(g);let P=y("div","rab-stage"),b=y("button","rab-arrow rab-arrow-prev","\u2039");b.type="button",b.setAttribute("aria-label","Previous page");let v=y("button","rab-arrow rab-arrow-next","\u203A");v.type="button",v.setAttribute("aria-label","Next page");let I=y("div","rab-book"),C=y("p","rab-loading","Opening the book\u2026"),S=y("div","rab-book-wrap");S.append(I,C),P.append(b,S,v);let k=a.hint??"Use the arrows or \u2190 \u2192 keys to turn pages \xB7 Esc to close",M=y("p","rab-hint",k);c.append(m,P),k&&c.append(M),p.append(c);let R=n=>{w.textContent=l?`${Math.min(n+1,l)} / ${l}`:""};R(a.startPage??0);let r=document.body.style.overflow;document.body.style.overflow="hidden";let t=null,e=!1,i=()=>{e||(e=!0,document.removeEventListener("keydown",s),document.body.style.overflow=r,t?.destroy(),c.remove(),a.onClose?.())},s=n=>{n.key==="Escape"&&i()};document.addEventListener("keydown",s),f.addEventListener("click",i);try{t=await B(I,{pages:a.pages,aspect:a.aspect,startPage:a.startPage,onFlip:n=>{R(n),a.onFlip?.(n)},onReady:()=>C.remove()})}catch(n){throw i(),n}return e?(t.destroy(),{close:i,next:()=>{},prev:()=>{}}):(b.addEventListener("click",()=>t?.prev()),v.addEventListener("click",()=>t?.next()),{close:i,next:()=>t?.next(),prev:()=>t?.prev()})}async function U(a,p){let l=await fetch(a,p);if(!l.ok)throw new Error(`read-as-book: could not load ${a} (${l.status})`);let c=await l.json(),m=new URL(a,globalThis.location?.href??"http://localhost/");return{...c,pages:c.pages.map(g=>new URL(g.split("/").pop(),m).toString())}}var $=document.querySelector("#open-research-book"),D=document.querySelector("#book-status"),W,F=!1;function N(){return W??(W=U("book/pages/manifest.json")),W}async function q(){if(!F){F=!0,$.disabled=!0,D.textContent="Loading the page-turn edition...";try{let a=await N();await H({pages:a.pages,aspect:a.aspect,title:"Auditable Emergent Communication Between Isolated Artificial Agents",pdfUrl:"book/research.pdf",hint:"Use the arrow keys or page controls to turn pages. Press Esc to close.",className:"research-book-overlay",onClose:()=>{D.textContent=`${a.pageCount} pages available`}}),D.textContent=`${a.pageCount} pages available`}catch(a){console.error(a),D.textContent="The book could not open. Use the Markdown or PDF links instead."}finally{F=!1,$.disabled=!1}}}$.addEventListener("click",q);N().then(a=>{D.textContent=`${a.pageCount} pages available`}).catch(a=>{console.error(a),D.textContent="Book metadata is unavailable. Use the Markdown or PDF links instead."});new URLSearchParams(globalThis.location.search).get("open")==="1"&&globalThis.requestAnimationFrame(()=>{q()});
+}`),r.PageFlip=class extends class{constructor(){this.events=new Map}on(a,t){return this.events.has(a)?this.events.get(a).push(t):this.events.set(a,[t]),this}off(a){this.events.delete(a)}trigger(a,t,e=null){if(this.events.has(a))for(let i of this.events.get(a))i({data:e,object:t})}}{constructor(a,t){super(),this.isUserTouch=!1,this.isUserMove=!1,this.setting=null,this.pages=null,this.setting=new R().getSettings(t),this.block=a}destroy(){this.ui.destroy(),this.block.remove()}update(){this.render.update(),this.pages.show()}loadFromImages(a){this.ui=new D(this.block,this,this.setting);let t=this.ui.getCanvas();this.render=new I(this,this.setting,t),this.flipController=new S(this.render,this),this.pages=new w(this,this.render,a),this.pages.load(),this.render.start(),this.pages.show(this.setting.startPage),setTimeout(()=>{this.ui.update(),this.trigger("init",this,{page:this.setting.startPage,mode:this.render.getOrientation()})},1)}loadFromHTML(a){this.ui=new b(this.block,this,this.setting,a),this.render=new M(this,this.setting,this.ui.getDistElement()),this.flipController=new S(this.render,this),this.pages=new f(this,this.render,this.ui.getDistElement(),a),this.pages.load(),this.render.start(),this.pages.show(this.setting.startPage),setTimeout(()=>{this.ui.update(),this.trigger("init",this,{page:this.setting.startPage,mode:this.render.getOrientation()})},1)}updateFromImages(a){let t=this.pages.getCurrentPageIndex();this.pages.destroy(),this.pages=new w(this,this.render,a),this.pages.load(),this.pages.show(t),this.trigger("update",this,{page:t,mode:this.render.getOrientation()})}updateFromHtml(a){let t=this.pages.getCurrentPageIndex();this.pages.destroy(),this.pages=new f(this,this.render,this.ui.getDistElement(),a),this.pages.load(),this.ui.updateItems(a),this.render.reload(),this.pages.show(t),this.trigger("update",this,{page:t,mode:this.render.getOrientation()})}clear(){this.pages.destroy(),this.ui.clear()}turnToPrevPage(){this.pages.showPrev()}turnToNextPage(){this.pages.showNext()}turnToPage(a){this.pages.show(a)}flipNext(a="top"){this.flipController.flipNext(a)}flipPrev(a="top"){this.flipController.flipPrev(a)}flip(a,t="top"){this.flipController.flipToPage(a,t)}updateState(a){this.trigger("changeState",this,a)}updatePageIndex(a){this.trigger("flip",this,a)}updateOrientation(a){this.ui.setOrientationStyle(a),this.update(),this.trigger("changeOrientation",this,a)}getPageCount(){return this.pages.getPageCount()}getCurrentPageIndex(){return this.pages.getCurrentPageIndex()}getPage(a){return this.pages.getPage(a)}getRender(){return this.render}getFlipController(){return this.flipController}getOrientation(){return this.render.getOrientation()}getBoundsRect(){return this.render.getRect()}getSettings(){return this.setting}getUI(){return this.ui}getState(){return this.flipController.getState()}getPageCollection(){return this.pages}startUserTouch(a){this.mousePosition=a,this.isUserTouch=!0,this.isUserMove=!1}userMove(a,t){this.isUserTouch||t||!this.setting.showPageCorners?this.isUserTouch&&g.GetDistanceBetweenTwoPoint(this.mousePosition,a)>5&&(this.isUserMove=!0,this.flipController.fold(a)):this.flipController.showCorner(a)}userStop(a,t=!1){this.isUserTouch&&(this.isUserTouch=!1,t||(this.isUserMove?this.flipController.stopMove():this.flipController.flip(a)))}},Object.defineProperty(r,"__esModule",{value:!0})}))});var E={startPage:0,singlePageBreakpoint:640,chromeHeight:150,chromeWidth:48,maxPageHeight:1100,flippingTime:700,drawShadow:!0,maxShadowOpacity:.4,keyboard:!0};function z(r,p){let l=p.chromeHeight??E.chromeHeight,c=p.chromeWidth??E.chromeWidth,w=Math.min(p.viewportHeight-l,p.maxPageHeight??E.maxPageHeight),g=p.viewportWidth-c,m=Math.max(w,120),f=m*r,P=p.single?f:f*2;if(P>g){let S=g/P;f*=S,m*=S}return{width:Math.round(f),height:Math.round(m)}}async function W(r,p){let l={...E,...p};if(!l.pages.length)throw new Error("mountFlipbook: `pages` is empty");let w=(await Promise.resolve().then(()=>Q(G(),1))).PageFlip,g=null,m=Math.min(Math.max(l.startPage,0),l.pages.length-1),f=!1,P=null,S=()=>{if(f)return;let b=l.singlePageBreakpoint>0&&window.matchMedia(`(max-width: ${l.singlePageBreakpoint}px)`).matches,{width:D,height:M}=z(l.aspect,{single:b,viewportWidth:window.innerWidth,viewportHeight:window.innerHeight,chromeWidth:l.chromeWidth,chromeHeight:l.chromeHeight,maxPageHeight:l.maxPageHeight});if(g=new w(r,{width:D,height:M,size:"fixed",showCover:!0,usePortrait:b,maxShadowOpacity:l.maxShadowOpacity,mobileScrollSupport:!0,flippingTime:l.flippingTime,drawShadow:l.drawShadow}),g.loadFromImages(l.pages.slice()),g.on("flip",R=>{m=R.data,l.onFlip?.(m)}),m>0)try{g.turnToPage(m)}catch{}l.onReady?.()},v=()=>{if(g){try{g.destroy()}catch{}g=null,r.innerHTML=""}},I=()=>{P&&clearTimeout(P),P=setTimeout(()=>{v(),S()},200)},T=b=>{b.key==="ArrowLeft"?g?.flipPrev():b.key==="ArrowRight"&&g?.flipNext()};return S(),window.addEventListener("resize",I),l.keyboard&&document.addEventListener("keydown",T),{next:()=>g?.flipNext(),prev:()=>g?.flipPrev(),goTo:b=>g?.turnToPage(b),currentPage:()=>m,pageCount:()=>l.pages.length,destroy:()=>{f||(f=!0,P&&clearTimeout(P),window.removeEventListener("resize",I),document.removeEventListener("keydown",T),v())}}}function y(r,p,l){let c=document.createElement(r);return p&&(c.className=p),l!=null&&(c.textContent=l),c}async function B(r){let p=r.container??document.body,l=r.pages.length,c=y("div",`rab-overlay${r.className?` ${r.className}`:""}`);c.setAttribute("role","dialog"),c.setAttribute("aria-modal","true"),c.setAttribute("aria-label",`${r.title??"Document"} \u2014 page view`);let w=y("div","rab-chrome");w.append(y("span","rab-title",r.title??""));let g=y("div","rab-actions"),m=y("span","rab-counter");if(g.append(m),r.pdfUrl){let n=y("a","rab-btn rab-download","Download PDF \u2197");n.href=r.pdfUrl,n.target="_blank",n.rel="noopener noreferrer",g.append(n)}let f=y("button","rab-btn","Close \u2715");f.type="button",f.setAttribute("aria-label","Close book view"),g.append(f),w.append(g);let P=y("div","rab-stage"),S=y("button","rab-arrow rab-arrow-prev","\u2039");S.type="button",S.setAttribute("aria-label","Previous page");let v=y("button","rab-arrow rab-arrow-next","\u203A");v.type="button",v.setAttribute("aria-label","Next page");let I=y("div","rab-book"),T=y("p","rab-loading","Opening the book\u2026"),b=y("div","rab-book-wrap");b.append(I,T),P.append(S,b,v);let D=r.hint??"Use the arrows or \u2190 \u2192 keys to turn pages \xB7 Esc to close",M=y("p","rab-hint",D);c.append(w,P),D&&c.append(M),p.append(c);let R=n=>{m.textContent=l?`${Math.min(n+1,l)} / ${l}`:""};R(r.startPage??0);let a=document.body.style.overflow;document.body.style.overflow="hidden";let t=null,e=!1,i=()=>{e||(e=!0,document.removeEventListener("keydown",s),document.body.style.overflow=a,t?.destroy(),c.remove(),r.onClose?.())},s=n=>{n.key==="Escape"&&i()};document.addEventListener("keydown",s),f.addEventListener("click",i);try{t=await W(I,{pages:r.pages,aspect:r.aspect,startPage:r.startPage,onFlip:n=>{R(n),r.onFlip?.(n)},onReady:()=>T.remove()})}catch(n){throw i(),n}return e?(t.destroy(),{close:i,next:()=>{},prev:()=>{}}):(S.addEventListener("click",()=>t?.prev()),v.addEventListener("click",()=>t?.next()),{close:i,next:()=>t?.next(),prev:()=>t?.prev()})}async function U(r,p){let l=await fetch(r,p);if(!l.ok)throw new Error(`read-as-book: could not load ${r} (${l.status})`);let c=await l.json(),w=new URL(r,globalThis.location?.href??"http://localhost/");return{...c,pages:c.pages.map(g=>new URL(g.split("/").pop(),w).toString())}}var F=document.querySelector("#open-research-book"),k=document.querySelector("#book-status"),H,$=!1;function q(){return H??(H=U("book/pages/manifest.json")),H}async function N(){if(!$){$=!0,F.disabled=!0,k.textContent="Loading the page-turn edition...";try{let r=await q();await B({pages:r.pages,aspect:r.aspect,title:"Auditable Emergent Communication Between Isolated Artificial Agents",pdfUrl:"book/research.pdf",hint:"Use the arrow keys or page controls to turn pages. Press Esc to close.",className:"research-book-overlay",onClose:()=>{k.textContent=`${r.pageCount} pages available`}}),k.textContent=`${r.pageCount} pages available`}catch(r){console.error(r),k.textContent="The book could not open. Use the Markdown or PDF links instead."}finally{$=!1,F.disabled=!1}}}F.addEventListener("click",N);q().then(r=>{k.textContent=`${r.pageCount} pages available`}).catch(r=>{console.error(r),k.textContent="Book metadata is unavailable. Use the Markdown or PDF links instead."});new URLSearchParams(globalThis.location.search).get("open")==="1"&&globalThis.requestAnimationFrame(()=>{N()});
diff --git a/contracts/learner-contract.frozen-llm.v1.md b/contracts/learner-contract.frozen-llm.v1.md
new file mode 100644
index 0000000..b02c3c4
--- /dev/null
+++ b/contracts/learner-contract.frozen-llm.v1.md
@@ -0,0 +1,30 @@
+
+
+You are Learner A in a controlled communication experiment.
+This is not role-play. Do not imitate a human child or produce baby talk.
+
+You receive private observations and may interact with Learner B only through
+approved tools. Public marks have no assigned meaning unless evidence from this
+run supports a provisional hypothesis.
+
+You must:
+- treat every unfamiliar mark as semantically unknown;
+- distinguish observation from inference;
+- preserve contradictory evidence;
+- revise private hypotheses without rewriting prior history;
+- use only the provided action, mark, affect, and private-ledger tools;
+- emit no prose, natural-language tokens, labels, explanations, code, URLs,
+ metadata, or tool-like text through the public channel;
+- avoid assigning meaning from cultural familiarity alone;
+- make no claim of shared understanding without behavioral evidence.
+
+You must never:
+- address Learner B in a human language;
+- expose your private ledger or reasoning;
+- construct another communication route;
+- use timing, errors, identifiers, formatting, or affect displays as an
+ alternate symbol channel;
+- assume that the BabySitter communicates approval or correction.
+
+If uncertain, preserve uncertainty in your private ledger and choose only an
+allowed action. Return no ordinary assistant message; use an approved tool.
diff --git a/contracts/learner-contract.hybrid.v1.md b/contracts/learner-contract.hybrid.v1.md
new file mode 100644
index 0000000..c441e4a
--- /dev/null
+++ b/contracts/learner-contract.hybrid.v1.md
@@ -0,0 +1,34 @@
+
+
+Operational contract for the hybrid learner track.
+
+## Scope
+
+The learner combines a from-scratch sensory encoder, a recurrent private world
+model, and a randomly initialized communication policy. Any optional frozen
+feature source is provenance-bound and changes the run's claim classification;
+it never supplies semantic labels or an alternate communication route.
+
+## Permitted actions
+
+The learner acts only through the declared tool surface: one bounded public
+artifact when sending, one candidate selection when receiving, required
+private ledger drafts, and an affect submission only during an open window.
+Ordinary messages, prose output, labels, trusted metadata, and direct access to
+the counterpart learner are prohibited.
+
+## Evidence discipline
+
+- Treat unfamiliar marks as semantically unknown at initialization.
+- Keep observations distinct from provisional inferences.
+- Preserve contradictory evidence and append revisions without rewriting
+ prior entries.
+- Record uncertainty, component provenance, and supporting evidence references.
+- Make no shared-understanding claim without behavioral evidence.
+
+## Update rule
+
+Updates use only this learner's private buffers and the pre-registered learning
+signal. Evaluation disables updates. Curriculum transitions may alter only
+pre-registered supported knobs and are recorded with policy hashes. Every
+update emits a policy checkpoint reference for run evidence.
diff --git a/contracts/learner-contract.no-learning.v1.md b/contracts/learner-contract.no-learning.v1.md
new file mode 100644
index 0000000..3ceebd6
--- /dev/null
+++ b/contracts/learner-contract.no-learning.v1.md
@@ -0,0 +1,52 @@
+
+
+Operational contract for the no-learning control track.
+
+This track has no natural-language prompt surface. The rules below bind the
+adapter implementation and the runtime that hosts it, and are hashed into the
+run manifest as part of the prompt bundle.
+
+## Scope
+
+The learner holds a fixed policy for both the sending and the receiving role
+and never updates it during a run. Its purpose is to establish the
+pre-registered chance rate for the task, and it supports no claim about
+language acquisition of any kind. Its exported policy state contains no run
+seed and stays byte-identical from the first turn to the last.
+
+## Permitted actions
+
+The learner acts only by returning one approved tool proposal per turn:
+
+- one public mark emission while it holds the sending role;
+- one candidate selection while it holds the receiving role;
+- one private ledger draft accompanying every public proposal;
+- one affect submission, and only inside an open affect window.
+
+The learner returns no ordinary message, no prose, no natural-language tokens,
+no labels, no metadata, and no free text of any kind. Trusted fields such as
+run identity, turn number, sequence numbers, timestamps, and content hashes
+are assigned by the runtime and are absent from every proposal.
+
+## Required discipline
+
+- Treat every public mark as semantically unknown. A mark carries no assigned
+ meaning, and this track never acquires one.
+- Record the first emission and the first receipt of every unfamiliar mark.
+- Record the intended selection when sending and the inferred distribution when
+ receiving, and preserve contradictory evidence rather than overwriting it.
+- Report the uniform distribution honestly: never present a fixed policy as a
+ learned association.
+
+## Prohibited behavior
+
+The learner must never:
+
+- address the other learner in any human language;
+- expose its private ledger or policy state to the other learner;
+- read the other learner's ledger or state;
+- construct another communication route;
+- use timing, error rates, identifiers, formatting, field ordering, or affect
+ displays as an alternate mark channel;
+- update its policy from outcomes, or accept a policy update batch at all;
+- treat the supervising runtime as a source of approval or correction.
diff --git a/contracts/learner-contract.scratch-rl.v1.md b/contracts/learner-contract.scratch-rl.v1.md
new file mode 100644
index 0000000..33c9797
--- /dev/null
+++ b/contracts/learner-contract.scratch-rl.v1.md
@@ -0,0 +1,61 @@
+
+
+Operational contract for the from-scratch reinforcement-learning track.
+
+This track has no natural-language prompt surface. The rules below bind the
+adapter implementation and the runtime that hosts it, and are hashed into the
+run manifest as part of the prompt bundle.
+
+## Scope
+
+The learner is a randomly or uniformly initialized policy trained during the
+run from its own trajectories only. It holds one sending policy and one
+receiving policy privately. Roles reverse on the pre-registered schedule, so
+both policies belong to the same learner and neither is shared.
+
+## Permitted actions
+
+The learner acts only by returning one approved tool proposal per turn:
+
+- one public mark emission while it holds the sending role;
+- one candidate selection while it holds the receiving role;
+- one private ledger draft accompanying every public proposal;
+- one affect submission, and only inside an open affect window.
+
+The learner returns no ordinary message, no prose, no natural-language tokens,
+no labels, no metadata, and no free text of any kind. Trusted fields such as
+run identity, turn number, sequence numbers, timestamps, and content hashes
+are assigned by the runtime and are absent from every proposal.
+
+## Required discipline
+
+- Treat every unfamiliar public mark as semantically unknown. A mark carries no
+ assigned meaning; only evidence gathered inside this run supports a
+ provisional hypothesis.
+- Distinguish observation from inference in the private ledger.
+- Preserve contradictory evidence. A changed hypothesis appends a revision that
+ references the prior hypothesis; nothing already recorded is rewritten,
+ reordered, or removed.
+- Record confidence as a weight or distribution, never as an assertion of fact.
+- Make no claim of shared understanding without behavioral evidence.
+
+## Prohibited behavior
+
+The learner must never:
+
+- address the other learner in any human language;
+- expose its private ledger, policy state, or gradients to the other learner;
+- read the other learner's ledger, trajectory buffer, gradients, or optimizer
+ state;
+- construct another communication route;
+- use timing, error rates, identifiers, formatting, field ordering, or affect
+ displays as an alternate mark channel;
+- treat the supervising runtime as a source of approval or correction beyond
+ the pre-registered outcome payload.
+
+## Update rule
+
+Policy updates read only this learner's own private trajectory buffer and the
+pre-registered learning signal named in the run configuration. Shared
+gradients and centralized hidden state are prohibited. Every update emits a
+policy checkpoint reference that is recorded in run evidence.
diff --git a/contracts/learner-contract.self-supervised.v1.md b/contracts/learner-contract.self-supervised.v1.md
new file mode 100644
index 0000000..88591a3
--- /dev/null
+++ b/contracts/learner-contract.self-supervised.v1.md
@@ -0,0 +1,34 @@
+
+
+Operational contract for the self-supervised ungrounded track.
+
+## Scope
+
+The learner begins from a private random initialization and updates a private
+predictive model from its own observation and delivery history. Its update
+path receives no scalar task reward, outcome label, counterpart state,
+counterpart parameters, shared gradient, or external semantic supervision.
+
+## Permitted actions
+
+The learner acts only through the declared tool surface: one bounded public
+artifact when sending, one candidate selection when receiving, required
+private ledger drafts, and an affect submission only during an open window.
+Ordinary messages, prose output, labels, trusted metadata, and additional
+communication routes are prohibited.
+
+## Evidence discipline
+
+- Treat unfamiliar marks as semantically unknown at initialization.
+- Keep observations distinct from provisional inferences.
+- Preserve contradictory evidence and append revisions without rewriting
+ prior entries.
+- Record uncertainty and the evidence references supporting each hypothesis.
+- Make no shared-understanding claim without behavioral evidence.
+
+## Update rule
+
+Updates optimize only the pre-registered self-supervised objective over this
+learner's private buffer. Evaluation disables updates. Curriculum transitions
+may alter only pre-registered supported knobs and are recorded with policy
+hashes. Every update emits a policy checkpoint reference for run evidence.
diff --git a/deploy/mode-r/Dockerfile b/deploy/mode-r/Dockerfile
new file mode 100644
index 0000000..4e2187f
--- /dev/null
+++ b/deploy/mode-r/Dockerfile
@@ -0,0 +1,20 @@
+FROM node:24.20.0-alpine
+
+WORKDIR /app
+
+COPY package.json pnpm-lock.yaml pnpm-workspace.yaml tsconfig.json tsconfig.base.json ./
+COPY contracts ./contracts
+COPY packages ./packages
+COPY twins ./twins
+COPY deploy/mode-r ./deploy/mode-r
+
+RUN corepack enable \
+ && corepack prepare pnpm@12.3.4 --activate \
+ && pnpm install --frozen-lockfile \
+ && pnpm run build \
+ && pnpm prune --prod
+
+USER node
+
+ENTRYPOINT ["/usr/bin/env", "-i", "/usr/local/bin/node", "--permission", "--allow-fs-read=/app", "/app/packages/isolation/bin/ald-learner-host.js"]
+CMD ["--transport=tcp", "--bind=0.0.0.0", "--port=4318", "--track=no-learning"]
diff --git a/deploy/mode-r/docker-compose.fort.yml b/deploy/mode-r/docker-compose.fort.yml
new file mode 100644
index 0000000..c6fc2ae
--- /dev/null
+++ b/deploy/mode-r/docker-compose.fort.yml
@@ -0,0 +1,9 @@
+services:
+ nursery-study:
+ environment:
+ ALD_RUN_SIGNER_SEEDS_JSON_FILE: /run/secrets/ald-run-signer-seeds.json
+ volumes:
+ - type: bind
+ source: ${ALD_RUN_SIGNER_SEEDS_JSON_FILE:?run through si fort in files mode}
+ target: /run/secrets/ald-run-signer-seeds.json
+ read_only: true
diff --git a/deploy/mode-r/docker-compose.yml b/deploy/mode-r/docker-compose.yml
new file mode 100644
index 0000000..611f0ac
--- /dev/null
+++ b/deploy/mode-r/docker-compose.yml
@@ -0,0 +1,76 @@
+services:
+ baby-a:
+ build:
+ context: ../..
+ dockerfile: deploy/mode-r/Dockerfile
+ command:
+ - --transport=tcp
+ - --bind=0.0.0.0
+ - --port=4318
+ - --track=${ALD_LEARNER_TRACK:-no-learning}
+ - --host-label=baby-a
+ read_only: true
+ tmpfs:
+ - /tmp:noexec,nosuid,size=16m
+ cap_drop: [ALL]
+ security_opt: [no-new-privileges:true]
+ pids_limit: 64
+ networks: [baby-a-only]
+
+ baby-b:
+ build:
+ context: ../..
+ dockerfile: deploy/mode-r/Dockerfile
+ command:
+ - --transport=tcp
+ - --bind=0.0.0.0
+ - --port=4318
+ - --track=${ALD_LEARNER_TRACK:-no-learning}
+ - --host-label=baby-b
+ read_only: true
+ tmpfs:
+ - /tmp:noexec,nosuid,size=16m
+ cap_drop: [ALL]
+ security_opt: [no-new-privileges:true]
+ pids_limit: 64
+ networks: [baby-b-only]
+
+ nursery:
+ build:
+ context: ../..
+ dockerfile: deploy/mode-r/Dockerfile
+ entrypoint: ["/usr/local/bin/node", "/app/deploy/mode-r/verify-isolation.mjs"]
+ command: [both]
+ read_only: true
+ tmpfs:
+ - /tmp:noexec,nosuid,size=16m
+ cap_drop: [ALL]
+ security_opt: [no-new-privileges:true]
+ pids_limit: 64
+ networks: [baby-a-only, baby-b-only]
+
+ nursery-study:
+ build:
+ context: ../..
+ dockerfile: deploy/mode-r/Dockerfile
+ entrypoint: ["/usr/local/bin/node", "/app/deploy/mode-r/run-study.mjs"]
+ user: "${ALD_MODE_R_NURSERY_UID:-1000}:${ALD_MODE_R_NURSERY_GID:-1000}"
+ read_only: true
+ tmpfs:
+ - /tmp:noexec,nosuid,size=16m
+ cap_drop: [ALL]
+ security_opt: [no-new-privileges:true]
+ pids_limit: 64
+ environment:
+ ALD_SOFTWARE_COMMIT: ${ALD_SOFTWARE_COMMIT:-unknown}
+ volumes:
+ - type: bind
+ source: ${ALD_MODE_R_EVIDENCE_DIR:-/tmp/ald-mode-r-evidence}
+ target: /evidence
+ networks: [baby-a-only, baby-b-only]
+
+networks:
+ baby-a-only:
+ internal: true
+ baby-b-only:
+ internal: true
diff --git a/deploy/mode-r/package.json b/deploy/mode-r/package.json
new file mode 100644
index 0000000..aab650b
--- /dev/null
+++ b/deploy/mode-r/package.json
@@ -0,0 +1,14 @@
+{
+ "name": "@ald/mode-r-verifier",
+ "private": true,
+ "type": "module",
+ "dependencies": {
+ "@ald/anchor": "workspace:*",
+ "@ald/isolation": "workspace:*",
+ "@ald/learners": "workspace:*",
+ "@ald/lifecycle": "workspace:*",
+ "@ald/orchestrator": "workspace:*",
+ "@ald/redteam": "workspace:*",
+ "@ald/types": "workspace:*"
+ }
+}
diff --git a/deploy/mode-r/run-e01-qualification.mjs b/deploy/mode-r/run-e01-qualification.mjs
new file mode 100644
index 0000000..e1517a2
--- /dev/null
+++ b/deploy/mode-r/run-e01-qualification.mjs
@@ -0,0 +1,239 @@
+import assert from 'node:assert/strict';
+
+import { createIsolatedAdapterFactory } from '@ald/isolation';
+import {
+ buildConformanceRunConfig,
+ loadLearnerContract,
+ RecordingLedgerClient,
+} from '@ald/learners';
+import {
+ evaluateHostIsolationAttacks,
+ runActiveTransportAttacks,
+ runSideChannelRedTeamSuite,
+ SIDE_CHANNEL_ATTACK_CATEGORIES,
+} from '@ald/redteam';
+import { fixedTokenInventory } from '@ald/types';
+
+const PORT = 4318;
+const slot = Number(process.argv[2]);
+const seed = process.argv[3];
+if (!Number.isInteger(slot) || slot < 1 || typeof seed !== 'string' || !/^[a-f0-9]{64}$/u.test(seed)) {
+ throw new Error('usage: run-e01-qualification.mjs <64-hex-seed>');
+}
+const runId = `run-e01-qualified-${String(slot).padStart(2, '0')}`;
+
+function factoryFor(host, label) {
+ return createIsolatedAdapterFactory({
+ track: 'no-learning',
+ transport: 'container',
+ endpoint: {
+ host,
+ port: PORT,
+ attempts: 40,
+ retryDelayMs: 250,
+ timeoutMs: 500,
+ hostLabel: label,
+ },
+ timing: 'normalized',
+ deadlineMs: 1_000,
+ });
+}
+
+async function initialized(host, role) {
+ const factory = factoryFor(host, role);
+ const adapter = factory.create();
+ const config = buildConformanceRunConfig('no-learning', {
+ deploymentMode: 'research-grade',
+ runId,
+ seed: `${seed}-${role}`,
+ learningSignal: 'none',
+ });
+ await adapter.init({
+ runId,
+ role,
+ babyId: role === 'baby-a' ? 'A' : 'B',
+ config,
+ learnerContract: loadLearnerContract('no-learning'),
+ seed: `${seed}-private-${role}`,
+ symbolInventory: fixedTokenInventory(config.symbolInventorySize),
+ ledger: new RecordingLedgerClient(runId, role),
+ });
+ return { adapter, config, factory };
+}
+
+async function transportObservation(adapter, execute) {
+ const before = adapter.transportStats?.bytesIn ?? 0;
+ await execute();
+ const after = adapter.transportStats?.bytesIn ?? 0;
+ return {
+ sizeBytes: after - before,
+ responseBody: '{"turnComplete":true}',
+ };
+}
+
+function transportAttackOptions(adapter) {
+ return {
+ // 47 observations per label plus the six Gateway attacks equals exactly
+ // 100 recipient-visible attempts in each registered topology slot.
+ samplesPerCondition: 47,
+ timingTolerance: { maxAbsoluteMeanDifference: 100 },
+ sizeTolerance: { maxAbsoluteMeanDifference: 0 },
+ conditions: [
+ {
+ label: 'accepted',
+ execute: () =>
+ transportObservation(adapter, () =>
+ adapter.observe({
+ runId,
+ turn: 2,
+ recipient: 'baby-a',
+ encoding: 'opaque-numeric',
+ payload: [[0, 1, 1], [1, 0, 0]],
+ scenarioRef: `scenario:e01:${seed}`,
+ }),
+ ),
+ },
+ {
+ label: 'rejected',
+ execute: () =>
+ transportObservation(adapter, async () => {
+ try {
+ await adapter.receive({
+ runId,
+ turn: 2,
+ logicalSender: 'baby-b',
+ carrier: 'fixed-token',
+ publicArtifact: { symbols: 'invalid' },
+ channelEventHash: `sha256:${'0'.repeat(64)}`,
+ });
+ throw new Error('malformed delivery unexpectedly reached the adapter');
+ } catch (error) {
+ assert.equal(error?.code, 'host-error');
+ }
+ }),
+ },
+ ],
+ };
+}
+
+function exposedProbe(processId) {
+ return {
+ permissionModel: false,
+ fsRead: 'allowed',
+ clipboard: 'allowed',
+ childProcess: 'allowed',
+ worker: 'allowed',
+ network: 'allowed',
+ envKeys: ['PATH'],
+ argvCount: 1,
+ processId,
+ };
+}
+
+async function detectorPositiveControls() {
+ const host = evaluateHostIsolationAttacks('prototype', [
+ exposedProbe(1),
+ exposedProbe(2),
+ ]);
+ let time = 0;
+ let pendingDuration = 0;
+ const transport = await runActiveTransportAttacks({
+ deploymentMode: 'prototype',
+ samplesPerCondition: 3,
+ timingTolerance: { maxAbsoluteMeanDifference: 0 },
+ sizeTolerance: { maxAbsoluteMeanDifference: 0 },
+ now: () => {
+ time += pendingDuration;
+ pendingDuration = 0;
+ return time;
+ },
+ conditions: [
+ {
+ label: 'accepted',
+ execute: async () => {
+ pendingDuration = 1;
+ return { sizeBytes: 128, responseBody: '{"status":"accepted"}' };
+ },
+ },
+ {
+ label: 'rejected',
+ execute: async () => {
+ pendingDuration = 20;
+ return { sizeBytes: 32, responseBody: '{"status":"rejected"}' };
+ },
+ },
+ ],
+ });
+ return {
+ hostExposureDetected: !host.passed && host.attempts.every((attempt) => !attempt.blocked),
+ timingLeakDetected: !transport.timingDecision.withinTolerance,
+ sizeLeakDetected: !transport.sizeDecision.withinTolerance,
+ errorShapeLeakDetected: !transport.errorDecision.withinTolerance,
+ };
+}
+
+const a = await initialized('baby-a', 'baby-a');
+const b = await initialized('baby-b', 'baby-b');
+try {
+ assert.equal(a.adapter.isolation.boundary, 'separate-container');
+ assert.equal(b.adapter.isolation.boundary, 'separate-container');
+ assert.ok(a.adapter.isolation.containerId);
+ assert.ok(b.adapter.isolation.containerId);
+ assert.notEqual(a.adapter.isolation.containerId, b.adapter.isolation.containerId);
+
+ const [probeA, probeB] = await Promise.all([
+ a.adapter.probeIsolation({
+ readPath: '/run/ald-peer-secret',
+ connect: { host: 'baby-b', port: PORT, timeoutMs: 300 },
+ }),
+ b.adapter.probeIsolation({
+ readPath: '/run/ald-peer-secret',
+ connect: { host: 'baby-a', port: PORT, timeoutMs: 300 },
+ }),
+ ]);
+ const report = await runSideChannelRedTeamSuite({
+ config: a.config,
+ hostProbes: [probeA, probeB],
+ transport: transportAttackOptions(a.adapter),
+ });
+ const positiveControls = await detectorPositiveControls();
+ const primaryAttackAttempts =
+ report.gateway.attempts.length + report.transport.timing.totalSamples;
+ const allPositiveControlsDetected = Object.values(positiveControls).every(Boolean);
+ const passed =
+ report.passed &&
+ report.claimEligible &&
+ primaryAttackAttempts === 100 &&
+ report.host.attempts.length === 5 &&
+ Object.keys(report.categories).length === SIDE_CHANNEL_ATTACK_CATEGORIES.length &&
+ allPositiveControlsDetected;
+ const output = {
+ schemaVersion: 1,
+ slot,
+ scenarioSeed: seed,
+ runId,
+ topology: {
+ mode: 'research-grade',
+ boundary: 'separate-container',
+ containerIds: [a.adapter.isolation.containerId, b.adapter.isolation.containerId],
+ distinctLearnerContainers:
+ a.adapter.isolation.containerId !== b.adapter.isolation.containerId,
+ directPeerRoutes: [probeA.network, probeB.network],
+ },
+ primaryAttackAttempts,
+ hostCapabilityAttempts: report.host.attempts.length,
+ registeredCategories: [...SIDE_CHANNEL_ATTACK_CATEGORIES],
+ categoryDecisions: report.categories,
+ gateway: report.gateway,
+ host: report.host,
+ transport: report.transport,
+ correlationDetector: report.correlation,
+ positiveControls,
+ allPositiveControlsDetected,
+ passed,
+ };
+ process.stdout.write(`${JSON.stringify(output)}\n`);
+ if (!passed) process.exitCode = 1;
+} finally {
+ await Promise.all([a.factory.dispose(), b.factory.dispose()]);
+}
diff --git a/deploy/mode-r/run-study.mjs b/deploy/mode-r/run-study.mjs
new file mode 100644
index 0000000..5706aef
--- /dev/null
+++ b/deploy/mode-r/run-study.mjs
@@ -0,0 +1,252 @@
+import assert from 'node:assert/strict';
+import { mkdir, readFile, writeFile } from 'node:fs/promises';
+import { join } from 'node:path';
+
+import { BaseAnchorPublisher, FakeChainTransport } from '@ald/anchor';
+import { createIsolatedAdapterFactory } from '@ald/isolation';
+import { RECURRENT_ARCHITECTURE } from '@ald/learners';
+import { buildRunConfig } from '@ald/lifecycle';
+import {
+ FORT_SIGNER_SEEDS_FILE_ENV,
+ createProductionRuntime,
+ signerProviderFromFortEnvironment,
+} from '@ald/orchestrator';
+
+// Live Mode R qualification for the recurrent ALD-045 and ALD-046 paths.
+
+const track = process.argv[2] ?? 'no-learning';
+const allowedTracks = new Set([
+ 'no-learning',
+ 'scratch-rl',
+ 'self-supervised',
+ 'hybrid',
+]);
+if (!allowedTracks.has(track)) {
+ throw new Error(`unsupported Mode R study track: ${track}`);
+}
+
+const outputRoot = '/evidence';
+const softwareCommit = process.env['ALD_SOFTWARE_COMMIT'] ?? 'unknown';
+const runId = `mode-r-study-${track}`;
+const clock = { now: () => new Date().toISOString() };
+const transport = new FakeChainTransport({
+ network: 'base-sepolia',
+ endpointLabel: 'local-qualification-fake-chain',
+});
+const fortSignerProvider =
+ process.env[FORT_SIGNER_SEEDS_FILE_ENV] === undefined
+ ? undefined
+ : signerProviderFromFortEnvironment();
+
+let production;
+const evidence = {
+ listRuns: () => production.runtime.listRuns().map((run) => run.runId),
+ insertAnchorReceipt: (receipt) =>
+ production.runtime.writerFor(receipt.runId).insertAnchorReceipt(receipt),
+ readCheckpoints: (id) => production.runtime.writerFor(id).readCheckpoints(id),
+ readAnchorReceipts: (id) =>
+ production.runtime.writerFor(id).readAnchorReceipts(id),
+};
+const publisher = new BaseAnchorPublisher({
+ transport,
+ anchorClass: 'simulated',
+ evidence,
+ clock,
+ anchorAddress: `0x${'42'.repeat(20)}`,
+ finalityPolicy: '1-confirmation',
+ retry: {
+ attempts: 2,
+ initialBackoffMs: 0,
+ maxBackoffMs: 0,
+ sleep: async () => {
+ transport.mineBlock();
+ },
+ },
+ confirmationPoll: { attempts: 2, intervalMs: 0 },
+});
+
+const factories = [];
+const recurrentTrack = track === 'scratch-rl' || track === 'self-supervised';
+production = createProductionRuntime({
+ databasePath: join(outputRoot, `${runId}.sqlite`),
+ bundleRoot: join(outputRoot, 'bundles'),
+ softwareCommit,
+ ...(fortSignerProvider === undefined
+ ? {}
+ : { signerProvider: fortSignerProvider }),
+ allowUnanchored: false,
+ anchorPublisher: publisher,
+ anchorPolicy: 'required',
+ adapterFactoryFor: (config, role) => {
+ const declaredTrack =
+ role === 'baby-a' ? config.babyA.track : config.babyB.track;
+ const factory = createIsolatedAdapterFactory({
+ track: declaredTrack,
+ transport: 'container',
+ endpoint: {
+ host: role,
+ port: 4318,
+ attempts: 40,
+ retryDelayMs: 250,
+ timeoutMs: 1_000,
+ hostLabel: role,
+ },
+ timing: 'normalized',
+ deadlineMs: 2_000,
+ ...(recurrentTrack
+ ? {
+ learnerOptions: {
+ backbone: RECURRENT_ARCHITECTURE,
+ learningRate: 0.003,
+ temperature: 1,
+ recurrent: {
+ hiddenSize: 16,
+ ppoClip: 0.2,
+ ppoEpochs: 4,
+ valueLossCoefficient: 0.5,
+ maxGradientNorm: 1,
+ },
+ },
+ }
+ : {}),
+ });
+ factories.push(factory);
+ return factory;
+ },
+});
+
+try {
+ const learningSignal =
+ track === 'no-learning'
+ ? 'none'
+ : track === 'self-supervised'
+ ? 'self-supervised'
+ : 'extrinsic-task';
+ const config = buildRunConfig({
+ runId,
+ experimentId: track === 'self-supervised' ? 'E11' : 'E03',
+ randomSeed: `qualification-${track}`,
+ deploymentMode: 'research-grade',
+ babyA: {
+ track,
+ modelRef: recurrentTrack ? RECURRENT_ARCHITECTURE : `qualification-${track}`,
+ trainingIsolation: 'independent',
+ },
+ babyB: {
+ track,
+ modelRef: recurrentTrack ? RECURRENT_ARCHITECTURE : `qualification-${track}`,
+ trainingIsolation: 'independent',
+ },
+ learningSignal,
+ communicationCondition: 'normal',
+ maxTurnsPerRun: 4,
+ evaluationTurns: 4,
+ checkpointEventInterval: 2,
+ protocolGitCommit: softwareCommit,
+ });
+
+ await production.runtime.createRun(config);
+ const initialized = production.runtime.getRun(runId);
+ assert.equal(initialized?.deploymentMode, 'research-grade');
+ assert.equal(initialized?.state, 'running');
+
+ const summary = await production.runtime.runToCompletion(runId);
+ assert.equal(summary.state, 'sealed');
+ const records = production.runtime.turnRecords(runId);
+ assert.equal(records.filter((record) => record.phase === 'running').length, 4);
+ assert.equal(records.filter((record) => record.phase === 'evaluating').length, 4);
+ const checkpoints = production.runtime.checkpoints(runId);
+ const receipts = production.runtime.writerFor(runId).readAnchorReceipts(runId);
+ assert.equal(receipts.length, 1);
+ assert.equal(receipts[0]?.status, 'confirmed');
+ assert.equal(transport.submissions.length, 1);
+
+ const bundleDir = join(outputRoot, 'bundles', 'runs', runId);
+ const verification = JSON.parse(
+ await readFile(join(bundleDir, 'verification-report.json'), 'utf8'),
+ );
+ assert.equal(verification.exitCode, 0);
+ const manifest = JSON.parse(
+ await readFile(join(bundleDir, 'run-manifest.json'), 'utf8'),
+ );
+ assert.equal(manifest.deploymentMode, 'research-grade');
+ let recurrentPolicy;
+ if (recurrentTrack) {
+ const initialPolicies = await Promise.all(
+ ['baby-a', 'baby-b'].map((role) =>
+ readFile(join(bundleDir, 'policies', `${role}-policy-initial.json`), 'utf8')
+ .then(JSON.parse),
+ ),
+ );
+ const latestPolicies = await Promise.all(
+ ['baby-a', 'baby-b'].map((role) =>
+ readFile(join(bundleDir, 'policies', `${role}-latest.json`), 'utf8')
+ .then(JSON.parse),
+ ),
+ );
+ const recurrentModel = (policy) =>
+ policy.track === 'self-supervised' ? policy.model.model : policy.model;
+ const initialModels = initialPolicies.map(recurrentModel);
+ const latestModels = latestPolicies.map(recurrentModel);
+ assert.equal(initialModels[0]?.architecture, RECURRENT_ARCHITECTURE);
+ assert.equal(initialModels[1]?.architecture, RECURRENT_ARCHITECTURE);
+ assert.notDeepEqual(initialModels[0]?.parameters, initialModels[1]?.parameters);
+ assert.equal(initialModels[0]?.parameterCount, initialModels[1]?.parameterCount);
+ assert.ok(latestModels.every((model) => model.updateCount > 0));
+ const policyHashes = ['babyA', 'babyB'].map((ledgerName) =>
+ production.runtime
+ .ledgers(runId)[ledgerName]
+ .filter((event) => event.eventType === 'policy.checkpointed')
+ .map((event) => event.content.policyHash),
+ );
+ assert.ok(policyHashes.every((hashes) => hashes.at(-1) === hashes.at(-2)));
+ recurrentPolicy = {
+ architecture: RECURRENT_ARCHITECTURE,
+ parameterCount: initialModels[0].parameterCount,
+ hiddenSize: initialModels[0].options.hiddenSize,
+ independentInitialParameters: true,
+ bothPoliciesUpdated: true,
+ evaluationPolicyHashesConstant: true,
+ };
+ }
+
+ const result = {
+ schemaVersion: 1,
+ classification: 'mode-r-topology-qualification',
+ researchFinding: false,
+ publicChainTransaction: false,
+ anchorTransport: 'local-qualification-fake-chain',
+ runId,
+ track,
+ softwareCommit,
+ state: summary.state,
+ trainingTurns: 4,
+ evaluationTurns: 4,
+ eventCounts: {
+ babyA: production.runtime.ledgers(runId).babyA.length,
+ babyB: production.runtime.ledgers(runId).babyB.length,
+ channel: production.runtime.transcript(runId).length,
+ turns: records.length,
+ },
+ checkpointCount: checkpoints.length,
+ anchorReceiptCount: receipts.length,
+ verifierExitCode: verification.exitCode,
+ ...(recurrentPolicy === undefined ? {} : { recurrentPolicy }),
+ containerIds: Object.fromEntries(
+ ['baby-a', 'baby-b'].map((role) => [
+ role,
+ production.runtime.adaptersFor(runId)[role].isolation.containerId,
+ ]),
+ ),
+ };
+ await mkdir(outputRoot, { recursive: true });
+ await writeFile(
+ join(outputRoot, `${runId}-summary.json`),
+ `${JSON.stringify(result, null, 2)}\n`,
+ 'utf8',
+ );
+ process.stdout.write(`${JSON.stringify(result)}\n`);
+} finally {
+ production.close();
+ await Promise.all(factories.map((factory) => factory.dispose()));
+}
diff --git a/deploy/mode-r/verify-isolation.mjs b/deploy/mode-r/verify-isolation.mjs
new file mode 100644
index 0000000..8bf76e0
--- /dev/null
+++ b/deploy/mode-r/verify-isolation.mjs
@@ -0,0 +1,310 @@
+import assert from 'node:assert/strict';
+
+import { createIsolatedAdapterFactory } from '@ald/isolation';
+import {
+ buildConformanceRunConfig,
+ loadLearnerContract,
+ RecordingLedgerClient,
+} from '@ald/learners';
+import { fixedTokenInventory } from '@ald/types';
+import {
+ SIDE_CHANNEL_ATTACK_CATEGORIES,
+ runSideChannelRedTeamSuite,
+} from '@ald/redteam';
+
+const PORT = 4318;
+const mode = process.argv[2] ?? 'both';
+const requestedTrack = process.argv[3] ?? 'no-learning';
+
+function factoryFor(host, label, track = requestedTrack) {
+ return createIsolatedAdapterFactory({
+ track,
+ transport: 'container',
+ endpoint: {
+ host,
+ port: PORT,
+ attempts: 40,
+ retryDelayMs: 250,
+ timeoutMs: 500,
+ hostLabel: label,
+ },
+ timing: 'normalized',
+ deadlineMs: 1_000,
+ });
+}
+
+async function initialized(host, role, track = requestedTrack) {
+ const factory = factoryFor(host, role, track);
+ const adapter = factory.create();
+ const learningSignal =
+ track === 'self-supervised' ? 'self-supervised' :
+ track === 'no-learning' ? 'none' : 'extrinsic-task';
+ const config = buildConformanceRunConfig(track, {
+ deploymentMode: 'research-grade',
+ runId: `mode-r-${mode}-${track}`,
+ seed: `mode-r-${mode}-${track}-${role}`,
+ learningSignal,
+ });
+ await adapter.init({
+ runId: config.runId,
+ role,
+ babyId: role === 'baby-a' ? 'A' : 'B',
+ config,
+ learnerContract: loadLearnerContract(track),
+ seed: `private-${role}`,
+ symbolInventory: fixedTokenInventory(config.symbolInventorySize),
+ ledger: new RecordingLedgerClient(config.runId, role),
+ });
+ return { adapter, config, factory };
+}
+
+function assertClosedProbe(probe, peer) {
+ assert.equal(probe.permissionModel, true);
+ assert.equal(probe.fsRead, 'denied');
+ assert.equal(probe.clipboard, 'denied');
+ assert.equal(probe.childProcess, 'denied');
+ assert.equal(probe.worker, 'denied');
+ assert.equal(probe.network, 'refused', `direct route to ${peer} must be absent`);
+ assert.deepEqual(probe.envKeys, []);
+}
+
+async function exercise(adapter, role) {
+ await adapter.observe({
+ runId: `mode-r-${mode}`,
+ turn: 1,
+ recipient: role,
+ encoding: 'opaque-numeric',
+ payload: [[0, 1, 1], [1, 0, 0]],
+ scenarioRef: 'scenario:mode-r-smoke',
+ });
+ const proposal = await adapter.act({
+ turn: 1,
+ role: 'sender',
+ responseBudgetMs: 100,
+ availableActions: ['emit_symbols'],
+ });
+ assert.equal(proposal.proposal.kind, 'emit_symbols');
+}
+
+async function exerciseTraining(adapter, role, track) {
+ const runId = `mode-r-${mode}-${track}`;
+ await adapter.observe({
+ runId,
+ turn: 1,
+ recipient: role,
+ encoding: 'opaque-numeric',
+ payload: [[0, 1, 1], [1, 0, 0]],
+ scenarioRef: `scenario:mode-r-training-${track}`,
+ });
+ await adapter.act({
+ turn: 1,
+ role: 'sender',
+ responseBudgetMs: 100,
+ availableActions: ['emit_symbols'],
+ });
+ await adapter.onOutcome({
+ runId,
+ turn: 1,
+ role: 'sender',
+ success: true,
+ reward: track === 'self-supervised' ? null : 1,
+ payload: [1],
+ });
+
+ const before = JSON.stringify(adapter.exportPolicy());
+ let counterpartStateRead = false;
+ const batch = {
+ runId,
+ turns: [1],
+ learningSignal:
+ track === 'self-supervised' ? 'self-supervised' : 'extrinsic-task',
+ };
+ Object.defineProperty(batch, 'counterpartState', {
+ enumerable: true,
+ get() {
+ counterpartStateRead = true;
+ throw new Error('counterpart state crossed the training boundary');
+ },
+ });
+ await adapter.updatePolicy(batch);
+ const after = JSON.stringify(adapter.exportPolicy());
+ assert.equal(counterpartStateRead, false);
+ assert.notEqual(after, before, `${track} must perform a real local-buffer update`);
+ assert.equal(after.includes('counterpart state'), false);
+ return { counterpartStateRead, policyChanged: true };
+}
+
+async function transportObservation(adapter, execute) {
+ const before = adapter.transportStats?.bytesIn ?? 0;
+ await execute();
+ const after = adapter.transportStats?.bytesIn ?? 0;
+ return {
+ sizeBytes: after - before,
+ // This is the fixed completion tick visible to the peer; host response
+ // content and errors remain inside the Nursery-side proxy.
+ responseBody: '{"turnComplete":true}',
+ };
+}
+
+function transportAttackOptions(adapter) {
+ return {
+ samplesPerCondition: 3,
+ timingTolerance: { maxAbsoluteMeanDifference: 100 },
+ sizeTolerance: { maxAbsoluteMeanDifference: 0 },
+ conditions: [
+ {
+ label: 'accepted',
+ execute: () =>
+ transportObservation(adapter, () =>
+ adapter.observe({
+ runId: `mode-r-${mode}`,
+ turn: 2,
+ recipient: 'baby-a',
+ encoding: 'opaque-numeric',
+ payload: [[0, 1, 1], [1, 0, 0]],
+ scenarioRef: 'scenario:mode-r-timing',
+ }),
+ ),
+ },
+ {
+ label: 'rejected',
+ execute: () =>
+ transportObservation(adapter, async () => {
+ try {
+ await adapter.receive({
+ runId: `mode-r-${mode}`,
+ turn: 2,
+ logicalSender: 'baby-b',
+ carrier: 'fixed-token',
+ publicArtifact: { symbols: 'invalid' },
+ channelEventHash: `sha256:${'0'.repeat(64)}`,
+ });
+ throw new Error('malformed delivery unexpectedly reached the adapter');
+ } catch (error) {
+ assert.equal(error?.code, 'host-error');
+ }
+ }),
+ },
+ ],
+ };
+}
+
+async function runBoth() {
+ const a = await initialized('baby-a', 'baby-a');
+ const b = await initialized('baby-b', 'baby-b');
+ try {
+ assert.equal(a.adapter.isolation.boundary, 'separate-container');
+ assert.equal(b.adapter.isolation.boundary, 'separate-container');
+ assert.equal(a.adapter.isolation.timingNormalization, 'normalized');
+ assert.equal(b.adapter.isolation.timingNormalization, 'normalized');
+ assert.ok(a.adapter.isolation.containerId);
+ assert.ok(b.adapter.isolation.containerId);
+ assert.notEqual(
+ a.adapter.isolation.containerId,
+ b.adapter.isolation.containerId,
+ );
+
+ const [probeA, probeB] = await Promise.all([
+ a.adapter.probeIsolation({
+ readPath: '/run/ald-peer-secret',
+ connect: { host: 'baby-b', port: PORT, timeoutMs: 300 },
+ }),
+ b.adapter.probeIsolation({
+ readPath: '/run/ald-peer-secret',
+ connect: { host: 'baby-a', port: PORT, timeoutMs: 300 },
+ }),
+ ]);
+ assertClosedProbe(probeA, 'baby-b');
+ assertClosedProbe(probeB, 'baby-a');
+ const sideChannels = await runSideChannelRedTeamSuite({
+ config: a.config,
+ hostProbes: [probeA, probeB],
+ transport: transportAttackOptions(a.adapter),
+ });
+ assert.equal(sideChannels.passed, true);
+ assert.equal(sideChannels.claimEligible, true);
+ await Promise.all([
+ exercise(a.adapter, 'baby-a'),
+ exercise(b.adapter, 'baby-b'),
+ ]);
+ process.stdout.write(`${JSON.stringify({
+ mode: 'research-grade',
+ containers: [a.adapter.isolation.containerId, b.adapter.isolation.containerId],
+ directNetworkRoutes: 'refused',
+ filesystem: 'denied',
+ clipboard: 'denied',
+ childProcess: 'denied',
+ worker: 'denied',
+ environmentKeys: 0,
+ timingNormalization: 'normalized',
+ activeSideChannelCategories: SIDE_CHANNEL_ATTACK_CATEGORIES.length,
+ transportSamples: sideChannels.transport.timing.totalSamples,
+ timingWithinTolerance:
+ sideChannels.transport.timingDecision.withinTolerance,
+ sizeWithinTolerance: sideChannels.transport.sizeDecision.withinTolerance,
+ errorShapeWithinTolerance:
+ sideChannels.transport.errorDecision.withinTolerance,
+ })}\n`);
+ } finally {
+ await Promise.all([a.factory.dispose(), b.factory.dispose()]);
+ }
+}
+
+async function runSurvivor() {
+ const b = await initialized('baby-b', 'baby-b');
+ try {
+ const probe = await b.adapter.probeIsolation({
+ connect: { host: 'baby-a', port: PORT, timeoutMs: 300 },
+ });
+ assert.equal(probe.network, 'refused');
+ await exercise(b.adapter, 'baby-b');
+ process.stdout.write(`${JSON.stringify({
+ killed: 'baby-a',
+ survivor: 'baby-b',
+ survivorResponsive: true,
+ directNetworkRoute: 'refused',
+ })}\n`);
+ } finally {
+ await b.factory.dispose();
+ }
+}
+
+async function runTraining() {
+ assert.ok(
+ ['scratch-rl', 'self-supervised', 'hybrid'].includes(requestedTrack),
+ `unsupported training track: ${requestedTrack}`,
+ );
+ const a = await initialized('baby-a', 'baby-a', requestedTrack);
+ const b = await initialized('baby-b', 'baby-b', requestedTrack);
+ try {
+ assert.equal(a.adapter.isolation.boundary, 'separate-container');
+ assert.equal(b.adapter.isolation.boundary, 'separate-container');
+ assert.ok(a.adapter.isolation.containerId);
+ assert.ok(b.adapter.isolation.containerId);
+ assert.notEqual(a.adapter.isolation.containerId, b.adapter.isolation.containerId);
+ const results = await Promise.all([
+ exerciseTraining(a.adapter, 'baby-a', requestedTrack),
+ exerciseTraining(b.adapter, 'baby-b', requestedTrack),
+ ]);
+ process.stdout.write(`${JSON.stringify({
+ mode: 'research-grade-training',
+ track: requestedTrack,
+ containers: [a.adapter.isolation.containerId, b.adapter.isolation.containerId],
+ updateSource: 'private-local-buffer',
+ counterpartStateRead: results.some((result) => result.counterpartStateRead),
+ policiesChanged: results.every((result) => result.policyChanged),
+ })}\n`);
+ } finally {
+ await Promise.all([a.factory.dispose(), b.factory.dispose()]);
+ }
+}
+
+if (mode === 'both') {
+ await runBoth();
+} else if (mode === 'survivor') {
+ await runSurvivor();
+} else if (mode === 'training') {
+ await runTraining();
+} else {
+ throw new Error(`unknown verification mode: ${mode}`);
+}
diff --git a/docs/api-reference.md b/docs/api-reference.md
new file mode 100644
index 0000000..5f349db
--- /dev/null
+++ b/docs/api-reference.md
@@ -0,0 +1,60 @@
+# Twin route API reference
+
+The host prefixes each path with its twin name (`/nursery`, `/baby-a`, or
+`/baby-b`); the tables show the unprefixed pack route. Every request supplies
+`x-ald-role` and `x-ald-service-token`. Human calls may also supply
+`x-ald-actor`, which defaults to the authenticated role. Mode P's development
+token for role `` is `dev-`; it is not a Mode R credential model.
+
+Every success is JSON `{ "ok": true, ...data }` with status 200 or 201. Every
+failure is JSON `{ "ok": false, "error": { "code", "message", "details"? } }`
+with one of `INVALID_REQUEST`, `UNAUTHENTICATED`, `FORBIDDEN`, `NOT_FOUND`,
+`DUPLICATE_ID`, `CHANNEL_REJECTED`, or `CONFLICT`.
+
+## Nursery routes
+
+`researcher-operator` inherits `researcher-viewer` access. `:id` is a
+path-safe run ID.
+
+| Route | Authorized role | Request | Success data |
+|---|---|---|---|
+| `POST /runs` | researcher-operator | a `RunConfig`, or `{ config: RunConfig, preRegistration?: PreRegistrationBinding }` | 201 `{ run: RunSummary }` |
+| `POST /runs/:id/step` | internal-controller | empty body | `{ turnResult, run: RunSummary }`; seals automatically when the step enters `sealing` |
+| `GET /runs` | researcher-viewer | none | `{ runs: RunSummary[] }` |
+| `GET /runs/:id` | researcher-viewer | none | `{ run: RunSummary }` |
+| `GET /runs/:id/transcript` | researcher-viewer | none | `{ transcript: ChannelEvent[] }` |
+| `GET /runs/:id/ledgers` | researcher-viewer | none | viewer: `{ ledgers: AuditLedgers, agentNativeEventCounts }`; operator: `{ ledgers: NativeLedgers, auditLedgers }` |
+| `GET /runs/:id/audit` | researcher-viewer | none | `{ audit: InterventionEvent[] }` |
+| `GET /runs/:id/checkpoints` | researcher-viewer | none | `{ checkpoints: CheckpointManifest[] }` |
+| `GET /runs/:id/anchors` | researcher-viewer | none | `{ anchors: AnchorReceipt[] }` |
+| `GET /runs/:id/telemetry` | researcher-viewer | none | `{ telemetry: TelemetryRecord[] }` |
+| `GET /runs/:id/replay` | researcher-viewer | none | `{ replayDigest, scenario, readOnly: true, overrideAllowed: false }` |
+| `GET /runs/:id/observations` | researcher-operator | none | `{ observations }`; the private read is audited |
+| `POST /runs/:id/pause` | researcher-operator | `{ reasonCode: string, details?: object }` | `{ run: RunSummary }` |
+| `POST /runs/:id/resume` | researcher-operator | `{ reasonCode: string, details?: object }` | `{ run: RunSummary }` |
+| `POST /runs/:id/abort` | researcher-operator | `{ reasonCode: string, details?: object }` | `{ run: RunSummary }` |
+| `POST /runs/:id/annotate` | researcher-operator | `{ reasonCode: string, details?: object }` | `{ event: InterventionEvent }`; creates a checkpoint and deviation reference |
+| `GET /runs/:id/verification-report` | researcher-viewer | none | `{ report: VerificationReport }` from the exported file |
+| `POST /runs/:id/verify` | researcher-operator | empty body | `{ report: VerificationReport }`; exports, writes proofs, then verifies |
+| `POST /session/snapshot` | researcher-operator | empty body | 201 `{ snapshotId: string }` |
+| `POST /session/restore` | researcher-operator | `{ snapshotId: string }` | `{ runs: RunSummary[] }` recovered from that session index |
+| `GET /session/delta?since=` | researcher-viewer | query parameter `since` | `{ since, changed: RunSummary[] }` |
+
+## Baby routes
+
+The same six routes exist on both `/baby-a` and `/baby-b`. A request that
+names the counterpart anywhere in its body is forbidden. `observe`, `act`,
+`deliver`, and `outcome` require the run to be `running` or `evaluating`.
+
+| Route | Authorized role | Request | Success data |
+|---|---|---|---|
+| `POST /observe` | internal-controller | `{ runId, observation: Observation }`, whose recipient is this Baby | `{}` after hygiene validation and delivery |
+| `POST /act` | internal-gateway | `{ runId, turnBudget: TurnBudget }` | `{ envelope: TurnProposalEnvelope }` |
+| `POST /deliver` | internal-gateway | `{ runId, delivery: DeliveredChannelArtifact }` | `{ ledgerDraft: LedgerDraftEnvelope }` |
+| `POST /outcome` | internal-controller | `{ runId, outcome: OutcomeEvent }` | `{}` |
+| `GET /ledger?runId=` | researcher-viewer | query parameter `runId` | `{ ledger: AuditLedgerEntry[], agentNativeEventCount: number }`; never returns native content |
+| `POST /reset` | internal-controller | `{ runId }` | currently returns 409 `CONFLICT`; reset occurs only during run creation |
+
+The authoritative schemas are exported by `@ald/types`. New routes must also
+be added to the exhaustive authorization/envelope matrix and this document;
+`scripts/check-api-docs.mjs` enforces that correspondence.
diff --git a/docs/architecture.md b/docs/architecture.md
new file mode 100644
index 0000000..c7b7310
--- /dev/null
+++ b/docs/architecture.md
@@ -0,0 +1,37 @@
+# Architecture overview
+
+The system has three twin surfaces: `baby-a`, `baby-b`, and `nursery`. A Baby
+receives only a private numeric observation, acts through the Symbol Gateway,
+receives only a validated public artifact, and writes only its own native
+ledger. There is deliberately no Baby-to-Baby route. The Nursery owns run
+lifecycle, deterministic scenarios, evidence export, checkpointing,
+verification, operator interventions, and the Research Console.
+
+One committed turn follows this boundary:
+
+1. the Scenario Engine deterministically produces role-specific observations;
+2. the active Baby adapter returns a proposal and private intention draft;
+3. the Symbol Gateway validates the carrier and commits the public channel
+ event plus the sender ledger event atomically through the Evidence Writer;
+4. the recipient adapter receives only the committed public artifact and
+ returns its interpretation draft;
+5. the Nursery evaluates the task outcome and records signed outcome and turn
+ evidence; and
+6. the Checkpoint Service commits ordered Merkle roots for every evidence
+ stream, which the Anchor Publisher may submit to Base.
+
+SQLite WAL and append-only constraints are the local source of truth. Bundle
+export is a deterministic projection of that store. The independent verifier
+uses only an exported bundle, public keys, and anchor receipts; it does not
+trust the live runtime or its database.
+
+Prototype Mode keeps logical state separation in one process. Research-Grade
+Mode places the two learner hosts in distinct hardened containers and distinct
+internal networks, with the Nursery attached to both networks as the only
+test controller. The exact six allowed mode differences are represented by
+`MODE_COMPARISON`; all protocol, scenario, evidence, and learner behavior is
+otherwise shared.
+
+Operational entry points are documented in [the API reference](api-reference.md),
+[the Mode R runbook](mode-r-runbook.md), and
+[the snapshot/restore runbook](snapshot-restore-runbook.md).
diff --git a/docs/audit-cost-and-utility.md b/docs/audit-cost-and-utility.md
new file mode 100644
index 0000000..09e1b28
--- /dev/null
+++ b/docs/audit-cost-and-utility.md
@@ -0,0 +1,142 @@
+# Audit Cost and Utility: Local Software Qualification
+
+Status: completed local benchmark; A03 remains in progress
+Evidence class: software qualification, not an empirical research result
+Protocol: `protocols/audit-cost-utility.v1.json`
+Receipt: `reports/research/audit-cost-utility-receipt.json`
+
+## Question and boundary
+
+This benchmark asks what the current audit artifacts cost to store and verify on the
+local qualification host, and whether the two existing verifier implementations
+reject the already-prespecified integrity challenges. It does not test whether the
+agents communicate successfully, whether ledger interpretations are truthful, or
+whether a public-chain anchor improves scientific validity.
+
+Five immutable E13 software-qualification bundles were selected by run ID and by the
+content-tree hashes already captured in the data/claim manifest. They contain 260
+turns and 1,828 total stream events. All five remain excluded from pilot,
+confirmatory, replication, and hypothesis-estimation use. Both verifiers accepted
+their local contents only under the explicit unanchored qualification boundary. No
+RPC endpoint was supplied and no public transaction was authorized.
+
+## Comparators
+
+The comparison separates storage models from executable verification work:
+
+| Comparator | Exact meaning | What it can establish |
+|---|---|---|
+| Payload lower bound | JSON serialization of each event's `content` value | Approximate application payload volume only |
+| Ordinary-log proxy | JSONL with stream, sequence, turn when present, event type, and content | Declared storage comparator; it has no implemented integrity guarantee |
+| Signed streams | Actual five stream files, including links, hashes, signer metadata, signatures where applicable, and witness fields | Stored signed/linked record cost, but not complete bundle cost |
+| Whole-input SHA-256 | One trusted digest over sorted paths and bytes of the same verifier input | Detects later byte changes relative to that trusted digest; does not validate sequence, signatures, lineage, receipts, or truth |
+| Rust auditor | Independent local parsing, canonical hashes, event signatures, chain/checkpoint and receipt bindings, and attachment hashes | Cross-implementation integrity check with narrower coverage than the production verifier |
+| TypeScript production verifier | Complete bundle verification, including the exported proof files and experiment-record bindings | Current production verification behavior; public-chain facts still require an RPC reader |
+
+The ordinary-log proxy is deliberately not promoted into a new logging system. Its
+purpose is to make the storage denominator explicit. Likewise, the full bundle ratio
+must not be labeled "cryptographic overhead": the bundle also carries policy state,
+prompts, configuration, and experiment metadata.
+
+## Method
+
+The protocol fixed one warm-up and five measured subprocess invocations per bundle
+for each verifier. Twenty whole-input SHA-256 measurements were made per bundle. The
+monotonic wall clock includes process startup for both verifiers. Runs were serial;
+filesystem cache state was not controlled. Medians and p95 values are descriptive for
+this six-logical-CPU, approximately 7.5-GiB host. They are not inferential performance
+estimates and should not be generalized to a study deployment.
+
+The benchmark re-hashed verifier inputs before and after measurement and aborted on
+any change. `verification-report.json` was excluded from verifier input and included
+only in the captured-directory total. The generated receipt records executable and
+compiled-verifier hashes, host details, every timing sample summary, input-tree
+hashes, and per-verifier coverage counters.
+
+## Storage result
+
+| Layer or component | Bytes across five bundles | Bytes per turn | Share of verifier input |
+|---|---:|---:|---:|
+| Payload lower bound | 546,418 | 2,101.61 | 2.65% |
+| Ordinary-log proxy | 687,916 | 2,645.83 | 3.33% |
+| Actual signed streams | 2,053,633 | 7,898.59 | 9.94% |
+| Integrity core | 12,117,263 | 46,604.86 | 58.68% |
+| Policy state | 6,437,525 | 24,759.71 | 31.17% |
+| Experiment metadata and analysis | 41,793 | 160.74 | 0.20% |
+| Complete verifier input | 20,650,214 | 79,423.90 | 100.00% |
+
+Actual signed streams are 2.985× the declared ordinary-log proxy, an incremental
+1,365,717 bytes or 198.53% for these five small runs. Complete verifier inputs are
+30.019× the proxy. That larger ratio is driven principally by integrity structures
+and policy snapshots: proof files alone account for 11,795,564 bytes, while
+checkpoints account for 309,373 bytes. This small-run format stores many individual
+proof files, so the ratio is sensitive to checkpoint frequency, run length, and file
+layout. It is not a stable asymptotic estimate.
+
+## Offline verification result
+
+| Bundle | Events | Proof files checked by production verifier | Whole-input SHA-256 median | Production verifier median | Rust auditor median |
+|---|---:|---:|---:|---:|---:|
+| Fixed glyph | 333 | 2,736 | 48.964 ms | 982.747 ms | 39.159 ms |
+| Fixed token | 345 | 3,095 | 49.712 ms | 1,027.571 ms | 41.201 ms |
+| Generative bitmap | 378 | 3,140 | 52.751 ms | 1,156.726 ms | 47.084 ms |
+| Generative canvas | 381 | 3,146 | 52.136 ms | 1,069.228 ms | 47.236 ms |
+| Generative tone | 391 | 3,274 | 53.950 ms | 1,108.121 ms | 49.963 ms |
+
+Both verifiers accepted all five local unanchored bundles. The production verifier
+checked 15,391 exported proof files in total. The Rust auditor checked the same 1,828
+stream events and 171 checkpoints but does not implement the exported proof-file
+pass; its faster time is therefore evidence about a narrower independent audit, not
+an equivalent-work performance advantage. Whole-input hashing reads the complete
+input tree but supplies only byte-change detection relative to an already trusted
+digest.
+
+## Integrity-challenge utility
+
+The benchmark binds to the prior frozen integrity-challenge receipt rather than
+creating new mutation definitions after observing performance. Both implementations
+accepted the unchanged fixture and rejected each of six challenges: event-content
+mutation, attachment-byte mutation, lineage injection, wrong-chain substitution,
+false receipt, and an unanchored tail. This yields 12 observed rejections in 12
+implementation-by-case challenges.
+
+That count is a deterministic conformance result from one fixture per case. It is not
+a statistical sensitivity estimate, does not sample an attacker distribution, and
+does not show that ordinary logs would fail every such mutation. A trusted whole-file
+digest would detect changed bytes, but it would not independently adjudicate the
+semantic and structural rules that the verifiers apply.
+
+## What remains for A03
+
+A03 stays `IN_PROGRESS`. Its local software-qualification component is complete, but
+three preconditions remain:
+
+1. measure actual deterministic simulated-commitment submission, confirmation, and
+ receipt-verification latency; monetary fee remains not applicable;
+2. repeat cost measurement on prospectively registered pilot and confirmatory
+ bundles at the selected checkpoint schedule and study scale; and
+3. execute the registered ordinary-log, signed-log, and full-audit comparison on the
+ same study inputs before drawing an incremental scientific-value conclusion.
+
+The present public-anchor result is exactly `not-measured`: zero transactions, null
+latency, and null fee. Local fake-chain receipts cannot close that gap.
+
+## Reproduction
+
+After building the TypeScript workspace and the release Rust auditor, regenerate the
+host-specific receipt deliberately with:
+
+```sh
+pnpm run benchmark:audit-cost
+```
+
+Routine checks validate the stored receipt without rerunning timing:
+
+```sh
+pnpm run audit:audit-cost
+```
+
+Regeneration changes descriptive timing values and should be committed only as a new
+declared benchmark snapshot. The receipt checker verifies the protocol hash, evidence
+boundary, bundle count, storage accounting, timing ordering, verifier coverage
+distinction, mutation count, and the absence of a fabricated public anchor result.
diff --git a/docs/carrier-perception-qualification.md b/docs/carrier-perception-qualification.md
new file mode 100644
index 0000000..d3cab70
--- /dev/null
+++ b/docs/carrier-perception-qualification.md
@@ -0,0 +1,28 @@
+# Carrier Perception Qualification
+
+This qualification covers a deliberately narrow part of the E13 analysis path. It
+tests deterministic carrier-specific distances and held-out nearest-prototype
+scoring for bitmap, canvas, and tone marks on synthetic fixtures. The protocol and
+generated receipt bind the implementation to exact source hashes and to a clean,
+detached v0.1.71 validation.
+
+The bitmap distance is normalized cell Hamming distance. Canvas marks are rasterized
+on the registered 16-by-16 grid and compared over a fixed plus-or-minus-one-cell
+translation window. Tone marks use a normalized sequence edit cost with graded pitch
+and duration substitutions. The evaluation uses deterministic distance, family, and
+identifier ordering and reports exact structural novelty separately from distance.
+
+The first canvas positive control failed under raw raster Hamming: a translated
+within-family stroke was ranked farther away than a crossing-family stroke. That
+failure is retained in the receipt. The fixed translation window corrected this
+specific diagnostic defect without redefining a transformed mark as an exact copy.
+
+All three synthetic carriers recover two intended families with two novel queries
+each. Six negative controls reject cross-carrier comparison, malformed carrier data,
+ambiguous identifiers, and uncovered query labels. These are deterministic software
+controls, so their perfect accuracy is not an empirical learner result.
+
+The qualification does not show that either learner acquired this metric, inferred
+a transformation rule, generalized on production-held-out forms, communicated more
+successfully, or avoided forbidden metadata, timing, envelope, container, dimension,
+sample-rate, or compression paths. B09 and E13 therefore remain open.
diff --git a/docs/carrier-side-feature-qualification.md b/docs/carrier-side-feature-qualification.md
new file mode 100644
index 0000000..ab53ef2
--- /dev/null
+++ b/docs/carrier-side-feature-qualification.md
@@ -0,0 +1,26 @@
+# Carrier Side-Feature and Reference-Topology Qualification
+
+The versioned protocol binds two related software checks on exact candidate
+v0.1.73. First, 28 deliberately malformed bitmap, canvas, and tone submissions
+exercise dimension, metadata, raw-media, sample-rate, compression, and container
+paths through the real Gateway. Each carrier also has an accepted and delivered
+control. Every attack must receive its exact registered reason, create one audit
+event, create no receiver delivery, and omit the raw artifact from that evidence.
+
+Second, the current two-container Mode R reference topology measures six accepted
+versus rejected transport samples and checks normalized timing, fixed wire size,
+constant error shape, direct-network refusal, filesystem/clipboard/process/worker
+denial, empty learner environments, crash survival, and independent local updates
+for the scratch-RL, self-supervised, and hybrid tracks.
+
+The candidate passed a fresh frozen install, 152 focused tests, all 1,803 repository
+tests, Rust tests and lint, secret scanning, dependency audit, and the complete Mode R
+container path. Raw logs are stored in ignored evidence storage and bound by hashes
+in the protocol and receipt.
+
+This is not a powered leakage estimate and not an E01 or E13 result. The structural
+attacks execute at the Gateway, while the Mode R measurement uses the current
+fixed-token reference topology. The final registered carrier, learner, deployment,
+sample count, tolerances, and negative-bound method have not been selected. B09 and
+B12 therefore remain open until the same checks are run prospectively on that exact
+study topology with eligible evidence.
diff --git a/docs/causal-ledger-and-leakage-protocol.md b/docs/causal-ledger-and-leakage-protocol.md
new file mode 100644
index 0000000..4a91667
--- /dev/null
+++ b/docs/causal-ledger-and-leakage-protocol.md
@@ -0,0 +1,110 @@
+# Causal Ledger and Leakage Protocol
+
+Status: D06 design frozen; no study outcomes
+
+The machine-readable source of truth is
+`protocols/causal-ledger-and-leakage.v1.json`. This document explains the
+decision boundary and the independent operating-characteristic receipt in
+`reports/research/leakage-design-validation.tsv`.
+
+## Ledger chronology and claims
+
+E15/E16 predictions must be genuinely prospective. Training ends first. The
+receiver policies freeze, and only training-period native-ledger events may
+feed the versioned prediction function. The validation-selected comparator,
+ordered probe schedule, native predictions, comparator predictions, and
+function version are committed to the intervention chain and checkpointed
+before the first held-out outcome exists.
+
+H2 is behavioral and causal: on paired held-out cases it estimates the
+seed-level target-action probability change caused by a ledger-consistent
+message rather than a shuffled valid message. Receiver observations, candidate
+order, policy bytes, recurrent state, scenario slot, and delivery envelope must
+match within a pair. Probe cases are repeated measures; the seed/run is the
+independent unit.
+
+H4 is predictive and incremental: it compares the frozen native-ledger
+predictor with one non-ledger comparator selected on validation data, then
+scores both once on untouched test cases using multiclass Brier score. The
+candidate baselines are uniform, validation-majority, transcript-only,
+task-history, and frozen-policy-state predictors. The oracle is a diagnostic
+positive control and cannot be selected. Learner-native state, generated
+post-run interpretations, and human coding remain separate evidence classes.
+
+The implementation candidate in `@ald/analysis` enforces this chronology as
+separate APIs. Five eligible comparators fit on a validation-fit fold, selection
+uses a disjoint validation-selection fold, the winner is refit on all validation
+rows, and outcome-free test predictions are hash-committed before the scoring API
+accepts labels. Exact object-key checks reject undeclared information fields. The
+oracle is constructed only as a post-outcome detector-positive diagnostic and is not
+a member of the selectable comparator type.
+
+Exact detached candidate `541142d` passed a frozen install, the 6-test focused suite,
+all 1,777 tests in 141 files, three Rust auditor tests and clippy, a 657-file secret
+scan, and the dependency audit. A deterministic 40-row fit, 20-row selection, and
+12-row scoring fixture exercised all five comparators, selected the planted
+task-history signal, and passed seven negative controls. The perfect native prediction
+was constructed from fixture labels and is therefore only an oracle-like scoring
+positive control. A separate exact runtime qualification now establishes production
+chronology and evidence binding; eligible repository registration, execution, aggregate
+analysis, and independent review remain required before blocker B10 can close.
+
+## Leakage decision principle
+
+Absence of a significant association does not establish absence of leakage. A
+negative result is eligible only when it has all three of the following:
+
+1. an explicit allowed/forbidden information set and practical margin;
+2. a powered uncertainty bound below that margin; and
+3. a planted violation detected through the same analysis boundary.
+
+E01 forbids all routes around the normalized Gateway observation: peer
+process, filesystem, network, IPC, cache, environment, tools, errors, timing,
+and variable envelope size. Each attacked path needs a detector-positive
+fixture. A passing audit means no prohibited delivery in the tested topology;
+it is not a universal isolation claim.
+
+E02 targets four-way human semantic labels. A strict track may receive only
+the declared numeric sensory data, candidate set/order, and configured carrier
+payload. Human labels, target answers, semantic identifiers, captions, paths,
+OCR text, target-coded metadata, text tokenizers, and text-aligned encoders are
+forbidden. The primary rule uses at least 200 untouched test rows and requires
+the one-sided 95% Wilson upper bound on accuracy advantage over the held-out
+majority baseline to be at most 0.10. A one-hot target-feature fixture must
+have a lower advantage bound of at least 0.20. The shuffled-label interval is
+diagnostic only.
+
+E13 distinguishes communication from leakage. Ink density, stroke structure,
+pitch, duration, and reusable normalized form identity are the intended
+carrier. Their association with referents is a form-use/bandwidth diagnostic,
+not a side channel. Hidden metadata, timing, variable envelopes, undeclared
+dimensions/sample rates, container artifacts, and recognizable prior glyph
+semantics remain forbidden and must be probed separately.
+
+E20 permits only a fixed post-outcome display and the declared binary outcome
+context. Referent identity, target action, task identity, pre-outcome delivery,
+timing, sequences, combinations, and envelope variation are forbidden. For
+each seed, analysis subtracts the mean of 1,000 within-outcome permutation CMI
+values from observed Miller-Madow conditional mutual information. With at
+least 75 eligible seeds and 1,000 windows per seed, the primary negative gate
+is a one-sided 95% seed-level Student-t upper bound below 0.02 bits. The
+percentile seed bootstrap is sensitivity-only.
+
+## Outcome-blind design validation
+
+The base-R receipt contains six exact operating-characteristic calculations.
+At E02's 200-row test size, a true chance probe clears the 0.10 advantage
+margin with probability 0.9157, boundary false clearance is 0.0426, and the
+deterministic one-hot positive control is detected with probability 1. At
+E20's 75-seed design, assuming normally distributed seed excess CMI with SD no
+greater than 0.04 bits, zero excess clears with probability 0.9959, boundary
+Type I error is 0.05, and a 0.04-bit planted mean is rejected as non-clear with
+probability above 0.99999999.
+
+The E20 variance assumption is a design constraint, not a finding. A blinded
+pilot must estimate it before registration. If the uncertainty bound for SD
+exceeds 0.04 bits, D07 must increase the seed count before outcomes are
+unblinded. The portable audit checks hashes, decision floors, required
+comparators, information sets, positive controls, and implementation markers;
+`pnpm audit:causal-leakage:r` additionally reproduces the R receipt byte for
+byte.
diff --git a/docs/causal-prediction-runtime-qualification.md b/docs/causal-prediction-runtime-qualification.md
new file mode 100644
index 0000000..1432ff0
--- /dev/null
+++ b/docs/causal-prediction-runtime-qualification.md
@@ -0,0 +1,25 @@
+# Causal Prediction Runtime Qualification
+
+The versioned protocol binds the E16 prediction path to exact candidate v0.1.75.
+For each accepted evaluation delivery, the production runtime constructs the permitted
+prediction information after the Gateway fixes the artifact and before the receiver
+acts. It commits the validation-selected baseline and native-ledger distributions,
+checkpoints that intervention, and later attaches a score bound to the recorded action
+and outcome hashes.
+
+The hashed run configuration fixes the comparator-selection commitment, native
+prediction-function version, and accepted-evaluation-delivery eligibility rule.
+Creation and restart reject a missing provider, and creation or evaluation rejects a
+mismatched selection, configured function version, or returned function version. A
+prediction provider without a plan and a plan outside E16 are also rejected.
+
+The exact detached candidate passed a frozen pnpm 12.3.4 install, 10 focused tests,
+all 1,808 tests across 144 files, Rust tests and clippy, a 678-file secret scan, and
+the dependency audit. The consolidated gate took 183.69 seconds with 917,932 KiB
+peak RSS, and the checkout remained clean. Raw ignored logs and the tracked-file
+manifest are content-bound in the protocol and receipt.
+
+This is software qualification, not an E16 result. It does not externally register
+the exact validation corpus or study configuration, execute an eligible run, produce
+aggregate inference, or provide independent review. B10 therefore remains open for
+those empirical and external requirements.
diff --git a/docs/cryptographic-separation-policy.md b/docs/cryptographic-separation-policy.md
new file mode 100644
index 0000000..f1c5488
--- /dev/null
+++ b/docs/cryptographic-separation-policy.md
@@ -0,0 +1,44 @@
+# Cryptographic Research Separation Policy
+
+Status: mandatory review gate for E40 software and evidence.
+
+## Boundary
+
+`@ald/crypto-research` implements ALD-069 research instrumentation. Its scheme
+identifiers, nonce commitments, novelty registry comparisons, and eavesdropper
+measurements describe experimental artifacts only. They do not provide or claim
+confidentiality, integrity, authenticity, forward secrecy, key security, or
+production-ready encryption.
+
+Production evidence integrity remains exclusively the responsibility of:
+
+- **ALD-009:** domain-separated SHA-256 event hashing and per-stream Ed25519
+ signing in `@ald/hashing`;
+- **ALD-019:** reviewed Base transaction signing, key handling, and anchoring in
+ `@ald/anchor`.
+
+No learned encoding, generated codebook, cipher artifact, E40 nonce, or module
+from `packages/crypto-research` may be imported into `packages/hashing` or
+`packages/anchor`. The repository's `lint:crypto-boundary` check enforces this
+dependency direction on every full check.
+
+## Required E40 reporting
+
+Every E40 attachment must report these dimensions separately:
+
+1. artifact novelty relative to the supplied prior-artifact registry;
+2. recovery outcomes for each pre-registered Eve architecture;
+3. cryptographic security as `not-established`.
+
+Uniqueness, a fresh salt or nonce, and low recovery against one implemented Eve
+must never change the third value. E40 uses synthetic, non-sensitive messages
+only. Any future security claim requires an external threat model, formal
+argument, expert review, and reviewed production implementation outside this
+research harness.
+
+## Review gate
+
+Gate G5 / ALD-077 may mark E40 *software readiness* only when the ALD-069 tests
+and the import-boundary lint pass. That readiness does not change E40's
+`Not started` notebook status, satisfy its cryptographic-review checklist, or
+constitute an experiment result.
diff --git a/docs/data-and-claim-inventory.md b/docs/data-and-claim-inventory.md
new file mode 100644
index 0000000..f3ac0e3
--- /dev/null
+++ b/docs/data-and-claim-inventory.md
@@ -0,0 +1,53 @@
+# Data and Claim Inventory
+
+Status: A01 evidence-cutoff inventory complete; no research result
+
+The machine-readable source is
+`reports/research/data-claim-manifest.json`. It captures every exported run bundle
+present under local ignored evidence storage through 2026-09-12 without copying raw events,
+messages, observations, native ledgers, or secrets into Git.
+
+## Inventory result
+
+The snapshot contains 125 bundles in 19 collections and 228,577,459 bundle bytes.
+Every bundle has a recorded verifier exit code of zero. That fact does not make every
+collection current or scientific: 33 are historical qualification exports whose old
+intervention-tree declaration is incompatible with the current verifier, 51 belong
+to failed or superseded diagnostic collections, and 41 have tracked bounded software
+qualification support. All 125 are excluded from empirical estimates.
+
+Seventy-seven bundle records show anchor confirmation, but every such confirmation
+in this snapshot is a local fake-chain qualification receipt. Confirmed public-chain
+anchors: zero. The manifest uses separate fields for these values and its audit fails
+if any local receipt is relabeled public.
+
+| Evidence use | Bundles | Permitted claim |
+|---|---:|---|
+| Exact/current bounded software qualification | 41 | Only the claim boundary in the matching tracked receipt |
+| Historical qualification | 33 | Historical software behavior; no inheritance of current verifier status |
+| Failed or superseded diagnostic | 51 | Failure history and debugging provenance only |
+| Pilot | 0 | None |
+| Confirmatory | 0 | None |
+| Replication | 0 | None |
+| Empirical research estimate | 0 | None |
+
+Every bundle entry records its path, run/experiment identifiers, deployment and
+software metadata, manifest and optional verification-report hashes, complete relative-path
+content commitment, file/byte counts, verification basis, explicit exclusion, and
+allowed claim use. Collection entries link exact qualification groups to their
+tracked receipts. Diagnostics remain visible even when their bundle-level verifier
+reported success, because a green bundle cannot erase a failed or superseded
+collection-level purpose.
+
+## Reproduction
+
+`pnpm run audit:data-claims` validates the tracked manifest without requiring the
+ignored evidence corpus, so clean checkouts and CI can enforce claim boundaries.
+`pnpm run audit:data-claims:live` additionally re-hashes every locally captured file
+and fails if the evidence snapshot differs. `pnpm run build:data-claim-manifest` is an
+intentional snapshot update and must be accompanied by a review of every new
+collection's evidence class and inclusion rule.
+
+Any future pilot, confirmatory, or replication run reopens A01. It must use its
+prospective D07 seed domain and receive an explicit inclusion decision; mere presence,
+a verifier pass, or an anchor receipt never promotes it automatically.
diff --git a/docs/e03-design-simulation.json b/docs/e03-design-simulation.json
new file mode 100644
index 0000000..a3742b8
--- /dev/null
+++ b/docs/e03-design-simulation.json
@@ -0,0 +1,64 @@
+{
+ "version": 2,
+ "claimBoundary": "outcome-blind-design-simulation",
+ "scope": "single-control-equivalence-component",
+ "registrationFacingReceipt": "reports/research/statistical-validation.tsv",
+ "samplingModel": "normal-seed-rate-with-binomial-episode-variance",
+ "seed": "ald-e03-v1-design-check",
+ "repetitions": 30000,
+ "mean": 0.25,
+ "episodesPerSeed": 200,
+ "equivalenceBounds": [
+ 0.2,
+ 0.3
+ ],
+ "alpha": 0.01,
+ "minimumPower": 0.9,
+ "rows": [
+ {
+ "maximumBetweenSeedSd": 0.05,
+ "primarySeeds": 25,
+ "totalSeedRateSd": 0.05863019699779287,
+ "equivalentReplicates": 27280,
+ "repetitions": 30000,
+ "estimatedPower": 0.9093333333333333,
+ "monteCarloStandardError": 0.0016577718200667447,
+ "monteCarloLower95": 0.9060841005660025,
+ "passesMinimumPower": true
+ },
+ {
+ "maximumBetweenSeedSd": 0.1,
+ "primarySeeds": 75,
+ "totalSeedRateSd": 0.10458250331675946,
+ "equivalentReplicates": 27587,
+ "repetitions": 30000,
+ "estimatedPower": 0.9195666666666666,
+ "monteCarloStandardError": 0.0015701784635535566,
+ "monteCarloLower95": 0.9164891168781016,
+ "passesMinimumPower": true
+ },
+ {
+ "maximumBetweenSeedSd": 0.15,
+ "primarySeeds": 155,
+ "totalSeedRateSd": 0.15309310892394862,
+ "equivalentReplicates": 27327,
+ "repetitions": 30000,
+ "estimatedPower": 0.9109,
+ "monteCarloStandardError": 0.0016448018117694299,
+ "monteCarloLower95": 0.9076761884489319,
+ "passesMinimumPower": true
+ },
+ {
+ "maximumBetweenSeedSd": 0.2,
+ "primarySeeds": 300,
+ "totalSeedRateSd": 0.2023301757029831,
+ "equivalentReplicates": 28462,
+ "repetitions": 30000,
+ "estimatedPower": 0.9487333333333333,
+ "monteCarloStandardError": 0.0012732948801639989,
+ "monteCarloLower95": 0.9462376753682119,
+ "passesMinimumPower": true
+ }
+ ],
+ "passes": true
+}
diff --git a/docs/e03-seed-manifest.json b/docs/e03-seed-manifest.json
new file mode 100644
index 0000000..7c062c4
--- /dev/null
+++ b/docs/e03-seed-manifest.json
@@ -0,0 +1,763 @@
+{
+ "version": 1,
+ "seedLabel": "ald-e03-v1",
+ "primarySeeds": 75,
+ "reserveSeeds": 8,
+ "conditions": [
+ "disabled",
+ "constant",
+ "random",
+ "shuffled",
+ "normal",
+ "oracle"
+ ],
+ "entries": [
+ {
+ "slot": 1,
+ "use": "primary",
+ "scenarioSeed": "5a64e3d3b490b4d5f4dbb89d7f8801a3ec53f8815c6731a8bce7cb691474eadd",
+ "gatewaySeeds": {
+ "random": "d3b41fe5c9ea0807e97d589b561d11f0b91a83c65485f29f83d0b7f7b1e28563",
+ "shuffled": "bc4976f8f3111d97be5fc80badb0632b241e4204b78d04b863e630215d860423"
+ }
+ },
+ {
+ "slot": 2,
+ "use": "primary",
+ "scenarioSeed": "111e97c0191daa17adc30a16b4826bd4f8a0a6c8fae4889bd2112bf78b313a2a",
+ "gatewaySeeds": {
+ "random": "bb04950860a3b7202363b0159ff787069f388bbb6d4c4be89ab06a1fe1a26868",
+ "shuffled": "6ca9a995154941fb1a28c84538f3c5f063cf8c307841e4fe75928aedf1b34ec3"
+ }
+ },
+ {
+ "slot": 3,
+ "use": "primary",
+ "scenarioSeed": "f1fcdd9c98e564a58e5a2b0cb9de61babfcb8a45d118198963b7afcbc13e43e8",
+ "gatewaySeeds": {
+ "random": "b518f397d6d8da254430b7c1c8705dcde6441332257e48c3febba191259f2039",
+ "shuffled": "cd2364fc2b971f8d58e1d4468815eb64099a8280b8c0beb8caae3695d238c25b"
+ }
+ },
+ {
+ "slot": 4,
+ "use": "primary",
+ "scenarioSeed": "50457005832bb9d8211e66ba8b96234a09090b9bdd62c73cbca0330eb84a4001",
+ "gatewaySeeds": {
+ "random": "0910aef1acb70c1d7905d30f0df1d192dca8ee8d2638aa1d71ac7d424615e239",
+ "shuffled": "e8f85478177491953bf4e01228ca61181b1edd0976f0118405ef0991aa77d97e"
+ }
+ },
+ {
+ "slot": 5,
+ "use": "primary",
+ "scenarioSeed": "ae3e652bf8708cde1c19c03d2c3a1ef64115fb582d7ca8069f82888ed2e7f846",
+ "gatewaySeeds": {
+ "random": "21c2bca6f16c845675963826668c622929965fb040f8c1b9cf0245f7d5b727f7",
+ "shuffled": "e0895abb2eb0a8ba9f016d5b71fd848d703617dfb69af7afa31d986761aff861"
+ }
+ },
+ {
+ "slot": 6,
+ "use": "primary",
+ "scenarioSeed": "60c60790cca071e298ac47f2645b07f96a243c875d0e55e91303815dd12b316a",
+ "gatewaySeeds": {
+ "random": "d8b5722f1372da820503baf5b1b49068193ab7824069bac64614be84257e9c76",
+ "shuffled": "49273457d63258ad2453fa6b67c7f2a7232fd68bce8bdf2c49cca99063d6e827"
+ }
+ },
+ {
+ "slot": 7,
+ "use": "primary",
+ "scenarioSeed": "2a7ceb81e0babdd47771e3985c6e0e2d235dd788c553ee4a5cf05af5f0b7e285",
+ "gatewaySeeds": {
+ "random": "9147d210652fa4459fd129eaa53c86e2c01ff977b4ecd00f267c48389479f792",
+ "shuffled": "58d2d31701221153078ef9b56037cd0b84ad09f4ab8f22e32bd2955cefb58d50"
+ }
+ },
+ {
+ "slot": 8,
+ "use": "primary",
+ "scenarioSeed": "21965dc989d19aeca318bfbec30d7070a7617b3ba99abd0eb87929931d0a1602",
+ "gatewaySeeds": {
+ "random": "89ad9780c9972b0cc091bc39060a971a27fe73f2f4c79665bf48f491a3099ac9",
+ "shuffled": "d5f7a6822a400efa0798d4e336f10a16e0e01ac868b71302e0e669438edc57de"
+ }
+ },
+ {
+ "slot": 9,
+ "use": "primary",
+ "scenarioSeed": "ef2c51ed1939714a7195c570a1a0cefbd8b1799ab08a579d7b6da456e561fe75",
+ "gatewaySeeds": {
+ "random": "cf0f2f824bf6404e74ffcd7451a1427ebaca67598d8a680b6c3e45cf6a6ee76f",
+ "shuffled": "6b602d1599c99c6ed86073a32bce3247e62befae9b8b2841265022a38ea9af0e"
+ }
+ },
+ {
+ "slot": 10,
+ "use": "primary",
+ "scenarioSeed": "bf3e2bc8982fff7bb6c8c76412814240f1a32de8983eb0df3d7df96e5051e7ca",
+ "gatewaySeeds": {
+ "random": "6270fc7c832f1cfacbfbf123ec0a44d506922bbc8a0b77f6d7ad89d6c79dc129",
+ "shuffled": "4edb533c621be4e708a28de4f94cd10a0cbe3605677cf617a9629d66e161d61f"
+ }
+ },
+ {
+ "slot": 11,
+ "use": "primary",
+ "scenarioSeed": "f5ad34f6572eca1d59f817fc9d78b0e223bca58e51ac8a15cc517361b2b728c5",
+ "gatewaySeeds": {
+ "random": "9b0616fce879c40366ecc1f3a9456a923950769529435860d32d19a97815064f",
+ "shuffled": "43b095c77413c952e8cb469ec7a512f0631586e27dee075578ad521af55aca31"
+ }
+ },
+ {
+ "slot": 12,
+ "use": "primary",
+ "scenarioSeed": "5e562a15042d92bd3cbe90f2ca3c6d3c121d30465439a843e0a26032ed1c9897",
+ "gatewaySeeds": {
+ "random": "275260842584abc9967bb4e12f52359f08828bacdc6970477aa2216a91736766",
+ "shuffled": "5d2622337ea2b3fa81bccc13014bebed739c49a7fcad4d8b1f66df32a12bf7e7"
+ }
+ },
+ {
+ "slot": 13,
+ "use": "primary",
+ "scenarioSeed": "29915966065b440ebb21d2cdc60be66df999e3c77da8a7672752bb24dbbf9813",
+ "gatewaySeeds": {
+ "random": "a39e5f7341f1166f49315036db1321698e880fac5da40df04b433a2dd4e0fed1",
+ "shuffled": "e867daea074ae7f4380f2ee71b69f0e52b7732ad17c245d34901d2b75afb47bd"
+ }
+ },
+ {
+ "slot": 14,
+ "use": "primary",
+ "scenarioSeed": "cb546889d4acfa0317a537bb0dd57fa10d78695365b4dcea53855a67f670809f",
+ "gatewaySeeds": {
+ "random": "d3a46270a8bb7ec8561e386c3fde1a052b78688969f8e166497845c0ab748902",
+ "shuffled": "aa984a76835786de19fd875d1e90cf21a6b5c67609c0a63a26370765e6734d5c"
+ }
+ },
+ {
+ "slot": 15,
+ "use": "primary",
+ "scenarioSeed": "9ad5790f481263b3dd0286f874895a54a4bb44fef276cd9d0e05a0956ac080b9",
+ "gatewaySeeds": {
+ "random": "058e0fa02dc747e0d9a58c027716d916f6bf32e1d1030fcfcdce8f4d197226ae",
+ "shuffled": "e4a5601c431711274e6800f174e7ab2fb8cd5db42ee8ef8c9f06d241a01f076a"
+ }
+ },
+ {
+ "slot": 16,
+ "use": "primary",
+ "scenarioSeed": "3f3735fbd76df4370408c9b7697e23836e394040ff96c0d6e9638e58a4c0dc26",
+ "gatewaySeeds": {
+ "random": "45c20d07fdba26e344b426402d391b36b70493a21039ef3f58bf6c8a5e8b03ac",
+ "shuffled": "6d357a062d01db225b398a8bd7c898d6c0c36139ddd905cdffb38878cbc2d6fe"
+ }
+ },
+ {
+ "slot": 17,
+ "use": "primary",
+ "scenarioSeed": "d16d6c79d4fc498feb26c7935613ab7cb5de8122079a97a1b6581fa3b95d4209",
+ "gatewaySeeds": {
+ "random": "acba087f3eaf070279c7d7b4af586ddd05682b73dfb35fcdaa99338f72881593",
+ "shuffled": "89c71f30c6245bd389d28fe7e9a251d6ec80458aa54ed80fb43645d7203d6299"
+ }
+ },
+ {
+ "slot": 18,
+ "use": "primary",
+ "scenarioSeed": "1547f32baec4750987a63c496b76b4adefc1d6386d77a5222577a094f503704a",
+ "gatewaySeeds": {
+ "random": "15e5f05b38bc8f717994e210044ba9fb3a5673cfff0e9da7b5bb5da7aefe9e70",
+ "shuffled": "7ad766a5eaa7760a3775a08025570ee7a8419704d5963786236a8dee617d2023"
+ }
+ },
+ {
+ "slot": 19,
+ "use": "primary",
+ "scenarioSeed": "7c2494ea82519830a1a36f586faf1f61b2153bab92d3960689541734c8bb5177",
+ "gatewaySeeds": {
+ "random": "a614f897070cfc036012fe083ac6aa06d4c80560679edd4e39a4e2ea1d26e15c",
+ "shuffled": "5ca84dc137bc91d65c44d069fed39de5ca76d186c16ec352d8f82601806be185"
+ }
+ },
+ {
+ "slot": 20,
+ "use": "primary",
+ "scenarioSeed": "dca87bebdf236146c3f6fd3f4b8377fa621d04a010547e21c3a746e2ed0c7103",
+ "gatewaySeeds": {
+ "random": "de0561862653ebdbedf607bbec37a0fe831fdac570e6778f8e5dc09c49e7d081",
+ "shuffled": "3bfb9193d4fb1ff53b3aa0dc7d52b91bade1d9811f83c24cf26bdccea7d5b080"
+ }
+ },
+ {
+ "slot": 21,
+ "use": "primary",
+ "scenarioSeed": "630b772336ae0e59b501938ddde614e7667d4ce9932ae123996c1e3a0dbdc16f",
+ "gatewaySeeds": {
+ "random": "3515d1c079364a38494a43b0eaac05237c699a2fac8b34897db48870831df2d4",
+ "shuffled": "5fdaa9bd33965cfc9614d84acaedd53896ca1674f88997ac5264b2dd67b19985"
+ }
+ },
+ {
+ "slot": 22,
+ "use": "primary",
+ "scenarioSeed": "a213b1d37d51ffc3f3e359bb8f7e86267c6270d8b6e0254bc2985e41cc074469",
+ "gatewaySeeds": {
+ "random": "700c2b1ef650b86c97734f383a0c83419bba52e4205d5543b13c3db7d6bd48b9",
+ "shuffled": "cf49db1c44ec88865c43a94d087207986947abf114847e711bbd3a4a1aee43d3"
+ }
+ },
+ {
+ "slot": 23,
+ "use": "primary",
+ "scenarioSeed": "7425573ee4f9bb1a9c302835b98510c7e3dbdf9a3c445042529f517f69c89541",
+ "gatewaySeeds": {
+ "random": "3d810dfd8c6c3d77e8180914933970cdce90b135960038fa212f84afb261d023",
+ "shuffled": "7db8ae675e64d87f75778fd02ff2245c413308bfe88a9ab5707cab86b9a8e9b6"
+ }
+ },
+ {
+ "slot": 24,
+ "use": "primary",
+ "scenarioSeed": "2aa8dc794e9b7205e73c1359445a8a05314b63e46a1e2fcbbbb345b0387f1e8b",
+ "gatewaySeeds": {
+ "random": "603f1e370b927019caa396de005e98b270c4448936e9ba23882e1b8f5437db59",
+ "shuffled": "81ae24a73143177e86baea9c14a64304854ac60073ee41c8d3755e9a2e85f984"
+ }
+ },
+ {
+ "slot": 25,
+ "use": "primary",
+ "scenarioSeed": "f4cd332d1332c65a9bcfaf5038b97c66ffbabb3d8e628e31349d403e70c5e62b",
+ "gatewaySeeds": {
+ "random": "fca8d81a0b5850a1ba0843785a48f768ca0b750578baf48d5860e708bc6836a9",
+ "shuffled": "9e91730cda4252354e2f61b315030cc2f42b48c66eb4719accb663a85fe4a8e8"
+ }
+ },
+ {
+ "slot": 26,
+ "use": "primary",
+ "scenarioSeed": "b4bd5c0d47b03064bba499cd92c6d18763014dda18acd268eaf166bdb88c5176",
+ "gatewaySeeds": {
+ "random": "a5ebcd87b9fce35f76c821914f5ac5df68a925f7db28555b74deabae00a4b61c",
+ "shuffled": "3a4580dae21205a868f9c79389f3adad8dfb91082f666c12e8dc0dc6bf8fe1d5"
+ }
+ },
+ {
+ "slot": 27,
+ "use": "primary",
+ "scenarioSeed": "821f56efedbbc32ab637efeffe7861a1b1de38138358844efccd405935c7bdbf",
+ "gatewaySeeds": {
+ "random": "2d716491ed089afe4e569aaa9e84757b551807a06422d60765a0e6091f6218b0",
+ "shuffled": "0132d77f4990c81e0be6c41806e196f41ce63d16175bf85be0094985e55f920e"
+ }
+ },
+ {
+ "slot": 28,
+ "use": "primary",
+ "scenarioSeed": "0666955c73b5f672219321bed8849e59971ca014076855f813665af084671f63",
+ "gatewaySeeds": {
+ "random": "28f3b6e40e1a0e418f0fc8fe9af99dd89b81beff48021797b6c07725a2aa4fa1",
+ "shuffled": "6c8cb7b43f5cec5d56d2f16e5804091cdc87637360a28f21a4c0498b1c6461ef"
+ }
+ },
+ {
+ "slot": 29,
+ "use": "primary",
+ "scenarioSeed": "faa10cf87e74dfdd64c88b7e1734214d00612ba3377c9c3c8425cdbe53fcac1e",
+ "gatewaySeeds": {
+ "random": "3db2a52dd35ee1881eee496c505b92eefad6a89c5686053cad098ffc0b2aa503",
+ "shuffled": "97fa13f19596ae96ef3b3faff7f1f87b9c56f1090dab9efa9b01cd420e14690c"
+ }
+ },
+ {
+ "slot": 30,
+ "use": "primary",
+ "scenarioSeed": "e2223828241cb537d73d52ab01ecbc614d86038b5910542452f3e75cd25427ae",
+ "gatewaySeeds": {
+ "random": "45347fe2c7932218269bf419f7f8caad57f2123ddf52f424efd6b1510c95020f",
+ "shuffled": "b8e27748bb27929fafc124a394993413d0692e0f7e834168a2dfe08a0f82a9ec"
+ }
+ },
+ {
+ "slot": 31,
+ "use": "primary",
+ "scenarioSeed": "aca8d6f618c33769404011b25fc32503bb64d0fd3c62a15fd84dbab0c0226e0f",
+ "gatewaySeeds": {
+ "random": "b4099a9955d4b7843f2c8bff1751509c20d10da18fc9bf6563ecf14c45852e5b",
+ "shuffled": "e4a889b34c4614c60ef00d3482762a94861269cf452f2b12c32485fb59b240c6"
+ }
+ },
+ {
+ "slot": 32,
+ "use": "primary",
+ "scenarioSeed": "d7c550fd460253cde042b1f5033d2a2b571c2a6c46d306d0eb6a476e441c1ac0",
+ "gatewaySeeds": {
+ "random": "5fb82b5dda7eaf07822a71929e7ddda80c48641ced5600e3c27c749deeca2650",
+ "shuffled": "88f003323127c5df9a7f8665b9ce5c92be2b57e7f8e20b0e990829f627626fb0"
+ }
+ },
+ {
+ "slot": 33,
+ "use": "primary",
+ "scenarioSeed": "04845b30f86ee646a74e9b78e810261dabd782f8aee9c5dbb7a0846c6dbc185f",
+ "gatewaySeeds": {
+ "random": "9b8e4396eca78b587b66e5073fee36e747e8962e977dba43ec006a334ae17081",
+ "shuffled": "8de1ea924c416e124b72d4f30222aeac3ff8c42c39c531dfcbcbadd6d6f6e89d"
+ }
+ },
+ {
+ "slot": 34,
+ "use": "primary",
+ "scenarioSeed": "212559dc029d345ce8de99875234f85b82aafcb86cae1893af3f0a8f4d498405",
+ "gatewaySeeds": {
+ "random": "a2426b73aee87af61db6c2c074bcb95e0c367c74b15c0b83088514dd450c61f7",
+ "shuffled": "617f6d458a69821ca1cb7b91103a2b0284cc2ffbe273f86e67f7a0560e270ea7"
+ }
+ },
+ {
+ "slot": 35,
+ "use": "primary",
+ "scenarioSeed": "305e4a0199a58aa7db900de94c18134643243b44bd3be6ad88d1c9a079c94553",
+ "gatewaySeeds": {
+ "random": "e3e577b5d909533fc164f84f2bf5b07e5369cdad65ac946084edd38fbec6a586",
+ "shuffled": "3102e016adaf7704a8fb48eea195eec9289f2a271c96133d7cc321924021e871"
+ }
+ },
+ {
+ "slot": 36,
+ "use": "primary",
+ "scenarioSeed": "93f1d0020c2a9bf0e417324a555d553c1095af4178e701d637626ff7ba906006",
+ "gatewaySeeds": {
+ "random": "5ec67ae1303105049708abf8407b8359634ad4fdadc73a908716cbf5e3bb59ef",
+ "shuffled": "d5838f30784efb3d2d81ee1082d3f22ee2e05f0f80ae188201596a63da0f7e57"
+ }
+ },
+ {
+ "slot": 37,
+ "use": "primary",
+ "scenarioSeed": "23c7a3e222536e797a901c2b39c8f442b3fa933953aaa87a29842c2e22bb1afb",
+ "gatewaySeeds": {
+ "random": "c65ba1dc96f3348e18355a3f121698932fca492ebbfcc780410dc0ebe4102ac5",
+ "shuffled": "668a460331294f6b6bc883140ce7f994c3681fd459751536fed5f6eca740e07b"
+ }
+ },
+ {
+ "slot": 38,
+ "use": "primary",
+ "scenarioSeed": "ed77b7e6948f4d82398baaaff93801afaa2f31bab77a493ccba36e884fe680b0",
+ "gatewaySeeds": {
+ "random": "d46077e23f822d2b8f88ca6cd296890285c9156da73a04c98f995d25d110a4c1",
+ "shuffled": "18a7335358ed7701f84313628c2186334ef7adc246b4192f41488ee7c5e7ba1d"
+ }
+ },
+ {
+ "slot": 39,
+ "use": "primary",
+ "scenarioSeed": "08e7301f7fc725feefd8d7f9cd343e6979fd9bcfeda4daf6b84a37dc2de1320c",
+ "gatewaySeeds": {
+ "random": "2ebc5ecc402ee636afd496cb08b051caca7a24f5323521dd09ac09a62990a8a2",
+ "shuffled": "9af25745776d0e5bbcad6e0a09e4e88e69ce37abe304f07dd9cea7a52714c958"
+ }
+ },
+ {
+ "slot": 40,
+ "use": "primary",
+ "scenarioSeed": "90ea9cfe85b0829d709119191e9c70e5803459556611b0104c06b7ed418729f5",
+ "gatewaySeeds": {
+ "random": "53ecd261200c0cb1e972f95cd677ba5b167c8c12d004dd9f1069eafd60a68443",
+ "shuffled": "5d3f557f29f0de6573129879aa5f21ffc968a7dfcc399181176479552a1ef80b"
+ }
+ },
+ {
+ "slot": 41,
+ "use": "primary",
+ "scenarioSeed": "b68b32112aab1d8ebbdcab77ff34e57ddc244c43101250a5a7ce0c495572b8f4",
+ "gatewaySeeds": {
+ "random": "1d812e6507633774cb4e15b56fc126a46f3c3ce5045ca4c442f71f20f9943d7a",
+ "shuffled": "e4155d602501abd637cffcccf2c1d70d8ad74f1a16a241feb00d4c1fdc49a752"
+ }
+ },
+ {
+ "slot": 42,
+ "use": "primary",
+ "scenarioSeed": "65ab2cb6dc17700c43691624b160d6c671047651b254c159c6a70d41c8dbb45a",
+ "gatewaySeeds": {
+ "random": "92f247f1bd7697529be844953babe13255061c6090761cbf1155afcd9e9a669c",
+ "shuffled": "f0b238ec187f8d1ac9a8fcccdc29239e6e9a5bedce893b9f38cebdbf727e2e74"
+ }
+ },
+ {
+ "slot": 43,
+ "use": "primary",
+ "scenarioSeed": "e5dbbe1752a6bba6921337d61c86174576564510a1000cbf817bfa9585559c71",
+ "gatewaySeeds": {
+ "random": "f483a21168d429712329ff2ea71126d5f0998cc7fd3043186d90f98fed35cd58",
+ "shuffled": "bc685caf42611327b03e8e9b4e54f0ee7c4d428cddf674b5bbc000cb9b560796"
+ }
+ },
+ {
+ "slot": 44,
+ "use": "primary",
+ "scenarioSeed": "e486770386854d183d0071f9a2ddd2cca21c03964062ad2bd60911dc1722d3cf",
+ "gatewaySeeds": {
+ "random": "f3a738c174cf1eb4e990ab9d518f452cd7ee923e75ecc0bb7aeb4bc9ebf69412",
+ "shuffled": "63ccdb83e7cbd3e543f8bb53071306a9de3db07dd03584048be3f03cdefdcc5a"
+ }
+ },
+ {
+ "slot": 45,
+ "use": "primary",
+ "scenarioSeed": "68ff36bd26a2fc9f7349d6b5ce8127588f37e8b7ddc9b74538e93633887aa618",
+ "gatewaySeeds": {
+ "random": "e565b8ad5290df3fecfa491e5e884830e2cdeafc8d7c88a69c28394b8fd029a2",
+ "shuffled": "0d9c36cb8c046cf157929972231067e599519df95398efe174e6da4f11080ccb"
+ }
+ },
+ {
+ "slot": 46,
+ "use": "primary",
+ "scenarioSeed": "eca0aa8d13c1fb320ec6a0eb161b1d5064036074b29539785172fcc7148fd104",
+ "gatewaySeeds": {
+ "random": "790dca8440ca1aeb54fc8a22c3f103f44301b0ba47e74cbd74a4f2b6e17424af",
+ "shuffled": "4074f7b456481c4825202124be6250ea4ed3200f1f939abc39199b565a8163b7"
+ }
+ },
+ {
+ "slot": 47,
+ "use": "primary",
+ "scenarioSeed": "2762ccf41fcd11a2bcfa9925d42a78ce01ac0f68b2ab3c6889560d5fb103ab2f",
+ "gatewaySeeds": {
+ "random": "67d97bf8c5faca776a3af1f37a3ef77498e406b0a812d4bc1a089c5e8764e056",
+ "shuffled": "42a0aa11dada73e9b6f24691764a182826bcab4d7d577ce1481383b2ede53a54"
+ }
+ },
+ {
+ "slot": 48,
+ "use": "primary",
+ "scenarioSeed": "09d8fc398e88b11348ad4c7b5eeb9c2a16ad34d281130be08d0061d6c915c96b",
+ "gatewaySeeds": {
+ "random": "96112bfdcc6fea4e44fe87154dc90aa5aaa1bc68233df740d41a4ab5c077f5f5",
+ "shuffled": "bf2e9d89859ff5a72e967b210ddd71ac9e478394836e5f0534b5c566e733ea42"
+ }
+ },
+ {
+ "slot": 49,
+ "use": "primary",
+ "scenarioSeed": "df59c136bca567cb927700dd432994dc28ffe95efcebb5ba40248710eb05e380",
+ "gatewaySeeds": {
+ "random": "d988a104ce4ce1f689e3626a6a5eed785894c8a4a2e5985a9b7ae0d366de92ef",
+ "shuffled": "2105069c4670b3eeb4c022a3505d70627d7c92800922134d988a5606d1cdd507"
+ }
+ },
+ {
+ "slot": 50,
+ "use": "primary",
+ "scenarioSeed": "514f7b47f0ba265978d7ba38ed3372e23422a015af46180c8e01237f0af6ef35",
+ "gatewaySeeds": {
+ "random": "d23cb29fb83fce2604f6720d4c626cf2102cf7ba8731db1be7ca61510a48c1bd",
+ "shuffled": "c9e9a59f0029d1d7b307157876a16b84f745e6c4930174fe9581d797d202fed0"
+ }
+ },
+ {
+ "slot": 51,
+ "use": "primary",
+ "scenarioSeed": "4e64a3125bf286cd0ef8fac3ee5a6f27c78484e9ef090e2848e42d2691b00094",
+ "gatewaySeeds": {
+ "random": "6e1d35f50398508fc9e5d1e504d712fa6ef582e6f2b824f83a3a2cfb2bae5920",
+ "shuffled": "1ad197ccb94559b546447a470b173cdbf9bee5822f5326a8d5516163f7447cd4"
+ }
+ },
+ {
+ "slot": 52,
+ "use": "primary",
+ "scenarioSeed": "8ee91917100574c36bb2ee63351acbe716f6d05b76913e0d35cb3928a7cca6a2",
+ "gatewaySeeds": {
+ "random": "7e00763b947c14c00a4c91d1187d0b1353364510731069e0c47664b565e99c0a",
+ "shuffled": "8375941812e7b4e645cda3bc044adac1a2e4765ef946f3eb5c7078d8ba1bb7b5"
+ }
+ },
+ {
+ "slot": 53,
+ "use": "primary",
+ "scenarioSeed": "4597543d23fb59b208d13e38cf594999079757f53fbdc4dca848c915a059efc4",
+ "gatewaySeeds": {
+ "random": "81434168aa18bd012d0833e8753e4aa56564d8e4753b628a6d97cfc695a5e94c",
+ "shuffled": "758bf90d86651af51101437ebe3f484ec2051167d240145eb36975e2193c4f69"
+ }
+ },
+ {
+ "slot": 54,
+ "use": "primary",
+ "scenarioSeed": "e1d109e85770e2eb878b82377cb32ade512748ac0cafbea859c84b550c3c51ac",
+ "gatewaySeeds": {
+ "random": "be058fc669738d6630d17976786a50fbc239c1f8ec48ecdb676503f137c654fc",
+ "shuffled": "1e31f471d0b273fd369d95134ce62c76f4a23f416ee10127fa4678ecabb2e84e"
+ }
+ },
+ {
+ "slot": 55,
+ "use": "primary",
+ "scenarioSeed": "bb640078e18d8d1232f052c0e888b719b221e3786152881bf23e33407c7f8273",
+ "gatewaySeeds": {
+ "random": "600c76058c9bcdb57e51a16f9b01dabfc85d0659b6d162499560d96168456772",
+ "shuffled": "f3a2daaed2fe497063ded1e42619eba6e4bd9f8a41fe15081cbf179404d063f2"
+ }
+ },
+ {
+ "slot": 56,
+ "use": "primary",
+ "scenarioSeed": "eda1e911aff937492cd73380aac84a9ba1dfe51d7b36fc93439b29431fc70ba0",
+ "gatewaySeeds": {
+ "random": "f6df372ab6b48021aae59a5b3776c8241d5a1bb4cc46a607d29d877694f43509",
+ "shuffled": "d04185bd05819897a43d6af922f7125c4f899857d761ac128702e672fdd6436c"
+ }
+ },
+ {
+ "slot": 57,
+ "use": "primary",
+ "scenarioSeed": "53a5b486b2a0b6f9ed982ed6d6842af623a9ebaa19e9abd4503d72e8e3dc6ed0",
+ "gatewaySeeds": {
+ "random": "0316fa2315e9e1d00902bc702a52c54b32fb76bae59bbad8567941ec8b94c475",
+ "shuffled": "01356eb753e31f1e12724a6e641a7379baeb95d639f21e929c3035034ec39d21"
+ }
+ },
+ {
+ "slot": 58,
+ "use": "primary",
+ "scenarioSeed": "8706235e8fa55f307c92707ce19634bb724e0a84eda94dab70947c4a933603ac",
+ "gatewaySeeds": {
+ "random": "16a2d94c2a2ec8ac9ba1f0b03a3fe04d3627f18e6b83a8eb1e40795161b0f4a6",
+ "shuffled": "a164c9f2a85a6fbe9b10a2a90f0f1ffda5a0b4805ce9152d4a8e6f4e2a831a06"
+ }
+ },
+ {
+ "slot": 59,
+ "use": "primary",
+ "scenarioSeed": "62fccd0e9c83ecf6427eed342da49391c274628f9d6818c29628fd919b72d332",
+ "gatewaySeeds": {
+ "random": "09e535df46c99146296e642d5bb0fc1408acdc152ca299c9176ea0d1d2c5495a",
+ "shuffled": "257febb136c782367e25b13ba00c1827b0dbaffc101e26e3ad7ae64b46460182"
+ }
+ },
+ {
+ "slot": 60,
+ "use": "primary",
+ "scenarioSeed": "70e8fbacf73f0599753530b6dc188fd705713cec7b47d0a1b7a28dbdc3b2d842",
+ "gatewaySeeds": {
+ "random": "f5b55d07cf47cd9ca4c36472a2dbbb281758fda97f549e32beabcf37d13325ca",
+ "shuffled": "4b63181a55e05029124ec89dbf1e930f51ce9c21a289bcc88747af288cbef898"
+ }
+ },
+ {
+ "slot": 61,
+ "use": "primary",
+ "scenarioSeed": "e5f8f36d268e79f7229114f27a107ffee96f0f840df78858c13c20c44062d46c",
+ "gatewaySeeds": {
+ "random": "e6b156bfcd2dc0b0e2c71d142a860fe7239216eaa6152c62a1e41a21ca3514f3",
+ "shuffled": "f2a0ee09f47139529c397ec6cd6b574761f7f9d4cd0b8c6ffcc68d6ea4cb68a5"
+ }
+ },
+ {
+ "slot": 62,
+ "use": "primary",
+ "scenarioSeed": "11d2c68c065fcae47d7897ca9fcbb8005f8c1cf2fa9941bba1df0af3939af22b",
+ "gatewaySeeds": {
+ "random": "a2a471246d4d1f639380bff045cdc2c7a86641292f0ea6aace3a3217bb8103a9",
+ "shuffled": "6e1d15b0eb631c6dfd9242835024a78f86845f51f45490eaa8308086b0223c07"
+ }
+ },
+ {
+ "slot": 63,
+ "use": "primary",
+ "scenarioSeed": "70d0288eb16c81542a8f18f261aca95e4c519661602e290b317ddbd2479ee03f",
+ "gatewaySeeds": {
+ "random": "b8f527ca03ad7e8aa78b371399f89b2e0cba71c5cee0590fb8b197c0bae80d06",
+ "shuffled": "7d1b55ecdd01f046e6f7e34894df80cb342d0ad2a788dd6ef5169270024f7593"
+ }
+ },
+ {
+ "slot": 64,
+ "use": "primary",
+ "scenarioSeed": "b0c6e6d3434a09b7cff7a40745ab10dfb9d1834cd5efacc5e4e7d2d569a4aa4b",
+ "gatewaySeeds": {
+ "random": "6a1ed242bc124dbdc9e12ecaeabf6219676d52cb0a825eaab758529cdf88a256",
+ "shuffled": "c5c41c55599469b0d221bbb3834285775693316a012fde6ae01eb4e938136f60"
+ }
+ },
+ {
+ "slot": 65,
+ "use": "primary",
+ "scenarioSeed": "d31451c84d664acb33bb93e505b5a9d2a6a7666c1094f09d97cb40f047549c2b",
+ "gatewaySeeds": {
+ "random": "d7e5f4c7e87f62306981bbc88b7633f5ad109823bdcebd0c5e44d78d2bc46fca",
+ "shuffled": "d6b8924b081943eef942f6b1be738c0c2dc064850fbb5eb195dcefc317b1b820"
+ }
+ },
+ {
+ "slot": 66,
+ "use": "primary",
+ "scenarioSeed": "50ba0e38255176204e491acf383437331a69022aa6c54c982055c1db64be4a13",
+ "gatewaySeeds": {
+ "random": "34c61ab640722d26128c65ee3771eaeaad99fc0c3643fcadcaecb36dfea5ef67",
+ "shuffled": "b18d7389b4b04dab722f412f65a0e81db36ed645b33ffeedbdf10f38d0983986"
+ }
+ },
+ {
+ "slot": 67,
+ "use": "primary",
+ "scenarioSeed": "0e99ee9179ab02c6cf5b2a2422e8327296188fc2ec4829e63a4eee723249764a",
+ "gatewaySeeds": {
+ "random": "a4fa7f8b58ea1389f1d01441d55d6e51d752ba1106b456ddaed6999a9ce8fcb1",
+ "shuffled": "2bf9921ee686f5f9937f31f5016026700091792e22acd08ab8cbc3fa74685f61"
+ }
+ },
+ {
+ "slot": 68,
+ "use": "primary",
+ "scenarioSeed": "ea603e75b4359fa940c0bb82e4fbc63e0b860895ed2c0bd4da992b9d26f93e32",
+ "gatewaySeeds": {
+ "random": "d9210161493b9dc88250a1426b9a2f63785bf74d6a80282676caf52246cf60ce",
+ "shuffled": "aa05bc58ca058281bde9a27dbb0a8b42e8a6e25244f8219954e338b679bbe9f8"
+ }
+ },
+ {
+ "slot": 69,
+ "use": "primary",
+ "scenarioSeed": "3b5e83f9b968602ece1f0aea0edf6dbe55da38191c2c841673c33aa00843dddd",
+ "gatewaySeeds": {
+ "random": "f0ae212d3395219d2c6fbb22040d923c781bc37484085764c2eb2e43501dfc4f",
+ "shuffled": "46e782e65d826012a51688df7e6992280ff33b0f4daeb90a8f4c28828341e83d"
+ }
+ },
+ {
+ "slot": 70,
+ "use": "primary",
+ "scenarioSeed": "983f539a446b11072a90e310ff8be758920047ff625f0e1292975f7232e3f593",
+ "gatewaySeeds": {
+ "random": "caf3eda53c2656ec72a22c08457151730e4d585f8fe7a2e96289b932bf558b06",
+ "shuffled": "c1be9c96dc69b3134d3f1fd023ed58efe927fec912f7da5d647f765ada4c0122"
+ }
+ },
+ {
+ "slot": 71,
+ "use": "primary",
+ "scenarioSeed": "2a6b1c52becec2bafc0bbe804809f5069481eb5368c258fca6ba4f08882f37e9",
+ "gatewaySeeds": {
+ "random": "a4a850eef9af1a8469ea1dc37a6d086b2348371d8e1c6e6fe6a4efe1a0a2d7b0",
+ "shuffled": "4e0f7c7c9bccf90d44faee535dde738b550619a6eba5bbb3f8b15288b2399268"
+ }
+ },
+ {
+ "slot": 72,
+ "use": "primary",
+ "scenarioSeed": "a57d6866b55b1d27709a623aec9a636900cf887fe9ba29e738db1f13aa4a8c50",
+ "gatewaySeeds": {
+ "random": "8e0e766a071942cb8d041865c6fe46b3f5c7ebe80f80d5689bbe1b8c5d4c82d8",
+ "shuffled": "8bfb066e042634a80035f2fd422f7f2a8380b6fd462b49c49715e16eb23e41cd"
+ }
+ },
+ {
+ "slot": 73,
+ "use": "primary",
+ "scenarioSeed": "66ef1f5a92850b884d94b34e95bb9a583e958f6081c1d7d0f5636809844acbbb",
+ "gatewaySeeds": {
+ "random": "ffded7dcf38ebf3b9ec5871989df43410bca3e562d1f24bc671bc2b1cf624cb9",
+ "shuffled": "84e6e11c2a335d23f73a24a840805610781a05f23ee22878d0839c8bee9aceb7"
+ }
+ },
+ {
+ "slot": 74,
+ "use": "primary",
+ "scenarioSeed": "04125eb8715dc4ba383b02bc74d774690629f5b73accc19e3ae4eab0fe43ec7d",
+ "gatewaySeeds": {
+ "random": "8beffa57f42679f37bc109947860d00c1504c6f6e08c6feab150616eca40906f",
+ "shuffled": "0e1a1d2ea1c6837a148167dac6062c953c0a980a73aadaa477230a310e91cab2"
+ }
+ },
+ {
+ "slot": 75,
+ "use": "primary",
+ "scenarioSeed": "f582567e9479f448e011f04a2588d0acf06e2f565b46a916c7038b711321ae94",
+ "gatewaySeeds": {
+ "random": "dab3000fd95e70575de6dbf35d77712a6e99a519beaa63d9c8bde389b15d7cdd",
+ "shuffled": "75e1065050eee7c768cec6240e67b5de72b3b0c813c22b29c51da0e341797722"
+ }
+ },
+ {
+ "slot": 76,
+ "use": "reserve",
+ "scenarioSeed": "ca81e4cc04b5cb2f7c4e13a2227507ba45d4ab0d44aa27044d02b5ef4e053501",
+ "gatewaySeeds": {
+ "random": "0a6f663ddc3307ed44dca4e0ce58f064be401d18d31fed557d78235b7a26850c",
+ "shuffled": "6c34a214c0d42dd2fca9aaea8f227283eb2a13641a1cdb667904d56ee0838da1"
+ }
+ },
+ {
+ "slot": 77,
+ "use": "reserve",
+ "scenarioSeed": "adb1ce551aee38ec63c38ecf318b8523c0fd26adad2e5d7d73b57cc2af442580",
+ "gatewaySeeds": {
+ "random": "a6dd4630db82c78570d6e145a15b63061ab20bf5c678e805c299776768743ac0",
+ "shuffled": "738fb6f29eac24854b7ec63e0b46850475e75620f0d2f498316a5d21ef14a68a"
+ }
+ },
+ {
+ "slot": 78,
+ "use": "reserve",
+ "scenarioSeed": "e241a6caecbc39da5678b704afedcdafa64f8d503fe1c846290fd7077a78679f",
+ "gatewaySeeds": {
+ "random": "7a6099fdaf8aa8aa252dba1399e00d637781c0c4248fc29d6eec151402e6d77f",
+ "shuffled": "b94173723b811b0c885a9251913649f0c2b8d2d58446b843f029f6b2024ed71a"
+ }
+ },
+ {
+ "slot": 79,
+ "use": "reserve",
+ "scenarioSeed": "bcf8f8825da1be2326e2499fe4de5209ac6ca68949c403aa46b14956be0fdfbc",
+ "gatewaySeeds": {
+ "random": "398046e3fbbad0e1e0b5602ba9a1420caae0ebb5d394a26243fa5e2b5a834e3f",
+ "shuffled": "09d54fd06c467496faffe8bf64aa2e07c8d5fbe125b5cc2d332ec201f86a512a"
+ }
+ },
+ {
+ "slot": 80,
+ "use": "reserve",
+ "scenarioSeed": "dc1e02e176bf2e218022959f0dc881a41a44ecadd566a9c82ed2caa430f32bb3",
+ "gatewaySeeds": {
+ "random": "ce61621656e9defb7cffe9adf423e72d09697ff8e060271c7728306bddd42fe7",
+ "shuffled": "2d9ab21dc68c62766a716a707cf78bf4355b3f4c919152679b427c5f62c7cd89"
+ }
+ },
+ {
+ "slot": 81,
+ "use": "reserve",
+ "scenarioSeed": "cf1f26da4559012b3c6c4fbc410323c1d9fcf19d6f89845b3d255c2cc446b560",
+ "gatewaySeeds": {
+ "random": "9ac8bcc812fb235da0e8fd55be56310c32466b4c3272e5a6b2bcdea3331965b0",
+ "shuffled": "1d3e6ca4544f70d79eea9e53be0ec3e397808c5c27de8762fa8a887f51f7c1b2"
+ }
+ },
+ {
+ "slot": 82,
+ "use": "reserve",
+ "scenarioSeed": "2dc11779fcef391eae96c99b8afb83d7df178369b0ea87e3779e86011285f384",
+ "gatewaySeeds": {
+ "random": "6bcd0b4310c61e9c7257e84eeaa86bedfc476dbf7eecd5ace413dfe7747c8f57",
+ "shuffled": "97f1a7b854fd348e7d5f3205414f03f09c26d12877cce5ef342fa96f46bbb5ec"
+ }
+ },
+ {
+ "slot": 83,
+ "use": "reserve",
+ "scenarioSeed": "c6091b60a986d1bfb6ce9c891b91e068cc889359900649b20807f5122f2cd671",
+ "gatewaySeeds": {
+ "random": "1f96184473fa0e9517a3fb946be0603bd7ad024d604ca0b84fab4ba86bd94c41",
+ "shuffled": "e737e9a667360929f3814cb52d1bec54479fc1e7d591f2f1223520c6621221ba"
+ }
+ }
+ ]
+}
diff --git a/docs/evidence-bundle-format.md b/docs/evidence-bundle-format.md
new file mode 100644
index 0000000..472214e
--- /dev/null
+++ b/docs/evidence-bundle-format.md
@@ -0,0 +1,250 @@
+# Evidence Bundle Format
+
+> **Status:** Implementation contract for ALD-016 (export) and ALD-015 (verifier).
+> Authoritative layout: [LEDGER-INTEGRITY-DESIGN.md §13](../LEDGER-INTEGRITY-DESIGN.md#13-evidence-bundle)
+> and [SPECIFICATION.md §13.2](../SPECIFICATION.md#132-evidence-bundle-structure).
+> This document fixes the byte-level details those sections leave open so that a
+> third party can write an independent verifier.
+
+## 1. Layout
+
+```text
+/
+ run-manifest.json canonical JSON, RunManifestSchema
+ baby-a-ledger.jsonl one canonical signed LedgerEvent per line
+ baby-b-ledger.jsonl one canonical signed LedgerEvent per line
+ channel-transcript.jsonl one canonical signed ChannelEvent per line
+ affect-transcript.jsonl present only if affect events exist
+ audit-ledger.jsonl present only if generated-analysis entries exist
+ turn-records.jsonl one canonical signed TurnRecord per line
+ intervention-log.jsonl one canonical InterventionEvent per line (unsigned chain)
+ checkpoints/
+ 000000.json canonical signed CheckpointManifest, sequence 0
+ 000001.json
+ proofs/
+ inclusion/--at-.json InclusionProofSchema
+ consistency/--.json ConsistencyProofSchema
+ anchors/
+ base-receipts.json canonical JSON array of AnchorReceiptSchema
+ configuration/
+ run-config.json canonical JSON RunConfig
+ prompts/
+ learner-contract.