Skip to content

feat: Add unified feature extraction - #41

Merged
chrisjz merged 24 commits into
mainfrom
feature/unified-feature-extraction
Jan 2, 2026
Merged

feat: Add unified feature extraction#41
chrisjz merged 24 commits into
mainfrom
feature/unified-feature-extraction

Conversation

@chrisjz

@chrisjz chrisjz commented Jan 2, 2026

Copy link
Copy Markdown
Member

Changes:

  • Add unified feature extraction for classical and quantum architectures

Addresses #37

Summary by CodeRabbit

  • New Features

    • Unified sensory modules (food chemotaxis, nociception, mechanosensation, etc.) and configurable multi-sensory PPO mode
    • LR warmup/decay scheduling for PPO training; preset experiment configs for stationary and pursuit predator scenarios
  • Bug Fixes

    • Predator gradient direction corrected
    • Improved gradient normalization and reward shaping
  • Documentation

    • Experiment logbook and updated ablation toolkit/specs and proposals
  • Tests

    • New tests for sensory modules and LR scheduling

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai

coderabbitai Bot commented Jan 2, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Centralized SensoryModule framework added and exported; PPOBrain extended to support legacy and unified sensory modes plus LR warmup/decay scheduling; Modular/QModular brains updated to use SENSORY_MODULES; predator gradient direction fix applied; multiple new PPO experiment configs, docs, ablation specs, and tests added.

Changes

Cohort / File(s) Summary
Core Sensory Module System
packages/quantum-nematode/quantumnematode/brain/modules.py
New CoreFeatures, ModuleName, SensoryModule class, SENSORY_MODULES registry; replaces per-feature extractors; adds extract_classical_features() and get_classical_feature_dimension().
Brain Package Exports
packages/quantum-nematode/quantumnematode/brain/__init__.py
Exports SENSORY_MODULES, ModuleName, extract_classical_features, get_classical_feature_dimension as part of public API.
PPO Brain Implementation
packages/quantum-nematode/quantumnematode/brain/arch/ppo.py
Adds PPOBrainConfig.sensory_modules and LR scheduling fields; PPOBrain accepts optional input_dim, auto-computes input_dim for unified mode, plugs extract_classical_features, and implements _get_current_lr/_update_learning_rate integrated into episode lifecycle.
Modular / Quantum Modular Brains
packages/quantum-nematode/quantumnematode/brain/arch/modular.py, packages/quantum-nematode/quantumnematode/brain/arch/qmodular.py
Replace RotationAxis / extract_features_for_module usage with SENSORY_MODULES[module].to_quantum_dict(params); switch axis keys to "rx"/"ry"/"rz"; update imports.
Environment Gradient Fix
packages/quantum-nematode/quantumnematode/env/env.py
get_separated_gradients: compute raw magnitudes first, apply tanh normalization, and fix predator direction to arctan2(-py,-px) for repulsive gradient.
Configs / Experiments
configs/examples/ppo_stationary_predators_sensory_small.yml, configs/examples/ppo_pursuit_predators_sensory_small.yml, artifacts/experiments/.../ppo_stationary_predators_sensory_small_tuned.yml, artifacts/experiments/.../ppo_pursuit_predators_sensory_small.yml
New PPO experiment/config YAMLs enabling unified sensory_modules (e.g., food_chemotaxis, nociception), tuned hyperparameters, LR warmup/decay schedules, and predator/foraging environment settings.
Documentation & Logbook
docs/experiments/README.md, docs/experiments/logbooks/006-unified-sensory-modules.md
Add Experiment 006 entry and comprehensive logbook describing design, ablations, implementation changes (gradient normalization, predator direction fix, LR scheduling), results and analysis.
Ablation Toolkit & Specs
openspec/changes/add-ablation-toolkit/*, openspec/changes/add-multi-sensory-environment/*, openspec/changes/add-thermotaxis-system/*
Add/rename ablation sections (sensory config, gradient mode, normalization), move feature extraction design to modules.py, and expand tasks/specs for multi-sensory experiments.
Tests — PPO LR Scheduling
packages/quantum-nematode/tests/quantumnematode_tests/brain/arch/test_ppo.py
New TestLRScheduling class (8 tests) validating warmup/decay computations and optimizer LR updates; note: block duplicated in file.
Tests — Sensory Modules & PPO Features
packages/quantum-nematode/tests/quantumnematode_tests/brain/test_modules.py, packages/quantum-nematode/tests/quantumnematode_tests/brain/test_ppo_features.py
Replace legacy extractor tests with SENSORY_MODULES-based tests; add CoreFeatures and SensoryModule validation; add comprehensive PPO feature-mode tests for legacy vs unified preprocessing and run behavior.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Config as Config (YAML)
  participant Env as Environment
  participant PPO as PPOBrain
  participant Modules as SENSORY_MODULES
  participant Optim as Optimizer

  Note over Config,PPO: Experiment loads config (sensory_modules, LR schedule)
  Config->>Modules: specify sensory_modules list
  Env->>Modules: provide sensory params (gradients, signals)
  Modules->>PPO: extract_classical_features(params, modules)
  PPO->>PPO: preprocess -> input tensor (2 features/module) or legacy(2)
  PPO->>Env: step(action)
  Env->>Env: compute separated gradients (food, predator) with fixed predator dir
  Env->>PPO: observation (including gradients)
  PPO->>Optim: during episode end -> _update_learning_rate(current_episode)
  Optim-->>PPO: optimizer.lr updated
  Note over PPO,Optim: iterative training with warmup -> decay schedules
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~70 minutes

Possibly related PRs

Poem

🐰 I sniff the grids and twitch my nose,

Modules sprout where old code froze;
Warmup hops, then LR drifts low,
Predators turn from threat to show,
Four features bloom — hooray, we grow! 🥕✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: Add unified feature extraction' accurately captures the main objective of this comprehensive PR, which introduces a modular sensory feature framework replacing monolithic per-feature extractors across classical and quantum architectures.
Docstring Coverage ✅ Passed Docstring coverage is 98.98% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov

codecov Bot commented Jan 2, 2026

Copy link
Copy Markdown

@chrisjz
chrisjz marked this pull request as ready for review January 2, 2026 10:52

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
packages/quantum-nematode/quantumnematode/brain/arch/ppo.py (1)

269-269: Remove unused noqa directive.

Static analysis indicates that PLR0913 and PLR0915 are non-enabled rules, making this directive unnecessary.

🔎 Proposed fix
-    def __init__(  # noqa: PLR0913, PLR0915
+    def __init__(
packages/quantum-nematode/quantumnematode/brain/modules.py (1)

321-331: Consider documenting that to_classical omits the binary field.

The to_classical() method returns only [strength, angle], omitting the binary field from CoreFeatures. For modules like mechanosensation that encode meaningful data in all three fields, this could result in information loss. If this is intentional (e.g., classical networks use a different encoding), consider adding a brief note in the docstring.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between faba374 and 5467129.

📒 Files selected for processing (21)
  • artifacts/experiments/20260102_052412/20260102_052412.json
  • artifacts/experiments/20260102_052412/ppo_stationary_predators_sensory_small_tuned.yml
  • artifacts/experiments/20260102_093709/20260102_093709.json
  • artifacts/experiments/20260102_093709/ppo_pursuit_predators_sensory_small.yml
  • configs/examples/ppo_pursuit_predators_sensory_small.yml
  • configs/examples/ppo_stationary_predators_sensory_small.yml
  • docs/experiments/README.md
  • docs/experiments/logbooks/006-unified-sensory-modules.md
  • openspec/changes/add-ablation-toolkit/proposal.md
  • openspec/changes/add-ablation-toolkit/specs/ablation-analysis/spec.md
  • openspec/changes/add-ablation-toolkit/tasks.md
  • openspec/changes/add-multi-sensory-environment/tasks.md
  • packages/quantum-nematode/quantumnematode/brain/__init__.py
  • packages/quantum-nematode/quantumnematode/brain/arch/modular.py
  • packages/quantum-nematode/quantumnematode/brain/arch/ppo.py
  • packages/quantum-nematode/quantumnematode/brain/arch/qmodular.py
  • packages/quantum-nematode/quantumnematode/brain/modules.py
  • packages/quantum-nematode/quantumnematode/env/env.py
  • packages/quantum-nematode/tests/quantumnematode_tests/brain/arch/test_ppo.py
  • packages/quantum-nematode/tests/quantumnematode_tests/brain/test_modules.py
  • packages/quantum-nematode/tests/quantumnematode_tests/brain/test_ppo_features.py
🧰 Additional context used
📓 Path-based instructions (3)
openspec/changes/*/tasks.md

📄 CodeRabbit inference engine (openspec/AGENTS.md)

Create tasks.md with numbered implementation sections and checkbox-style task lists (- [ ] format) to track completion before confirming work is finished

Files:

  • openspec/changes/add-ablation-toolkit/tasks.md
  • openspec/changes/add-multi-sensory-environment/tasks.md
openspec/changes/*/proposal.md

📄 CodeRabbit inference engine (openspec/AGENTS.md)

Write proposal.md with three sections: Why (1-2 sentences on problem/opportunity), What Changes (bulleted list with BREAKING markers for breaking changes), and Impact (affected specs and code)

Files:

  • openspec/changes/add-ablation-toolkit/proposal.md
openspec/changes/*/specs/**/*.md

📄 CodeRabbit inference engine (openspec/AGENTS.md)

openspec/changes/*/specs/**/*.md: Use ## ADDED|MODIFIED|REMOVED|RENAMED Requirements headers in delta specs, with each requirement containing at least one scenario using #### Scenario: format (4 hashtags, not bullets or bold)
Use SHALL/MUST for normative requirements in spec deltas; avoid should/may unless intentionally marking non-normative requirements
When using MODIFIED Requirements, paste the complete existing requirement (header + all scenarios) from openspec/specs//spec.md and edit to reflect new behavior, ensuring the header text matches exactly (whitespace-insensitive)
Format scenarios with bullet points for WHEN/THEN conditions using WHEN and THEN bold markers, not prose or alternative structures

Files:

  • openspec/changes/add-ablation-toolkit/specs/ablation-analysis/spec.md
🧠 Learnings (7)
📓 Common learnings
Learnt from: chrisjz
Repo: SyntheticBrains/nematode PR: 15
File: packages/quantum-nematode/quantumnematode/brain/arch/qmodular.py:744-750
Timestamp: 2025-12-13T10:34:16.900Z
Learning: In QModularBrain (packages/quantum-nematode/quantumnematode/brain/arch/qmodular.py), the prepare_episode() and post_process_episode() hooks are intentionally kept as no-ops until the feature to save only successful episodes is implemented for all brain architectures (currently only modular brain has it).
📚 Learning: 2025-12-30T13:55:00.474Z
Learnt from: chrisjz
Repo: SyntheticBrains/nematode PR: 36
File: openspec/changes/add-multi-sensory-environment/tasks.md:229-229
Timestamp: 2025-12-30T13:55:00.474Z
Learning: In Markdown review, if the repository uses mdformat to format Markdown, do not flag backslash escapes that mdformat may automatically insert (e.g., \< for <). Treat such escapes as intentional formatter-enforced formatting, not unnecessary markup. This applies to all Markdown files in the repo (e.g., openspec/changes/add-multi-sensory-environment/tasks.md and similar). If unsure, verify formatter configuration (mdformat rules) before marking as unnecessary.

Applied to files:

  • openspec/changes/add-ablation-toolkit/tasks.md
  • openspec/changes/add-ablation-toolkit/proposal.md
  • docs/experiments/logbooks/006-unified-sensory-modules.md
  • docs/experiments/README.md
  • openspec/changes/add-multi-sensory-environment/tasks.md
  • openspec/changes/add-ablation-toolkit/specs/ablation-analysis/spec.md
📚 Learning: 2026-01-01T07:04:38.772Z
Learnt from: chrisjz
Repo: SyntheticBrains/nematode PR: 40
File: configs/examples/modular_predators_small_validate.yml:55-55
Timestamp: 2026-01-01T07:04:38.772Z
Learning: Maintain backward-compatible defaults in YAML configs (e.g., RewardConfig.penalty_boundary_collision defaults to 0.0). When overriding in examples, show explicit values (e.g., 0.02) and ensure the spec documents this two-tier setup so maintainers understand the relationship between default and overridden values.

Applied to files:

  • configs/examples/ppo_pursuit_predators_sensory_small.yml
  • configs/examples/ppo_stationary_predators_sensory_small.yml
📚 Learning: 2025-12-30T14:07:46.289Z
Learnt from: CR
Repo: SyntheticBrains/nematode PR: 0
File: openspec/AGENTS.md:0-0
Timestamp: 2025-12-30T14:07:46.289Z
Learning: Applies to openspec/changes/*/proposal.md : Write proposal.md with three sections: Why (1-2 sentences on problem/opportunity), What Changes (bulleted list with **BREAKING** markers for breaking changes), and Impact (affected specs and code)

Applied to files:

  • openspec/changes/add-ablation-toolkit/proposal.md
📚 Learning: 2025-12-13T10:34:16.900Z
Learnt from: chrisjz
Repo: SyntheticBrains/nematode PR: 15
File: packages/quantum-nematode/quantumnematode/brain/arch/qmodular.py:744-750
Timestamp: 2025-12-13T10:34:16.900Z
Learning: In QModularBrain (packages/quantum-nematode/quantumnematode/brain/arch/qmodular.py), the prepare_episode() and post_process_episode() hooks are intentionally kept as no-ops until the feature to save only successful episodes is implemented for all brain architectures (currently only modular brain has it).

Applied to files:

  • packages/quantum-nematode/quantumnematode/brain/arch/modular.py
  • packages/quantum-nematode/tests/quantumnematode_tests/brain/test_ppo_features.py
  • packages/quantum-nematode/quantumnematode/brain/modules.py
  • openspec/changes/add-multi-sensory-environment/tasks.md
  • packages/quantum-nematode/tests/quantumnematode_tests/brain/test_modules.py
  • packages/quantum-nematode/quantumnematode/brain/arch/qmodular.py
  • packages/quantum-nematode/quantumnematode/brain/arch/ppo.py
📚 Learning: 2025-12-30T14:07:46.289Z
Learnt from: CR
Repo: SyntheticBrains/nematode PR: 0
File: openspec/AGENTS.md:0-0
Timestamp: 2025-12-30T14:07:46.289Z
Learning: Applies to openspec/changes/*/specs/**/*.md : When using MODIFIED Requirements, paste the complete existing requirement (header + all scenarios) from openspec/specs/<capability>/spec.md and edit to reflect new behavior, ensuring the header text matches exactly (whitespace-insensitive)

Applied to files:

  • openspec/changes/add-ablation-toolkit/specs/ablation-analysis/spec.md
📚 Learning: 2025-12-30T14:07:46.289Z
Learnt from: CR
Repo: SyntheticBrains/nematode PR: 0
File: openspec/AGENTS.md:0-0
Timestamp: 2025-12-30T14:07:46.289Z
Learning: Use ADDED for new standalone capabilities or sub-capabilities orthogonal to existing requirements; use MODIFIED when changing behavior, scope, or acceptance criteria of an existing requirement; use RENAMED when only the requirement name changes; combine RENAMED and MODIFIED when renaming with behavior changes

Applied to files:

  • openspec/changes/add-ablation-toolkit/specs/ablation-analysis/spec.md
🧬 Code graph analysis (6)
packages/quantum-nematode/tests/quantumnematode_tests/brain/arch/test_ppo.py (2)
packages/quantum-nematode/quantumnematode/brain/arch/ppo.py (4)
  • PPOBrainConfig (71-129)
  • PPOBrain (261-797)
  • _get_current_lr (467-494)
  • _update_learning_rate (496-503)
packages/quantum-nematode/quantumnematode/brain/arch/dtypes.py (1)
  • DeviceType (20-34)
packages/quantum-nematode/quantumnematode/brain/arch/modular.py (1)
packages/quantum-nematode/quantumnematode/brain/modules.py (1)
  • to_quantum_dict (308-319)
packages/quantum-nematode/quantumnematode/brain/modules.py (3)
packages/quantum-nematode/quantumnematode/brain/actions.py (1)
  • Action (8-16)
packages/quantum-nematode/quantumnematode/env/env.py (1)
  • Direction (50-57)
packages/quantum-nematode/quantumnematode/brain/arch/_brain.py (1)
  • BrainParams (126-213)
packages/quantum-nematode/tests/quantumnematode_tests/brain/test_modules.py (3)
packages/quantum-nematode/quantumnematode/brain/modules.py (6)
  • CoreFeatures (53-64)
  • ModuleName (72-94)
  • count_total_qubits (518-531)
  • to_quantum (262-306)
  • to_classical (321-331)
  • to_quantum_dict (308-319)
packages/quantum-nematode/quantumnematode/env/env.py (1)
  • Direction (50-57)
packages/quantum-nematode/quantumnematode/brain/arch/_brain.py (1)
  • BrainParams (126-213)
packages/quantum-nematode/quantumnematode/brain/__init__.py (1)
packages/quantum-nematode/quantumnematode/brain/modules.py (3)
  • ModuleName (72-94)
  • extract_classical_features (442-486)
  • get_classical_feature_dimension (489-504)
packages/quantum-nematode/quantumnematode/brain/arch/qmodular.py (1)
packages/quantum-nematode/quantumnematode/brain/modules.py (1)
  • to_quantum_dict (308-319)
🪛 Ruff (0.14.10)
packages/quantum-nematode/quantumnematode/brain/arch/ppo.py

269-269: Unused noqa directive (non-enabled: PLR0913, PLR0915)

Remove unused noqa directive

(RUF100)

🔇 Additional comments (46)
openspec/changes/add-ablation-toolkit/specs/ablation-analysis/spec.md (1)

1-235: LGTM! Spec follows all formatting guidelines.

The spec delta correctly uses:

  • ## ADDED Requirements header
  • ### Requirement: headers for each requirement
  • #### Scenario: format (4 hashtags) for all scenarios
  • GIVEN/WHEN/THEN/AND bullet points
  • SHALL/MUST for normative requirements

The new ablation requirements (PPOBrain Sensory Module Ablation, Gradient Mode Ablation, Feature Normalization Ablation) are well-structured and provide clear acceptance criteria.

packages/quantum-nematode/quantumnematode/env/env.py (1)

1320-1355: Predator direction inversion is correctly implemented.

The changes introduce explicit raw magnitude computation and normalize predator direction semantics:

  1. Raw magnitudes (lines 1321, 1324): Computed before normalization, allowing separate processing.
  2. Predator direction inversion (line 1330): Negating both components converts the repulsive gradient direction (away from predator) to a threat-indicator direction (toward predator), giving consistent semantics where:
    • food_direction: points toward food (approach this direction)
    • predator_direction: points toward predator (avoid this direction)
  3. Magnitude normalization (lines 1338-1339): tanh scaling ensures bounded [0,1] range, matching combined gradient scaling and providing proper inputs for sensory modules.

The implementation correctly separates magnitude computation from direction semantics, enabling unified feature extraction.

openspec/changes/add-ablation-toolkit/tasks.md (3)

97-166: LGTM! New ablation sections follow task format guidelines.

Sections 4-6 (PPOBrain Sensory Configuration, Gradient Mode, and Feature Normalization Ablation) correctly use:

  • Numbered implementation sections
  • - [ ] checkbox-style task lists
  • Clear subsection structure
  • Validation sections for each major component

The expansion provides systematic coverage of PPOBrain-specific ablation capabilities.


168-295: Section renumbering is correct and consistent.

Sections 7-10 (formerly 4-7) maintain:

  • Proper numbering sequence
  • Original task structure and content
  • Checkbox format throughout
  • Code examples unchanged (section 7.1)

The renumbering accommodates the new sections 4-6 without disrupting existing task definitions.


300-343: Dependency diagram and success criteria correctly updated.

Dependency diagram (lines 300-328):

  • Clearly shows PPOBrain Ablation branch splitting into sections 4, 5, 6
  • Correctly indicates parallel execution capability after framework completion
  • Notes dependency on PPOBrain infrastructure (section 3)

