Orchestrata Ultimate › Plans › spec-023-goal-consolidation-plan

SPEC-023 Goal-System Consolidation Plan

Source: plans/spec-023-goal-consolidation-plan.md at 8a2cb42ad · last changed 2026-07-27 · first committed 2026-07-14 · 70 lines.

Prose pending.

Plan text

SPEC-023 Goal-System Consolidation Plan

Current state (audited 2026-07-14)

Three overlapping goal implementations exist:

Implementation Location Scope Live? Notes
Session CLI goal claude/tools/session/session.py:47-140 Singular session goal (state.goal) ✅ Yes — used by the live Click CLI (session goal set/status/update) Simple Goal/GoalCriterion/GoalProgress models from session.models; no verification execution
SessionController GoalMixin src/orchestrata_ultimate/session/controller/_goals.py Same singular session goal (state.goal) ❌ No — 0 production refs Duplicates the CLI methods; adds check_goal_before_stop and dead verify_command/verify_pattern fields that are never executed
PM Portfolio goals src/orchestrata_ultimate/agents/volks/pm/goal_registry.py Multiple portfolio goals (state.portfolio_goals) ⚠️ Opt-in — only when PMVolk.context_path is set Richer lifecycle (ACTIVE/RUNNING/COMPLETED/BLOCKED/DEFERRED/CANCELLED), priorities, success criteria, gap analysis, GoalReportGenerator

SPEC-023 requirements vs reality

specs/023-goal-system/spec.md expects:

Reality:

Decision fork

Before any wiring, choose ONE canonical goal surface:

  1. Make the CLI SessionController canonical (recommended)

    • Keep the singular session goal in state.goal.
    • Move the duplicate GoalMixin methods into the CLI SessionController (or delete GoalMixin if the CLI already covers them).
    • Implement real criterion evaluation in session/cli/lifecycle.py (_run_end_* path) or session/session.py.
    • Wire check_goal_before_stop into session end / SessionController.end().
    • Delete session/controller/_goals.py.
    • Keep portfolio goals as a separate PM concern (do not merge).
  2. Make session/controller/_goals.py canonical and delete the CLI duplication

    • Less attractive: the CLI is the user-facing surface and is actively used.
  3. Merge singular session goal into the PM portfolio-goal model

    • Overkill for a simple session objective; portfolio goals are multi-item, PM-managed, and optional.

Proposed minimal execution plan (if Option 1 is chosen)

  1. Delete src/orchestrata_ultimate/session/controller/_goals.py and remove its import/composition from any SessionController.
  2. Add criterion execution to the live SessionController:
    • GoalCriterion.verify_command: run as a subprocess (like the CLI already runs git/pytest); capture returncode.
    • GoalCriterion.verify_pattern: match stdout/stderr or a file against the regex.
    • Update criterion status to met/failed.
  3. Wire check_goal_before_stop:
    • Call from SessionController.end() (and the session end CLI) when a goal is active and not yet achieved.
    • Return/echo the remaining-criteria message and abort the end operation (or require --force).
  4. Audio alarm (SPEC-023 FR-006/013):
    • Add a small session/alarm.py utility that tries paplay/aplay/ffplay and falls back to the terminal bell.
    • Call from goal-completion and blocker paths.
  5. Tests:
    • Real subprocess criterion execution with a passing/failing shell command.
    • Pattern matching against command output.
    • session end blocked when criteria unmet; allowed when all met or --force.
    • Alarm utility tries each backend without crashing when absent.

Blocker

This work requires choosing between the three implementations above and deciding the behavior of session end when criteria are unmet (abort vs warn vs require --force). That is a product/UX decision, not a unilateral code change.

Suggested next step

Confirm Option 1 (CLI SessionController canonical, delete GoalMixin, keep portfolio goals separate) and the desired session end behavior. Then execute the plan above.