Skip to content

Pull Request: JuniperData Service Extraction & Integration Infrastructure#38

Merged
pcalnon merged 194 commits into
mainfrom
subproject.juniper_data.feature.spiral_gen.extract
Feb 18, 2026
Merged

Pull Request: JuniperData Service Extraction & Integration Infrastructure#38
pcalnon merged 194 commits into
mainfrom
subproject.juniper_data.feature.spiral_gen.extract

Conversation

@pcalnon

@pcalnon pcalnon commented Feb 8, 2026

Copy link
Copy Markdown
Owner

Pull Request: JuniperData Service Extraction & Integration Infrastructure

Date: 2026-02-06
Version(s): 0.1.0 → 0.4.0
Author: Paul Calnon
Status: READY_FOR_MERGE


Summary

This PR extracts JuniperData as a standalone dataset generation microservice from the Juniper monorepo, replacing the legacy JuniperCanopy codebase with a purpose-built FastAPI service. The branch delivers the complete JuniperData application (v0.1.0–v0.4.0), including 8 dataset generators, 7 storage backends, REST API with 16 endpoints, Docker containerization, a shared client library, dataset lifecycle management, comprehensive CI/CD pipeline with security scanning, and 699 tests across service and client.

SemVer Impact: MINOR (cumulative across v0.1.0–v0.4.0)
Breaking Changes: YES — Complete repository transformation from JuniperCanopy to JuniperData


Context / Motivation

JuniperData was designed as a standalone microservice to provide dataset generation capabilities to the Juniper ecosystem. Previously, dataset generation was embedded within JuniperCascor's SpiralProblem class. This extraction enables:

  • Independent deployment — JuniperData runs as a containerized service on port 8100
  • Shared data contract — NPZ artifacts with standardized keys (X_train, y_train, X_test, y_test, X_full, y_full)
  • Multi-consumer architecture — Both JuniperCascor and JuniperCanopy consume datasets via REST API
  • Feature flag integrationJUNIPER_DATA_URL environment variable enables JuniperData mode in consumers
  • Extensible generator framework — Plugin architecture supports adding new dataset types

Related Documentation:


Priority & Work Status

Priority Work Item ID Status
P0 Fix mypy type errors in test files (20 errors → 0) DATA-001 ✅ Complete
P0 Fix flake8 unused imports in datasets.py DATA-002 ✅ Complete
P1 Fix flake8 issues in generate_golden_datasets.py DATA-003 ✅ Complete
P1 Create Dockerfile for JuniperData service DATA-006 ✅ Complete
P1 Add health check probes for container orchestration DATA-007 ✅ Complete
P1 End-to-end integration tests DATA-008 ✅ Complete
P2 API versioning strategy documentation DATA-009 ✅ Complete
P2 NPZ artifact schema documentation DATA-010 ✅ Complete
P2 Parameter validation parity with consumers DATA-011 ✅ Complete
P2 Shared JuniperData client package DATA-012 ✅ Complete
P2 Client test coverage DATA-013 ✅ Complete
P2 XOR generator (additional generator types) DATA-014 ✅ Partial
P2 Dataset lifecycle management DATA-016 ✅ Complete
P3 B008 warnings in API route defaults DATA-004 Not Started (intentional FastAPI patterns)
P3 SIM117 suggestions in test files DATA-005 Not Started (handled by relaxed rules)
P3 Storage backend extensions DATA-015 Not Started
P3 API rate limiting and authentication DATA-017 Not Started
P3 IPC architecture DATA-018 Deferred
P3 GPU-accelerated data generation DATA-019 Deferred
P3 Continuous profiling integration DATA-020 Deferred

Priority Legend

  • P0: Critical — Core bugs or blockers
  • P1: High — High-impact features or fixes
  • P2: Medium — Polish and medium-priority
  • P3: Low — Advanced/infrastructure features

Changes