Success criteria (lines 336-340):

  • Comprehensive coverage of new ablation modes (sensory, gradient, normalization)
  • Maintains seed-controlled reproducibility requirement

Both sections accurately reflect the expanded ablation scope.

configs/examples/ppo_stationary_predators_sensory_small.yml (1)

1-95: Configuration is well-structured and consistent.

Strengths:

  • Header comments (lines 1-14) clearly document differences from legacy config
  • sensory_modules (lines 38-41) correctly aligned with use_separated_gradients: true (line 70)
  • Stationary predator configuration (lines 80-89) is consistent:
    • speed: 0.0 and movement_pattern: stationary both enforce stationary behavior
    • kill_radius: 0 with damage_radius: 2 enables health-based gameplay
  • Explicit reward/penalty values (lines 45-58) follow backward-compatibility guidance

Minor observation:
Lines 83-84 have redundant stationary specification (speed: 0.0 and movement_pattern: stationary). While clear, consider if one is sufficient or if both provide useful validation.

Based on learnings, explicit config values in examples are appropriate.

packages/quantum-nematode/quantumnematode/brain/arch/qmodular.py (3)

41-46: LGTM: Import updated for centralized sensory module registry.

The addition of SENSORY_MODULES and removal of RotationAxis and extract_features_for_module correctly reflects the transition to the unified sensory module architecture.


296-298: LGTM: Safe string-key access for quantum gate parameters.

The change from RotationAxis enum to direct string keys "rx", "ry", "rz" with .get() defaults aligns with the to_quantum_dict() interface documented in modules.py (lines 307-318) and provides safe fallback to 0.0 if keys are missing.


368-370: No issue found — all ModuleName enum values are registered in SENSORY_MODULES.

The direct dictionary access SENSORY_MODULES[module] is safe. All 12 ModuleName enum members (PROPRIOCEPTION, CHEMOTAXIS, FOOD_CHEMOTAXIS, NOCICEPTION, MECHANOSENSATION, THERMOTAXIS, AEROTAXIS, VISION, ACTION, APPETITIVE, AVERSIVE, OXYGEN) have entries in the SENSORY_MODULES registry—either as direct registrations or as aliases. Since self.modules is typed as dict[ModuleName, list[int]], its keys can only be ModuleName enum values, guaranteeing all keys exist in the registry.

Likely an incorrect or invalid review comment.

packages/quantum-nematode/quantumnematode/brain/__init__.py (1)

6-21: LGTM: Public API expanded for unified sensory module architecture.

The new exports (SENSORY_MODULES, ModuleName, extract_classical_features, get_classical_feature_dimension) provide a clean public interface for the centralized sensory module registry and classical feature extraction, as documented in the relevant code snippets from modules.py.

docs/experiments/logbooks/006-unified-sensory-modules.md (4)

1-58: Excellent experiment documentation structure.

The document provides clear motivation, hypothesis, and problem definition. The explanation of why 4-feature credit assignment is harder than 2-feature (lines 40-48, 289-312) effectively frames the experimental challenge.


59-122: LGTM: Implementation changes well-documented with code examples.

The architecture evolution table and key implementation changes provide clear technical detail. The code snippets for gradient normalization (line 73), predator direction fix (line 79), and LR scheduling (lines 91-94) enable reproducibility.


123-313: Strong experimental methodology and analysis.

The systematic ablation studies (lines 154-203) demonstrate rigorous experimentation. The clear metric definitions (lines 127-131), session ID traceability, and "what worked/didn't work" tables (lines 266-287) make this excellent scientific documentation.

The pursuit predator findings (lines 252-260) appropriately identify that scenario-specific reward tuning is required, with remaining performance gap attributed to temporal credit assignment.


314-384: Comprehensive conclusions with actionable insights.

The 7 key findings (lines 315-330) succinctly capture experiment outcomes. The future work section (lines 340-351) appropriately defers LSTM complexity while acknowledging the temporal credit assignment gap. Data references (lines 353-383) provide full traceability for reproducibility.

artifacts/experiments/20260102_052412/ppo_stationary_predators_sensory_small_tuned.yml (3)

21-46: LGTM: Brain configuration matches documented experiment parameters.

The PPO configuration correctly implements the LR warmup/decay schedule (lines 39-42) and unified sensory modules (lines 43-45) as documented in the experiment logbook. The doubled network capacity (128 hidden dims, 512 buffer) aligns with the findings that larger networks help with 4-feature credit assignment.


49-63: LGTM: Reward shaping aligns with experimental findings.

The reward configuration (distance_scale: 0.3, predator_proximity: 0.3, health_damage: 1.5) implements the tuning identified as critical in the experiment analysis. These values balance food/predator signal strength to improve credit assignment with separated gradients.


69-99: LGTM: Environment configuration properly enables separated gradients.

The use_separated_gradients: true (line 74) is correctly set to enable the unified sensory module architecture. The stationary predator setup (speed: 0.0, line 87) matches the experiment scenario, and the health/damage parameters are consistent with the documented tuning.

packages/quantum-nematode/tests/quantumnematode_tests/brain/test_ppo_features.py (4)

11-63: LGTM: Comprehensive legacy mode backward compatibility tests.

