Skip to content

docs(eeg): define offline encoder boundary and Shadow Lab MVP - #30

Closed
aurascoper wants to merge 3 commits into
research/eeg-fusion-basefrom
docs/eeg-offline-encoder-boundary
Closed

docs(eeg): define offline encoder boundary and Shadow Lab MVP#30
aurascoper wants to merge 3 commits into
research/eeg-fusion-basefrom
docs/eeg-offline-encoder-boundary

Conversation

@aurascoper

Copy link
Copy Markdown
Owner

W0 planning package. Documents, schemas, and contract tests only.

scope: planning_and_contracts_only
application_code_change: false
implementation_authorized: false
model_execution: false
live_control: false
promotion_status: not_eligible
base_is_authoritative: false
future_disposition:
  - rebase_after_branch_convergence
  - or_cherry_pick_e66bd09_and_c814235

Why this base, and why draft

Based on research/eeg-fusion-base because these artifacts extend the D0 fusion
contracts that live only there. That base is not the authoritative baseline:
the branches forked at 3e1b55b, so docs/eeg-methods-scope carries PR #29 but
lacks 16 D0 commits, while this base carries the 16 but lacks the fix. Neither is
a superset.

Left draft and unmerged deliberately — merging would add another layer to an
already-forked staging topology. Its disposition after convergence is a rebase,
or a cherry-pick of e66bd09 and c814235.

Commits

e66bd09 research(eeg): register offline encoder artifact boundary
c814235 docs(eeg): define the EEG Shadow Lab MVP scope

What it decides

Exploration found the intended "runtime integration" is not currently buildable
as such, for structural reasons:

  • The packaged app has no Python interpreter — package-app-bundle.sh copies the
    app binary, its dylibs, and SpectralProbe, and no Swift code invokes Python.
  • The window contracts disagree: the app windows at 2 s, while contracts.py and
    configs/muse-four-channel-v0.json pin 4 s / 1024 samples and every adapter
    hard-asserts [B, 4, 1024]. Stride agrees at 1 s; the window does not.
  • The existing worker protocol is already file handoff across machines. There is
    no IPC or streaming path anywhere in NeuralComposeEEG/.

So ADR-011 records an artifact boundary, not a worker boundary: encoders run
offline and produce immutable provenance-bound artifacts; Swift only imports,
validates, and replays them.

nc-eeg-encoder-state-v0 uses a closed discriminated source union, with top-level
if/then rules making the source type constrain the window clock fields, so a
synthetic fixture and a physical replay are distinguishable and neither validates
as the other. Every record pins 1024 samples and asserts
live_two_second_window_used: false, making the 2 s/4 s boundary a validation
failure rather than a silent pad.

A fusion encoder-output record deliberately does not validate as an encoder
state, and a separate test pins the existing F0–F2 evidence bundle byte-identical
to HEAD — its byte identity is part of its provenance.

ADR-011, not ADR-010: 010 is reserved for the Rust Compute Engine and lives at
docs/architecture/rust-compute-engine/ on research/rust-workspace, outside
decision-log/, so a directory listing reports it as free when it is not. The new
decision-log/README.md registry exists to make that visible, alongside the
ADR-004 duplication and the absent-but-cited ADR-009.

Stages are W0–W7 because P0–P4 is already the policy ladder in
EXP-NC-EEG-FUSION-001; W6/W7 reuse it rather than duplicating it.

Prerequisites named, not worked around

EEGPT's checkpoint_sha256 stays null — a placeholder digest would be worse —
and EEGNet remains absent from the encoder-ID registry. Tests assert both remain
untouched here.

Verification

119 NeuralComposeEEG tests pass (88 pre-existing, 31 new). Fusion artifacts
regenerate byte-identically. Ruff clean. No broken internal links.
git diff --check clean. No Sources/, Package.swift, configs/, Scripts/,
or .github/ file modified — application_code_change: false holds literally.

Note these tests are local-only: CI runs no Python (R9).

🤖 Generated with Claude Code

aurascoper and others added 3 commits July 24, 2026 22:01
W0 planning package for the EEGNet/EEGPT/fusion/Qwen programme. Documents and
schemas only: no encoder executes, no model is downloaded or trained, and no
application code changes.

Exploration showed the intended "runtime integration" is not currently
buildable as such, for reasons that are structural rather than incidental:

  - The packaged app has no Python interpreter. package-app-bundle.sh copies
    the app binary, its dylibs, and SpectralProbe into Contents/MacOS, and no
    Swift code invokes Python.
  - The window contracts disagree. The app windows at 2 s (EEGWindowing.swift,
    constructed in AppContainer), while contracts.py and
    configs/muse-four-channel-v0.json pin 4 s / 1024 samples and every adapter
    hard-asserts [B, 4, 1024]. Stride agrees at 1 s; the window does not.
  - The existing worker protocol is already file handoff (.npz + .json) across
    machines. There is no IPC or streaming path anywhere in NeuralComposeEEG.

So the honest description of the next several stages is an offline encoder
artifact pipeline with a strict Swift replay boundary, and ADR-011 records that
boundary rather than a worker boundary.

nc-eeg-encoder-state-v0 uses a closed discriminated source union so a synthetic
fixture and a physical replay are distinguishable and neither validates as the
other, with top-level if/then rules making the source type additionally
constrain the window's clock fields. Every record carries window_geometry
pinning 1024 samples and asserting live_two_second_window_used: false, so
feeding the live 2 s window to a 1024-sample consumer is a validation failure
rather than a silent pad. The containing recording is identified once, by the
source union, so two copies of a source hash cannot disagree.

A fusion encoder-output record deliberately does NOT validate as an encoder
state; a test pins that, and separately pins the existing F0-F2 evidence bundle
as byte-identical to HEAD. Its byte identity is part of its provenance and is
not adjusted to satisfy a later schema.

The scope-contract test also executes the JSON Schema when jsonschema is
importable, and verifies closure structurally when it is not. A declared but
never-executed schema is decoration.

Two prerequisites are named, not worked around: EEGPT's checkpoint_sha256 is
null and stays null, since a placeholder digest would be worse; and EEGNet
remains absent from the encoder-ID registry in contracts.py. Tests assert both
remain untouched on this branch.

Stages are named W0-W7 because P0-P4 is already the policy ladder in
EXP-NC-EEG-FUSION-001. W6/W7 reuse that ladder rather than duplicating it.

ADR-011, not ADR-010: ADR-010 is reserved for the Rust Compute Engine and lives
at docs/architecture/rust-compute-engine/ on research/rust-workspace, outside
decision-log/, so a directory listing reports it as free when it is not. The
new decision-log/README.md registry exists to make that visible, and records
the ADR-004 duplication and the absent-but-cited ADR-009 alongside it.

Verified: 112 NeuralComposeEEG tests pass (88 pre-existing, 24 new); fusion
artifacts regenerate byte-identically; ruff clean; no broken internal links;
git diff --check clean; no runtime, config, script, or CI file modified.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Names what the first useful EEGNet + EEGPT + fusion + Qwen product actually is,
so it is not mistaken for something larger: an offline-analysis plus in-app
shadow-replay research preview. Not a live BCI assistant, and not a
weight-fusion system.

  Muse recording -> offline 4 s re-windowing -> EEGNet and EEGPT outside the
  app -> immutable encoder-state artifacts -> strict Swift import/replay ->
  fixed F2 probability fusion -> deterministic policy baseline -> optional
  local Qwen shadow recommendation -> telemetry only

No component speaks, changes pacing, modifies acquisition, or controls the user
experience.

Scope decisions recorded here:

  - Fusion is F0/F1/F2 only. F3 logistic, F4 MLP, F5 uncertainty-gated mixture
    and F6 distillation remain later experiments, and a missing encoder yields
    an unavailable state rather than a silent substitution of the other.
  - Qwen receives only the bounded structured state and an enumerated legal
    action set, never raw EEG, unrestricted embeddings, dialogue transcripts,
    or inferred cognitive state. The deterministic P0 and compact P1 baselines
    are evaluated before Qwen P2; without them there is no evidence the
    language model contributes anything.
  - The research-preview DMG excludes Python, Julia, raw EEG, training
    machinery, public corpora, unpinned checkpoints, dialogue corpora and LoRA
    adapters, and downloads nothing at first launch. Qwen ships as a separate
    manually installed model pack with a pinned manifest.
  - Two MVP levels are distinguished: a synthetic engineering MVP buildable
    after branch stabilization, which proves the app-facing integration and
    says nothing about physical EEG; and a physical research MVP that sits
    after D3 and encoder selection, not merely after the code compiles.
  - Releases are 0.2.0 (stability) then 0.3.0 Research Preview. "v2" would
    imply a production transition the evidence does not support. The branch
    still declares 0.1.0/1 -- the same version as the build that crashed in the
    Bundle.module -> PromptProfile.load -> LiveRuntimeFactory path -- so the
    version bump and DMG tooling are release prerequisites, not part of this
    planning package.

Seven new contract tests pin the load-bearing claims, including a cross-check
that the document's legal-action list does not drift from the executable list
in fusion_contract.py.

Verified: 119 NeuralComposeEEG tests pass; ruff clean; no broken internal
links; git diff --check clean; no runtime, config, script or CI file modified.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Adopts a graduated execution-state vocabulary in place of booleans, adds a
fused-state schema that fails closed when an encoder is missing, and reaffirms
the cognitive-inference and legal-action boundaries with tests.

"Executing" is ambiguous as a boolean: it can mean ran-once-on-a-fixture,
embedded-in-the-app, or controls-something. Each subsystem now carries a state:

  eegnet_execution:      none | synthetic_offline | physical_offline
  eegpt_execution:       none | synthetic_adapter_smoke | physical_compatibility
                              | physical_comparison
  qwen_policy_execution: none | synthetic_shadow | physical_shadow
  live_control:          false   -- not a variable

Every non-none value has an explicit flip gate, and the two reachable MVP
levels are now expressed in this vocabulary. No flip grants live authority.

nc-eeg-fused-state-v1 adds per-encoder and fusion completion status. A fusion
marked unavailable_due_to_missing_encoder is FORBIDDEN from carrying fused
probabilities, so losing an encoder cannot silently become a one-model
prediction; symmetrically, a completed fusion must carry all of them, and a
missing encoder must not carry checkpoint identity.

v1 rather than amending v0 in place, for a concrete reason: v0's fusion.status
is a const "complete" and its probability fields are root-required, so an
unavailable fused state is unrepresentable there without either weakening the
closed contract or invalidating the six committed artifacts. v0 stays the
frozen D0 evidence schema; its artifacts are not migrated and are verified
byte-identical.

Four proposals were considered and declined, each against committed code:

  - inject_contextual_anchor as a fourth legal action. fusion_contract.py pins
    the registry by exact list equality to three inert actions; an actuating
    verb in a registry whose safety property is inertness is a contradiction.
  - state_focused / state_overwhelmed labels and HIPPEA operationalization.
    The committed label set is protocol-observable, and cognitive inference
    from this montage is both prohibited and unsupported by any evidence here.
  - a Draft-07 w5-f2-fused-state-v0.json. Wrong draft, no disposition block,
    and it collides with an existing committed schema name.
  - streaming mesh transport. It reopens the offline boundary ADR-011 closed;
    reserved instead as deferred ADR-012 with its open questions named
    (transport integrity, packet-loss semantics, cross-node clock provenance).

The predictive-processing motivation survives as background: it explains why
uncertainty and encoder disagreement are worth measuring at all, while stating
that predictive_entropy and encoder_disagreement are properties of the
estimator, not of the participant. It introduces no label and adds no artifact
field.

Verified: 133 NeuralComposeEEG tests pass (119 baseline, 14 new); v0 schema,
artifacts and fixture byte-identical; ruff clean; no broken internal links;
git diff --check clean; no Sources/, Package.swift, configs/, src/, Scripts/ or
.github/ file modified.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@aurascoper

Copy link
Copy Markdown
Owner Author

Parked, not rejected. This planning-and-contract package remains preserved at 1251b5b. Integration is tracked in issue #34 and will occur by rebase or selective cherry-pick after the currently divergent EEG branches converge. No application runtime, model execution, live control, or promotion authority is granted.

One correction carried into #34: this PR has three commits, not the two named in the description. 1251b5b ("graduated execution states and fail-closed fusion v1") is the branch head and contributes independently — it adds nc-eeg-fused-state-v1.schema.json and docs/science/predictive-processing-background.md. Any future integration must account for all three.

The branch docs/eeg-offline-encoder-boundary is retained deliberately and must not be deleted until #34 is resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant