Orchestrata Ultimate › Plans › spec-audit › B-session-gov-di
Cluster B — Session, governance, verification & DI (spec audit)
Source: plans/spec-audit/B-session-gov-di.md at 8a2cb42ad · last changed 2026-07-27 · first committed 2026-07-04 · 318 lines.
Prose pending.
Plan text
Cluster B — Session, governance, verification & DI (spec audit)
Investigation agent B. Read-only audit of src/orchestrata_ultimate/ against 6 specs, evidence-based
per _METHOD.md. AST toolkit (symbols/refs) + targeted reads. No source/test files modified.
Cross-references the prior docs/spec-gap-register.md (which audited SPEC-023 and SPEC-010; SPEC-006,
007a, 007b, 024, 060 were not in that pass — fresh here).
SPEC-006 Session Management — PARTIAL
- Specifies: Dual-storage (Redis hot / Neo4j cold) session lifecycle + fact emission + portfolio +
recovery + carryover + handover (FR-001–012), plus local
context.json/context.mdfile sync, automated archive, integrity verification, git-based recovery, and a session CLI (FR-013–017). - Verified:
- FR-013–017 (local context sync / archive / integrity / git-recovery / CLI): ✅ LIVE.
sessionconsole script →session/cli/witharchive(--verify→verify_history_integrity,--recover→recover_from_git,--stats),status,list.SessionController(session/controller/_core.py:160) +SessionArchiver(session/archive.py:36) + aContextDatamodel with atomic writes.pyproject.toml:78session = "...session.cli:main". This is the operational, wired path. - FR-001/002 open/close: ✅ present — but in three parallel impls (see orphan note): file-based
SessionController.begin/end(_core.py:239,311);session/session.py;kernel/session_manager.py:217SessionManager.create_session/close_session/archive_session/query_session_history;ISessionManagerprotocol (session/interfaces.py:30) withopen_session/close_session. - FR-004/005 fact emission + storage: ✅
FactEmitter(session/fact_emitter.py:84) over Redis+Neo4j+Prolog stores (emit/emit_typed/batch_emit/get_facts/query_facts/flush_to_prolog);SessionSync(session/sync.py:20) flush/sync/link. ⚠️FactEmitterhas 1 production use (session/mcp_tools.py:49) — exposed as an MCP tool, not wired into the main gateway/pipeline. - FR-006 Prolog integration: ✅
PrologSessionInterface(session/prolog_interface.py:55) assert/retract/query session facts. - FR-007/008 portfolio: ✅
session/portfolio.py(PortfolioDatamodels) +KGPortfolioManager(knowledge_graph/portfolio.py:35) stats/dashboard/cross-project query. - FR-011 recovery: ✅
RecoveryManager(session/recovery.py:25) checkpoint/recover/rollback/can_recover. - FR-003 active-session/heartbeat/auto-close-stale: ⚠️ partial —
SessionController._auto_close_unclosed(_core.py:535) for the file path;kernel/session_manager.pydelete_expired_sessions/TTL for the Redis path. No single unified "one active session per portfolio + heartbeat" enforcement. - ⚠️ Orphan/duplication:
kernel/session_manager.py SessionManagerhas 0 refs (0 import, 0 use, 0 instantiations) — a fully orphaned third session subsystem. The Redis/Neo4j dual-storage half (FactEmitter/stores) is reachable only via MCP tools, not the runtime pipeline.
- FR-013–017 (local context sync / archive / integrity / git-recovery / CLI): ✅ LIVE.
- Remaining work / plan:
- Scope: Decide the canonical session subsystem. The file-based
context.jsonSessionControlleris the live one (FR-013–017). Either (a) delete the orphanedkernel/session_manager.py SessionManagerand wire thesession/Redis/Neo4jFactEmitterpath into the pipeline for FR-004/005 durability, or (b) formally scope the dual-storage half as MCP-only and update the spec. FR-003 unified active-session tracking is the only genuine capability gap. - Target files:
src/orchestrata_ultimate/kernel/session_manager.py(delete/consolidate),src/orchestrata_ultimate/session/fact_emitter.py+session/sync.py(wiring),src/orchestrata_ultimate/gateway/handlers/ororchestrator/pipeline_runner.py(wire fact flow). - Approach: This is a consolidation + wiring decision, not new capability — most FRs are implemented.
Pick one lifecycle owner, route
session.opened/closedfacts through it, retire the duplicates. - Dependencies: SPEC-007 (Prolog session facts), SPEC-008 (Neo4j), SPEC-023 (goal lives in the same
context.jsonowned bySessionController), SPEC-010 (memorymigrate_to_coldwantssession.closed). - Effort: M. Risk: med (three subsystems; consolidation touches wide surface).
- Scope: Decide the canonical session subsystem. The file-based
- Evidence log:
symbols --pattern SessionController/SessionManager/FactEmitter/PortfolioManager/Recovery→ located all lifecycle classes acrosssession/,kernel/,knowledge_graph/.refs SessionManager→0 def-external, 0 import, 0 use(kernel impl orphaned).refs FactEmitter→ 1 use (session/mcp_tools.py:49);refs RedisSessionStore→ 5 uses (in-package).session/cli/archive.py:41,48→verify_history_integrity()/recover_from_git()wired (FR-015/016).
SPEC-007 (007a) Prolog Governance / PAM++ — PARTIAL (mostly DONE + DIVERGENCE)
- Specifies: Constitutional policy enforcement via Prolog — 11 articles, 10 core predicates, ethical boundaries, dynamic policy management, violation tracking, safe mode, monitoring. Spec "How" names pyswip.
- Verified:
- Policy engine: ✅
PolicyEngine(governance/policy_engine.py:107,IPolicyEngine) — wired intogateway/server.py:264(refs PolicyEngine→ IMP/USE in gateway). Constructor injects prolog_client, cache, constitutional, ethical, monitoring, audit, safe_mode, violations. - Runtime gate: ✅
PrologGate(governance/prolog_gate.py:15) — wired intokernel/pipeline.py:96(refs PrologGate→ USE).load_rulesconsultsgovernance.pl, constitutional.pl, agents.pl, ethics.pl, pam_rules.pl, completion.plviaPrologEngine(the janus adapter), consulting variable-bearing rules and asserting only ground facts at runtime — exactly the memory-noted architecture. - 11 articles: ✅
ConstitutionalEnforcer(governance/constitutional.py:154) with anARTICLESlist (Article + ArticlePriority phases). - Ethical: ✅
EthicalBoundary(governance/ethical.py:79). Dynamic policy: ✅DynamicPolicyManager(governance/dynamic_policy.py:97) add/remove/reload/rollback (reload re-asserts ground facts viabridge.assert_fact). Safe mode: ✅SafeModeManager(safe_mode.py:70). Violations: ✅ViolationTracker(violations.py:60). Monitoring: ✅GovernanceMonitoring(monitoring.py:118). Cache: ✅GovernanceCache(cache.py:61). Audit: ✅GovernanceAudit(audit.py:66). - ⚠️ DIVERGENCE (spec out of date): the spec's 10 predicate signatures (
may_execute/3,constitutional_check/3,has_permission/3,may_access/4,ethical_check/2, …) do not match the code.governance.pl:692definesmay_execute/2(Agent,Action); ownership is the volk model inpam_rules.pl(pam_owns/2,can_delegate/3,has_permission/3over resources). Constitutional/ ethical/safe-mode/metrics are implemented in Python (not pure Prolog predicates). Backend is janus, not pyswip (spec Metadata/Dependencies say pyswip). Intentional — proven byprolog_gate.pycomments and the janus migration memory. Action = update the spec, not the code. - ⚠️ US-008 metrics → Prometheus export: ❌
GovernanceMonitoringhas no prometheus (Redis counters only). Shared gap with SPEC-060 FR-004 (below).
- Policy engine: ✅
- Remaining work / plan:
- Scope: Update SPEC-007a to describe the actual architecture (janus adapter;
may_execute/2+ volk ownership; Python-side constitutional/ethical/safe-mode). Optionally add Prometheus export toGovernanceMonitoring(couples to SPEC-060 FR-004). - Target files:
specs/007-prolog-governance/spec.md(doc);governance/monitoring.py(if metrics added). - Dependencies: SPEC-060 (extends this), SPEC-006 (session facts feed governance), SPEC-014 gateway.
- Effort: S (spec update). Risk: low.
- Scope: Update SPEC-007a to describe the actual architecture (janus adapter;
- Evidence log:
symbols PolicyEngine/PrologGate/ConstitutionalEnforcer/EthicalBoundary/ DynamicPolicyManager/SafeModeManager/ViolationTracker/GovernanceMonitoring/GovernanceCache/GovernanceAuditall resolve.refs PolicyEngine→gateway/server.py:264;refs PrologGate→kernel/pipeline.py:96.governance.pl:692may_execute(Agent, Action). Nojanus/pyswipimport ingovernance/— it goes throughcore.prolog_adapter/PrologEngine.grep prometheus governance/→ none.
SPEC-007 (007b) Verification Agent (U:Vfy) — ORPHANED
- Specifies: Prolog-guided constraint verification; multi-tier Execution → Supervisor → U:Vfy agents; 5 checkpoint milestones; 5-attempt immutable retry limit before human escalation; CXP message protocol; Prolog as final arbiter (SATISFIED / NOT_MET).
- Verified: The whole subsystem is built but not wired (0 refs):
ExecutionAgent(verification/agents/execution_agent.py:18),SupervisorAgent(supervisor_agent.py:15),VerificationAgent(verification_agent.py:33) — each 0 refs.VerificationCoordinator(verification/orchestration/coordinator.py:28) — 0 refs (0 import, 0 use).- CXP protocol: ✅
VerificationCXPAdapter(verification/protocols/verification_cxp.py:30) — full message set (constraint / request / result / escalation / feedback / proof) — but unreferenced. - Supporting layers all present: constraints (
constraints/evaluator.py), checkpoints (checkpoints/verifier.py),escalation_handler.py,requirements/prolog_generator.py,requirements_parser.py,VerificationSession(session/verification_session.py), model adapters (models/deepseek_r1|opus|qwen_max|grok4_minimax). - The only production consumers of the
verificationpackage areagents/volks/junior/volk.pyimportingverification/review/(code-review helpers/checks) — a different capability (the /review engine), not the U:Vfy constraint-verification flow. Nothing inorchestrator/,kernel/,gateway/invokes the agents/coordinator/CXP adapter. - ⚠️ DIVERGENCE:
max_attemptsdefaults to 3 everywhere (config/verification_config.py:28,escalation_handler.py:32,orchestration/coordinator.py:32,session/verification_session.py:67,types.py:263) vs the spec's immutable 5. (Mirrors the SPEC-029MAX_SELF_REVIEW_CYCLES=3note.)
- Remaining work / plan:
- Scope: Decide the fate of the U:Vfy multi-tier flow. Either (a) wire it — instantiate
VerificationCoordinator, route its CXP messages through the orchestrator/CXP bus, and trigger it at the pipeline's verify checkpoint; alignmax_attempts(5 or record 3 as the intentional cap); or (b) retire the orphaned agents/coordinator/CXP adapter, keeping onlyverification/review/(the live code-review path used by U:Jr). - Target files:
orchestrator/pipeline_runner.py(invocation),verification/orchestration/coordinator.py,verification/protocols/verification_cxp.py(CXP bus hookup), or deletion of the agents/orchestration subtree. - Approach: This is a design call — is U:Vfy a live agent or aspirational? The code-review sub-package is already the de-facto verification. Wiring is a full-subsystem integration; deletion is a cleanup.
- Dependencies: SPEC-004 (CXP), SPEC-005 (multi-agent orchestrator), SPEC-007a (Prolog arbiter), SPEC-003 (intent → constraints).
- Effort: L (wire) or S (retire). Risk: med (whole subsystem; behavior change if wired).
- Scope: Decide the fate of the U:Vfy multi-tier flow. Either (a) wire it — instantiate
- Evidence log:
refs VerificationAgent/ExecutionAgent/SupervisorAgent→ each0 use.refs VerificationCoordinator→1 def, 0 import, 0 use.grep -rE 'VerificationCoordinator|ExecutionAgent' outside verification/→ none.grep max_attempts verification/→ all= 3.
SPEC-023 Goal-Driven Session System — PARTIAL (confirms + refines register)
- Specifies: BDI goal system persisted in
context.json— persistence, session-start injection, continuous progress evaluation (executeverify_command/ matchverify_pattern), Stop-hook goal guard, audio alarm,/goallifecycle commands, reflective re-planning (3-strike), state machine. - Verified (in
src/):- FR-001/010/014 data model: ✅
Goal/GoalCriterion/GoalTask/GoalProgress(session/models.py:343–410) withverify_command/verify_pattern/retry_counts;ProjectState.goal(models.py:157). /goalcommands (FR-007): ⚠️ PARTIAL — wired CLIgoalgroup (session/cli/goals.py, on thesessionconsole script):set/status/criterion/task/progress/abandon/achieve. Missingblock/unblockon the CLI. The CLI manipulatesctx_data.state.goaldirectly via_get_manager(root)— it does not call theSessionControllergoal methods.- ⚠️ Duplication:
GoalMixin(session/controller/_goals.py:14) implementsset_goal/get_goal/get_goal_status/update_goal_status/log_goal_progress/check_goal_before_stop/ add_blocker/clear_blocker— orphaned:refs set_goal→0 use,refs check_goal_before_stop→0 use,refs get_goal_status→0 use. Sosrc/carries two goal CRUD paths (orphaned Mixin + wired CLI), and a third lives out-of-srcin the operationalclaude/tools/session_cli.py(cmd_set_goal/cmd_get_goal/cmd_achieve_goal/cmd_abandon_goal). - FR-002 session-start goal injection: ❌
session/hooks/session_auto_start_hook.pyhas no goal reference (grep: 0 hits). - FR-005 Stop-hook goal guard: ❌ no Stop /
goal_check_hook.pyundersrc/session/hooks/;check_goal_before_stopexists but orphaned. - FR-003/004 continuous evaluation +
verify_commandexecution: ❌goal_evaluate()does not exist anywhere (symbols goal_evaluate→ 0).verify_command/verify_patternare never executed (dead fields). Also absent from the liveclaude/tools/session_cli.py(noevaluate). - FR-006/013 audio alarm + backend detection: ❌ zero audio code (
symbols Alarm→ 0; grepffplay|paplay→ 0). - FR-008/012 reflective re-planning + 3-strike: ❌
retry_countsfield unused; no re-planning logic.
- FR-001/010/014 data model: ✅
- Remaining work / plan:
- Scope: (1) Pick the canonical goal owner — consolidate the orphaned
GoalMixin, the wired CLI group, and the out-of-srcclaude/tools/session_cli.pyinto one (recommend:SessionController+GoalMixin, have the CLI call it). (2) Implementgoal_evaluate()(runverify_command, matchverify_pattern, transition criteria, log progress) with a safe-command whitelist per the spec's security section. (3) Add goal injection tosession_auto_start_hook.py(FR-002) and a Stop-hook wired tocheck_goal_before_stop(FR-005). (4) Add CLIblock/unblock. (5)AudioAlarmutility (ffplay→paplay→aplay→mpv→bell) (FR-006/013). (6) Retry/3-strike re-planning (FR-008). - Target files:
session/controller/_goals.py,session/cli/goals.py,session/hooks/session_auto_start_hook.py, a newsession/hooks/goal_check_hook.py, a newsession/audio_alarm.py. - Dependencies: SPEC-006 (goal lives in
context.jsonowned bySessionController; injection/stop hooks are session hooks) — consolidation of goal impls is coupled to the SPEC-006 session consolidation. CI-result parsing for evaluation. SPEC-007 (governance article alignment). - Effort: L. Risk: med (which controller is canonical is a design decision — do not blind-wire).
- Scope: (1) Pick the canonical goal owner — consolidate the orphaned
- Evidence log:
refs set_goal/check_goal_before_stop/get_goal_status→ 0 use each.symbols goal_evaluate/symbols Alarm→ 0.grep goal session_auto_start_hook.py→ 0.session/models.py:352-353,410verify_command/verify_pattern/retry_counts.cli/goals.pyreads/writesctx_data.state.goaldirectly (noSessionControllercall).
SPEC-024 Dependency Injection Container — DONE (library) / ORPHANED (adoption)
- Specifies: Interface-based registration, async
resolvewith constructor injection, scopes (SINGLETON/TRANSIENT/REQUEST), circular-dependency detection, factory + instance registration, container builder, named-container registry, introspection. - Verified: The container is fully implemented against every FR/API contract in SPEC-024
(
di/container.py):DIContainer(:98):register(:145, scope/config/factory/dependencies),register_instance(:254), asyncresolve(:288) with_resolve_with_context/_resolve_dependencies/_resolve_param(constructor injection viainspect), cycle detection (ResolutionContext.resolution_stack), scope caching (_cached_instance/_store_instance),has/get_registry_info/get_all_registrations/set_context/get_context/shutdown. ✅ContainerBuilder(:686):with_config/with_component/with_instance/with_context/build/with_components. ✅ContainerRegistry(:859):register/get/has/get_with_parent/shutdown_all. ✅ComponentRegistration/ResolutionContextdataclasses present.- SPEC-024's own "Success Criteria" checklist (all
[x]) is genuinely satisfied. - ⚠️ ORPHANED adoption: the container assembles nothing at runtime.
refs DIContainer→ consumers are onlydi/__init__.py(re-export) andagents/di.py.agents/di.py register_agentsregisters 4 agent instances (VolkRuntime/VolkPool/TaskExecutor/VolkCoordinator) — butrefs register_agents→ 0 use (never called).grep 'DIContainer(|ContainerRegistry|ContainerBuilder(| register_agents'in production (outsidedi/+agents/di.py) → none. So the register's note is confirmed and stronger: the container resolves no component (not just "no memory engine") — the whole system is wired by direct constructors.
- Remaining work / plan: For SPEC-024 itself: none — the container meets its spec. The real work
is a system-wide DI-adoption initiative (out of SPEC-024's scope but the reason the container exists):
call
register_agentsfrom the kernel bootstrap, registerIMemoryEngine(SPEC-010 FR-001), governance, session, providers — i.e. convert direct constructors toresolve().- Target files: kernel bootstrap /
orchestratorstartup;agents/di.pycaller;gateway/handlers/memory.pyorchestrator/pipeline_runner.py(memory), etc.
- Dependencies: SPEC-010 (memory DI FR-001), SPEC-005 (agents), SPEC-011 (providers). This is a cross-cutting refactor decision, not a container fix.
- Effort: S for SPEC-024 (nothing). Adoption is L and belongs to a separate DI initiative.
- Class rationale: DONE vs its own spec; flagged ORPHANED because the capability has no live consumer.
- Target files: kernel bootstrap /
- Evidence log:
symbols di/container.py→ full API present.refs DIContainer→ only di + agents/di.py.refs register_agents→0 use.grep 'DIContainer(|ContainerRegistry|register_agents'prod → empty.
SPEC-060 Enhanced PAM++ Governance (Runtime Integration) — PARTIAL / GAP
- Specifies: Runtime integration for PAM++ — FastAPI
GovernanceMiddlewareenforcement returning 451, Redis decision cache (<5ms), hot reload + rollback + WebSocket policy push, Prometheus/metrics, and graceful degradation modes (allow_all / deny_all / cache_only). - Verified:
- Policy eval core: ✅
PolicyEngine+GovernanceCache(Redis decision cache, FR-002) +DynamicPolicyManager(add/remove/reload/rollback,dynamic_policy.py:129–332). FR-003 hot reload + rollback ✅ (in-memory rule set re-asserted as Prolog ground facts viabridge.assert_fact). - FR-001 middleware enforcement (FastAPI, 451): ❌ no
GovernanceMiddlewareclass exists (symbols Middleware|govern→ none). The gateway is WebSocket-based:GovernanceHandler(gateway/handlers/governance.py:19) withhandle_evaluate/handle_query/handle_decisionsover WS. No 451 HTTP status, no FastAPI middleware. DIVERGENCE (WS gateway, not a FastAPI HTTP app) plus a real enforcement-surface gap. - FR-004 Prometheus metrics
/metrics: ❌GovernanceMonitoringhas no prometheus (Redis violation counters only). GAP (shared with SPEC-014 FR-021 — gateway has no HTTP/metrics). - FR-005 graceful degradation (allow_all/deny_all/cache_only): ❌ no
degradation_modeimplementation; only adefault_denyreason string ingovernance/resource_access.py:309. GAP. - WebSocket policy push (part of FR-003): ⚠️ WS infra exists (
GovernanceHandler+ pubsub) but nopolicy_updatepush on reload is wired. - Cross-check with SPEC-010 memory governance (register FR-013): memory ops still lack PAM++ predicates
(
can_store_memory/can_read_memoryabsent) — SPEC-060 runtime enforcement never reaches the memory engine. Confirmed still open.
- Policy eval core: ✅
- Remaining work / plan:
- Scope: (1) Add an enforcement surface — either a real HTTP/FastAPI
GovernanceMiddlewarewith 451, or formally re-spec FR-001 onto the WSGovernanceHandler(DIVERGENCE decision). (2) Implement degradation modes (allow_all/deny_all/cache_only) with a health probe (FR-005). (3) Add Prometheus export toGovernanceMonitoring+ a/metricsendpoint (FR-004; needs the SPEC-014 HTTP surface). (4) Wire apolicy_updateWS push onDynamicPolicyManager.reload(FR-003). - Target files:
gateway/(HTTP surface or WS re-spec),governance/monitoring.py(prometheus),governance/policy_engine.pyor a new degradation manager,governance/dynamic_policy.py(WS push). - Approach: Much of SPEC-060 presupposes a FastAPI HTTP app the project deliberately doesn't run (WS gateway). Split into a spec-update (FR-001 → WS) + the genuinely-missing runtime features (degradation, metrics).
- Dependencies: SPEC-014 (gateway HTTP surface for middleware +
/metrics), SPEC-010 (memory PAM++ predicates), SPEC-007a (extends it). - Effort: M–L. Risk: med (spans gateway + governance + memory; FR-001 needs a design call).
- Scope: (1) Add an enforcement surface — either a real HTTP/FastAPI
- Evidence log:
symbols Middleware|govern→ none.gateway/handlers/governance.py:19GovernanceHandler(WS).grep degradation_mode|allow_all|deny_all|cache_only governance/→ onlydefault_deny(resource_access.py:309).grep prometheus governance/→ none.dynamic_policy.py:217reloadre-asserts ground facts (no WS push).grep 451|Governance Required→ none.
Cluster summary table
| Spec | Class | Effort | Hard deps |
|---|---|---|---|
| SPEC-006 Session Management | PARTIAL (live file-half DONE; dual-storage under-wired; 3rd impl orphaned) | M | SPEC-007, 008, 023, 010 |
| SPEC-007a Prolog Governance / PAM++ | PARTIAL → mostly DONE + DIVERGENCE (janus not pyswip; predicate sigs stale) | S (spec update) | SPEC-060, 006, 014 |
| SPEC-007b Verification (U:Vfy) | ORPHANED (full subsystem, 0 production refs; max_attempts=3 not 5) | L (wire) / S (retire) | SPEC-004, 005, 007a, 003 |
| SPEC-023 Goal System | PARTIAL (model+CRUD DONE; evaluation/alarm/hooks/replanning MISSING; dup impls) | L | SPEC-006, CI parsing, 007 |
| SPEC-024 Dependency Injection | DONE (library) / ORPHANED (resolves nothing at runtime) | S (spec) / L (adoption) | SPEC-010, 005, 011 |
| SPEC-060 Enhanced PAM++ Runtime | PARTIAL/GAP (core+cache+reload present; middleware/451/metrics/degradation absent) | M–L | SPEC-014, 010, 007a |
Real remaining work (this cluster)
- SPEC-023 — biggest genuine feature gap:
goal_evaluate(),AudioAlarm, session-start injection, Stop-hook guard, re-planning; plus consolidating three goal impls. - SPEC-060 — degradation modes, Prometheus
/metrics, and an enforcement surface (needs SPEC-014 HTTP). - SPEC-007b — a design decision: wire the orphaned U:Vfy subsystem or retire it (+ align max_attempts).
- SPEC-006 — consolidation/wiring of the dual-storage half + delete the orphaned kernel SessionManager.
- SPEC-007a / SPEC-024 — mostly spec-update / adoption-decision, not code holes.
Cross-cluster dependencies noticed
- goal-system (023) ↔ session (006): the goal lives in the same
context.jsonowned bySessionController; injection/stop guards are session hooks. Consolidating the 3 goal impls is coupled to consolidating the 3 session impls — do these together. - DI (024) ↔ memory (010): the container is ready and idle; SPEC-010 FR-001 (resolve
IMemoryEngine) is the flagship use case. DI adoption ≙ SPEC-010 memory-DI work. - PAM++ (060 / 007a) ↔ memory (010) + compliance (026): memory ops lack PAM++ predicates
(
can_store_memory/can_read_memory, SPEC-010 FR-013); SPEC-060 runtime enforcement never reaches the memory engine. Compliance/audit paths shareGovernanceAudit. - PAM++ (060) ↔ gateway (014): FR-001 middleware + FR-004
/metricsneed an HTTP surface the WS gateway lacks (SPEC-014 FR-021 gap) — same missing surface. - verification (007b) ↔ orchestrator/CXP (004/005): wiring U:Vfy requires CXP-bus + orchestrator integration at the pipeline verify checkpoint.
- governance (007a) ↔ session (006):
PrologSessionInterfacefeeds session facts into the same janus-backed governance engine.