The tests verify that PPOBrain maintains backward compatibility with the legacy 2-feature preprocessing mode, including default input_dim (line 19), explicit overrides (line 27), correct output shapes (lines 43-44), and value correctness for aligned gradients (lines 60-62).


65-163: Excellent coverage of unified sensory mode semantics.

The tests thoroughly verify input_dim auto-computation (lines 68-98), module-specific feature extraction (lines 118-137), and critically test semantic range preservation (lines 138-162). The assertion that strength = 0.0 means "no signal" (line 152) correctly validates the classical feature semantics documented in the modules implementation.


165-204: LGTM: Integration tests verify end-to-end functionality.

The tests confirm that run_brain produces valid actions in both unified mode (lines 168-187) and legacy mode (lines 189-203), verifying action structure and probability ranges without overspecifying expected behavior.


206-275: LGTM: Thorough coverage of scientific module names and multi-sensory configurations.

The tests verify all major scientific module names (FOOD_CHEMOTAXIS, NOCICEPTION, MECHANOSENSATION) and their specific feature semantics. The MECHANOSENSATION test (lines 240-260) correctly validates contact-based binary features, and the multi-sensory test (lines 262-275) confirms the architecture scales to 4 modules (8 features).

openspec/changes/add-ablation-toolkit/proposal.md (1)

1-106: LGTM! Proposal structure aligns with guidelines.

The proposal correctly follows the required three-section format (Why, What Changes, Impact) and the expanded ablation study scope (sensory configuration, gradient modes, normalization) is well-organized and comprehensive.

As per coding guidelines, proposal.md should contain three sections with appropriate structure, which this document maintains.

packages/quantum-nematode/quantumnematode/brain/arch/modular.py (5)

92-92: LGTM! Centralized sensory module registry.

The import of SENSORY_MODULES enables unified feature extraction across quantum brain architectures.


414-419: LGTM! Consistent refactoring to string-based feature keys.

The switch from RotationAxis enum to string keys ("rx", "ry", "rz") and centralized SENSORY_MODULES[module].to_quantum_dict(params) simplifies feature encoding and aligns with the unified sensory module architecture.


537-538: LGTM! Consistent use of centralized feature extraction.

The refactoring to SENSORY_MODULES[module].to_quantum_dict(params) is applied consistently in run_brain, maintaining alignment with the unified sensory module pattern.


1180-1182: LGTM! Trajectory gradient computation updated.

The trajectory_parameter_shift_gradients method correctly uses the new centralized feature extraction pathway.


1316-1319: LGTM! Parameter-shift gradients updated.

The parameter_shift_gradients method correctly uses the new centralized feature extraction pathway, completing the consistent refactoring across all gradient computation paths.

artifacts/experiments/20260102_093709/ppo_pursuit_predators_sensory_small.yml (1)

1-94: LGTM! Well-documented pursuit predator configuration.

The configuration properly enables unified sensory modules (food_chemotaxis, nociception) and LR scheduling with clear documentation of pursuit-specific parameter tuning.

configs/examples/ppo_pursuit_predators_sensory_small.yml (1)

1-94: LGTM! Example configuration for pursuit predators.

The configuration demonstrates unified sensory module usage and LR scheduling in a pursuit predator scenario. Parameter values are well-documented and align with the experimental artifact version.

Based on learnings, the explicit penalty values (e.g., penalty_boundary_collision: 0.02) properly override defaults and are documented for maintainability.

openspec/changes/add-multi-sensory-environment/tasks.md (1)

158-234: LGTM! Documentation accurately reflects the unified sensory module implementation.

The task list correctly documents the completed SensoryModule architecture, module renaming, brain integration, and PPO training improvements. The checkbox format follows the coding guidelines for tasks.md files.

packages/quantum-nematode/quantumnematode/brain/arch/ppo.py (5)

42-46: LGTM!

The imports correctly bring in the new unified sensory module utilities needed for feature extraction.


333-355: LGTM!

The LR scheduling configuration is well-structured with sensible defaults (10% of base LR for warmup start and decay end) and clear logging of the schedule phases.


446-465: LGTM!

The preprocess method cleanly handles both unified sensory mode and legacy 2-feature mode, maintaining backward compatibility while enabling the new modular architecture.


467-503: LGTM!

The LR scheduling implementation correctly handles warmup and decay phases with linear interpolation. The method properly respects the schedule configuration and updates the optimizer appropriately.


760-761: LGTM!

The LR update is correctly placed after the episode count increment, ensuring the learning rate is adjusted before the next episode begins.

packages/quantum-nematode/quantumnematode/brain/modules.py (6)

52-64: LGTM!

The CoreFeatures dataclass provides a clean, architecture-agnostic representation with well-documented semantic ranges for each field.


102-135: LGTM!

The relative angle computation correctly normalizes the difference between target and agent directions to [-1, 1], with proper handling of None inputs.


177-182: LGTM!

The mechanosensation module appropriately repurposes the CoreFeatures fields for binary contact signals, with clear documentation in the registry describing the unconventional but intentional semantic mapping.


421-428: Note: ACTION module extracts data but returns zeros.