Added

  • Core Application (juniper_data/)

    • __init__.py — Package init with version (v0.3.0)
    • __main__.py — CLI entry point with argparse (host, port, storage-path, log-level, reload)
    • core/models.py — 11 Pydantic v2 models (DatasetMeta, CreateDatasetRequest/Response, GeneratorInfo, PreviewData, DatasetListFilter, BatchDeleteRequest/Response, UpdateTagsRequest, DatasetStats)
    • core/split.py — Dataset shuffle and split utilities (shuffle_data(), split_data(), shuffle_and_split())
    • core/dataset_id.py — Deterministic SHA-256 hash-based dataset ID generation
    • core/artifacts.py — NPZ artifact handling with checksums
  • Generator Framework (juniper_data/generators/) — 8 generators registered in GENERATOR_REGISTRY

    • spiral/ — N-spiral classification dataset generator (modern + legacy_cascor algorithms)
    • xor/ — XOR classification dataset generator (4-quadrant diagonal class assignment)
    • gaussian/ — Gaussian blobs classification dataset generator (mixture-of-Gaussians)
    • circles/ — Concentric circles classification dataset generator (binary inner/outer)
    • checkerboard/ — Checkerboard pattern classification dataset generator (2D alternating grid)
    • csv_import/ — CSV/JSON import generator for custom datasets
    • mnist/ — MNIST and Fashion-MNIST dataset generator
    • arc_agi/ — ARC-AGI visual reasoning tasks generator (requires arc-agi>=0.9.0)
  • Storage Layer (juniper_data/storage/) — 7 backend implementations

    • base.py — Abstract DatasetStore with lifecycle methods
    • memory.pyInMemoryDatasetStore for testing and ephemeral use
    • local_fs.pyLocalFSDatasetStore for file-based persistence (JSON metadata + NPZ artifacts)
    • cached.pyCachedDatasetStore caching layer with error logging
    • hf_store.pyHuggingFaceDatasetStore for HuggingFace Hub storage
    • kaggle_store.pyKaggleDatasetStore for Kaggle Datasets storage
    • postgres_store.pyPostgresDatasetStore for PostgreSQL storage
    • redis_store.pyRedisDatasetStore for Redis storage
  • REST API (juniper_data/api/)

    • app.py — FastAPI application factory with lifespan management, CORS middleware, exception handlers
    • settings.py — Pydantic-settings configuration with JUNIPER_DATA_ env prefix
    • routes/health.py — Health endpoints: GET /v1/health, GET /v1/health/live, GET /v1/health/ready
    • routes/generators.py — Generator discovery: GET /v1/generators, GET /v1/generators/{name}/schema
    • routes/datasets.py — 11 dataset endpoints:
      • POST /v1/datasets — Create dataset (deterministic caching)
      • GET /v1/datasets — List with pagination (limit/offset)
      • GET /v1/datasets/filter — Advanced filtering (generator, tags, date range, sample count)
      • GET /v1/datasets/stats — Aggregate statistics
      • POST /v1/datasets/batch-delete — Bulk delete (up to 100 IDs)
      • POST /v1/datasets/cleanup-expired — TTL-based cleanup
      • GET /v1/datasets/{id} — Metadata retrieval
      • GET /v1/datasets/{id}/artifact — NPZ download (StreamingResponse)
      • GET /v1/datasets/{id}/preview — JSON sample preview
      • DELETE /v1/datasets/{id} — Single dataset deletion
      • PATCH /v1/datasets/{id}/tags — Tag management (add/remove)
  • Shared Client Library (juniper_data_client/)

    • client.pyJuniperDataClient with all API methods, automatic retry logic, connection pooling
    • exceptions.py — Exception hierarchy (ConnectionError, TimeoutError, NotFoundError, ValidationError)
    • pyproject.toml — Standalone pip-installable package configuration
    • py.typed — PEP 561 type marker for mypy strict mode
    • README.md — Comprehensive documentation with usage examples
  • Docker Containerization

    • Dockerfile — Multi-stage build (python:3.11-slim), non-root user (juniper:1000), port 8100
    • .dockerignore — Build context exclusions (tests, docs, notes, caches)
    • HEALTHCHECK instruction (30s interval, 10s timeout, 5s start period, 3 retries)
  • CI/CD Pipeline

    • .github/workflows/ci.yml — Full pipeline: pre-commit (Python 3.12-3.14), unit tests (80% coverage gate), integration tests, security scanning (Gitleaks, Bandit SARIF, pip-audit), slow tests (weekly), build verification
    • .github/workflows/codeql.yml — Weekly semantic code analysis
    • .github/dependabot.yml — Automated dependency updates (pip + GitHub Actions)
    • .pre-commit-config.yaml — 16+ hooks: black, isort, flake8 (with bugbear, comprehensions, simplify), mypy, bandit, pyupgrade (py311+), shellcheck, YAML/TOML/JSON validation
    • GitHub Actions pinned to SHA for supply chain security
  • Test Suite (658 tests + 41 client tests)

    • tests/unit/ — 589 unit tests across 25 test files
    • tests/integration/ — 69 integration tests across 5 test files
    • tests/fixtures/ — Golden dataset fixtures (2-spiral, 3-spiral) for parity testing
    • tests/conftest.py — Shared fixtures (TestClient, storage, sample datasets)
    • juniper_data_client/tests/test_client.py — 41 client tests using responses HTTP mocking
  • Documentation

    • docs/api/JUNIPER_DATA_API.md — 622-line API reference with versioning strategy, endpoint documentation, NPZ schema, client examples (Python, curl, Docker Compose)
    • notes/INTEGRATION_DEVELOPMENT_PLAN.md — 20 work items compiled from 5 documentation sources
    • notes/test_suite_audit/ — Test suite audits and CI/CD enhancement plans
    • notes/mcp_tools/ — MCP/Serena setup documentation
    • AGENTS.md — Complete project guide (updated from JuniperCanopy)
    • CLAUDE.md — Symlink to AGENTS.md for Claude Code integration
  • Infrastructure

    • conf/juniper_data.conf — Application launch configuration (renamed from juniper_canopy.conf)
    • conf/juniper_data_functions.conf — Shell functions (renamed from juniper_canopy_functions.conf)
    • conf/conda_environment.yaml — Updated Conda environment for JuniperData
    • conf/script_util.cfg — Script utility configuration
    • conf/logging_config-CASCOR.yaml — Cascor logging configuration
    • util/juniper_data.bash — Application launch script
    • pyproject.toml — Complete project configuration (dependencies, tool settings, test markers)

