Files
detections/.cursor/skills/monorepo-e2e/SKILL.md
T
Oleksandr Bezdieniezhnykh 3482173e7d
ci/woodpecker/push/02-build-push Pipeline was successful
chore: sync .cursor from suite
Made-with: Cursor
2026-04-25 19:44:40 +03:00

8.4 KiB
Raw Blame History

name, description
name description
monorepo-e2e Syncs the suite-level integration e2e harness (`e2e/docker-compose.suite-e2e.yml`, fixtures, Playwright runner) when component contracts drift in ways that affect the cross-service scenario. Reads `_docs/_repo-config.yaml` to know which suite-e2e artifacts are in play. Touches ONLY suite-e2e files — never per-component CI, docs, or component internals. Use when a component changes a port, env var, public API endpoint, DB schema column, or detection model that the suite e2e exercises.

Monorepo Suite-E2E

Propagates component changes into the suite-level integration e2e harness. Strictly scoped — never edits docs, component internals, per-component CI configs, or the production deploy compose.

Scope — explicit

In scope Out of scope
e2e/docker-compose.suite-e2e.yml (overlay, healthchecks, seed services) Production _infra/deploy/<target>/docker-compose.ymlmonorepo-cicd owns it
e2e/fixtures/init.sql (seeded rows that the spec depends on) Component DB migrations — owned by each component
e2e/fixtures/expected_detections.json (detection baseline) Detection model itself — owned by detections/
e2e/runner/tests/*.spec.ts selector / contract-driven edits New scenarios (user-driven, not drift-driven)
e2e/runner/Dockerfile / package.json Playwright version bumps Net-new e2e infrastructure (use monorepo-onboard or initial scaffolding)
.woodpecker/suite-e2e.yml (suite-level pipeline) Per-component .woodpecker/01-test.yml / 02-build-push.ymlmonorepo-cicd owns those
Suite-e2e leftover entries under _docs/_process_leftovers/ Per-component leftovers — owned by each component

If a component change needs doc updates too, tell the user to also run monorepo-document. If it needs production-deploy or per-component CI updates, run monorepo-cicd. This skill only updates the suite-e2e surface.

Preconditions (hard gates)

  1. _docs/_repo-config.yaml exists.
  2. Top-level confirmed_by_user: true.
  3. suite_e2e.* section is populated in config (see "Required config block" below). If absent, abort and ask the user to extend the config via monorepo-discover.
  4. Components-in-scope have confirmed contract mappings (port, public API path, DB tables touched), OR user explicitly approves inferred ones.

Required config block

This skill expects _docs/_repo-config.yaml to carry:

suite_e2e:
  overlay: e2e/docker-compose.suite-e2e.yml
  fixtures:
    init_sql: e2e/fixtures/init.sql
    baseline_json: e2e/fixtures/expected_detections.json
    binary_fixtures:
      - e2e/fixtures/sample.mp4
      - e2e/fixtures/model.tar.gz
  runner:
    dockerfile: e2e/runner/Dockerfile
    package_json: e2e/runner/package.json
    spec_dir: e2e/runner/tests
  pipeline: .woodpecker/suite-e2e.yml
  scenario:
    description: "Upload video → detect → overlays → dataset → DB persistence"
    components_exercised:
      - ui
      - annotations
      - detections
      - postgres-local
    api_contracts:
      - component: ui
        path: /api/admin/auth/login
      - component: annotations
        path: /api/annotations/media/batch
      - component: annotations
        path: /api/annotations/media/{id}/annotations
    db_tables:
      - media
      - annotations
      - detection
      - detection_classes
    model_pin:
      detections_repo_path: <path-to-model-config-or-classes-source>
      classes_source: annotations/src/Database/DatabaseMigrator.cs

If suite_e2e: is missing the skill stops — it does not invent a default mapping.

Mitigations (M1M7)

  • M1 Separation: this skill only touches suite-e2e files; no production deploy compose, no per-component CI, no docs, no component internals.
  • M3 Factual vs. interpretive: port, env var, API path, DB column — FACTUAL, read from the components' code. Whether a baseline still matches the model — DEFERRED to the user (the skill flags drift, never silently re-records).
  • M4 Batch questions at checkpoints.
  • M5 Skip over guess: a component change that doesn't map cleanly to one of the in-scope artifacts → skip and report.
  • M6 Assumptions footer + append to _repo-config.yaml assumptions_log.
  • M7 Drift detection: verify every path under suite_e2e.* exists on disk; stop if not.

Workflow

Phase 1: Drift check (M7)

Verify every file listed under suite_e2e.* (excluding binary_fixtures, which are gitignored) exists on disk. Missing file → stop and ask:

  • Run monorepo-discover to refresh, OR
  • Skip the missing artifact (recorded in report)

For binary_fixtures paths that are absent (expected — they live in S3/LFS), check whether expected_detections.json._meta.video_sha256 is still a TBD-... placeholder. If yes, surface this as a known leftover (_docs/_process_leftovers/2026-04-22_suite-e2e-binary-fixtures.md) and continue.

Phase 2: Determine scope

Same as monorepo-cicd Phase 2 — ask the user, or auto-detect. For auto-detect, flag commits that touch suite-e2e-relevant concerns:

Commit pattern Suite-e2e impact
New port exposed by <component> Healthcheck override may change in e2e/docker-compose.suite-e2e.yml
New required env var on <component> e2e/docker-compose.suite-e2e.yml e2e-runner env block + init.sql seed
Public API path renamed / removed Spec selector / API call path in e2e/runner/tests/*.spec.ts
DB schema column renamed in a db_tables entry init.sql column reference + spec pg.query text
New required DB table referenced by spec init.sql insert block (skip if owned by component migration)
Detection model rev change in detections/ expected_detections.json _meta.model.revision + flag baseline as stale
New canonical detection class added expected_detections.json._meta annotation

Present the flagged list; confirm.

Phase 3: Classify changes per component

Change type Target suite-e2e files
Port / env var change e2e/docker-compose.suite-e2e.yml
API path / contract change e2e/runner/tests/*.spec.ts
DB schema reference change e2e/fixtures/init.sql and spec SQL queries
Model / class catalog change e2e/fixtures/expected_detections.json (mark _meta.fixture_version bump + leftover entry for binary refresh)
Playwright dependency drift e2e/runner/package.json + e2e/runner/Dockerfile
Suite scenario steps gone stale Stop and ask — scenario edits are user-driven, not drift-driven

Phase 4: Apply edits

Edit each in-scope file. After each batch, run ReadLints on touched files. Do NOT run the suite e2e itself — that's a downstream pipeline operation, not a sync-skill responsibility.

For expected_detections.json: when the model revision changes, the skill does not re-record the baseline — the binary fixture cannot be regenerated from the dev environment. Instead:

  1. Set _meta.model.revision to the new revision.
  2. Set _meta.fixture_version to a new bumped version with a -stale suffix (e.g., 0.2.0-stale).
  3. Append a new entry to _docs/_process_leftovers/ describing the required re-record.
  4. Leave expected.by_class untouched — the spec's tolerance check will fail loudly until the binary refresh lands.

Phase 5: Update assumptions log

Append a new assumptions_log: entry to _docs/_repo-config.yaml recording:

  • Date, components in scope, which suite-e2e files were touched
  • Any inferred contract mappings still tagged confirmed: false
  • Any leftover entries created

Phase 6: Report

Render a Choose-format summary of the synced files, surface any _process_leftovers/ entries created, and end. Do NOT auto-commit.

Self-verification

  • No file outside e2e/, .woodpecker/suite-e2e.yml, or _docs/_process_leftovers/ was edited
  • _docs/_repo-config.yaml suite_e2e: block was not silently mutated except for assumptions_log append
  • expected_detections.json was not re-recorded (only metadata bumped + leftover added)
  • Every spec edit traces to a flagged commit pattern in Phase 2
  • ReadLints clean on every touched file

Failure handling

Same retry / escalation protocol as monorepo-cicd — see protocols.md. The most common failure mode is the binary-fixture leftover (sample.mp4 missing or SHA-mismatched); this skill does not attempt to resolve it, only surfaces it.