Skip to content

[M4-P14] Pre-commit Hook Implementation for Jupytext Sync #996

@Gorkowski

Description

@Gorkowski

Dependencies:

#995 [M4-P13] ──► #THIS [M4-P14]

Dependencies:


Description

Implement a pre-commit hook that automatically syncs and executes Jupytext paired notebooks when .py files are changed. This is Phase 14 of the M4 Jupytext Full Migration maintenance plan.

The hook will ensure that when developers edit .py files, the corresponding .ipynb files are automatically updated and validated before commit.

Context

This is part of the M4 maintenance plan to complete Jupytext paired sync migration. After all 35 notebooks are converted (M4-P1 through M4-P13), this phase implements the automation to maintain sync going forward.

Value:

  • Automates notebook sync on every commit
  • Prevents out-of-sync notebooks from being committed
  • Validates notebooks execute correctly before commit
  • Excludes slow simulation notebooks (handled in CI instead)

Scope

Estimated Lines of Code: ~100 lines
Complexity: Medium

Files to Create:

  • .opencode/hooks/sync-execute-notebooks.sh (~50 LOC)

Files to Modify:

  • .pre-commit-config.yaml (+20 LOC)

Acceptance Criteria

Hook Script

  • Create .opencode/hooks/ directory if not exists
  • Create sync-execute-notebooks.sh hook script
  • Script lints .py file with ruff
  • Script syncs .py to .ipynb using validate_notebook --sync
  • Script executes notebook to validate it works
  • Script stages both .py and .ipynb files
  • Script handles errors gracefully with clear messages

Pre-commit Configuration

  • Add local hook to .pre-commit-config.yaml
  • Configure hook to run only on docs/Examples/**/*.py files
  • Configure exclusions for slow notebooks (Simulations directory based on P11-P13 timing data)
  • Hook passes filenames to script

Testing

  • Test hook with a sample notebook edit
  • Verify hook correctly syncs and executes
  • Verify hook stages both files
  • Verify slow notebooks are excluded
  • Verify hook fails gracefully on errors

Technical Notes

Hook Script Implementation

#!/usr/bin/env bash
# .opencode/hooks/sync-execute-notebooks.sh
set -e

for py_file in "$@"; do
    ipynb_file="${py_file%.py}.ipynb"
    
    echo "Processing: $py_file"
    
    # 1. Lint
    ruff check "$py_file" --fix --quiet || true
    ruff format "$py_file" --quiet
    
    # 2. Sync
    python3 .opencode/tool/validate_notebook.py "$ipynb_file" --sync
    
    # 3. Execute
    python3 .opencode/tool/run_notebook.py "$ipynb_file"
    
    # 4. Stage
    git add "$py_file" "$ipynb_file"
done

Pre-commit Configuration

# .pre-commit-config.yaml (addition)
- repo: local
  hooks:
    - id: jupytext-sync-execute
      name: Sync and execute changed notebooks
      entry: .opencode/hooks/sync-execute-notebooks.sh
      language: script
      files: ^docs/Examples/.*\.py$
      exclude: |
        (?x)^(
          docs/Examples/Simulations/.*  # Slow notebooks - CI only
        )$
      pass_filenames: true

Exclusion Strategy

Based on execution times from M4-P11 through M4-P13:

Directory Handling
docs/Examples/Simulations/ Exclude from pre-commit (slow)
All other docs/Examples/ Include in pre-commit

Slow notebooks will be validated in CI instead (M4-P15).

Error Handling

The script should:

  1. Exit with non-zero status if any step fails
  2. Print clear error messages indicating which notebook failed
  3. Not leave notebooks in inconsistent state

References

Maintenance Plan:

  • adw-docs/dev-plans/maintenance/M4-jupytext-full-migration.md - Full migration plan

Related:

Metadata

Metadata

Assignees

No one assigned

    Labels

    agentCreated or managed by ADW automationblockedBlocked - review required before ADW can processmaintenanceMaintenance work - refactoring, technical debt, testingmodel:defaultUse base/sonnet tier (workflow default)type:completeFull complete workflow (plan → build → test → review → document → ship)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions