* docs: add Ralph PRD for workflow lifecycle overhaul * feat: Add Ralph story event types to WorkflowEventType Implements US-001 from PRD. Changes: - packages/workflows/src/store.ts — append ralph_story_started and ralph_story_completed to WorkflowEventType union * feat: Add workflow event emit CLI subcommand Implements US-002 from PRD. Changes: - packages/workflows/src/store.ts — already has new event types (US-001) - packages/cli/src/commands/workflow.ts — add workflowEventEmitCommand - packages/cli/src/cli.ts — wire workflow event emit subcommand with --run-id, --type, --data flags * fix: Fix PRD directory discovery duplication in Ralph DAG Implements US-003 from PRD. Changes: - .archon/workflows/defaults/archon-ralph-dag.yaml — detect-input now outputs JSON with input_type and prd_dir fields; when condition updated to use field access; validate-prd discovery block replaced with $detect-input.output.prd_dir substitution * feat: Emit Ralph story lifecycle events from implement loop Implements US-004 from PRD. Changes: - .archon/workflows/defaults/archon-ralph-dag.yaml — add bun run cli workflow event emit calls after Phase 1.2 (story started) and Phase 5.1 (story completed) with || true for best-effort emission * chore: Update PRD tracking — all stories complete * fix: address review — event type validation, discovery fallback, docs - Derive WorkflowEventType from WORKFLOW_EVENT_TYPES const array (enables runtime validation at CLI boundary, matches TRIGGER_RULES pattern) - Add isValidEventType() guard in CLI — exit 1 on unknown --type - Restore validate-prd discovery fallback for empty prd_dir after generation - Clarify success message as best-effort in workflowEventEmitCommand - Improve --data JSON warning to explain consequence (event emitted without data) - Remove .archon/ralph/ artifacts (gitignored per-run PRD files) - Add workflow event emit to CLAUDE.md, cli-user-guide, cli-developer-guide
23 KiB
Archon CLI Developer Guide
Technical reference for understanding CLI internals.
Package Structure
packages/cli/
├── src/
│ ├── cli.ts # Entry point, argument parsing, routing
│ ├── commands/
│ │ ├── workflow.ts # workflow list/run implementation
│ │ ├── isolation.ts # isolation list/cleanup implementation
│ │ └── version.ts # version command
│ └── adapters/
│ └── cli-adapter.ts # IPlatformAdapter for stdout
└── package.json # Defines "archon" binary
Entry Point Flow
┌─────────────────────────────────────────────────────────────────┐
│ archon <command> [subcommand] [options] [arguments] │
└─────────────────────────────────┬───────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ cli.ts:15-39 Load environment │
│ .env (cwd) → ~/.archon/.env (fallback) │
└─────────────────────────────────┬───────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ cli.ts:115-135 Parse arguments │
│ --cwd, --branch, --no-worktree, --help │
└─────────────────────────────────┬───────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ cli.ts:154-170 Git repository check │
│ Skip for version/help, validate and resolve to │
│ repo root for workflow/isolation commands │
└─────────────────────────────────┬───────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ cli.ts:172-246 Route to command handler │
│ switch(command) → workflow | isolation | version│
└─────────────────────────────────┬───────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ cli.ts:244-252 Exit with code, always closeDatabase() │
└─────────────────────────────────────────────────────────────────┘
Code: packages/cli/src/cli.ts:106-259
Git repository check:
- Commands
workflow,isolation, andcompleterequire running from a git repository - Commands
version,help,setup, andchatbypass this check - When in a subdirectory, automatically resolves to repository root
- Exit code 1 if not in a git repository
workflow list Flow
┌──────────────────────────────────────────────────────────────────┐
│ archon workflow list [--json] │
└──────────────────────────────┬───────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────────┐
│ workflow.ts workflowListCommand(cwd, json?) │
└──────────────────────────────┬───────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────────┐
│ @archon/workflows/workflow-discovery │
│ discoverWorkflowsWithConfig(cwd, config) │
│ - Loads bundled defaults │
│ - Searches .archon/workflows/ recursively │
│ - Merges (repo overrides defaults by name) │
└──────────────────────────────┬───────────────────────────────────┘
│
┌───────────────┴───────────────┐
│ json=true │ json=false
▼ ▼
┌──────────────────────────┐ ┌───────────────────────────────────┐
│ JSON output to stdout │ │ Human-readable list to stdout │
│ { workflows, errors } │ │ name, description, type, options │
└──────────────────────────┘ └───────────────────────────────────┘
Code: packages/cli/src/commands/workflow.ts
workflow run Flow
┌─────────────────────────────────────────────────────────────────┐
│ archon workflow run <name> [message] [--branch X] [--from X] [--no-worktree]│
└─────────────────────────────────┬───────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ workflow.ts:78-92 Discover & find workflow by name │
│ Error if not found (lists available) │
└─────────────────────────────────┬───────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ workflow.ts:99 Create CLIAdapter for stdout │
└─────────────────────────────────┬───────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ workflow.ts:104-133 Database setup │
│ - Create conversation: cli-{timestamp}-{random} │
│ - Lookup codebase from directory (warn if fails) │
└─────────────────────────────────┬───────────────────────────────┘
│
▼
┌─────────────┴─────────────┐
│ │
no --branch --branch
│ │
▼ ▼
┌───────────────────────────┐ ┌───────────────────────────────────┐
│ Use cwd as-is │ │ workflow.ts:152-168 │
│ │ │ Auto-detect git repo │
│ │ │ Auto-register codebase if needed │
└─────────────┬─────────────┘ └───────────────┬───────────────────┘
│ │
│ ┌─────────────┴─────────────┐
│ │ │
│ --no-worktree (default)
│ │ │
│ ▼ ▼
│ ┌─────────────────────────┐ ┌─────────────────────────┐
│ │ workflow.ts:171-175 │ │ workflow.ts:177-219 │
│ │ git.checkout(cwd, branch)│ │ Check existing worktree │
│ │ │ │ If healthy → reuse │
│ │ │ │ Else → provider.create()│
│ │ │ │ Track in DB │
│ └────────────┬────────────┘ └────────────┬────────────┘
│ │ │
└────────────────┴─────────────┬─────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ workflow.ts:235-243 executeWorkflow() │
│ - Pass adapter, conversation, workflow, cwd, message │
│ - Stream AI responses to stdout │
│ - Return success/failure │
└─────────────────────────────────────────────────────────────────┘
Code: packages/cli/src/commands/workflow.ts:72-251
Worktree Provider: packages/core/src/isolation/providers/worktree-provider.ts
workflow event emit Flow
┌──────────────────────────────────────────────────────────────────┐
│ archon workflow event emit --run-id <uuid> --type <type> [...] │
└──────────────────────────────┬───────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────────┐
│ cli.ts Validate --run-id, --type (required) │
│ Validate --type against WORKFLOW_EVENT_TYPES │
│ Parse --data as JSON (warn + skip if invalid) │
└──────────────────────────────┬───────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────────┐
│ workflow.ts workflowEventEmitCommand(runId, eventType, data?) │
│ createWorkflowStore().createWorkflowEvent(...) │
│ Non-throwing (fire-and-forget) │
└──────────────────────────────────────────────────────────────────┘
Code: packages/cli/src/cli.ts (case 'event'), packages/cli/src/commands/workflow.ts:workflowEventEmitCommand
Contract: Event persistence is best-effort. createWorkflowEvent catches all errors internally — the CLI prints a confirmation but cannot guarantee the event was stored.
isolation list Flow
┌─────────────────────────────────────────────────────────────────┐
│ archon isolation list │
└─────────────────────────────────┬───────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ isolation.ts:19-57 isolationListCommand() │
└─────────────────────────────────┬───────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ @archon/core isolationDb.listAllActiveWithCodebase() │
│ - Joins isolation_environments with codebases │
│ - Returns: path, branch, workflow_type, codebase_name, │
│ platform, days_since_activity │
└─────────────────────────────────┬───────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ isolation.ts:30-55 Group by codebase, print table │
└─────────────────────────────────────────────────────────────────┘
Code: packages/cli/src/commands/isolation.ts:19-57
isolation cleanup Flow
┌─────────────────────────────────────────────────────────────────┐
│ archon isolation cleanup [days] │
└─────────────────────────────────┬───────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ isolation.ts:62-99 isolationCleanupCommand(daysStale) │
│ default: 7 days │
└─────────────────────────────────┬───────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ @archon/core isolationDb.findStaleEnvironments(days) │
│ - WHERE last_activity_at < now - days │
│ - Excludes telegram platform │
└─────────────────────────────────┬───────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ For each stale environment: │
│ 1. provider.destroy(path, options) │
│ 2. Update DB status → 'destroyed' │
│ 3. Log result │
└─────────────────────────────────────────────────────────────────┘
Code: packages/cli/src/commands/isolation.ts:62-99
CLI Adapter
Implements IPlatformAdapter for terminal output.
┌─────────────────────────────────────────────────────────────────┐
│ CLIAdapter │
├─────────────────────────────────────────────────────────────────┤
│ sendMessage(convId, msg) → Output to stdout │
│ getStreamingMode() → 'batch' │
│ getPlatformType() → 'cli' │
│ ensureThread() → passthrough │
│ start() / stop() → no-op │
└─────────────────────────────────────────────────────────────────┘
Code: packages/cli/src/adapters/cli-adapter.ts:13-47
Key Dependencies
| Function | Package | Location | Purpose |
|---|---|---|---|
discoverWorkflowsWithConfig(cwd, config) |
@archon/workflows/workflow-discovery |
workflows/src/workflow-discovery.ts |
Find and parse workflow YAML |
executeWorkflow(...) |
@archon/workflows/executor |
workflows/src/executor.ts |
Run workflow steps |
getIsolationProvider() |
@archon/isolation |
isolation/src/factory.ts |
Get WorktreeProvider singleton |
conversationDb.* |
@archon/core |
core/src/db/conversations.ts |
Conversation CRUD |
codebaseDb.* |
@archon/core |
core/src/db/codebases.ts |
Codebase CRUD |
isolationDb.* |
@archon/core |
core/src/db/isolation-environments.ts |
Worktree tracking |
git.* |
@archon/git |
packages/git/src/ |
Git operations |
closeDatabase() |
@archon/core |
core/src/db/connection.ts |
Clean shutdown |
Conversation ID Format
CLI conversations use ID format: cli-{timestamp}-{random}
Example: cli-1705932847321-a7f3b2
Generated at: packages/cli/src/commands/workflow.ts:26
Worktree Reuse Logic
When --branch is provided:
- Lookup:
isolationDb.findActiveByWorkflow(codebaseId, 'task', branchName) - Health check:
provider.healthCheck(path)on existing - Reuse: If found and healthy (warns if
--fromwas specified but not applied) - Create: If not found or unhealthy — passes
fromBranchto provider if specified via--from
Worktrees stored at: ~/.archon/worktrees/<repo>/<branch-slug>/
Code: packages/cli/src/commands/workflow.ts:177-219
Exit Codes
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Error (logged to stderr, including not in git repo) |
Database Connection
- Connection opened on first database call
- Always closed in
finallyblock after command completes - Default: SQLite at
~/.archon/archon.db(zero setup, auto-initialized) - Optional: PostgreSQL when
DATABASE_URLis set (for cloud/advanced deployments)
Code: packages/cli/src/cli.ts:229-241