The ACTION module has a real _action_core extractor but uses transform_type="placeholder", meaning to_quantum() will return zeros regardless of input. This is likely intentional for deferred implementation, but worth verifying this matches the expected behavior.


472-486: LGTM!

The function correctly sorts modules for consistent feature ordering and defensively handles missing modules. The approach ensures deterministic output regardless of input order.


489-504: LGTM!

Simple and correct utility for computing the expected feature dimension.

packages/quantum-nematode/tests/quantumnematode_tests/brain/test_modules.py (5)

15-30: LGTM!

Good coverage of CoreFeatures default and custom value initialization.


33-80: LGTM!

The tests correctly verify the transform logic for both standard and binary types, with appropriate assertions for shape, dtype, and computed values.


83-129: LGTM!

Thorough testing of proprioception module across all direction values, correctly verifying the RZ-only encoding.


274-300: LGTM!

Good coverage of module name values, legacy aliases, and registry completeness verification.


393-480: LGTM!

Excellent test coverage for food_chemotaxis and nociception modules, including quantum transforms, classical semantic ranges, and legacy alias verification.

Comment thread packages/quantum-nematode/quantumnematode/brain/arch/ppo.py Outdated
Comment thread packages/quantum-nematode/quantumnematode/brain/modules.py

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
packages/quantum-nematode/quantumnematode/brain/arch/ppo.py (1)

72-91: Docstring correctly updated to reference brain/modules.py.

The docstring now correctly references brain/modules.py for modular feature extraction (line 80), resolving the previous comment about the outdated reference to brain/features.py.

🧹 Nitpick comments (1)
packages/quantum-nematode/quantumnematode/brain/arch/ppo.py (1)

269-269: Remove unused noqa directive.

The static analysis tool reports that PLR0913 and PLR0915 are not enabled in the project configuration, making the noqa directive unnecessary. Consider removing it for cleaner code.

