Skip to content

test(edifice): minimal offline regression test for the mission pipeline (pull → report → push) #77

Description

@BluegReeno

Summary

We just ran the full /edifice loop by hand (pull → improve → report → push) and it surfaced a live backend bug (#74) only at the last step. Nothing guards this pipeline in CI, so an Archon change to hal-mcp or the edifice mapping can silently break the report that field users depend on (IC Ingénieurs today; suivi_chantier prospects such as G. Baron next).

Add a minimal, offline, deterministic regression test that locks the pipeline's contract. Goal: a change that breaks pull→report→push turns a CI job red, not a field mission.

Companion: BluegReeno/bluegreen-marketplace#44 covers the client-side render half (build_context → DOCX). This issue covers the backend half. Land them together for full coverage.

Scope (MVP)

Two fixtures under tests/fixtures/edifice/, mirroring what the PWA stores — one diagnostic and one suivi_chantier mission, each with ≥1 note and ≥1 photo reference (tiny stub images, not real photos):

  1. Backend contract — push_mission_context (guards fix(hal-mcp): push_mission_context upserts partial note rows — every push fails on project_id NOT NULL #74). Given seeded edifice_notes, a push of partial observations must: UPDATE by note_id (never insert/upsert), preserve project_id and untouched columns, report updated = rows actually affected, and report an unknown note_id as skipped/error (never a phantom insert). Idempotent: pushing twice changes nothing. → Best placed as a Deno test beside supabase/functions/hal-mcp/index.ts, ideally landed with the fix(hal-mcp): push_mission_context upserts partial note rows — every push fails on project_id NOT NULL #74 fix; add a deno test step to CI if none exists.

  2. Pull/report contract — get_mission_with_assets → context shape. Assert the assembled mission+assets payload keeps the shape the edifice skill's build_context.py consumes, for both project_types: notes carry note_id + photos[], assessment maps to the diagnostic IE scale / suivi_chantier states, photo filenames resolve. This pins the backend↔skill contract so a shape drift is caught here rather than in the field.

Assertions are structural invariants, not bytes — e.g. "2 observations, each with a note_id and a resolvable photo", never a hash of a rendered .docx (the renderer re-encodes images, so bytes change every run — a byte-exact test would be permanently red and get disabled).

Non-goals / companion

  • DOCX render smoke test (build_context.pyrender_diagnostic.py / render_cr_visite.py → assert "opens, N disorders, M images"): those scripts live in the skill/plugin repo (bluegreen-marketplace), not here. Tracked as the companion BluegReeno/bluegreen-marketplace#44; out of scope for this repo.
  • No improve (LLM) step in the test — represent the qualified mission as a fixed context.json fixture, not a live model call.
  • No live Supabase in CI — mock the client or gate behind the existing live marker; the default pytest -m "not live" run must stay green offline.

Acceptance

Maintenance

Fixtures are versioned beside the tests. When a behavior change is intentional, update the fixture / expected invariants in the same PR and review the diff (golden-file discipline). Keep the improve step as a fixture and anything needing real Supabase behind live, so the offline suite never rots into a permanently-red state nobody trusts.

Related


Filed from a Cowork session that walked the full loop end-to-end. Intentionally left unlabeled / not queued for Archon — pick it up when priorities allow.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions