Orchestrata Ultimate › Plans › spec-audit › reverify-2026-10-18 › B-session-gov-di
Cluster B — Session, Governance, DI (re-verification, 2026-10-18)
Source: plans/spec-audit/reverify-2026-10-18/B-session-gov-di.md at 8a2cb42ad · last changed 2026-10-18 · first committed 2026-10-18 · 320 lines.
Prose pending.
Plan text
Cluster B — Session, Governance, DI (re-verification, 2026-10-18)
Read-only re-audit of src/orchestrata_ultimate/ against 5 specs (006, 007, 023, 024, 060),
on branch components (337 commits ahead of the 2026-07-14 audits). Evidence-only: AST toolkit
(symbols/refs/source), no source/test/spec modified, no tests run, no infra started.
Builds on: docs/spec-gap-register.md (2026-07-14), plans/spec-audit/B-session-gov-di.md
(session 195), plans/spec-023-goal-consolidation-plan.md, plans/spec-audit/00-MASTER-PLAN.md
§2/§6 (S9 Helmsman / S10 Sentinel). Main-session pre-verified findings are trusted, not re-run:
SPEC-023 FR-006/013 audio alarm = 0 src hits (OPEN), goal_evaluate = 0 defs (OPEN), GoalRegistry
wired into agents/volks/pm/volk.py (landed), session CLI goals exist at session/cli/goals.py.
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.md sync, automated
archive, integrity verification, git-based recovery, and a session CLI (FR-013–017).
Verified (fresh, current code):
- FR-013–017 (file sync / archive / integrity / git-recovery / CLI): ✅ LIVE.
SessionControlleris the file-based controller atsession/controller/_core.py:123(nowclass SessionController (GoalMixin, GitOpsMixin, ChangelogMixin, TestStateMixin)).SessionArchiver(session/archive.py:36) is wired into the CLI atsession/cli/archive.py:55. Thearchivecommand carries--verify→mgr.verify_history_integrity(),--recover→mgr.recover_from_git(),--stats(session/cli/archive.py:18-49).verify_history_integritylives atsession/context.py:629;recover_from_git(max_commits=200)atsession/context.py:762.session/cli/main.py:164-174registersarchive,status,list,task,achievement,goal,sync,query,artifact,begin,choice. - FR-001/002 open/close: ✅ file-based
SessionController.begin(_core.py:179) /end(_core.py:236) with_auto_close_unclosedand git commit+tag+push on close. - FR-004/005 fact emission/storage: ✅
FactEmitter(session/fact_emitter.py:59) over Redis+Neo4j+Prolog. ⚠️ 1 production use only —session/mcp_tools.py:34(MCP tool), not the runtime pipeline.refs FactEmitter→ 1 src use, rest tests. - FR-006 Prolog integration: ✅
session/prolog_interface.pypresent in src (FR-006 session facts). - FR-007/008 portfolio: ✅
KGPortfolioManager(knowledge_graph/portfolio.py:31) +session/portfolio.py. - FR-010/011/012 carryover/recovery/handover: ✅
session/carryover.py,RecoveryManager(session/recovery.py:25),session/handover.pyall present. - ⚠️ Orphan third subsystem (unchanged):
kernel/session_manager.py:198 SessionManagerstill has 0 production refs —refs SessionManager --module orchestrata_ultimate.kernel.session_manager→ 1 def, 3 imports + 7 uses, all intests/(test_session_manager_extended, test_kernel_session, test_coverage_session_manager). Not instantiated by anysrc/module. - ⚠️ FR-003 unified active-session/heartbeat/auto-close-stale: still split between the file path
(
_auto_close_unclosed) and the orphaned Redis path (delete_expired_sessions); no single "one active session per portfolio + heartbeat" enforcement. - ⚠️
EventEmittingSessionController(session/event_emitting_session_controller.py:30) still unwired in production (only re-exported viasession/__init__.py:14) →session.closedevent is emitted by a class nothing instantiates (cross-cluster SPEC-010migrate_to_coldstill unfed).
Remaining work / plan:
- Scope: consolidation decision (unchanged from session 195): the file-based
SessionControlleris the live owner (FR-013–017). Either (a) delete the orphanedkernel/session_manager.pyand wire thesession/Redis/Neo4jFactEmitterpath into the runtime 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:
kernel/session_manager.py(delete/consolidate),session/fact_emitter.py+session/sync.py(wiring),event_emitting_session_controller.py(wire into a persistent engine — couples to K3 / SPEC-010). - Approach: consolidation + wiring, not new capability.
- Dependencies: SPEC-007 (Prolog session facts), SPEC-008 (Neo4j), SPEC-023 (goal lives in the
same
context.jsonowned bySessionController), SPEC-010 (migrate_to_coldwantssession.closed). - Effort: M. Risk: medium (three subsystems; consolidation touches wide surface).
Evidence log:
symbols --pattern SessionController→session/controller/_core.py:123(GoalMixin-composed) +claude/tools/session/session.py:25(dev CLI).refs SessionManager --module orchestrata_ultimate.kernel.session_manager→ 1 def, 0 src use.refs FactEmitter→ 1 src use (session/mcp_tools.py:34).source session.cli.archive→--verify/--recover/--statswired (:18-49).symbols --pattern verify_history_integrity→session/context.py:629;recover_from_git→context.py:762.refs EventEmittingSessionController→ onlysession/__init__.pyre-export, no production instantiation.
SPEC-007 (007a) Prolog Governance / PAM++ — DIVERGENCE (mostly DONE)
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 (fresh, current code):
- Policy engine: ✅
PolicyEngine(governance/policy_engine.py:47) — wired intogateway/server.py:555(import) /:571(use); also wrapped bygovernance/event_emitting_policy_engine.py:14. - Runtime gate: ✅
PrologGate(governance/prolog_gate.py:41) — now wired in three places:kernel/pipeline.py:147,kernel/pipeline_escalation.py:71,orchestrator/pipeline_runner.py:256(refs PrologGate→ 3 src use).load_rulesconsultsgovernance.pl, constitutional.pl, agents.pl, ethics.pl, pam_rules.pl, completion.pl(prolog_gate.py:65-72). - 11 articles: ✅
ConstitutionalEnforcer(governance/constitutional.py:129). Ethical: ✅EthicalBoundary(governance/ethical.py:34). Safe mode: ✅SafeModeManager(governance/safe_mode.py:43). Violations / Monitoring / Cache / Audit classes all present ingovernance/. Dynamic policy: ✅DynamicPolicyManager(governance/dynamic_policy.py:42) withadd_rule/remove_rule/reload(:129)/rollback(:227)/validate_before_activate(:178). - ⚠️ DIVERGENCE (spec out of date — unchanged): backend is janus-swi, not pyswip
(
prolog_gate.py:43docstring "janus-swi viacore.prolog_adapter";prolog_gate.py:57-59comment). Predicate arity ismay_execute/2(prolog_gate.py:88may_execute(self, agent, action), querymay_execute(Agent, Action):118, rule_source"may_execute/2":126), not the spec'smay_execute/3. Constitutional/ethical/safe-mode/metrics are Python-side. Action = update the spec, not the code. - ⚠️ US-008 metrics → Prometheus export: ❌
GovernanceMonitoring(governance/monitoring.py:43) is Redis-only (record_query/record_violation/get_latency_percentiles/get_cache_hit_rate); no Prometheus. Shared gap with SPEC-060 FR-004.
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.
Evidence log:
refs PolicyEngine --module orchestrata_ultimate.governance.policy_engine→gateway/server.py:555/571.refs PrologGate→kernel/pipeline.py:147,pipeline_escalation.py:71,pipeline_runner.py:256.symbols --pattern ConstitutionalEnforcer|EthicalBoundary|SafeModeManager→ all resolve ingovernance/.source governance.prolog_gate→:43janus-swi,:88/:118/:126may_execute/2.source governance.monitoring→ Redis metrics only, no prometheus import.
SPEC-023 Goal-Driven Session System — PARTIAL
Specifies: BDI goal system persisted in context.json — persistence, session-start injection,
continuous progress evaluation (verify_command/verify_pattern), Stop-hook goal guard, audio alarm,
/goal lifecycle commands, reflective re-planning (3-strike), state machine.
Verified (fresh, current code):
- FR-001/010/014 data model: ✅
GoalCriterion/GoalTask/GoalProgress/Goal(session/models.py:355-410).verify_command/verify_patternstill onGoalCriterion(:364-365);retry_countsstill onGoal(:410); newcurrent_step(:411-415) for plan-window task rendering. - Goal lifecycle consolidation (material change since 2026-07-14):
GoalMixin(session/controller/_goals.py:18) is now composed into the liveSessionController—_core.py:17imports it,_core.py:123SessionController(GoalMixin, ...). Methods present:set_goal,get_goal,get_goal_status,update_goal_status(achieved/blocked/abandoned),log_goal_progress,check_goal_before_stop,add_blocker,clear_blocker,load_goal_tasks_from_plan(NEW),advance_goal_step(NEW),set_goal_step(NEW).refs GoalMixin→ 1 use (_core.py:123). - FR-007
/goalCLI (session/cli/goals.py, registered atsession/cli/main.py:169): ✅set/status/criterion/task/progress/abandon/achieve/advance/step. ⚠️ Missingblockandunblockcommands (add_blocker/clear_blockerexist in GoalMixin but are not exposed on the CLI);abandontakes no[reason]arg (spec REQ-023-035 wants a reason). - GoalRegistry → volk context (main-session finding re-confirmed): ✅
GoalRegistry(agents/volks/pm/goal_registry.py:99, full lifecyclecreate/activate/update/complete/block/ defer/cancel/record_iteration) is wired intoPMVolk—agents/volks/pm/volk.py:11import,:199-202self._goal_registry = GoalRegistry(self._context_manager) if ... else None,:365-393_record_goal_progress→record_iteration+GoalReportGenerator.generate. ⚠️ This is the SPEC-012 portfolio-goal system; the SPEC-023 singularstate.goalis not injected into volk context (see below). - ❌ FR-002 session-start goal injection:
session/hooks/session_auto_start_hook.pyhas no goal reference (source ... | grep goal|Goal→ 0). - ❌ FR-005 session-end / Stop-hook goal guard:
check_goal_before_stop(_goals.py:180) exists but is not called fromend()(source session.controller._core→end()body:236-293has no goal check) and not registered as a Stop hook (nogoal_check_hook.py;session/hooks/holds onlysession_auto_start_hook.py,session_fact_hook.py,session_pre_close_hook.py— the pre-close hook validates checklist/git/tests, not goals).refs check_goal_before_stop→ 0 src use (18 uses all intests/). - ❌ FR-003/004 continuous evaluation +
verify_commandexecution:goal_evaluate→ 0 symbols (main-session finding re-confirmed).verify_command/verify_patternremain dead fields. - ❌ FR-006/013 audio alarm:
Alarm/AudioAlarm→ 0 symbols (main-session finding re-confirmed). - ❌ FR-008 reflective re-planning / 3-strike:
retry_countsunused; no re-planning logic. - ❌ FR-015 multi-session goal visibility:
get_goal_statusproduction refs =claude/tools/session_cli.py:428(dev CLI) only; no session-goal injection into the pipeline/volk context (the KGContextInjectoratknowledge_graph/context_injector.py:501injects graph context, not goal state).
Remaining work / plan:
- Scope: (1) implement
goal_evaluate()(runverify_command, matchverify_pattern, transition criteria, log progress) with a safe-command whitelist per the spec's security section. (2) Add the missingblock/unblockCLI commands (GoalMixin methods already exist). (3) Wirecheck_goal_before_stopintoSessionController.end()(or a Stop hook) — the session-end gate. (4) Add goal injection tosession_auto_start_hook.py(FR-002) and inject the SPEC-023state.goalinto volk context (closes the SPEC-009 goal-injection gap). (5)AudioAlarmutility (ffplay→paplay→aplay→mpv→bell) (FR-006/013). (6) Retry/3-strike re-planning (FR-008). - Target files:
session/controller/_goals.py(addgoal_evaluate),session/cli/goals.py(block/unblock),session/controller/_core.py(end-gate),session/hooks/session_auto_start_hook.py(injection), a newsession/audio_alarm.py. - Approach: the 3-goal-impl consolidation is now mostly done (GoalMixin is composed into
SessionController; the dev CLI and the PMGoalRegistryare separate concerns per the plan). Remaining work is the genuinely-missing feature half (evaluation/alarm/gate/injection). - Dependencies: SPEC-006 (goal lives in
context.jsonowned bySessionController; injection/stop guards are session hooks). CI-result parsing for evaluation. SPEC-007 (governance alignment). - Effort: L. Risk: medium (the
session endgate behavior — abort vs warn vs--force— is still an un-decided UX call perplans/spec-023-goal-consolidation-plan.md).
Evidence log:
refs GoalMixin→_core.py:123(USE).refs check_goal_before_stop→ 0 src use.symbols --pattern goal_evaluate→ 0;symbols --pattern Alarm/AudioAlarm→ 0.source session.controller._goals→ full goal lifecycle method set.source session.cli.goals→set/status/criterion/task/progress/abandon/achieve/advance/step(no block/unblock).refs GoalRegistry→agents/volks/pm/volk.py:11(IMP),:199(USE).source session.hooks.session_auto_start_hook→ no goal refs.
SPEC-024 Dependency Injection Container — DONE (library; D4-descoped scope matches code)
Specifies: Interface-based registration, async resolve with constructor injection, scopes
(SINGLETON/TRANSIENT/REQUEST), circular-dependency detection, factory + instance registration, container
builder, named-container registry, introspection. (Rewritten 2026-07-06: FR-008 hierarchy + batch
registration descoped; role reframed as plugin SDK + gateway assembly roots.)
Verified (fresh, current code):
DIContainer(di/container.py:65):register(:111),register_instance(:218), asyncresolve(:253),_resolve_with_context/_resolve_dependencies/_resolve_param(constructor injection viainspect),_cached_instance/_store_instance,set_context/get_context,shutdown(:586),get_registry_info/has/get_all_registrations. ✅ Full spec.ContainerBuilder(:685):with_config/with_component/with_instance/with_context/build. ✅ContainerRegistry(:838):register/get/has/shutdown_all. ✅- D4 descope confirmed:
get_with_parent→ 0 symbols (FR-008 removed);with_components→ 0 symbols (batch registration removed). - Adoption matches the rewritten spec exactly:
refs DIContainerproduction consumers aregateway/server.py:26(import) +:459/:479(use) — the gateway assembly root — and the capability-gatedPluginContext.resolve(plugin/context.py:113, checksdi_accesscapability:126, resolves:135). These are precisely the two composition roots D4 documents. - Prior audit's "orphaned
agents/di.py register_agents" is RESOLVED:refs register_agents→ 0 def, 0 import, 0 use — the orphaned registration module was deleted, not left dangling.
Remaining work / plan:
- Scope: none for SPEC-024 itself — the container meets its (descoped) spec and its two
documented consumers are wired. System-wide DI adoption (resolve
IMemoryEngine, retire direct constructors) is a separate cross-cutting initiative (K3 / SPEC-010), out of this spec's scope. - Target files: n/a (or
kernelbootstrap /orchestratorstartup for the separate adoption track). - Dependencies: SPEC-010 (memory DI FR-001), SPEC-005, SPEC-011. K3 persistent-engine decision is the blocking call.
- Effort: S (nothing for the spec). Adoption is L and belongs to K3/Mnemosyne. Risk: low.
Evidence log:
symbols --pattern DIContainer→ full API atdi/container.py:65.symbols --pattern get_with_parent/with_components→ 0 each.refs DIContainer --module orchestrata_ultimate.di.container→gateway/server.py:459/479(src use).source plugin.context→resolve(:113),di_accesscapability gate (:126),:135.refs register_agents --module orchestrata_ultimate.agents.di→ 0 def/import/use.
SPEC-060 Enhanced PAM++ Governance (Runtime Integration) — PARTIAL / GAP
Specifies: Runtime integration for PAM++ — FastAPI GovernanceMiddleware enforcement 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 (fresh, current code):
- FR-002 decision caching: ✅
GovernanceCache(Redis, ingovernance/cache.py). - FR-003 hot reload + rollback: ✅
DynamicPolicyManager.reload(governance/dynamic_policy.py:129) +rollback(:227) +validate_before_activate(:178) + version bump. ⚠️ WebSocket policy push: not wired —dynamic_policy.pyhas nopolicy_update/websocket push on reload. - FR-001 middleware enforcement (FastAPI + 451): ⚠️ DIVERGENCE (unchanged) —
GovernanceMiddleware→ 0 symbols. The enforcement surface is WebSocket:GovernanceHandler(gateway/handlers/governance.py:20,handle_evaluate/handle_query/handle_decisions/handle_rules/publish_decision_event) plus a newPolicyGate(gateway/handlers/_policy_gate.py:28,check(action, context), fail-closed, SPEC-014 REQ-014-080). No 451 HTTP status, no FastAPI middleware. - FR-004 Prometheus metrics: ❌
GovernanceMonitoring(governance/monitoring.py:43) is Redis-only. Gateway/metricsnow EXISTS (K1 landed —gateway/http_surface.py:125serves Prometheus default-registry exposition, alongside/health/ready), but governance decision metrics are not pushed to it. - FR-005 graceful degradation (allow_all/deny_all/cache_only): ❌ absent — no
degradation_modeimplementation;source governance.policy_engine | grep degradation|deny_all|allow_all|cache_only→ 0 hits. - REQ-060-033 policy management API (
/api/v1/governance/policies,/reload,/decisions,/metrics): ❌ absent fromgateway/http_surface.py(only/health/ready/metricsmounted).
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+PolicyGate(DIVERGENCE decision). (2) Implement degradation modes (allow_all/deny_all/cache_only) with a health probe (FR-005). (3) ExportGovernanceMonitoringcounters/histograms to Prometheus so/metrics(now present) reports governance decisions (FR-004). (4) Wire apolicy_updateWS push onDynamicPolicyManager.reload(FR-003). - Target files:
gateway/handlers/_policy_gate.py(enforcement),governance/monitoring.py(prometheus),governance/policy_engine.pyor a new degradation manager,governance/dynamic_policy.py(WS push). - Approach: split into a spec-update (FR-001 → WS) + the genuinely-missing runtime features
(degradation, metrics). The K1 gateway-HTTP blocker for FR-004 is now removed (
/metricsexists). - Dependencies: SPEC-014 (K1 done —
/metricspresent; FR-001 middleware still needs a decision), SPEC-010 (memory PAM++ predicates still absent), SPEC-007a (extends it). - Effort: M–L. Risk: medium (spans gateway + governance; FR-001 needs a design call).
Evidence log:
symbols --pattern GovernanceMiddleware→ 0.symbols --pattern Degradation→ 0 src hits.source gateway.handlers._policy_gate→PolicyGate(:28), fail-closed, WS-level.source gateway.http_surface→/health/ready/metrics(:96/:112/:125).source governance.monitoring→ Redis-only (no prometheus import).source governance.dynamic_policy→reload(:129)/rollback(:227), no WS push.source governance.policy_engine→ no degradation/default-policy fields.
Cluster summary table
| Spec | Class | Effort | Hard deps |
|---|---|---|---|
| SPEC-006 Session Management | PARTIAL (live file-half DONE; dual-storage MCP-only; kernel impl orphaned) | M | SPEC-007, 008, 023, 010 |
| SPEC-007a Prolog Governance / PAM++ | DIVERGENCE (mostly DONE; janus + may_execute/2 vs spec) | S (spec update) | SPEC-060, 006, 014 |
| SPEC-023 Goal System | PARTIAL (lifecycle+model DONE & consolidated; evaluation/alarm/gate/injection MISSING) | L | SPEC-006, CI parsing, 007 |
| SPEC-024 Dependency Injection | DONE (library; D4-descoped scope matches code; orphaned agents/di.py removed) | S (none) | — (adoption = K3, cross-cutting) |
| SPEC-060 Enhanced PAM++ Runtime | PARTIAL/GAP (cache+reload present; middleware/451/metrics/degradation absent; K1 /metrics now present) |
M–L | SPEC-014, 010, 007a |
Real remaining work (this cluster)
- SPEC-023 — biggest genuine feature gap:
goal_evaluate()(0 defs),AudioAlarm(0 symbols), session-start goal injection, session-end gate (check_goal_before_stopunwired),block/unblockCLI commands, re-planning. Goal lifecycle consolidation (GoalMixin → SessionController) is now done. - SPEC-060 — degradation modes, governance→Prometheus export (K1
/metricsblocker now removed), a WS policy push on reload, and the FR-001 enforcement-surface decision (WS vs FastAPI). - SPEC-006 — consolidation/wiring of the dual-storage half + delete the orphaned
kernel/session_manager.py(still 0 src refs). - SPEC-007a — spec-text update only (janus / may_execute/2 divergence), no code holes.
- SPEC-024 — no spec work; system-wide DI adoption remains a separate K3/Mnemosyne track.
Cross-cluster dependencies noticed
- goal (023) ↔ session (006):
state.goallives in thecontext.jsonowned bySessionController; injection + the end-gate are session hooks. Goal impl consolidation is done; the remaining gate/injection work is coupled to session hooks. - PAM++ (060/007a) ↔ gateway (014): K1 gateway-HTTP landed (
http_surface.py/health//ready//metrics), so SPEC-060 FR-004 only needs governance→Prometheus export; FR-001 middleware/451 still needs a WS-vs-HTTP decision. Memory PAM++ predicates (can_store_memory/can_read_memory, SPEC-010 FR-013) remain absent. - DI (024) ↔ memory (010): container is complete and its two documented consumers are wired; the
flagship adoption use case (resolve
IMemoryEngine) is blocked on K3 (persistent-engine lifecycle owner). - session (006) ↔ memory (010):
EventEmittingSessionControlleremitssession.closedbut is unwired, somigrate_to_coldstill has no producer — same K3 decision.