🔎 Proposed fix
-    def __init__(  # noqa: PLR0913, PLR0915
+    def __init__(
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5467129 and 74165e0.

📒 Files selected for processing (5)
  • openspec/changes/add-multi-sensory-environment/design.md
  • openspec/changes/add-multi-sensory-environment/proposal.md
  • openspec/changes/add-thermotaxis-system/tasks.md
  • packages/quantum-nematode/quantumnematode/brain/arch/ppo.py
  • packages/quantum-nematode/quantumnematode/brain/modules.py
✅ Files skipped from review due to trivial changes (1)
  • openspec/changes/add-thermotaxis-system/tasks.md
🧰 Additional context used
📓 Path-based instructions (1)
openspec/changes/*/proposal.md

📄 CodeRabbit inference engine (openspec/AGENTS.md)

Write proposal.md with three sections: Why (1-2 sentences on problem/opportunity), What Changes (bulleted list with BREAKING markers for breaking changes), and Impact (affected specs and code)

Files:

  • openspec/changes/add-multi-sensory-environment/proposal.md
🧠 Learnings (4)
📓 Common learnings
Learnt from: chrisjz
Repo: SyntheticBrains/nematode PR: 15
File: packages/quantum-nematode/quantumnematode/brain/arch/qmodular.py:744-750
Timestamp: 2025-12-13T10:34:16.900Z
Learning: In QModularBrain (packages/quantum-nematode/quantumnematode/brain/arch/qmodular.py), the prepare_episode() and post_process_episode() hooks are intentionally kept as no-ops until the feature to save only successful episodes is implemented for all brain architectures (currently only modular brain has it).
📚 Learning: 2025-12-13T10:34:16.900Z
Learnt from: chrisjz
Repo: SyntheticBrains/nematode PR: 15
File: packages/quantum-nematode/quantumnematode/brain/arch/qmodular.py:744-750
Timestamp: 2025-12-13T10:34:16.900Z
Learning: In QModularBrain (packages/quantum-nematode/quantumnematode/brain/arch/qmodular.py), the prepare_episode() and post_process_episode() hooks are intentionally kept as no-ops until the feature to save only successful episodes is implemented for all brain architectures (currently only modular brain has it).

Applied to files:

  • openspec/changes/add-multi-sensory-environment/proposal.md
  • openspec/changes/add-multi-sensory-environment/design.md
  • packages/quantum-nematode/quantumnematode/brain/modules.py
  • packages/quantum-nematode/quantumnematode/brain/arch/ppo.py
📚 Learning: 2025-12-30T13:55:00.474Z
Learnt from: chrisjz
Repo: SyntheticBrains/nematode PR: 36
File: openspec/changes/add-multi-sensory-environment/tasks.md:229-229
Timestamp: 2025-12-30T13:55:00.474Z
Learning: In Markdown review, if the repository uses mdformat to format Markdown, do not flag backslash escapes that mdformat may automatically insert (e.g., \< for <). Treat such escapes as intentional formatter-enforced formatting, not unnecessary markup. This applies to all Markdown files in the repo (e.g., openspec/changes/add-multi-sensory-environment/tasks.md and similar). If unsure, verify formatter configuration (mdformat rules) before marking as unnecessary.

Applied to files:

  • openspec/changes/add-multi-sensory-environment/proposal.md
  • openspec/changes/add-multi-sensory-environment/design.md
📚 Learning: 2025-12-27T08:02:58.340Z
Learnt from: chrisjz
Repo: SyntheticBrains/nematode PR: 22
File: openspec/changes/add-phase0-foundation-baselines/design.md:64-69
Timestamp: 2025-12-27T08:02:58.340Z
Learning: Design.md files under openspec/changes/ should document architectural or design decisions and rationale, not normative requirements. Do not use SHALL/MUST language in design.md (reserve such language for spec.md files). The strict SHALL/MUST wording should appear only in openspec/changes/*/specs/*/specs.md (spec deltas). Use objective, rationale-focused language in design.md and place any formal requirements in the appropriate spec files.

Applied to files:

  • openspec/changes/add-multi-sensory-environment/design.md
🧬 Code graph analysis (2)
packages/quantum-nematode/quantumnematode/brain/modules.py (3)
packages/quantum-nematode/quantumnematode/brain/actions.py (1)
  • Action (8-16)
packages/quantum-nematode/quantumnematode/env/env.py (1)
  • Direction (50-57)
packages/quantum-nematode/quantumnematode/brain/arch/_brain.py (1)
  • BrainParams (126-213)
packages/quantum-nematode/quantumnematode/brain/arch/ppo.py (1)
packages/quantum-nematode/quantumnematode/brain/modules.py (3)
  • ModuleName (72-94)
  • extract_classical_features (448-492)
  • get_classical_feature_dimension (495-510)
🪛 Ruff (0.14.10)
packages/quantum-nematode/quantumnematode/brain/arch/ppo.py

269-269: Unused noqa directive (non-enabled: PLR0913, PLR0915)

Remove unused noqa directive

(RUF100)

🔇 Additional comments (11)
openspec/changes/add-multi-sensory-environment/design.md (1)

65-65: LGTM! Documentation accurately reflects the module consolidation.

The update from brain/features.py to brain/modules.py correctly reflects the unified feature extraction layer implementation.

openspec/changes/add-multi-sensory-environment/proposal.md (1)

66-66: LGTM! Proposal accurately reflects the module path update.

The reference update to brain/modules.py correctly documents the location of the unified feature extraction layer.

packages/quantum-nematode/quantumnematode/brain/modules.py (5)

1-28: Excellent documentation of the unified sensory module architecture.

The module docstring clearly explains the architecture-agnostic feature extraction, the transformation paths for quantum and classical brains, and the C. elegans neuroscience conventions.


160-174: Documentation consistency issue resolved.

The nociception semantics are now consistent: both the docstring (line 165) and the registry description (lines 369-370) correctly state that predator_gradient_direction points TOWARD predators, and angle=0 means the predator is directly ahead. This resolves the previous documentation inconsistency.


177-182: Unconventional but documented field semantics for mechanosensation.

The mechanosensation module repurposes strength and angle fields for binary signals (boundary and predator contact), deviating from their typical directional semantics in other modules. While unconventional, this is explicitly documented, and the comment at lines 324-328 explains why the binary field is omitted in classical feature extraction to maintain consistency.


448-492: LGTM! Robust classical feature extraction with deterministic ordering.

The function correctly sorts modules for consistent feature ordering and gracefully handles missing modules with zero values. The semantic-preserving ranges ([0,1] for strength, [-1,1] for angle) are well-documented.


344-440: Well-structured sensory module registry with backward compatibility.

The registry provides a comprehensive mapping of sensory modules with C. elegans neuron references. The legacy aliases (lines 438-440) ensure backward compatibility for renamed modules (APPETITIVE → FOOD_CHEMOTAXIS, AVERSIVE → NOCICEPTION).

packages/quantum-nematode/quantumnematode/brain/arch/ppo.py (4)

114-129: Well-designed configuration extensions for unified sensory mode and LR scheduling.

The new config fields are clearly documented with sensible defaults. The LR scheduling parameters support warmup and decay phases, and the sensory_modules field enables the unified feature extraction mode.


289-314: Solid input dimension computation with clear mode selection.

The logic correctly auto-computes input_dim from sensory_modules when unified mode is enabled, warns on conflicts, and falls back to legacy 2-feature mode when appropriate. The logging clearly indicates which mode is active.


467-503: LR scheduling implementation is correct and well-integrated.

The learning rate scheduling correctly implements warmup (linear increase) and optional decay (linear decrease) phases. The _update_learning_rate method is properly called in _complete_episode_tracking (lines 760-761) to adjust the optimizer's learning rate per episode.


431-465: Clean preprocessing implementation supporting both legacy and unified modes.

The method cleanly separates unified sensory mode (lines 446-448) using extract_classical_features from the legacy 2-feature mode (lines 450-465), with clear documentation of the semantic ranges for each mode.

@chrisjz
chrisjz merged commit db84a06 into main Jan 2, 2026
5 checks passed
@chrisjz
chrisjz deleted the feature/unified-feature-extraction branch January 2, 2026 11:19
@coderabbitai coderabbitai Bot mentioned this pull request Feb 6, 2026
chrisjz added a commit that referenced this pull request Mar 3, 2026
…xtraction

feat: Add unified feature extraction
@coderabbitai coderabbitai Bot mentioned this pull request Mar 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant