Step 9 — autonomous patch loop:
- patcher.py: clawdforge session → unified diff → worktree apply → verify recipe → push branch → open Gitea PR
- migration 007: patch_attempts (UNIQUE per finding+attempt, max 3 attempts)
- runner.py: post-parse hook fires patcher.maybe_draft_for_job when notify.auto_patch=true
- server.py: POST /jobs/{id}/patches, GET /patches, GET /patches/{id}
- digest.py: patch-drafted lines + open-follow-up count via Gitea PR state check
- mcp: crafting_table_draft_patch stub replaced with real implementation
- tests/test_patcher.py + tests/test_patches_api.py: 27 new tests
No auto-merge — patches stop at PR-open. Cobb merges.
Step 10 — production recipes:
- examples/recipes/clawdforge.json: 14 subprojects across all SDKs, audit nightly
- examples/recipes/cauldron.json: single Flask subproject, audit nightly
- examples/recipes/tradecraft.json: nightly audit, auto_patch=false (manual review)
- examples/register-all.sh: bulk-register helper with GITEA_TOKEN substitution
- README "Autonomous patch loop" + "First production recipes" sections
Tests: server 116→143, mcp 65→67. All green.
Spec: memory/spec-crafting-table.md
55 lines
2 KiB
Text
55 lines
2 KiB
Text
# crafting-table runtime config — every key is optional; defaults shown.
|
|
#
|
|
# Copy to `.env` and edit, or pass each key explicitly to `docker compose`.
|
|
|
|
# SQLite ledger location (created on first boot)
|
|
CRAFTING_DB=/data/crafting.db
|
|
|
|
# Where workspaces (bare clones + per-job worktrees) live
|
|
CRAFTING_WORKSPACE=/workspace
|
|
|
|
# Per-job log files: /data/jobs/<job_id>.log
|
|
CRAFTING_LOG_DIR=/data/jobs
|
|
|
|
# Admin bearer plaintext is written here on first boot, chmod 600
|
|
CRAFTING_ADMIN_BEARER=/data/admin-bearer.txt
|
|
|
|
# Bounded asyncio pool size — how many recipes can run concurrently
|
|
CRAFTING_MAX_CONCURRENT=4
|
|
|
|
# HTTP listen socket
|
|
CRAFTING_PORT=8810
|
|
CRAFTING_BIND=0.0.0.0
|
|
|
|
# Default per-job timeout in seconds (recipes can override via timeout_secs)
|
|
CRAFTING_DEFAULT_JOB_TIMEOUT=1800
|
|
|
|
# Override the default LAN allowlist if you want stricter scoping.
|
|
# Default: 10/8, 172.16/12, 192.168/16, 127/8, ::1/128
|
|
# CRAFTING_LAN_CIDRS=192.168.0.0/16,127.0.0.0/8
|
|
|
|
# Workspace gc — how often to sweep for stale worktrees, and the age cutoff.
|
|
CRAFTING_GC_INTERVAL=3600
|
|
CRAFTING_GC_AGE=86400
|
|
|
|
# --- Email digest (optional, off by default) -------------------------------
|
|
# If CRAFTING_SMTP_HOST is empty, the digest scheduler stays disabled and
|
|
# the server logs a "digest disabled" warning at startup. Setting it on
|
|
# enables the daily 06:00 PT loop.
|
|
# CRAFTING_SMTP_HOST=postfix.sulkta.com
|
|
# CRAFTING_SMTP_PORT=587
|
|
# CRAFTING_SMTP_USER=crafting-table@sulkta.com
|
|
# CRAFTING_SMTP_PASS=
|
|
# CRAFTING_SMTP_FROM=crafting-table@sulkta.com
|
|
# CRAFTING_SMTP_TLS=1
|
|
|
|
# --- Autonomous patch loop (wave 3, optional) ------------------------------
|
|
# All four CRAFTING_CLAWDFORGE_* + CRAFTING_GITEA_* must be set for the
|
|
# patcher to come up. Missing any → patcher disabled, /jobs/{id}/patches
|
|
# returns 503. Runner hook silently no-ops.
|
|
# CRAFTING_CLAWDFORGE_URL=http://192.168.0.5:8800
|
|
# CRAFTING_CLAWDFORGE_TOKEN=cf_...
|
|
# CRAFTING_GITEA_URL=http://192.168.0.5:3001
|
|
# CRAFTING_GITEA_TOKEN=
|
|
# CRAFTING_PATCHER_MAX_ATTEMPTS=3
|
|
# CRAFTING_PATCHER_BRANCH_PREFIX=crafting-table/auto/
|