Skip to content

Backlog

Stable BL-NNN ids. Ids are never renumbered and resolved items are never deleted (status moves to resolved). Each item cites its source ADR. Sizes: XS, S, M, L.

ID Item Size Status Source ADR
BL-001 Add full Apache-2.0 LICENSE text and NOTICE XS resolved 0001
BL-002 Write ADR-0002..0010 and complete pyproject.toml + Makefile S resolved 0002
BL-003 Complete STPA artifacts 01..07 (losses, hazards, constraints, control structure, UCAs, loss scenarios, security constraints) M resolved 0009
BL-004 Execution core: patterns/policy/redaction/audit/contract/runner (vendored + fused), with invariant tests L resolved 0004, 0005
BL-005 StoreProtocol + ladder; SQLite default backend (bitemporal, append-only trigger, active-fact constraint, sqlite-vec) L resolved 0002, 0003
BL-006 Postgres+AGE+pgvector production backend behind the same Protocol M resolved 0002, 0003
BL-007 Fact model + host_type; osquery and AIDE collectors (read-only) M resolved 0007
BL-008 Drift engine: desired-state sources (tofu plan, ansible check, known-good) + findings L resolved 0007
BL-009 Actuation adapters (ssh/opentofu/ansible/runbook/talosctl/redfish/cloud) with DRY_RUN -> approve -> execute L resolved 0004, 0005
BL-010 Skills engine: manifest, registry, routing-chain dispatcher; eval gate + schema guard M resolved 0010
BL-011 Tamper-evident audit + evidence: supervisor writer, Merkle, RFC 3161, optional Rekor M resolved 0008
BL-012 MCP server surface: config, transport guards (stdio/http, SSRF egress, consent), tools with annotations L resolved 0006, 0041
BL-013 CI workflows (codeql, sbom, dependency-review, fuzz; pinned SHAs; least-privilege) + ci-success aggregate M resolved 0001
BL-014 Hardened deploy: Helm chart, systemd units, optional zarf M resolved 0006
BL-015 Compliance map: complete EU AI Act / NIS2 / CRA / GDPR / ISO 27001 mapping to controls S resolved 0009
BL-016 Migration note: import prototype host-knowledge and known-good baselines into the model S resolved 0007
BL-017 Audit read and ingest tools through the single path (query_facts, fact_history, ingest_observation, drift_scan currently bypass run()) S resolved 0011, 0016
BL-018 Write an audit record for trifecta denials before raising TrifectaViolation (context + actuate) S resolved 0011, 0013
BL-019 Include the tool name in the classify/deny probe; document that any future stdin/env passthrough must be classified S resolved 0011, 0016
BL-020 SSH adapter host-key policy (StrictHostKeyChecking accept-new/yes, BatchMode=yes, UserKnownHostsFile) S resolved 0011, 0013
BL-021 run_subprocess process-group isolation (start_new_session=True plus killpg on timeout) S resolved 0011, 0013
BL-022 Keep Talos snapshot hash verification on etcd-restore (never pass --recover-skip-hash-check; optional sidecar verify) S resolved 0011, 0016
BL-023 Pre-flight talosctl health HARD precondition before talosctl upgrade S resolved 0011, 0016
BL-024 Runbook actuation by registry id (preferred) or a canonicalised, base-dir-contained path M resolved 0011, 0016
BL-025 Safe-default destructive scope for talosctl reset (no implicit --wipe-mode ALL; ALL is T3-confirmed) S resolved 0011, 0016
BL-026 Finite-or-default numeric parsing of collected host data at every collector site S resolved 0011, 0016
BL-027 Additive store extension Protocols plus content-hash compare-and-set for supersede M resolved 0011, 0021
BL-028 Postgres backend engine-level append-only (REVOKE plus BEFORE TRUNCATE trigger; optional RESTRICTIVE RLS floor) M resolved 0011, 0018
BL-029 Serialise audit hash-chain appends for concurrent writers (process lock now; pg_advisory_xact_lock for the PG path) S resolved 0011, 0016
BL-030 Stamp raw_snapshot_hash of each collected snapshot into the Merkle checkpoint M resolved 0011, 0019
BL-031 Machine-checkable compliance map (bidirectional code/control/article validator plus framework coverage) in CI M resolved 0011, 0021
BL-032 helm-unittest chart assertions for the praxis chart, gated in CI M resolved 0011, 0027
BL-033 Supply-chain parity: real zarf digest, CycloneDX SBOM, values/sbom/zarf CI parity, governance-as-code labels M resolved 0011, 0032, 0035
BL-034 Multi-severity parse_ansible_check (FAILED to ERROR, unreachable to CRITICAL, ok to known-good) S resolved 0011, 0013
BL-035 Documented audit/evidence retention tiers bound in config (NIS2 Art. 23, ISO 27001 A.8.15) S resolved 0011, 0023
BL-036 Governance hygiene bundle (module back-citation headers, agent hard-rules, values-prod overlay plus version-bump checklist, namespace default-deny NetworkPolicy, regulatory-deadline data, empty-string-not-loopback test) M resolved 0011, 0034
BL-037 verify_evidence fail-closed (return, never raise) and require checkpoints to cover the full log; document LocalStamper forgeability M resolved 0012
BL-038 Postgres append-only trigger: guard all identity columns, split per-table (facts vs edges), correct the parity docstring M resolved 0012
BL-039 Store triggers: block any t_invalid/t_superseded/superseded_actor mutation that leaves a row active (supersede-without-actor bypass) S resolved 0012
BL-040 Patterns: fix the chmod/chown -R / deny and the /etc/ write tier (\b-before-/ defect); bump PATTERNS_VERSION S resolved 0012
BL-041 Redaction: cover space-separated credential flags and URL/DSN credentials; redact the stdio server error path S resolved 0012
BL-042 SSRF: normalise decimal/hex/octal/trailing-dot IP forms; assert_egress_allowed fail-closed on a non-IP host S resolved 0012
BL-043 OpenTofu DRY_RUN uses a full tofu plan so the preview scope matches the apply scope XS resolved 0012
BL-044 _bounded_error never raises, so run() always writes exactly one audit record XS resolved 0012
BL-045 Docs honesty: ADR-0006 consent audit note; qualify SECURITY.md/LIMITATIONS.md; fix STPA _ssrf.py path and read-tool audit claim S resolved 0012
BL-046 SSRF: resolve hostnames and check every resolved IP (rebinding-aware); wire the filter into the egress path M resolved 0012, 0025, 0030
BL-047 talosctl: enforce the T3 single-target rule on host.nodes, not only host.name S resolved 0012, 0013
BL-048 talosctl: replace action.split() with a verb allowlist; pass structured params S resolved 0012, 0013
BL-049 Wire CredentialBroker into the actuation path (scoped, revocable enforcement) M resolved 0012, 0016
BL-050 Audit hash chain: anchored high-water-mark to detect tail truncation M resolved 0012, 0019
BL-051 Helm NetworkPolicy: restrict ingress with a from: selector S resolved 0012, 0018
BL-052 CI: make CodeQL/fuzz/sbom/dependency-review required gates, not branch-protection-external S resolved 0012, 0036
BL-053 Add coverage tooling and a cov-fail-under gate S resolved 0012, 0018
BL-054 Store: _cosine finite-input guard; seq uniqueness or identity column to remove the MAX(seq)+1 race S resolved 0012, 0013
BL-055 Audit logger: do not reopen the file after _degrade; close the sink on degraded close S resolved 0012, 0013
BL-056 stdio server: bound the per-line read; correct JSON-RPC notification and batch handling S resolved 0012, 0016
BL-057 Manifest parser: exact --- fence, size cap, reject indented keys, reject duplicate keys S resolved 0012, 0013
BL-058 Collectors: AIDE empty output is not clean; per-collector size caps; finite numeric parse (with BL-026) S resolved 0012, 0013
BL-059 Drift: escalate UNEXPECTED security-predicate findings; split multi-host Ansible subjects S resolved 0012, 0013
BL-060 Deploy and config: Helm health probes, systemd drop-in dedupe, pin cyclonedx-bom, strip whitespace HTTP_HOST, normalise compliance-map path citations M resolved 0012, 0026
BL-061 Test and fuzz wave: Postgres parity suite, evidence tamper matrix, host_type refusal per adapter, SSRF bypass tests, fuzz manifest/merkle/evidence M resolved 0012, 0020
BL-062 Route read tools (query_facts, fact_history, collector/skill reads) through the audited path, or formally document the deliberate exclusion; reconcile with invariant 1 wording S resolved 0012, 0016
BL-063 Actuation subprocess hardening: scrub env (GIT_TERMINAL_PROMPT=0, DEBIAN_FRONTEND=noninteractive, neutralise *_ASKPASS) and detach stdin (DEVNULL) so a wrapped tool cannot read the MCP stdio stream or hang on a prompt S resolved 0013
BL-064 Audit log opened O_APPEND and owner-only (0o600, plus chmod of a pre-existing file) so redacted parameters are not world/group readable XS resolved 0013
BL-065 Redaction: add provider token shapes (github_pat_, glpat-, npm_, AIza, ya29., Stripe, OpenAI scoped) and make Authorization value-complete (no SigV4 signature leak) S resolved 0013
BL-066 Self-containment: remove the out-of-tree prototype reference from context.py (no sibling repo named in code or docs) XS resolved 0013
BL-067 Config: strip whitespace from PRAXIS_HTTP_HOST so a "127.0.0.1\n" value is recognised as loopback; empty defaults to loopback (residual of BL-060) XS resolved 0013
BL-068 Store: add a seq identity/uniqueness so the MAX(seq)+1 read cannot race across two store instances on one file (residual of BL-054) S resolved 0013, 0016
BL-069 Clarify the self-contained rule (no coupling to sibling fleet repos, not anti-PyPI); record ADR-0014 and an appended audit note on ADR-0001; correct the over-absolute "implements everything itself" wording across the docs S resolved 0014
BL-070 Adopt pydantic at the external-input boundary (MCP tool arguments, config, SKILL.md frontmatter) as the single source of truth for the JSON Schema and the parse/validate step; keep the execution core dependency-free M resolved 0014
BL-071 SBOM CI repair: correct the cyclonedx-py environment output flag (--outfile to --output-file; the job had failed on every push to main since it was added), pin cyclonedx-bom==7.3.0 so a future unpinned major bump cannot change the CLI surface, and align the SBOM runner to Python 3.12 (the requires-python floor and the ci.yml matrix), so the supply-chain job is reproducible and off a bleeding-edge interpreter (closes the cyclonedx-bom pin in BL-060; residual of BL-033) S resolved 0014
BL-072 Approval gate human-binding: replace the deterministic expected_token (and its echo in the DRY_RUN body) with a server-issued, single-use, TTL-bound nonce surfaced out-of-band, so an autonomous caller cannot self-approve T2/T3 L resolved 0015, 0016
BL-073 Floor free-form shell/runbook/exec actuation at T2 (SSHAdapter.base_tier T1 to T2); keep the denylist upgrade-only; add the missing destructive patterns (find -delete, iptables -F, nft flush ruleset, kubectl drain/cordon, mass DELETE/UPDATE, Windows Remove-Item -Recurse/Format-Volume/Stop-Computer) and bump PATTERNS_VERSION M resolved 0015, 0016
BL-074 Wire BudgetTracker into ExecutionContext/run() so a per-session action, cost, and wall-time ceiling is enforced on the audited path M resolved 0015, 0016
BL-075 Give the kill switch an operator actuator (an MCP kill/restore tool plus a signal or file sentinel) and a durable trip record, so SEC-8 emergency stop is engageable at runtime, not only via the unwired broker S resolved 0015, 0016
BL-076 Wire runtime audit anchoring: invoke periodic make_checkpoint from the server (or a supervised sidecar), implement a non-forgeable stamper (real RFC 3161 or a transparency-log anchor), and make operating-system append-only (chattr +a/WORM) a required, documented deploy control until then L resolved 0015, 0019
BL-077 Bound redact_args recursion depth and size inside the audited path and move it under the runner's failure containment, so a deeply nested args payload audits-and-denies instead of raising out of run() unaudited S resolved 0015, 0016
BL-078 execution/audit.py::_canonical: add default=str (as action_id already does) so AuditLogger.record can never raise on a non-JSON-native arg value (logger-never-raises by construction) XS resolved 0015, 0016
BL-079 Open the SQLite store file (and WAL/SHM sidecars) 0o600 so restricted facts are not group/world readable (mirror BL-064 for the audit log) XS resolved 0015, 0016
BL-080 Scope the actuation subprocess environment to an allowlist (PATH, LANG, SSH_AUTH_SOCK, TALOSCONFIG, the prompt-suppression knobs) instead of copying the full server environment, so unrelated secrets do not reach wrapped tools and their plugins S resolved 0015, 0016
BL-081 Ansible adapter input validation: apply the _SAFE_TARGET host check to host.name before --limit, and confine the playbook action to a configured base directory (extends BL-024 from runbook to ansible) S resolved 0015, 0016
BL-082 talosctl: reject post-verb tokens beginning with - (take structured resource args), and validate each nodes/endpoints value as an IP or RFC 1123 host, closing the --talosconfig flag-injection residual of BL-047/BL-048 S resolved 0015, 0016
BL-083 Move trifecta containment into the single audited path keyed off request.untrusted/context (not only the run_action handler); arm the latch on any read of attacker-influenced facts, not just live collection; remove or wire the dead ExecutionRequest.untrusted field M resolved 0015, 0016
BL-084 Validate and consume the approval before guard_actuation for all tiers, so the trifecta audit cannot record a T2+ call as gated on token presence while the executor later denies it on token validity S resolved 0015, 0016
BL-085 Route ingest_observation through run() (or document the deliberate exclusion) and add its UCA row, so the one untrusted-driven state-writing tool is audited and STPA-covered (sharpens BL-017/BL-062) S resolved 0015, 0016
BL-086 Helm: move storeDsn to a secretKeyRef (existingSecret), mirroring the http-token pattern, and block an inline plaintext DSN in the Deployment env S resolved 0015, 0018
BL-087 Deploy hardening: systemd PrivateUsers/ProcSubset=pid/RemoveIPC added and base-unit/drop-in de-duplicated, Helm DNS egress scoped to kube-system, egressCIDRs carry an always-on 169.254.0.0/16 except (ADR-0020). RESIDUAL (open): IPAddressDeny/SocketBindDeny and a sandbox runtimeClassName are documented but operator-scoped (a deny-all default bricks SSH actuation), so they are not preset M resolved 0015, 0020, 0034
BL-088 Supply-chain: pin the fuzz interpreter to a stable Python, bound ruff/mypy/pytest/psycopg[binary]/hatchling versions, add a hash-locked dev requirements file for CI installs, and scope the SBOM to the production dependency graph S resolved 0015, 0018
BL-089 STPA traceability: add SEC "Prevents" coverage for UCA-4..7, UCA-10, UCA-12/13, UCA-23; mark act_cloud/act_redfish rows planned; add a set_mode escalation test S resolved 0015, 0022
BL-090 Annotate the aspirational compliance-map rows (NIS2 Art. 21 broker BL-049; CRA Annex I NetworkPolicy ingress BL-051 and digest-pin BL-033) with their tracking item; append audit notes to ADR-0004/0005/0008 per ADR-0015 Decision 6 S resolved 0015, 0016
BL-091 Postgres seq race residual: the SQLite backend computes seq inside the INSERT under facts_seq_unique/edges_seq_unique (BL-068), but store/postgres.py still reads _next_seq as a separate SELECT MAX(seq)+1 with no unique index on seq, so the MAX(seq)+1 race BL-054 claimed closed is unmitigated on the Postgres path (reachable once replicaCount>1). Add CREATE UNIQUE INDEX IF NOT EXISTS {facts,edges}_seq_unique to _SCHEMA and a parity test in the Postgres suite. Schema change: proposal, not executed in the audit pass; implemented and live-verified in the 0018 wave. S resolved 0017, 0018
BL-092 Supply-chain reviewability: no Dockerfile/Containerfile exists, yet deploy/helm/praxis/values.yaml and deploy/zarf.yaml reference a digest-pinned ghcr.io/rmednitzer/praxis image, so the deployed container cannot be built or inspected from the repo (at odds with the ADR-0001 digest-pin posture; adjacent BL-033). Add a minimal non-root, pinned-base (distroless) Dockerfile that runs python -m praxis, or document the external build. S resolved 0017, 0032
BL-093 Deploy doc clarity: the Helm chart defaults transport: http, but the server refuses any non-stdio transport with NotImplementedError (server.py), so helm install with defaults yields CrashLoopBackOff until HTTP serving lands (BL-012). deploy/README.md already names stdio as the working path; add a values.yaml comment and a chart NOTES.txt warning so the staged-not-runnable state is visible at install time. XS resolved 0017, 0018
BL-094 Audit integrity: AuditLogger.record hashed the live args rendering while _write rendered the asdict() deep copy, and str() of a copy is not stable (a deepcopied set may iterate differently), so a record with non-JSON-native args could fail its own entry_hash and an honest log verified as tampered (invariant 3; found by the BL-053 coverage gate re-running the suite under fresh hash seeds, deterministic at PYTHONHASHSEED=24). Fixed by normalizing the payload through one canonical JSON round-trip before hashing, so the hash and the written line derive from one rendering; regression test uses a deterministic copy-sensitive str() probe. S resolved 0018
BL-095 Non-forgeable checkpoint stamper (residual of BL-076, split per the BL-054/BL-068 precedent): implement a real RFC 3161 TSP client (ASN.1 TimeStampReq/Resp behind an optional extra and the SSRF egress filter) or a transparency-log anchor (Rekor), replacing the keyless LocalStamper whose token anyone who can write the evidence file can forge; until then OS append-only storage on the audit, evidence, and anchor files is the documented required control (SECURITY.md, ADR-0019) M resolved 0019, 0029, 0030
BL-096 SSRF: block the deprecated 6to4 relay anycast 192.88.99.0/24 (RFC 7526) with a deterministic network constant rather than interpreter registry data, which varies across patch versions; add an IPv4-in-IPv6 (v4-mapped/NAT64/6to4) and userinfo/bracketed-host bypass test sweep (BL-061) XS resolved 0020
BL-097 Redaction hardening: add the PyPI upload-token shape, run the npm and GitLab token bodies unbounded from their length floor so a longer token collapses whole (no audit-log tail), and add a context-gated compact MySQL -p<password> redaction that fires only when a MySQL-family client is present (no -p-as-port over-scrub). Strengthens SEC-9; no PATTERNS_VERSION change S resolved 0021
BL-098 Talos partition-scoped reset: an additive system_labels param mapping to talosctl reset --system-labels-to-wipe (allowlisted EPHEMERAL/STATE, normalised), preserving STATE so a node rejoins; mutually exclusive with --wipe-mode (both refused); the documented system-disk default (BL-025) is unchanged; the partition reset keeps T3 via the existing reset classifier match S resolved 0021
BL-099 CIS-Talos desired-state baseline as drift data: transcribe the CIS Kubernetes benchmark + Talos-defaults mapping into KNOWN_GOOD facts for the drift engine, with a false-positive suppression set. Needs a fact-predicate schema decision first (kubelet/API-server/sysctl predicates); open a dedicated ADR before implementing L resolved 0021, 0024, 0028
BL-100 Multi-sink audit fan-out with per-sink failure containment: when a second audit sink is wired (the Postgres audit path, a syslog target) introduce a MultiSink that contains a per-sink Exception so one failing sink cannot silence the others, with BaseException still propagating (the BL fan-out containment class applied to the audit write side). Latent until a second sink exists M resolved 0021, 0037
BL-101 Audit request_id/client_id correlation: thread the MCP request and client identifiers (optional, additive to the audit record) so concurrent calls can be correlated to audit entries without timestamp matching. Lower value for the stdio-default single-operator server; revisit when the HTTP transport (BL-012) serves multiple clients S resolved 0021, 0038
BL-102 Client-side-only talosctl pre-flight health probe: evaluate passing --server=false to the talosctl health gate (_health_ok) so a post-bootstrap cluster's server-side checks cannot spuriously block an upgrade. A behavioural change to a HARD safety precondition (SEC-5, BL-023); raised for an operator decision rather than changed unilaterally XS resolved 0021, 0031
BL-103 Live-PostgreSQL verification of the compare-and-set create-if-absent translation (BL-027): the Postgres put_fact_if translates a partial-unique-index IntegrityError on the create path to VersionConflict (the create-if-absent case cannot be FOR UPDATE-locked), matching the SQLite BEGIN IMMEDIATE serialization and the CAS contract. The translation is verified by reasoning against the psycopg API; add a concurrent-create-if-absent test gated on PRAXIS_TEST_PG_DSN (two writers, expected_version=None, exactly one wins with VersionConflict) and confirm against a live database S resolved 0021
BL-104 Per-session execution-context isolation for the multi-client HTTP transport: the server builds one ExecutionContext per process, so the SessionTaint latch and the ApprovalRegistry are process-global and ApprovalRegistry.validate-then-consume is not atomic. Correct and safe on the stdio transport (single process, single-threaded loop, one operator; the global latch fails safe by over-tainting). Becomes load-bearing only when HTTP serving (BL-012) multiplexes concurrent clients onto one context: give each client session its own taint (and context where appropriate) and make the single-use nonce check-and-burn atomic, so one client cannot observe another's taint or race an approval. #71 (BL-101) adds per-request correlation but not isolation. Latent until multi-client HTTP serving lands. M resolved 0039, 0041
BL-105 OpenTofu workspace selection via a confined chdir: re-add -chdir support to the OpenTofu adapter behind a PRAXIS_TOFU_ROOT confinement (parallel to playbook_root/runbook_root, confine_to_root), fail-closed when chdir is supplied without a configured root, and expose it as a RunActionArgs field. The unconfined passthrough was removed in the 2026-06-14 audit (F-003); this re-adds the capability safely when a workspace-selection feature is needed S resolved 0040
BL-106 Timing-safe approval-token comparison: switch ApprovalRegistry token lookup to secrets.compare_digest before any network-accessible submission path exists. Latent today (the approval nonce is a server-minted, single-use, TTL-bound value surfaced out-of-band, and HTTP serving is not wired), but constant-time comparison is the correct default and is a prerequisite of the HTTP transport (BL-012); complements BL-104 (atomic check-and-burn). Found in the 2026-06-14 audit S resolved 0040, 0041
BL-107 Total-message-byte cap for a multi-client transport: the stdio _drain_line is bounded per chunk but iterates unboundedly over a single hostile oversized line (a single-client stall only, acceptable for stdio). Add a total-message-byte cap before the HTTP transport (BL-012) serves untrusted clients. Found in the 2026-06-14 audit S resolved 0040, 0041
BL-108 Per-pair and per-value caps in CommandProbeCollector.parse: the 4 MiB tool-output ceiling bounds the raw string but not the number of key-value pairs or individual value lengths a hostile probe can produce. Add a _MAX_PAIRS and per-value cap (silent truncation, consistent with the never-raises collector contract). Defense-in-depth for untrusted collected data (invariant 8). Found in the 2026-06-14 audit S resolved 0040
BL-109 Make the compliance catalog proving-test lists exhaustive: docs/governance/compliance-controls.json cites the minimum one proving test per control (validator rule R9), but the STPA 07 tables name more per SEC constraint. Either expand the proving_tests arrays to the full set or add a header note that the catalog lists representative tests. Found in the 2026-06-14 audit XS resolved 0040
BL-110 Concurrent HTTP serving: the v1 HTTP transport (ADR-0041) is a single-threaded HTTPServer (one request at a time) so the single-connection SQLite store is never touched cross-thread; per-session isolation is already full. Make the store thread-safe (SQLite check_same_thread=False + a serialization lock or per-thread connections; PostgresStore likewise) and switch to ThreadingHTTPServer so requests execute in parallel (e.g. actuating several hosts at once) without weakening the bitemporal/append-only invariants. M resolved 0041, 0042
BL-111 First-class kubectl/helm actuation under the ADR-0043 scoped-static-kubeconfig contract: add HostType.KUBERNETES; KubectlAdapter/HelmAdapter wrapping the on-PATH tools (verb allowlist, no free-form options per BL-082, native --dry-run=server/helm --dry-run); pin --kubeconfig/--context from trusted inventory with confine_to_root paths; refuse exec-stanza kubeconfigs fail-closed; tier reads T0, mutators T2 (kubectl mutators already T2 in patterns.py), helm uninstall/kubectl delete namespace|pvc|crd T3; SEC-5 host_type gate; broker grant per cluster-host; pre-stage act_kubectl/act_helm UCAs in STPA 05 and map to SEC-5/6/8 in STPA 07. Otherwise Kubernetes/Helm stays a bastion-host skill (cloud/exec auth). No new Python dependency. L open 0043
BL-112 Treat non-zero wrapped actuation subprocess exits as audited execution errors without copying stdout/stderr bodies into exception text, so failed tools cannot be recorded as successful actuation and output-body logging remains barred. S resolved 0040
BL-113 Re-confirm the EU AI Act high-risk application dates and their in-force status against the Official Journal once the Digital Omnibus on AI is formally adopted and published. The 2026-06-23 distillation pass (ADR-0044) recorded the provisionally-agreed deferral (Annex III 2026-08-02 -> 2027-12-02; Annex I 2027-08-02 -> 2028-08-02) in docs/governance/regulatory-deadlines.md, flagged provisional pending the OJ; when the OJ publishes, replace the provisional annotations with the published dates and close this item. Documentation only; no code change. XS open 0044