Phase 2 — Runtime Engine Scope

Phase 1 (built) renders the 16-model schema as an AI-Safe CRUD register: investigations, regulator requests decomposed into requirements, evidence with privilege review, response drafts, submissions and production items — browsable, with a dashboard. But the states are static: the seed shows a request already received, a submission already issued. Nothing is computed or transitioned by the system.

Phase 2 is the runtime that makes it live — computing the effective deadlines, enforcing the state machines, running the deadline scans and applying the privilege and submission rules the pack specifies. Same shape as the (built, cluster-proven) orchestrator engine, but single-app.

Everything below is drawn from the pack's workflows.yaml, rules.yaml, the DSL computed/event blocks and the InvestigationDashboard. It is a scope, not a design.


A. Computed-field engine

The DSL computed fields are seeded statically today; Phase 2 recomputes them:

Field Rule
RegulatoryRequest.effective_due_at coalesce(extended_due_at, due_at)
RegulatoryRequest.days_remaining business-days between now and effective_due_at
RegulatoryRequest.is_overdue effective_due_at < now() AND status ∉ {submitted, acknowledged, closed}
Requirement.is_overdue due_at < now() AND status ∉ {submitted, waived, closed}

The effective due date (extension overrides base) is the key subtlety — every deadline calculation must use it.

Decisions: compute-on-read vs recompute-on-tick.

B. State machines & guarded actions

The pack defines three workflows. Today a user free-edits status; Phase 2 exposes each transition as a guarded action.

Workflow Notable transitions & guards
investigation (draft→active→stayed→closed→archived) open_investigation requires lead_legal_counsel + regulator_id; close guarded by all requests closed
regulatory_request (received→triaged→assigned→collecting→drafting→legal_review→awaiting_approval→submitted→acknowledged→closed) *→overdue on deadline missed (exception transition)
requirement (open→in_progress→evidence_complete→response_drafted→reviewed→approved→submitted→closed) drives the response lifecycle

Decisions: UI buttons vs API; role → PIN/RBAC; the request pipeline is long — which steps are explicit actions vs derived.

C. Deadline engine (scheduled scans)

A background tick that watches the effective deadlines — "notices never lapse":

  • Tiered warnings at 20 / 10 / 5 / 2 / 1 days before effective_due_at (rules.yaml → deadlines.warn_days).
  • Overdue — past effective_due_at and not submitted → flip request/requirement to overdue and escalate after 4 hours.
  • Submission receipt follow-up — chase an issued submission with no receipt after 24 hours (submissions.receipt_followup_hours).

Decisions: cadence; business-calendar (AU_QLD) business-day math (pack ships business_calendars.yaml); exception dedupe.

D. Rules / cross-record automation

From rules.yaml (this app's rules are heavily privilege- and evidence-centric):

  • Privilege — require legal review when evidence is potentially_privileged/privileged; prohibit production when privileged or withheld; require a reason when withheld.
  • Confidentialityhighly_confidential export requires approval; external share requires legal approval; regulator_only restricts internal distribution.
  • Evidence integritysha256 required for documents/email-exports/data; a produced item is immutable; custodian required.
  • Submission gateissue requires approved_by + approved_at + at least one requirement; generate a production manifest on issue.
  • Exception raising — auto-raise on overdue request/requirement, missing owner, missing privilege review, failed submission.
  • DSL eventsrequest.received (triage-required), requirement.overdue (→ governance.exception.raise), submission.issued (→ receipt-awaiting).

Decisions: event bus (in-app vs orchestrator); enforce prohibitions hard vs flag; manifest format.

E. Executive dashboard & KPIs

The DSL InvestigationDashboard metrics, wired via the repo KPI framework (kpi_engine.py + kpis.py): active investigations; overdue requests; open requirements; potentially-privileged evidence; open exceptions.


How it would be built

  1. A per-app engine module (mirror server/lib/orchestrator_engine/): compute pass (A), deadline scanner (C), guarded actions (B), rules/privilege evaluator (D). Opt-in env flag, single worker.
  2. KPIs (E) via the existing framework — quick, independent win.
  3. Business-calendar underpins the effective-due-date math.
  4. Tests per workstream (test_orchestrator_flows.py is the template).

Suggested sequencing

  1. KPIs / dashboard (E) — visible, no engine.
  2. Computed fields (A) — accurate effective_due_at / is_overdue.
  3. Deadline engine (C) — tiered warnings + overdue escalation.
  4. Privilege & submission rules (D) — the compliance guardrails (this domain's highest-value automation).
  5. State machines + guards (B) — governed transitions across the long pipeline.

Each slice is independently shippable and demoable. The orchestrator (built and run live this session) is the working template for the engine, scheduler and tests.