Skip to content

feat(sample-data): list-driven sample data generation for --test - #20

Merged
Xander-git merged 1 commit into
feature/gui-imrprovement-v2from
feature/sample-data-generation
May 30, 2026
Merged

Xander-git merged 1 commit into
feature/gui-imrprovement-v2from
feature/sample-data-generation

Conversation

@Xander-git

Copy link
Copy Markdown
Collaborator

Summary

Replaces the single hardcoded --add-test-samples equipment literal with a list-driven sample-data generator. A declarative SAMPLES list (2 equipment / 3 projects / 7 runs) is expanded into a full on-disk demo tree under the -test sandbox, with every folder's metadata written through the real production producers (ReadmeGenerator, CreationWriter, EquipmentCacheWriter) so it can't drift from what the wizard writes.

Design spec: docs/superpowers/specs/2026-05-29-sample-data-generation-design.md.

What changed

  • sample_data/spec.py (Pydantic SAMPLES), generator.py (SampleDataGenerator + generate_samples() facade + guardrailed destructive wipe), __init__.py.
  • controller/metadata_assembly.py — extracted build_readme_context / build_creation_json (+ moved pure helpers) now shared by the controller and the seeder. controller/creation.py delegates to them (behavior-preserving, guarded by parity tests).
  • config/test_bootstrap.py — shared write_starter_test_config / bootstrap_test_config in a light module (no pystray import), used by both the tray flag and the dev command.
  • dev/seed.pypython -m exlab_wizard.dev.seed (always wipe + regenerate).
  • tray/main.py — deletes the inline TESTRIG literal; seeds via the shared bootstrap on first launch only (never wipes an existing sandbox).

Design notes

  • Determinism: fixed clock; README/creation.json/payload bytes are byte-identical across runs. Only equipment.json's writer-stamped first_seen_at/last_modified_at differ (documented; excluded from the determinism assertions).
  • Faithfulness: seeded EquipmentConfig.local_root/nas_root are base roots so run-walking (orchestrator quiescence poller / validator, which compose local_root / equipment.id) discovers the tree.
  • Safety: the destructive wipe is fenced to the -test sandbox (_app_name() ends in -test) with strict-subpath containment; only ever removes local_root/<prefixed_id>. Symlink-escape and out-of-sandbox cases are tested.
  • Seeded SYNCED / BLOCKED_BY_VALIDATION values are deliberate UI fixtures written into creation.json; no run is actually verified or transferred.

Test plan

  • uv run pytest tests/unit tests/integration --ignore=tests/integration/test_pyinstaller_smoke.py2362 passed, 3 skipped (44 new tests: assembly parity, generator e2e, determinism, guardrails incl. symlink escape, base-root fidelity, dev command, tray no-op).
  • ruff check / ruff format --check / mypy clean on all changed files.
  • Real python -m exlab_wizard.dev.seed run produces the expected tree (2 equipment, 3 projects, 7 runs, 10 metadata triples, 2 equipment.json, 3 test_runs.json, 1 scan-trigger payload) and is byte-deterministic across two runs.

🤖 Generated with Claude Code

Replace the single hardcoded `--add-test-samples` equipment literal with a
declarative `SAMPLES` list expanded by a generator that seeds a full demo
tree (equipment -> projects -> runs). Every folder's metadata is written
through the real production producers (ReadmeGenerator, CreationWriter,
EquipmentCacheWriter) so it cannot drift from what the wizard writes.

- sample_data/{spec,generator,__init__}: Pydantic SAMPLES + generator +
  generate_samples() facade with a guardrailed destructive wipe.
- controller/metadata_assembly: extract build_readme_context /
  build_creation_json (+ moved helpers) shared by the controller and the
  seeder; creation.py now delegates (behavior-preserving, parity-tested).
- config/test_bootstrap: shared write_starter_test_config /
  bootstrap_test_config (light module; no pystray import) used by both the
  tray flag and the new dev command.
- dev/seed: `python -m exlab_wizard.dev.seed` (always wipe + regenerate).
- tray/main: delete the inline TESTRIG literal; seed via the shared
  bootstrap on first launch only (never wipes an existing sandbox).

Deterministic (fixed clock; README/creation.json/payload bytes identical
across runs; only equipment.json's writer-stamped timestamps differ).
Seeded equipment roots are base paths so run-walking (quiescence poller /
validator) discovers the tree. Destructive wipe is fenced to the -test
sandbox with strict-subpath containment. Full suite green (2362 passed,
3 skipped); ruff + mypy clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Xander-git
Xander-git merged commit 9493a28 into feature/gui-imrprovement-v2 May 30, 2026
3 checks passed
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