Skip to content

Record whether CORA reached the enclosure permit substrate - #643

Merged
xmap merged 1 commit into
mainfrom
feat-enclosure-permit-probe-trail
Aug 10, 2026
Merged

Record whether CORA reached the enclosure permit substrate#643
xmap merged 1 commit into
mainfrom
feat-enclosure-permit-probe-trail

Conversation

@xmap

@xmap xmap commented Aug 10, 2026

Copy link
Copy Markdown
Owner

Summary

  • Item 3 of the 2-BM coverage-window commissioning ladder: the permit-status projection advances only on a change, so a stale value has meant "no transition since" and "not observed since" the same way. A silent monitoring gap reads as "nothing happened."
  • Adds a permit probe trail: entries_enclosure_permit_probes, one append-only row per observation, separate from the EnclosurePermitObserved record of what the interlock said. reach_tier (RELAYED/UNREACHED) records whether CORA reached the configured channel; status_claimed distinguishes a real status-bearing observation from a probe-only re-affirmation.
  • A new periodic poll (off by default, enclosure_permit_probe_tick_seconds=None) writes probe-only rows so a quiet, unchanging PV doesn't read as a coverage gap, without ever driving a permit transition on its own.
  • A stronger "confirmed direct round trip" tier is deliberately not shipped: no producer can currently prove one (2-BM reads through a caching EPICS CA gateway), and an unearned strong claim is worse than none.
  • The probe write can never suppress the real permit transition (wrapped in its own try/except), and no probe row is written at all while a process boots in degraded schema mode, since the event store is read-only there and a dense trail would misrepresent a window CORA could not actually record.
  • Adds tests/architecture/test_entries_table_grants.py, closing the same missing-GRANT class of bug already latent on five older entries_* tables (tracked as a separate follow-up, not fixed here — those need their own production migration).

Went through three review rounds before landing: an initial design lock, a re-cut after adversarial + baseline + migration-safety review found 9 blockers (including a route that would have let a stale poll read flip a live permit status, and a startup-race regression against a fix that shipped the same day), and a final pass against the built code that caught a test-double gap silently turning a cancellation test into an infinite loop.

Test plan

  • uv run pyright clean
  • uv run ruff check / ruff format --check clean
  • uv run tach check clean (caught and fixed a real module-boundary violation)
  • Full architecture fitness suite: 30401 passed, 621 skipped
  • Full unit tier: 12482 passed, 1 skipped
  • Verified stable under pytest -n 4 (the earlier hang only reproduced under the full-suite run)
  • atlas migrate validate (real CLI) exit 0
  • Postgres-backed integration tests in test_enclosure_permit_monitor.py not run locally (no Docker in the dev sandbox); will run in CI

🤖 Generated with Claude Code

The permit-status projection advances only on a change, so a stale
value has meant "no transition since" and "not observed since" the
same way: a silent gap in coverage reads as nothing happened. This
adds a permit probe trail, entries_enclosure_permit_probes, one
append-only row per observation the monitor's EnclosureObserver
surfaces, separate from the EnclosurePermitObserved record of what the
interlock said. reach_tier (RELAYED/UNREACHED) records whether CORA
reached the configured channel this tick; a status-bearing push or
disconnect still drives the permit transition as before, while a new
periodic poll writes probe-only rows (no status claim, never a
transition) so a quiet, unchanging PV doesn't read as a coverage gap.

A stronger tier for a confirmed direct round trip is deliberately not
shipped: no producer here can prove one yet (2-BM reads through a
caching gateway), and an unearned strong claim is worse than none. The
probe write can never suppress the real permit transition, and no row
is written at all while a process boots in degraded schema mode, since
the event store is read-only there and a dense trail would misrepresent
a window CORA could not actually record.

Went through three review rounds (design, re-cut, and a pass against
the built code) that caught a startup-race regression, a route that
could have let a stale poll read flip a live permit status, and a test
double gap that silently turned a cancellation test into an infinite
loop. Also adds a fitness test closing the same missing-GRANT class of
bug already latent on five older entries_ tables (tracked separately;
not fixed here).

Item 3 of the 2-BM coverage-window commissioning ladder. The polling
cadence defaults off (enclosure_permit_probe_tick_seconds=None) pending
staff confirmation, since it would read the PSS gateway on a timer.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@xmap
xmap force-pushed the feat-enclosure-permit-probe-trail branch from 6cfaa21 to 8df3903 Compare August 10, 2026 16:36
@github-actions

Copy link
Copy Markdown

Coverage report

Click to see where and how coverage changed

FileStatementsMissingCoverageCoverage
(new stmts)
Lines missing
  apps/api/src/cora/api
  _enclosure_permit_observer.py 204-205
  main.py
  apps/api/src/cora/enclosure
  _monitor.py 201
  wire.py
  apps/api/src/cora/enclosure/aggregates/enclosure
  __init__.py
  permit_probes.py 93
  apps/api/src/cora/enclosure/ports
  enclosure_observer.py
  apps/api/src/cora/infrastructure
  config.py
  schema_version.py
Project Total  

This report was generated by python-coverage-comment-action

@xmap
xmap merged commit 25bea1f into main Aug 10, 2026
19 checks passed
@xmap
xmap deleted the feat-enclosure-permit-probe-trail branch August 10, 2026 16:57
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