This document prevents “architecture freestyling” by providing a single authoritative map:
- CLI commands (Typer)
- The core functions they call
- The state they read/write
- The events they emit
- The adapters they may use
Rule: Implement commands exactly as mapped here unless docs/GOLDEN_PATH.md changes.
Repository currently uses a top-level codeframe/ Python package and web-ui/ at top level.
Add these subpackages under codeframe/:
codeframe/cli/app.py(Typer root)commands/(subcommands grouped by domain)
codeframe/core/models.py(Pydantic/dataclasses for domain objects)state_machine.py(authoritative transitions)events.py(event log interface + event types)workspace.py(workspace registration + config)config.py(environment configuration: package manager, test framework, lint tools)prd.py(PRD store + AI-driven generation)tasks.py(task generation + CRUD with dependencies)blockers.py(blocker store + AI-powered resolution)runtime.py(single-task orchestrator/worker loop)conductor.py(batch orchestration, multi-task execution)dependency_analyzer.py(LLM-based dependency inference)checkpoints.py(snapshot + restore with git refs)gates.py(enhanced review/test runners)git_integration.py(Git workflow and PR management)
codeframe/adapters/(optional but recommended)llm/(provider-specific clients)git/(branch/worktree/patch utilities + PR operations)fs/(file operations)persistence/(SQLite/filesystem implementations)
codeframe/server/(FastAPI wrapper; optional during Golden Path)app.py(FastAPI app)routes/(thin wrappers over core)
Legacy quarantine:
- Move
web-ui/->legacy/web-ui/(orlegacy/equivalent)
- SQLite or filesystem-backed store.
- Recommended location:
.codeframe/in workspace repo OR repo rootcodeframe.db. - Must support: workspaces, PRDs, tasks, blockers, checkpoints, event log pointers.
- Core emits events for all meaningful actions.
- CLI prints selected events to stdout and can tail the log.
- Server/UI may subscribe later; server is not required for event recording.
Statuses:
BACKLOG,READY,IN_PROGRESS,BLOCKED,DONE,MERGED(optional later)
Transitions enforced in codeframe/core/state_machine.py.
Notation:
- CLI entrypoint:
codeframe/cli/app.py - Core functions are suggested names; adjust if repo already has similar functions.
Each command:
- Calls core functions
- Writes durable state
- Emits events
Purpose: Create/register a workspace.
CLI module:
codeframe/cli/commands/workspace.py
Core calls:
codeframe.core.workspace.create_or_load(repo_path) -> Workspacecodeframe.core.events.emit(workspace_id, "WORKSPACE_INIT", payload)
State writes:
- Workspace record (id, path, created_at, config)
Notes:
- Must not start server.
- Must succeed even if repo already initialized (idempotent).
Purpose: Show current workspace summary + task counts + latest activity.
CLI module:
codeframe/cli/commands/status.py
Core calls:
codeframe.core.workspace.get_current() -> Workspacecodeframe.core.tasks.list_by_status(workspace_id) -> dict[Status, list[Task]]codeframe.core.events.list_recent(workspace_id, limit=20) -> list[Event]
State reads only.
Emits: optional STATUS_VIEWED event (not required).
Purpose: Quick environment validation with health score.
CLI module:
codeframe/cli/env_commands.py
Core calls:
codeframe.core.environment.EnvironmentValidator.validate_environment(project_path) -> ValidationResult
Output:
- Project type (Python, JavaScript, Rust, etc.)
- Health score percentage
- Available/missing tools summary
- Quick recommendations (top 3)
Purpose: Comprehensive environment diagnostics.
CLI module:
codeframe/cli/env_commands.py
Core calls:
codeframe.core.environment.EnvironmentValidator.validate_environment(project_path) -> ValidationResult
Output:
- Full tools table with status, version, and path
- Warnings and conflicts
- Complete recommendations list
Purpose: Install a specific missing tool.
CLI module:
codeframe/cli/env_commands.py
Core calls:
codeframe.core.installer.ToolInstaller.can_install(tool) -> boolcodeframe.core.installer.ToolInstaller.install_tool(tool, confirm) -> InstallResult
Supported installers:
- PipInstaller: pytest, ruff, mypy, black, flake8, pylint, isort, bandit, coverage, pre-commit, httpx, requests
- NpmInstaller: eslint, prettier, jest, typescript, ts-node, webpack, vite, vitest, mocha, chai
- CargoInstaller: clippy, rustfmt, rust-analyzer, ripgrep, fd-find, bat, tokei, cargo-edit, cargo-watch
- SystemInstaller: git, docker, make, curl, wget, jq, gh (requires manual execution)
Purpose: Automatically install all missing required tools.
CLI module:
codeframe/cli/env_commands.py
Core calls:
codeframe.core.environment.EnvironmentValidator.validate_environment(project_path) -> ValidationResultcodeframe.core.installer.ToolInstaller.install_tool(tool, confirm) -> InstallResult(for each missing tool)
State writes:
- Installation history in
.codeframe/environment.json
Purpose: Initialize project environment configuration.
CLI module:
codeframe/cli/app.py(config_app subgroup)
Core calls:
codeframe.core.config.load_environment_config(workspace_path) -> EnvironmentConfig | Nonecodeframe.core.config.save_environment_config(workspace_path, config) -> None- Auto-detection reads: pyproject.toml, package.json, lock files
Options:
--detect: Auto-detect settings from project files (non-interactive)--force: Overwrite existing config file--workspace/-w: Workspace path (defaults to cwd)
State writes:
.codeframe/config.yaml
Purpose: Display current project configuration.
Core calls:
codeframe.core.config.load_environment_config(workspace_path) -> EnvironmentConfig | Nonecodeframe.core.config.get_default_environment_config() -> EnvironmentConfig(fallback)
State reads only.
Purpose: Set individual configuration values.
Core calls:
codeframe.core.config.load_environment_config(workspace_path) -> EnvironmentConfig | Nonecodeframe.core.config.save_environment_config(workspace_path, config) -> Noneconfig.validate() -> list[str](validation errors)
Valid keys:
package_manager: uv, pip, poetry, npm, pnpm, yarnpython_version: e.g., 3.11test_framework: pytest, jest, vitest, mochalint_tools: comma-separated, e.g., "ruff,mypy"test_command: custom test command overridelint_command: custom lint command override
State writes:
.codeframe/config.yaml
Purpose: AI-driven interactive PRD generation.
CLI module:
codeframe/cli/commands/prd.py
Core calls:
codeframe.core.prd.start_discovery_session(workspace_id) -> DiscoverySessioncodeframe.core.prd.ask_followup_questions(session, context) -> DiscoverySessioncodeframe.core.prd.generate_prd(session) -> PrdRecordcodeframe.core.prd.refine_prd(prd_id, feedback) -> PrdRecordcodeframe.core.events.emit(workspace_id, "PRD_GENERATED", payload)
State writes:
- Discovery session records
- Comprehensive PRD record with technical specs
- Version history and change tracking
Adapter usage:
- LLM adapter for interactive discovery and content generation
- Analysis adapter for technical requirement extraction
Purpose: Store PRD text + metadata.
CLI module:
codeframe/cli/commands/prd.py
Core calls:
codeframe.core.prd.load_file(path) -> strcodeframe.core.prd.store(workspace_id, text, metadata) -> PrdRecordcodeframe.core.events.emit(workspace_id, "PRD_ADDED", payload)
State writes:
- PRD record (id, title, text, created_at)
Purpose: Iterative PRD improvement based on feedback.
CLI module:
codeframe/cli/commands/prd.py
Core calls:
codeframe.core.prd.get(workspace_id, prd_id) -> PrdRecordcodeframe.core.prd.suggest_improvements(prd) -> list[Suggestion]codeframe.core.prd.apply_feedback(prd_id, feedback) -> PrdRecordcodeframe.core.events.emit(workspace_id, "PRD_REFINED", payload)
State writes:
- Updated PRD record
- Suggestion and feedback history
Purpose: Print PRD content. Without ID shows latest; with ID shows specific PRD.
CLI module:
codeframe/cli/app.py(prd subcommand group)
Core calls:
codeframe.core.prd.get_latest(workspace_id) -> PrdRecord(if no ID)codeframe.core.prd.get_by_id(workspace_id, prd_id) -> PrdRecord(if ID provided)
CLI options:
--full: Show complete content (default truncates long PRDs)--workspace/-w: Workspace path (defaults to cwd)
Purpose: List all PRDs in the workspace.
CLI module:
codeframe/cli/app.py(prd subcommand group)
Core calls:
codeframe.core.prd.list_all(workspace_id) -> list[PrdRecord]
Output:
- Table showing: ID (truncated), Title, Version, Created date
Purpose: Delete a PRD from the workspace.
CLI module:
codeframe/cli/app.py(prd subcommand group)
Core calls:
codeframe.core.prd.get_by_id(workspace_id, prd_id) -> PrdRecordcodeframe.core.prd.delete(workspace_id, prd_id, check_dependencies) -> boolcodeframe.core.events.emit(workspace_id, "PRD_DELETED", payload)
CLI options:
--force, -f: Skip confirmation prompt--workspace/-w: Workspace path (defaults to cwd)
State writes:
- Removes PRD record from database
Validation:
- Checks for dependent tasks (raises
PrdHasDependentTasksErrorif found withcheck_dependencies=True)
Purpose: Export a PRD to a file.
CLI module:
codeframe/cli/app.py(prd subcommand group)
Core calls:
codeframe.core.prd.export_to_file(workspace_id, prd_id, file_path, force) -> bool
CLI options:
--latest: Export the latest PRD instead of requiring ID--force, -f: Overwrite existing file--workspace/-w: Workspace path (defaults to cwd)
State reads only (exports content to file)
Purpose: Show version history for a PRD.
CLI module:
codeframe/cli/app.py(prd subcommand group)
Core calls:
codeframe.core.prd.get_versions(workspace_id, prd_id) -> list[PrdRecord]
Output:
- Table showing: Version number, ID (truncated), Change summary, Created date
- Versions sorted by version number descending (newest first)
Purpose: Show diff between two versions of a PRD.
CLI module:
codeframe/cli/app.py(prd subcommand group)
Core calls:
codeframe.core.prd.diff_versions(workspace_id, prd_id, v1, v2) -> str
Output:
- Unified diff format showing additions (+) and removals (-)
Purpose: Create a new version of an existing PRD.
CLI module:
codeframe/cli/app.py(prd subcommand group)
Core calls:
codeframe.core.prd.load_file(file_path) -> strcodeframe.core.prd.create_new_version(workspace_id, prd_id, content, change_summary) -> PrdRecordcodeframe.core.events.emit(workspace_id, "PRD_UPDATED", payload)
CLI options:
--file, -f: Path to file with new content (required)--message, -m: Change summary message (required)--workspace/-w: Workspace path (defaults to cwd)
State writes:
- New PRD record with incremented version
- Links to parent via
parent_id - Shares
chain_idwith all versions in the chain
Purpose: Generate tasks from PRD.
CLI module:
codeframe/cli/commands/tasks.py
Core calls:
codeframe.core.prd.get_latest(workspace_id) -> PrdRecordcodeframe.core.tasks.generate_from_prd(workspace_id, prd_id) -> list[Task]codeframe.core.events.emit(workspace_id, "TASKS_GENERATED", payload)
State writes:
- Task records (id, title, description, status=BACKLOG/READY)
Adapter usage:
- LLM provider adapter may be used inside
generate_from_prd(allowed). - But keep provider code out of core; core uses an interface like
LLMClient.
Purpose: List tasks.
Core calls:
codeframe.core.tasks.list(workspace_id, status=None) -> list[Task]
Purpose: Manually transition state.
Core calls:
codeframe.core.state_machine.transition(task, new_status) -> Taskcodeframe.core.tasks.update_status(workspace_id, task_id, new_status)codeframe.core.events.emit(workspace_id, "TASK_STATUS_CHANGED", payload)
Future state:
- Allow other task attributes to be set, like
provider, etc. codeframe task set <attribute> <task_id> <attribute_value>
Purpose: Get current state.
Core calls:
-codeframe.core.tasks.get_status(workspace_id, task_id)
Future state:
- Allow other task attributes to be retrieved
Purpose: Begin execution of a task.
CLI module:
codeframe/cli/commands/work.py
Core calls:
workspace = codeframe.core.workspace.get_current()task = codeframe.core.tasks.get(workspace_id, task_id)codeframe.core.tasks.update_status(..., IN_PROGRESS)run_id = codeframe.core.runtime.start_task_run(workspace_id, task_id) -> RunRecordcodeframe.core.events.emit(workspace_id, "RUN_STARTED", payload)
Runtime behavior (core):
- Orchestrator executes agent plan for the task.
- Emits step events:
AGENT_STEP_STARTED,AGENT_STEP_COMPLETEDPATCH_UPDATED/FILES_MODIFIEDBLOCKER_CREATEDwhen stuck
Adapter usage (runtime):
- LLM adapter
- git adapter (branch/worktree/patch)
- fs adapter
Important constraint:
- Must work without FastAPI server running.
Purpose: Continue after blocker resolution or pause.
Core calls:
codeframe.core.runtime.resume_task_run(workspace_id, task_id)
Purpose: Stop execution (graceful).
Core calls:
codeframe.core.runtime.stop_task_run(workspace_id, task_id)
Purpose: Execute multiple tasks in sequence (or parallel in Phase 2).
CLI module:
codeframe/cli/commands/work.py(batch subcommand group)
Core calls:
batch = codeframe.core.conductor.start_batch(workspace_id, task_ids, strategy, max_parallel)codeframe.core.events.emit(workspace_id, "BATCH_STARTED", payload)- For each task: spawns subprocess
cf work start <task_id> --execute codeframe.core.events.emit(workspace_id, "BATCH_COMPLETED", payload)
State writes:
- BatchRun record (id, task_ids, status, strategy, results)
CLI options:
--all-ready: Process all READY tasks instead of specifying IDs--strategy serial|parallel: Execution strategy (default: serial)--max-parallel N: Max concurrent tasks when parallel (default: 4)--dry-run: Show execution plan without running--on-failure continue|stop: Behavior on task failure (default: continue)--retry N, -r N: Max retry attempts for failed tasks (default: 0, no retries)
Important constraint:
- Must work without FastAPI server running.
- Phase 1: Serial execution only (parallel flag accepted but runs serial)
- Phase 2: True parallel execution with dependency analysis
Purpose: Show batch execution status.
Core calls:
codeframe.core.conductor.list_batches(workspace_id)(if no batch_id)codeframe.core.conductor.get_batch(workspace_id, batch_id)(if batch_id provided)
Output:
- Batch ID, status, strategy
- Task progress (completed/total)
- Per-task status and duration
Purpose: Cancel a running batch.
Core calls:
codeframe.core.conductor.cancel_batch(workspace_id, batch_id)codeframe.core.events.emit(workspace_id, "BATCH_CANCELLED", payload)
Behavior:
- Sends SIGTERM to running subprocesses
- Marks batch as CANCELLED
- Does not affect already-completed tasks
Purpose: Re-run failed/blocked tasks from a previous batch.
Core calls:
codeframe.core.conductor.resume_batch(workspace_id, batch_id, force)codeframe.core.events.emit(workspace_id, "BATCH_STARTED", payload)withis_resume=True
CLI options:
--force, -f: Re-run all tasks including completed ones
Behavior:
- Loads existing BatchRun record
- Identifies tasks with FAILED or BLOCKED status
- Re-executes only those tasks (or all with --force)
- Merges new results into existing batch
- Updates batch status based on final results
Example:
cf work batch resume abc123 # Re-run failed/blocked only
cf work batch resume abc123 --force # Re-run all tasksPurpose: Tail event log in terminal.
Core calls:
codeframe.core.events.tail(workspace_id, since=<cursor>) -> iterator[Event]
Purpose: List open blockers.
CLI module:
codeframe/cli/commands/blockers.py
Core calls:
codeframe.core.blockers.list_open(workspace_id) -> list[Blocker]
Purpose: Answer a blocker and unblock work.
Core calls:
codeframe.core.blockers.answer(workspace_id, blocker_id, text)codeframe.core.events.emit(workspace_id, "BLOCKER_ANSWERED", payload)- Optional:
codeframe.core.runtime.notify_blocker_answered(...)
Purpose: Mark blocker resolved (optional if answer implies resolved).
Core calls:
codeframe.core.blockers.resolve(workspace_id, blocker_id)emit(..., "BLOCKER_RESOLVED")
Purpose: Run verification gates.
CLI module:
codeframe/cli/commands/gates.py
Core calls:
result = codeframe.core.gates.run(workspace_id, repo_path) -> GateResultemit(..., "GATES_COMPLETED", payload)
Adapters:
- process runner / shell adapter
MVP gates:
- run
pytestif present - record pass/fail + logs
Purpose: Export changes safely.
CLI module:
codeframe/cli/commands/artifacts.py
Core calls:
patch_path = codeframe.core.runtime.export_patch(workspace_id, repo_path, out_path=None)emit(..., "PATCH_EXPORTED", payload)
Adapters:
- git adapter or filesystem diff tool
Purpose: Create a commit for completed work.
Core calls:
commit_hash = codeframe.core.runtime.create_commit(workspace_id, repo_path, message)emit(..., "COMMIT_CREATED", payload)
Notes:
- This can be postponed in favor of patch export early.
Purpose: Begin task execution with automatic branch creation.
CLI module:
codeframe/cli/commands/work.py
Core calls:
branch_name = codeframe.core.git.create_feature_branch(workspace_id, task_id)run = codeframe.core.runtime.start_task_run(workspace_id, task_id, branch=branch_name)emit(..., "TASK_STARTED_WITH_BRANCH", payload)
Adapter usage:
- git adapter for branch management
Purpose: Create pull request with optional auto-generated description from commits.
CLI module:
codeframe/cli/pr_commands.py
Core calls:
GitHubIntegration.create_pull_request(branch, title, body, base)
Options:
--title/-t: PR title (required)--branch/-b: Source branch (defaults to current)--base: Target branch (defaults to main)--body: PR description body--auto-description/--no-auto-description: Auto-generate from commits
Adapter usage:
codeframe.git.github_integration.GitHubIntegration
Examples:
codeframe pr create --title "Add new feature"
codeframe pr create --branch feature/auth --title "Auth system" --base develop
codeframe pr create --title "Quick fix" --no-auto-descriptionPurpose: List pull requests with optional filtering.
CLI module:
codeframe/cli/pr_commands.py
Core calls:
GitHubIntegration.list_pull_requests(state)
Examples:
codeframe pr list
codeframe pr list --status closed
codeframe pr list --format jsonPurpose: Get detailed information about a specific PR.
CLI module:
codeframe/cli/pr_commands.py
Core calls:
GitHubIntegration.get_pull_request(pr_number)
Examples:
codeframe pr get 42
codeframe pr get 42 --format jsonPurpose: Merge pull request with specified strategy.
CLI module:
codeframe/cli/pr_commands.py
Core calls:
GitHubIntegration.get_pull_request(pr_number)(validate state)GitHubIntegration.merge_pull_request(pr_number, method)
Examples:
codeframe pr merge 42
codeframe pr merge 42 --strategy rebasePurpose: Close a pull request without merging.
CLI module:
codeframe/cli/pr_commands.py
Core calls:
GitHubIntegration.close_pull_request(pr_number)
Examples:
codeframe pr close 42Purpose: Show PR status for current branch.
CLI module:
codeframe/cli/pr_commands.py
Core calls:
get_current_branch()(git helper)GitHubIntegration.list_pull_requests(state="open")- Filters to find PR matching current branch
Examples:
codeframe pr statusPurpose: Show git status summary with CodeFRAME context.
CLI module:
codeframe/cli/commands/git.py
Core calls:
status = codeframe.core.git.get_enhanced_status(workspace_id)
Purpose: Snapshot durable state + optionally repo ref.
CLI module:
codeframe/cli/commands/checkpoints.py
Core calls:
checkpoint = codeframe.core.checkpoints.create(workspace_id, name)emit(..., "CHECKPOINT_CREATED", payload)
Purpose: List checkpoints.
Core calls:
codeframe.core.checkpoints.list(workspace_id) -> list[Checkpoint]
Purpose: Restore state snapshot.
Core calls:
codeframe.core.checkpoints.restore(workspace_id, checkpoint_id)
Purpose: Print a short status report of the workspace.
CLI module:
codeframe/cli/commands/summary.py
Core calls:
prd = prd.get_latest(...)tasks = tasks.list(...)blockers = blockers.list_open(...)artifacts = runtime.list_artifacts(...)emit(..., "SUMMARY_VIEWED", payload)(optional)
Output includes:
- PRD title
- Tasks by status
- Open blockers
- Latest artifact(s)
- Latest checkpoint
Purpose: Start FastAPI server as a wrapper over core.
CLI module:
codeframe/cli/commands/server.py
Server module:
codeframe/server/app.py
Hard rules:
- FastAPI routes must call core functions.
- No domain logic lives in routes.
- Golden Path must work without running
serve.
- Any existing Typer CLI scaffolding that:
- already runs headlessly
- maps to Golden Path commands cleanly
- does not import FastAPI routes or UI modules
- Create a new
codeframe/cli/app.pyTyper root. - Add the Golden Path commands as above.
- Leave old CLI commands in legacy or deprecate later.
prd generate- AI-driven interactive PRD generation with follow-up questionsprd refine- iterative PRD improvement based on user feedback- Enhanced
initwith auto-discovery and environment configuration - PRD versioning and change tracking
- Enhanced
tasks generatewith dependency analysis and effort estimation - Task template system for common implementation patterns
- Critical path identification and workstream grouping
tasks analyze- dependency graph visualization and analysis
codeframe git_integrationmodule implementation- Enhanced
work start --create-branchwith automatic branch management pr createwith AI-generated comprehensive descriptionspr mergewith automated verification and merge strategies- Git adapter for branch/worktree/patch operations
- Enhanced
gates.runwith comprehensive test suite - AI-assisted code review and best practices checking
- Quality metrics tracking and trend analysis
- Technical debt accumulation monitoring
- Security and performance regression detection
- Enhanced blocker system with AI-powered suggestions
- Contextual blocker display with rich background information
- Learning system for blocker pattern recognition
- Similar past blocker solutions and recommendations
- Rich checkpoint snapshots with complete workspace state
- Cross-environment checkpoint portability
- Seamless workflow resumption from any checkpoint
- Executive reporting with progress and risk metrics
Basic Golden Path (already complete):
- Basic
init+ durable state ✓ DONE - Basic
prd add✓ DONE (superseded byprd generate) - Basic
tasks generate✓ DONE (enhanced above) - Basic
work start✓ DONE (enhanced with git integration) - Basic blockers ✓ DONE (enhanced above)
- Basic review/gates ✓ DONE (enhanced above)
- Basic patch/commit ✓ DONE (enhanced with PR workflow)
- Basic checkpoint + summary ✓ DONE (enhanced above)
Batch Execution (already complete):
work batch run✓ DONE (enhanced with git integration)work batch status✓ DONEwork batch cancel✓ DONE- Parallel execution & retry ✓ DONE
- Observability ✓ DONE
Only after Enhanced MVP phases are complete:
- Production readiness features
- Advanced multi-provider support
- Performance optimization at scale
- Enterprise security and compliance features
- multi-provider switching
- Don’t build new HTTP endpoints to support the CLI.
- Don’t require
codeframe serveto be running for CLI commands. - Don’t implement UI concepts (tabs, panels, progress bars) in core.
- Don’t refactor the entire repo layout “because it’s cleaner.”
- Don’t add multi-model selection logic before Golden Path works.
- Don’t import legacy UI/server modules into core.
If any of these are false, stop and fix before adding features:
- Golden Path commands work without FastAPI running.
- Core contains domain logic; server is thin.
- Legacy UI is quarantined and not depended upon by core.
- Events are written durably and viewable from CLI.