Changed

  • Repository Identity — Transformed from JuniperCanopy (Dash visualization dashboard) to JuniperData (dataset generation microservice)
  • Directory Structure — Replaced src/ package structure with juniper_data/ for proper package discovery
  • README.md — Rewritten for JuniperData service documentation
  • AGENTS.md — Rewritten from JuniperCanopy guide to JuniperData project guide
  • CHANGELOG.md — Rewritten with JuniperData version history (v0.1.0–v0.4.0)
  • pyproject.toml — Reconfigured for JuniperData (dependencies, tool config, test markers, coverage settings)
  • CI/CD Pipeline — Rebuilt from scratch for JuniperData (simplified, focused, security-hardened)
  • Pre-commit Configuration — Updated with JuniperData-specific settings and additional hooks
  • Shell Scripts — Retained and updated utility scripts; removed Canopy-specific scripts
  • Conda Environment — Updated for JuniperData development dependencies

Fixed

  • DATA-001: mypy Type Errors in Test Files — 20 errors → 0 across 4 test files
    • Type narrowing assertions in test_storage.py and test_storage_workflow.py
    • # type: ignore[arg-type] for negative tests in test_spiral_generator.py
    • getattr() pattern for dynamic attributes in test_api_app.py
  • DATA-002: flake8 Unused Imports — Removed unused Any and Dict from datasets.py
  • DATA-003: flake8 Issues in generate_golden_datasets.py — Added # noqa: E402 for late imports, converted bare f-strings
  • CI-001: pip-audit failing on local package — Fixed grep pattern in CI pipeline to handle modern pip's underscore-normalized package names (juniper_data vs juniper-data), which caused pip-audit --strict to fail with "Dependency not found on PyPI"
  • MNIST-001: 12 failing MNIST generator tests — Generator's _load_and_preprocess called ds.with_format("numpy") for bulk column access, but test mocks didn't configure with_format(), returning a generic MagicMock that produced empty arrays on np.array(). Fixed by adding formatted_ds mocks returning proper numpy data. Also added missing n_samples support via ds.select() in the generator.
  • SEC-007: Bandit B615 nosec placement — Moved # nosec B615 from the comment line above hf_load_dataset() to inline on the call itself; bandit only honors # nosec directives on the same line as the flagged code

Removed

  • JuniperCanopy Application (src/) — Entire Dash dashboard application (185 files)
    • src/backend/ — Cascor integration, Redis, Cassandra, statistics, training monitor/state machine
    • src/frontend/ — Dashboard manager, all UI components (metrics, network visualizer, dataset plotter, etc.)
    • src/communication/ — WebSocket manager
    • src/demo_mode.py, src/config_manager.py, src/main.py — Application entry points
    • src/tests/ — All JuniperCanopy tests (~2,900 tests)
    • src/assets/ — Logo images and icons
    • src/logger/ — Custom logging module
  • Legacy Configuration.codecov.yml, .coveragerc, .markdownlint.json, .yamllint.yaml, conftest.py (root)
  • Legacy Documentation — Development phases (phase0-3), fix notes, release notes (v0.14–v0.25), analysis reports, roadmaps
  • Legacy Infrastructure — Canopy-specific conf/ files (docker-compose, app_config, main.conf, proto.conf), requirements.txt files, conda CI environment, setup_environment scripts, performance profiling, Canopy utility scripts
  • Legacy Artifactssnapshots/, demo symlink, src/logs symlink

Security

  • SEC-001: Bandit Security Scanning — Blocking checks for medium+ severity findings
  • SEC-002: pip-audit Strict Mode — Fails on any known vulnerability
  • SEC-003: Dependabot Configuration — Automated weekly dependency updates (pip + GitHub Actions)
  • SEC-004: GitHub Actions Pinned to SHA — Supply chain security for all Actions
  • SEC-005: Non-root Docker User — Container runs as juniper (UID 1000)
  • SEC-006: CodeQL Analysis — Weekly semantic code analysis workflow

Impact & SemVer

  • SemVer impact: MINOR (0.3.0 → 0.4.0) — New features added; v0.1.0–v0.4.0 cumulative
  • User-visible behavior change: YES — Complete application replacement
  • Breaking changes: YES
    • What breaks: The entire JuniperCanopy application (src/) is removed and replaced with JuniperData (juniper_data/)
    • Migration steps: This is a planned extraction; JuniperCanopy continues independently in its own repository
  • Performance impact: N/A — New application, not comparable to predecessor
  • Security/privacy impact: IMPROVED — Non-root Docker, Bandit SAST, pip-audit, CodeQL, Dependabot, SHA-pinned Actions
  • Guarded by feature flag: YES — JUNIPER_DATA_URL environment variable enables JuniperData mode in consumers

Testing & Results

Test Summary

Test Type Passed Failed Skipped Notes
Unit 589 0 0 25 test files covering all source modules
Integration 69 0 0 5 test files (API, E2E, lifecycle, storage)
Client 41 0 0 juniper-data-client package (96% coverage)
Total 699 0 0 All passing on Python 3.14.2

Coverage

Component Coverage Target Status
juniper_data (overall) 97.47% 80% ✅ Exceeded
24 of 26 source files 100% 80% ✅ Exceeded
storage/base.py 99.10% 80% ✅ Exceeded
storage/local_fs.py 79.57% 80% ⚠️ Near
juniper-data-client 96% N/A ✅ Exceeded

Environments Tested

  • Python 3.14.2 (local development): ✅ All 699 tests pass
  • CI matrix: Python 3.12, 3.13, 3.14 (configured)
  • Conda environment (JuniperData): ✅ Functional

Verification Checklist

  • Main user flow(s) verified: Dataset create → download → verify cycle (E2E tests)
  • Edge cases checked: Invalid generators, missing datasets, expired TTL, batch operations
  • No regression in related areas: JuniperCascor/JuniperCanopy maintain independent codebases
  • Feature defaults correct and documented: API defaults, generator defaults, storage defaults
  • Logging/metrics updated: Structured logging via uvicorn, configurable log levels
  • Documentation updated: AGENTS.md, API docs, CHANGELOG.md, INTEGRATION_DEVELOPMENT_PLAN.md
  • Legacy parity verified: algorithm="legacy_cascor" matches JuniperCascor SpiralProblem statistics
  • Parameter aliases verified: n_points/noise_level accepted for consumer compatibility
  • Docker configuration verified: Multi-stage build, health checks, non-root user
  • CI/CD pipeline verified: All hooks pass, security scanning configured

API Changes

New Endpoints (All New)

Method Endpoint Description Breaking?
GET /v1/health Health check (backward compatible) No
GET /v1/health/live Kubernetes liveness probe No
GET /v1/health/ready Kubernetes readiness probe No
GET /v1/generators List available generators No
GET /v1/generators/{name}/schema Get generator parameter schema No
POST /v1/datasets Create/generate dataset No
GET /v1/datasets List datasets with pagination No
GET /v1/datasets/filter Advanced dataset filtering No
GET /v1/datasets/stats Aggregate statistics No
POST /v1/datasets/batch-delete Bulk delete (up to 100) No
POST /v1/datasets/cleanup-expired Remove expired datasets No
GET /v1/datasets/{id} Get dataset metadata No
GET /v1/datasets/{id}/artifact Download NPZ artifact No
GET /v1/datasets/{id}/preview JSON sample preview No
DELETE /v1/datasets/{id} Delete dataset No
PATCH /v1/datasets/{id}/tags Add/remove dataset tags No

NPZ Artifact Schema (Data Contract)

Key Shape Dtype Description
X_train (n_train, n_features) float32 Training features
y_train (n_train, n_classes) float32 Training labels (one-hot)
X_test (n_test, n_features) float32 Test features
y_test (n_test, n_classes) float32 Test labels (one-hot)
X_full (n_samples, n_features) float32 Full dataset features
y_full (n_samples, n_classes) float32 Full dataset labels (one-hot)

Files Changed

Total: 451 files changed, 19,150 insertions(+), 94,825 deletions(-):

Category Count
New files 128
Modified files 43
Deleted files 274

New Components

Core Application:

  • juniper_data/__init__.py — Package init with version
  • juniper_data/__main__.py — CLI entry point (argparse + uvicorn)
  • juniper_data/core/models.py — 11 Pydantic data models
  • juniper_data/core/split.py — Shuffle and split utilities
  • juniper_data/core/dataset_id.py — Deterministic ID generation
  • juniper_data/core/artifacts.py — NPZ artifact handling

