Decisions

  • Pending: Notification channel — terminal only, or also messaging (iMessage/WhatsApp)?
  • Pending: Stale threshold — how many days without activity before flagging?
  • Pending: Gate enforcement — strict (blocks transition) or advisory (warns but allows)?
  • Pending: Auto-close — fully automatic on user confirmation, or require explicit archive command?
  • Pending: Pitch state — include in state machine or handle separately in FR-050?

User Tasks


Summary

Replace the current convention-based feature lifecycle with a code-enforced Python state machine that validates transitions, executes side effects, and auto-manages features through their lifecycle.

Problem / Motivation

Opus currently manages the feature lifecycle through rules and conventions — Claude follows instructions about moving files between folders, updating dashboards, and checking gates. This approach has several weaknesses:

  • No enforcement: Nothing prevents invalid transitions (e.g., moving to in-progress with unresolved decisions)
  • No automation: Dashboard updates, file moves, and git commits are all manual
  • No visibility: No timestamps on state transitions, no stale detection, no activity tracking
  • No nudging: Features waiting for user input can sit indefinitely without reminders
  • Inconsistency: Different sessions may handle transitions differently depending on context loaded

Nexie solves this with a formal state machine that makes the lifecycle programmatic, validated, and automated.

Proposed Solution

Build a Python state machine module that:

  1. Defines valid states and transitions as a formal graph:

    pitch -> idea -> new -> planned -> in-progress -> done
                                           |
                                           v
                                        blocked
    

    Pitch state: When the system (via FR-050 monitoring) proactively identifies a pain point, the workflow enters the “pitch” state. The system sends a structured 3-line message: Problem Proposal “Should I create an FR?“. User approves or rejects.

    Fast-track logic: When the user initiates a feature request directly (via /new-feature or messaging), the pitch state is skipped and the workflow goes straight to “design” (spec creation by feature request specialist).

  2. Validates every transition — checks gates before allowing state changes:

    • new -> planned: All open questions must be answered
    • planned -> in-progress: No unresolved decisions, prerequisites met
    • in-progress -> done: All phases complete, tests pass
  3. Executes side effects on transition:

    • Move FR file to the correct directory
    • Update feature-dashboard.md
    • Update related dashboards (review, tasks)
    • Add history entry to the FR
    • Commit changes to git with structured message
  4. Tracks timing per state:

    • created_at, entered_new_at, entered_planned_at, started_at, completed_at
    • Duration in each state for retrospective analysis
  5. Generates notifications when action is needed:

    • Unresolved decisions blocking progress
    • Stale features (no activity for X days)
    • Phase completion (ready for next phase)
  6. Provides query interface:

    • “What’s blocked?” — features waiting on decisions or prerequisites
    • “What’s stale?” — features without recent activity
    • “What just completed?” — recent state transitions

Auto-close/archive flow (when user confirms “FR-040 is done”):

  • Moves file from in-progress/ to done/
  • Updates feature-dashboard.md (status done, increment done count)
  • Updates user-review-dashboard.md if applicable
  • Adds completion entry to FR history log with timestamp
  • Commits all changes to git: feat: close FR-040 — [title]

Open Questions

1. Notification Channel

Question: How should the state machine deliver notifications and nudges?

OptionDescription
A) Terminal onlyPrint notifications in Claude Code session. Simple, no external dependencies
B) Terminal + vault inboxWrite notifications to vault/90_inbox/ as notes. Visible in Obsidian
C) Terminal + messagingSend via iMessage/WhatsApp (requires FR-023). Full push notification experience

Recommendation: Option A for Phase 1-2, Option B for Phase 3. Messaging can come later via FR-023.

Decision:

2. Stale Threshold

Question: How many days without activity before a feature is flagged as stale?

OptionDescription
A) 3 daysAggressive — catches issues fast but may be noisy
**B) 7 daysBalanced — one week without progress is worth flagging
C) 14 daysRelaxed — only flags truly abandoned work

Recommendation: Option B — 7 days is a natural review cycle. Make it configurable per-FR for flexibility.

Decision:

3. Gate Enforcement

Question: Should gates strictly block transitions or just warn?

OptionDescription
A) Strict — block invalid transitionsPrevents mistakes but may frustrate when exceptions are legitimate
B) Advisory — warn but allow overrideFlags issues, user decides. Respects user autonomy
C) Configurable per-gateSome gates are strict (security), others advisory

Recommendation: Option B to start — Opus is user-driven, not system-driven. Strict gates can be added for critical paths later.

Decision:


Phase Overview

PhaseDescriptionStatus
Phase 1State definitions + transition rules
Phase 2Side effects + auto-transitions
Phase 3Nudging + stale detection + notifications

Phase 1: State Definitions + Transition Rules —

Goal: Define the state graph, transition validation, and gate checking as a Python module.

File / FeatureDetailsOwnerStatus
src/opus/workflow/states.pyState enum: idea, new, planned, in_progress, blocked, done. Transition graph definitionopus
src/opus/workflow/machine.pyState machine class: current state, transition(target), validate(target), historyopus
src/opus/workflow/gates.pyGate definitions: what must be true for each transition. Parse FR to check gatesopus
FR parsingRead FR frontmatter and content to extract status, decisions, phases, prerequisitesopus
Unit testsValid transitions succeed, invalid transitions rejected, gates enforced correctlyopus

Phase 2: Side Effects + Auto-Transitions —

Goal: Execute automated actions on state transitions and detect when transitions should happen automatically.

File / FeatureDetailsOwnerStatus
src/opus/workflow/effects.pySide effect registry: file moves, dashboard updates, history entries, git commitsopus
File movesAuto-move FR files between lifecycle directories on transitionopus
Dashboard updatesAuto-update feature-dashboard.md counts and statusopus
History loggingAuto-add timestamped entries to FR history tableopus
Git commitsAuto-commit with structured message: feat: transition FR-XXX to [state]opus
Auto-transition detectionWhen all phase tasks are done, auto-advance to next phase or completionopus
Timing trackingRecord timestamps for each state entry, calculate duration per stateopus

Phase 3: Nudging + Stale Detection + Notifications —

Goal: Proactively detect features needing attention and notify the user.

File / FeatureDetailsOwnerStatus
src/opus/workflow/monitor.pyPeriodic scan of all FRs: check for stale, blocked, needing-input statesopus
Stale detectionFlag features with no git commits or file changes for X daysopus
Decision nudgingDetect FRs with unresolved decisions that are blocking progressopus
Notification deliveryFormat and deliver notifications (terminal print, vault inbox note)opus
Query interfaceCLI/skill queries: “what’s blocked?”, “what’s stale?”, “what completed this week?“opus
Integration with briefingFeed stale/blocked items into daily briefing (FR-037)opus

Prerequisites / Gap Analysis

Requirements

RequirementDescription
REQ-1Python project scaffold (FR-009) — state machine is Python code

Current State

ComponentStatusDetails
Python scaffoldFR-009 not started
Feature lifecycle rulesdoneDefined in .claude/rules/ and vault conventions
Feature dashboarddonevault/00_system/dashboards/feature-dashboard.md exists
File directory structuredoneideas/, new/, planned/, in-progress/, done/ directories exist

Gap (What’s missing?)

GapEffortBlocker?
Python scaffold (FR-009)MedYes — code needs a runtime
FR frontmatter parserLowNo — can be built as part of Phase 1
Git automation helpersLowNo — subprocess calls to git

Test

Manual tests

TestExpectedActualLast
Valid transition (new planned) with gates metTransition succeeds, side effects executepending-
Invalid transition (new in-progress) skipping plannedTransition rejected with reasonpending-
Gate check: unresolved decisions block planned in-progressTransition blocked, decisions listedpending-
Auto-close: user confirms doneFile moved, dashboard updated, git committedpending-

AI-verified tests

ScenarioExpected behaviorVerification method

E2E tests

ScenarioAssertion

Integration tests

ComponentCoverage

Unit tests

ComponentTestsCoverage

History

DateEventDetails
2026-03-04CreatedInspired by Nexie’s code-enforced workflow state machine
2026-03-04UpdatedAdded pitch state and fast-track logic (inspired by Nexie)

References

  • FR-009 (Python Project Scaffold) — code infrastructure prerequisite
  • FR-028 (Feature Workflow Automation) — related but broader; state machine is the engine
  • FR-027 (Feature Overview Sync Check) — dashboard sync becomes a side effect of transitions
  • FR-037 (Daily Briefings) — stale/blocked items feed into briefings
  • FR-045 (Complexity Routing) — routing triggers state transitions
  • FR-046 (Job Registry) — state transitions can create jobs
  • FR-050 (Proactive Monitoring) — monitoring uses state machine data
  • Nexie (Sven Hennig) — original inspiration for code-enforced lifecycle