Files
tireless/asset/config/config.toml.tmpl
rob thijssen 4e42f87576
Some checks failed
deploy / build (push) Has been cancelled
deploy / deploy (push) Has been cancelled
feat(tireless): scaffold workspace, dashboard and staged design plan
Autonomous issue-to-PR driver for Claude Code and OpenCode, structured per
lair/architecture generic.md.

Workspace: entities/core/data/agent library crates plus api, worker and cli
binaries. Two pieces of real logic land with tests — lane routing (cc for
judgement, oc for specification) and the limit governor.

Constraints encoded as code rather than comments:
- agents are spawned as vendor binaries; tireless never calls a provider API
- ANTHROPIC_API_KEY is never set by tireless, only passed through
- assert_not_anthropic refuses to start an OpenCode lane pointed at Anthropic
- every run passes the governor; provider rate-limit signals win over our own
  accounting

Deployment assets target bob.hanzalova.internal:23296 (registered in
port-allocations.md), fronted by hanzalova at tireless.internal.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DHhHtohxcdk1PL3tfnYJdH
2026-08-02 12:46:42 +03:00

94 lines
3.0 KiB
Cheetah

# tireless configuration.
#
# Rendered from this template by the deploy workflow, substituting {{PLACEHOLDER}}
# values from Gitea repo secrets. The rendered file is never committed.
#
# Secrets that belong in the *environment* rather than here (tokens, and the
# optional ANTHROPIC_API_KEY) live in /etc/tireless/tireless.env — see
# asset/systemd/tireless-runner.service.
[api]
# Loopback: nginx on the same host fronts it. Registered in
# architecture/port-allocations.md.
bind = "127.0.0.1:23296"
[database]
# mTLS, passwordless (architecture/generic.md §5). The host cert identifies the
# client; pg_ident.conf maps its CN to the role. Certs rotate every 24h.
host = "magrathea.kosherinata.internal"
port = 5432
database = "tireless"
user = "tireless_rw"
client_cert = "/etc/pki/tls/misc/{{DEPLOY_HOST_FQDN}}.pem"
client_key = "/etc/pki/tls/private/{{DEPLOY_HOST_FQDN}}.pem"
root_cert = "/etc/pki/ca-trust/source/anchors/root-internal.pem"
[forge.gitea]
base_url = "https://git.lair.cafe"
# Token for the dedicated `tireless` bot account, from the environment.
token_env = "GITEA_TOKEN"
[forge.github]
enabled = false
token_env = "GITHUB_TOKEN"
[poll]
# Floor on per-repo poll interval, in seconds. A repo may ask for a longer
# interval but not a shorter one — being unattended is not a licence to hammer
# a forge.
min_interval_seconds = 120
default_interval_seconds = 300
# Jitter added to each repo's schedule so N repos do not all fire together.
jitter_seconds = 30
[labels]
opt_in = "tireless"
mode_plan = "tireless/plan"
mode_implement = "tireless/implement"
force_cc = "tireless/agent:cc"
force_oc = "tireless/agent:oc"
state_claimed = "tireless/claimed"
state_blocked = "tireless/blocked"
state_done = "tireless/done"
[work]
# Per-repo bare mirrors and per-job clones live here.
root = "/var/lib/tireless"
# Keep a failed job's clone for this long so it can be inspected. Successful
# jobs are cleaned immediately.
failed_retention_hours = 72
[lane.cc]
# Claude Code. A subscription is one person's allowance: one session at a time.
max_concurrent = 1
max_runs_per_window = 12
window_hours = 5
# Wall-clock ceiling for a single run.
timeout_seconds = 3600
model = "opus"
# Consecutive failures before the lane stops asking for work.
failure_threshold = 3
[lane.oc]
# OpenCode against helexa cortex. The constraint here is the GPU fleet, not a
# bill, so the ceilings are far higher.
#
# This lane must never be pointed at Anthropic: OpenCode is a third-party
# harness, and driving an Anthropic subscription through one is the pattern
# Anthropic blocks. tireless refuses to start if `provider` or `base_url` looks
# Anthropic-shaped. See doc/plan/design.md §3.
provider = "lair-helexa"
model = "Qwen/Qwen3.6-27B"
base_url = "http://hanzalova.internal:31313/v1"
max_concurrent = 2
max_runs_per_window = 240
window_hours = 5
timeout_seconds = 2700
failure_threshold = 3
[quiet]
# Optional global quiet window in local time. No poll runs and no job is claimed
# between these times. Leave unset to run around the clock.
# from = "23:00"
# until = "07:00"