Generators:

  • juniper_data/generators/spiral/generator.py — Spiral dataset generator (modern + legacy algorithms)
  • juniper_data/generators/spiral/params.py — Spiral params with consumer aliases
  • juniper_data/generators/spiral/defaults.py — Default constants
  • juniper_data/generators/xor/generator.py — XOR classification generator
  • juniper_data/generators/xor/params.py — XOR parameter model

Storage:

  • juniper_data/storage/base.py — Abstract store with lifecycle methods
  • juniper_data/storage/memory.py — In-memory store
  • juniper_data/storage/local_fs.py — Filesystem store

API:

  • juniper_data/api/app.py — FastAPI application factory
  • juniper_data/api/settings.py — Pydantic-settings configuration
  • juniper_data/api/routes/health.py — Health probe endpoints
  • juniper_data/api/routes/generators.py — Generator discovery endpoints
  • juniper_data/api/routes/datasets.py — Dataset CRUD + lifecycle endpoints

Client Library:

  • juniper_data_client/client.py — REST client with retries and connection pooling
  • juniper_data_client/exceptions.py — Exception hierarchy
  • juniper_data_client/pyproject.toml — Package configuration

Infrastructure:

  • Dockerfile — Multi-stage Docker build
  • .dockerignore — Build context exclusions
  • .github/workflows/ci.yml — CI/CD pipeline
  • .github/workflows/codeql.yml — CodeQL analysis
  • .github/dependabot.yml — Dependency automation
  • conf/juniper_data.conf — Application launch config
  • util/juniper_data.bash — Launch script

Tests:

  • juniper_data/tests/unit/test_spiral_generator.py — 43 spiral generator tests
  • juniper_data/tests/unit/test_split.py — 18 data split tests
  • juniper_data/tests/unit/test_dataset_id.py — 16 ID generation tests
  • juniper_data/tests/unit/test_storage.py — 44 storage tests
  • juniper_data/tests/unit/test_artifacts.py — 11 artifact tests
  • juniper_data/tests/unit/test_api_app.py — 17 app factory tests
  • juniper_data/tests/unit/test_api_routes.py — 18 route tests
  • juniper_data/tests/unit/test_api_settings.py — 11 settings tests
  • juniper_data/tests/unit/test_main.py — 10 entry point tests
  • juniper_data/tests/unit/test_lifecycle.py — 27 lifecycle tests
  • juniper_data/tests/unit/test_xor_generator.py — 18 XOR generator tests
  • juniper_data/tests/integration/test_api.py — 18 API integration tests
  • juniper_data/tests/integration/test_e2e_workflow.py — 14 E2E workflow tests
  • juniper_data/tests/integration/test_lifecycle_api.py — 17 lifecycle API tests
  • juniper_data/tests/integration/test_storage_workflow.py — 8 storage workflow tests
  • juniper_data_client/tests/test_client.py — 35 client tests

