References:
- CONSTITUTION.md
- WORKFLOWS.md
- SECURITY.md
task_id, title, objective, status, priority, schema_version, timestamps, workspace_path
run_id, task_id, workflow, status, risk_level, run_path, timestamps, schema_version
All artifacts/*.json must include: schema_version, task_id, run_id, timestamps, status, metrics, warnings/errors.
Required artifacts baseline for any write-capable workflow:
- patch.diff (if changes)
- executor_report.json
- patch_apply_report.json
- verifier_report.json
- gate_report.json
- journal/events.jsonl
Spec files are stored in
docs/specs/<task_id>_SPEC.md(not run artifacts).
Filesystem:
- fs.read
- fs.write_file
- fs.apply_patch
Execution:
- exec.run (sandboxed, allowlisted, network policy)
Git:
- git.status, git.diff, git.commit(allowed_files)
DB:
- task., run., lease., worker.
Governance:
- approvals.write
- migrate.check/apply
The MCP server (src/ybis/services/mcp_server.py) exposes 7+ tools for external clients (FastMCP-based, with a local MCPServer wrapper for scripts):
task_create(title, objective, priority): Create a new task- Returns:
{task_id, title, objective, status, priority}
- Returns:
task_status(task_id): Get task and latest run information- Returns:
{task_id, title, objective, status, priority}
- Returns:
task_claim(worker_id): Claim a pending task for a worker- Returns:
{task_id, title, objective, run_id, run_path, status: "claimed"}or{task: null}if none available - Note: This atomically claims a task via lease mechanism. Only one worker can claim a task at a time.
- Returns:
task_complete(task_id, run_id, status, result_summary, worker_id): Mark task as complete and release lease- Returns:
{task_id, run_id, status, result_summary, lease_released: true}
- Returns:
artifact_read(task_id, run_id, artifact_name): Read artifact from a run- Returns:
{content: {...}, raw: "..."}or{error: "..."} - Common artifacts:
plan.json,verifier_report.json,gate_report.json,executor_report.json
- Returns:
artifact_write(run_id, name, content): Write artifact to a run's artifacts directory- Returns:
{run_id, artifact_name, artifact_path, status: "written"} - Note: This is used by external workers to write execution results.
- Returns:
approval_write(task_id, run_id, approver, reason): Write approval for blocked run- Returns:
{task_id, run_id, approver, status: "approved"} - Creates
approval.jsonartifact that allows the run to resume.
- Returns:
# 1. Claim a task
result = await mcp.task_claim(worker_id="my-worker")
if result["task"]:
task_id = result["task_id"]
run_id = result["run_id"]
# 2. Execute work (external logic)
# ... do work ...
# 3. Write artifacts
await mcp.artifact_write(run_id, "executor_report.json", json.dumps(report))
# 4. Complete task
await mcp.task_complete(task_id, run_id, "completed", "Work done", "my-worker")Input: Task object with title and objective
Output: Plan object with:
objective: Clear description of what to dofiles: List of file paths to modifyinstructions: Step-by-step instructionssteps: Multi-step plan (optional)referenced_context: Relevant codebase context from RAG
Process:
- Planner queries vector store (RAG) for relevant context
- Planner uses Code Graph for impact analysis ("Changing X affects Y, Z")
- Planner uses LlamaIndex for legacy code context (if available)
- LLM generates structured JSON plan
- Plan includes impact warnings from dependency analysis
Spec-First Protocol:
- Architect (What/Why): Defines requirements
- Spec Writer (How): Creates technical spec (implicit in plan)
- Executor (Implementation): Implements plan exactly
Forbidden: "Cowboy Coding" - All code must trace back to a plan/spec.
Purpose: Multi-worker coordination with atomic task claiming.
- Tasks are claimed via atomic database operations
- Only one worker can hold a lease for a task at a time
- Leases have TTL (default: 300 seconds)
- Workers must send heartbeats to renew leases
- Startup: Worker initializes DB connection, generates unique
worker_id - Poll Loop: Worker polls for pending tasks every
poll_intervalseconds - Claim: Worker attempts to claim a task via
claim_task(task_id, worker_id, duration_sec) - Heartbeat: Background thread sends heartbeats every
heartbeat_intervalseconds - Execute: Worker executes workflow (plan → execute → verify → gate)
- Complete: Worker updates task status and releases lease
- Heartbeat updates lease expiration time
- If heartbeat fails, lease expires and task becomes available again
- Prevents "zombie" workers from holding tasks indefinitely
worker = YBISWorker(worker_id="worker-1", poll_interval=5, heartbeat_interval=60)
await worker.start() # Runs until stoppedKey Methods:
start(): Start worker loop and heartbeat threadstop(): Gracefully stop worker_poll_and_execute(): Main polling loop (internal)_heartbeat_loop(): Background heartbeat thread (internal)