Documentation:

  • docs/api/JUNIPER_DATA_API.md — 622-line API reference
  • notes/INTEGRATION_DEVELOPMENT_PLAN.md — Integration work items
  • notes/test_suite_audit/*.md — Test suite audit reports
  • AGENTS.md — Updated project guide

Modified Components

Configuration:

  • pyproject.toml — Reconfigured for JuniperData (dependencies, tools, markers)
  • .pre-commit-config.yaml — Updated hooks and settings
  • .gitignore — Updated for JuniperData structure
  • conf/conda_environment.yaml — Updated for JuniperData dependencies
  • conf/*.conf — Updated shell configuration files

Reports:

  • reports/junit/results.xml — Updated test results

Removed Components

JuniperCanopy Application (185 src/ files):

  • src/backend/ — cascor_integration.py, data_adapter.py, redis_client.py, cassandra_client.py, statistics.py, training_monitor.py, training_state_machine.py
  • src/frontend/ — dashboard_manager.py, 10 component files (metrics_panel, network_visualizer, dataset_plotter, decision_boundary, about_panel, etc.)
  • src/communication/ — websocket_manager.py
  • src/main.py — 2,030-line application entry point
  • src/demo_mode.py — 1,004-line demo mode
  • src/config_manager.py — 492-line configuration manager
  • src/tests/ — ~2,900 tests across unit, integration, regression, and performance suites
  • src/assets/ — 15 logo/icon files

Legacy Infrastructure (86 files):

  • conf/docker-compose.yaml, conf/Dockerfile, conf/app_config.yaml
  • conf/requirements.txt, conf/requirements_ci.txt
  • conf/setup_environment.conf, conf/setup_environment_functions.conf
  • 30+ utility scripts (util/*.bash)
  • Legacy notes/development/, notes/fixes/, notes/releases/ documentation

Risks & Rollback Plan

  • Key risks:
    • Repository transformation is non-reversible in the traditional sense (old JuniperCanopy code removed)
    • Consumer integration requires updating JuniperCascor and JuniperCanopy to use the shared client package
  • Monitoring / alerts to watch:
    • JuniperData service health endpoint: GET /v1/health
    • CI/CD pipeline status on main branch
    • Dependency vulnerability alerts via Dependabot
  • Rollback plan:
    • Git revert to main branch restores JuniperCanopy codebase
    • JuniperCanopy application continues independently in its own repository
    • Consumer feature flags (JUNIPER_DATA_URL) allow graceful degradation when JuniperData is unavailable

Related Issues / Tickets


What's Next

Remaining Items

Feature Status Priority
Publish juniper-data-client to PyPI Not Started P1
Update JuniperCascor to use shared client package Not Started P1
Update JuniperCanopy to use shared client package Not Started P1
Additional generators (Gaussian mixture, circles, checkerboard) ✅ Complete P3
Storage backend extensions (cached, HF, Kaggle, Postgres, Redis) ✅ Complete P3
API rate limiting and authentication Not Started P3
IPC architecture (gRPC) Deferred P3
GPU-accelerated data generation Deferred P3
Continuous profiling integration Not Started P3

Notes for Release

Release: JuniperData v0.4.0 — Integration Infrastructure & Client Library:

Key highlights:

  • Complete standalone dataset generation microservice
  • FastAPI REST API with 16 endpoints on port 8100
  • Two generators: spiral (modern + legacy algorithms) and XOR classification
  • Dataset lifecycle management (TTL, tagging, filtering, batch operations)
  • Shared client library (juniper-data-client) for JuniperCascor/JuniperCanopy integration
  • Docker containerization with multi-stage build and health probes
  • 699 tests (658 service + 41 client)
  • CI/CD pipeline with Python 3.11-3.14, security scanning, pre-commit hooks
  • Comprehensive API documentation with NPZ artifact schema

Review Notes

  1. Repository Transformation: This PR replaces the entire JuniperCanopy codebase with JuniperData. The src/ directory (185 files) is removed and juniper_data/ (82 new files) takes its place. This is a planned extraction, not an accidental deletion.

  2. Version History: The CHANGELOG documents the complete development history from v0.1.0 (initial release) through v0.4.0 (this PR). Each version built incrementally on the previous one.

  3. Client Library: The juniper_data_client/ package is designed to be published to PyPI and consumed by both JuniperCascor and JuniperCanopy, replacing their current duplicate client code.

  4. Legacy Parity: The algorithm="legacy_cascor" mode in SpiralGenerator reproduces the statistical properties of JuniperCascor's original SpiralProblem implementation, ensuring backward compatibility.

  5. New Modules: 6 new generators and 5 new storage backends added after the initial PR description was written.

  6. B008 Warnings: The 9 B008 flake8 warnings in datasets.py are intentional FastAPI patterns (using Query(), Depends() in function defaults) and should not be "fixed."

  7. Test Count Growth: From 0 tests (main branch had JuniperCanopy tests) to 699 JuniperData-specific tests (658 service + 41 client).

pcalnon and others added 30 commits January 29, 2026 22:53
…splitting utilities

- Implement tests for deterministic dataset ID generation, ensuring consistent IDs for identical parameters and different parameters produce unique IDs.
- Validate dataset ID format and hash characteristics.
- Create comprehensive tests for the SpiralGenerator, covering output shapes, one-hot encoding correctness, and parameter validation.
- Introduce tests for shuffle and split utilities, ensuring data integrity during shuffling and correct sizes during splitting.
- Created unit tests for dataset ID generation covering deterministic ID generation, parameter variations, and ID format validation.
- Implemented unit tests for the SpiralGenerator, including output shapes, one-hot encoding correctness, and parameter validation.
- Added tests for shuffle and split utilities to ensure data integrity during shuffling and splitting operations.
- Updated `pyproject.toml` to include new testing dependencies and adjusted configurations.
- Removed unnecessary `__pycache__` files from the source directories.
- Created junit test result XML files for both integration and unit tests.
- Added a new directory for test scripts and created a symlink to it.
- Implemented a script to run tests with specified parameters and configurations.
- Developed a comprehensive script to execute all tests with coverage reporting options.
- Enhanced the test execution process by setting up environment variables and paths.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Memory files for project context:
- project_overview.md: Purpose, tech stack, dependencies
- suggested_commands.md: Development commands reference
- code_style_conventions.md: Naming, formatting, patterns
- task_completion_checklist.md: Quality checks before commit
- codebase_structure.md: Directory layout and components

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Detailed analysis of JuniperData testing infrastructure covering:
- Test validity and correctness (207 tests analyzed)
- CI/CD pipeline configuration issues
- Pre-commit hook coverage gaps
- Security scanning configuration
- Prioritized recommendations for improvements

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add comprehensive development plan consolidating audit findings
- Update audit reports with refined analysis and formatting
- Update test files and coverage reports
- Update Serena configuration and memory files

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Updated the metrics table for better readability and clarity.
- Improved the formatting of issue descriptions and assessments in the audit report.
- Added detailed recommendations for addressing identified issues, including silent test passes and security scan configurations.
- Enhanced the priority matrix and best practices compliance review sections for clearer guidance.
- Included specific commands for verification and outlined implementation risks and consequences of inaction.
- Created new files for Dependabot and CodeQL workflows to improve dependency management and security analysis.
Security Remediation (Critical):
- SEC-001: Bandit now blocks on medium+ severity findings
- SEC-002: pip-audit uses --strict to fail on vulnerabilities
- SEC-003: Add Dependabot for automated dependency updates
- TST-001: Fix silent ImportError pass in test_main.py

Code Quality Enforcement (High):
- TST-002: Enable Flake8 linting on test code
- TST-003: Enable MyPy type checking on test code
- TST-004: Remove global pytest warning suppression
- CFG-001: Remove E722/F401 from Flake8 ignores
- Fix 7 unused imports in test files

Infrastructure Improvements (Medium):
- SEC-004: Pin all GitHub Actions to commit SHAs
- CFG-003: Fix MyPy type errors in production code
- CFG-005: Remove --continue-on-collection-errors
- INF-001: Add CodeQL security analysis workflow
- INF-002: Add Codecov coverage upload integration
- INF-003: Add slow test job with weekly schedule

Best Practice Refinements (Low):
- L-01: Add pyupgrade hook for Python 3.11+ syntax
- L-02: Add shellcheck hook for shell script linting

All 207 tests passing. See TEST_SUITE_CICD_ENHANCEMENT_DEVELOPMENT_PLAN.md
for full implementation details.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Added assertions to check for non-None values in dataset metadata and artifact bytes across multiple test files to enhance robustness.
- Updated test_api_app.py to safely access dynamic route attributes using getattr().
- Included type ignore comments in test_spiral_generator.py for invalid algorithm parameter validation.
- Ensured artifact bytes are checked for None in test_storage.py for both in-memory and local filesystem stores.
- Updated integration development plan to reflect the completion of mypy type error fixes and flake8 issues, along with the addition of a Dockerfile and health check probes.
- Created a new script `juniper_data.bash` for handling Juniper data processing with configurable parameters.
- Removed the outdated `run.bash` script that contained hardcoded paths and parameters.
- Updated symlink for `try.bash` to point to `juniper_data.bash`.
- Updated version numbers in ci.yml, .pre-commit-config.yaml, AGENTS.md, CHANGELOG.md, JUNIPER_DATA_API.md, __init__.py, INTEGRATION_DEVELOPMENT_PLAN.md, and pyproject.toml to reflect the new version 0.4.0.
- Added detailed pull request description for JuniperData Service Extraction & Integration Infrastructure.
- Enhanced CHANGELOG with new features, fixes, and modifications for version 0.4.0.
- Implemented unit tests for CachedDatasetStore, ensuring proper save, retrieve, delete, and cache functionalities.
- Added unit tests for CirclesGenerator and GaussianGenerator, covering parameter validation, data generation, and class distribution.
- Introduced unit tests for API security, including API key authentication and rate limiting, ensuring correct behavior under various scenarios.
- Updated integration development plan to reflect new test counts and completed features.
… unit tests for new generators

- Implement KaggleDatasetStore for downloading and caching datasets from Kaggle.
- Implement PostgresDatasetStore for metadata storage with filesystem artifacts.
- Add unit tests for CheckerboardGenerator and CsvImportGenerator, covering various scenarios and parameter validations.
- Update integration development plan to reflect new features and completed tasks.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Overtoad <paul.calnon@gmail.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 149 out of 465 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Overtoad <paul.calnon@gmail.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 149 out of 465 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

pcalnon and others added 2 commits February 17, 2026 14:56
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Overtoad <paul.calnon@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Overtoad <paul.calnon@gmail.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 149 out of 465 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread juniper_data/generators/mnist/generator.py Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 149 out of 465 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread juniper_data/generators/xor/params.py Outdated
Comment thread conf/run_all_tests.conf Outdated
pcalnon and others added 3 commits February 17, 2026 16:21
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Overtoad <paul.calnon@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Overtoad <paul.calnon@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Overtoad <paul.calnon@gmail.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 149 out of 465 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Overtoad <paul.calnon@gmail.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 149 out of 465 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

…fixing mock with_format

The generator's _load_and_preprocess calls ds.with_format("numpy") for bulk column
access, but test mocks didn't configure with_format(), causing np.array() to produce
empty arrays. Added formatted_ds mocks returning proper numpy data. Also added missing
n_samples handling via ds.select() in the generator.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@pcalnon

pcalnon commented Feb 17, 2026

Copy link
Copy Markdown
Owner Author

merging large refactor for juniper cascor

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 149 out of 465 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread conf/logging_config-CASCOR.yaml
Comment thread juniper_data/generators/mnist/generator.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Overtoad <paul.calnon@gmail.com>
Comment thread juniper_data/generators/mnist/generator.py Fixed

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 149 out of 465 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread juniper_data/generators/xor/params.py
Comment thread juniper_data/storage/__init__.py
Comment thread conf/get_code_stats.conf
Comment thread conf/common.conf
Comment thread conf/common.conf
pcalnon and others added 2 commits February 17, 2026 17:09
The # nosec B615 directive was on the comment line above the flagged
hf_load_dataset() call. Bandit only honors nosec on the same line as the
code it suppresses.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The hard `import arc_agi` in __init__.py caused ModuleNotFoundError for
consumers that don't need ARC-AGI functionality (e.g. JuniperCascor),
preventing all JuniperData integration tests from running. Move arc-agi
from core dependencies to optional-dependencies and guard the import
with try/except, exposing an ARC_AGI_AVAILABLE flag.

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

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 149 out of 465 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 149 out of 465 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread conf/logging_config-CANOPY.yaml
Comment thread conf/logging_config-CANOPY.yaml
Comment thread conf/logging_config.yaml Outdated
Comment thread juniper_data/__init__.py
pcalnon and others added 2 commits February 17, 2026 17:55
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Overtoad <paul.calnon@gmail.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 149 out of 465 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +42 to +50
buffer = io.BytesIO()
# Ensure a stable serialization order by sorting keys before saving.
ordered_arrays = {key: arrays[key] for key in sorted(arrays.keys())}
np.savez(buffer, **ordered_arrays) # type: ignore[arg-type] # numpy stubs incomplete for **kwargs
buffer.seek(0)
return buffer.read()


def compute_checksum(arrays: dict[str, np.ndarray]) -> str:

Copilot AI Feb 18, 2026

Copy link

Choose a reason for hiding this comment

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

The checksum is computed from the NPZ container bytes produced by np.savez(). Even with sorted keys, the resulting bytes (and therefore checksum) are not guaranteed deterministic across calls because the underlying ZIP metadata (e.g., timestamps) can vary. Additionally, other code paths serialize NPZ differently (e.g., compressed vs uncompressed), which can cause checksum mismatches depending on which serializer is used. Consider computing the checksum from a deterministic representation (e.g., sorted keys + dtype/shape + raw array bytes) and standardize NPZ serialization (compressed vs uncompressed) across the project.

Copilot uses AI. Check for mistakes.
Comment thread juniper_data/api/app.py
Comment on lines +29 to +32
logging.basicConfig(
level=getattr(logging, settings.log_level.upper(), logging.INFO),
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
)

Copilot AI Feb 18, 2026

Copy link

Choose a reason for hiding this comment

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

Settings supports log levels like TRACE/VERBOSE/FATAL (see Settings defaults), but Python's standard logging module doesn't define those levels, so getattr(logging, ...) will silently fall back to INFO. This makes config values misleading and can cause unexpected logging behavior. Either restrict Settings.log_level to standard logging levels (DEBUG/INFO/WARNING/ERROR/CRITICAL) or explicitly register custom levels and map them consistently for both uvicorn and stdlib logging.

Copilot uses AI. Check for mistakes.


_JUNIPER_DATA_API_KEYS_LIST_EMPTY: list[str] | None = None
_JUNIPER_DATA_API_KEYS_LIST_VALUES: list[str] | None = []

Copilot AI Feb 18, 2026

Copy link

Choose a reason for hiding this comment

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

Avoid using a mutable list literal as a module-level default (_JUNIPER_DATA_API_KEYS_LIST_VALUES = []). Even if it's not currently used as the default, it can be accidentally referenced later and mutated, causing shared state across imports. Prefer a tuple, or set it to None and use default_factory at the model field when you actually want an empty collection.

Suggested change
_JUNIPER_DATA_API_KEYS_LIST_VALUES: list[str] | None = []
_JUNIPER_DATA_API_KEYS_LIST_VALUES: list[str] | None = None

Copilot uses AI. Check for mistakes.
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.

4 participants