Files
MOPAC/harness.toml.example
mrcharles c869ac1b06 config: keyproxy mpk refs, loop daemon knobs, redmine status map, gitea section
mpk: key refs resolve through the ukrrs/mopac-keyproxy hop ([keyproxy]
url + token_ref, POST /v1/resolve, short in-memory cache); env:/file:/
literal: refs keep working untouched, so the harness runs with or
without keyproxy up. [loop] gains poll_interval_secs + state_dir for the
self-host daemon; [redmine.status_map] (quoted TOML keys) drives status
transitions; [gitea] carries the optional REPORT-commit step, off by
default. All hosts live in harness.toml, none in code.

💘 Generated with Crush

Assisted-by: Crush:glm-5.2
2026-08-28 22:05:41 -05:00

156 lines
4.9 KiB
TOML

# MOPAC harness configuration, v0 (2026-08-28).
#
# Copy to harness.toml and adjust. harness.toml is gitignored: secrets never
# live in this file, only refs (env:NAME | file:PATH | literal:VALUE |
# mpk:PLACEHOLDER via [keyproxy]; the bw: bitwarden ref lands with the key
# wrapper in build phase 3).
# Vertical / stack identity for this harness instance.
vertical = "demo"
# Where the bash tool executes and REPORTs land (relative to the CWD the
# harness is started from).
work_root = "."
report_dir = "reports"
[loop]
# Bounded turn: max LLM round trips per task (tool calls included).
max_rounds = 8
# `harness loop` daemon: Redmine scan interval and state location
# (append-only loop.jsonl, dedup by issue id + updated_on).
poll_interval_secs = 120
state_dir = "state/loop"
[redmine]
url = "https://rm.example.org"
key_ref = "env:HARNESS_REDMINE_KEY"
# Released scope: raw /issues.json filter params...
scope_query = "project=mopac&status_id=released&limit=25"
# ...or a saved custom query id (scope_query wins when both are set).
# scope_query_id = 42
# Custom field carrying the TASK class; issues without it get default_class.
class_field = "Class"
default_class = "primary"
# `harness loop` status transitions: after a REPORT is noted back on the
# issue, an issue whose CURRENT status matches a key here is moved to the
# value. Statuses are names (resolved via /issue_statuses.json); an empty
# map leaves status alone.
[redmine.status_map]
"In Progress" = "Done"
[litellm]
base_url = "http://192.168.3.78:4001"
key_ref = "env:HARNESS_LITELLM_KEY"
timeout_secs = 120
max_retries = 2
# KEYPROXY (optional): resolve `mpk:` key refs through the ukrrs/mopac-keyproxy
# hop (POST /v1/resolve, bearer auth). Without this section, env:/file:/
# literal: refs keep working as-is — the loop runs with or without keyproxy up.
# [keyproxy]
# url = "http://127.0.0.1:8082"
# token_ref = "env:HARNESS_KEYPROXY_TOKEN" # local ref only (no mpk: recursion)
# cache_ttl_secs = 60
# GITEA (optional, off by default): `harness loop` commits each REPORT file
# to this repo right after writing it (contents API, create-or-update).
# [gitea]
# url = "https://git.example.org"
# key_ref = "env:HARNESS_GITEA_KEY"
# owner = "ukrrs"
# repo = "MOPAC-reports"
# branch = "main" # empty = repo default branch
# commit_reports = false
# MODEL ROUTING v0 (static, config-only, no heuristics): [models] is the
# tier map (tier alias -> concrete proxy model); [models.classes] maps task
# classes to tiers. Requests go out with the CONCRETE model name resolved
# here. Swapping models (e.g. glm-4.7-flash -> glm-5.3-flash once it is
# configured on the proxy) is a one-line edit in this file.
[models]
mopac-study = "glm-4.7-flash" # flash tier
mopac-code = "glm-5.2" # flagship
mopac-review = "glm-5-turbo" # mid
mopac-primary = "glm-5.3" # default / flagship+
mopac-vision = "glm-4.6v" # vision when needed
default_tier = "mopac-primary"
[models.classes]
study = "mopac-study"
read = "mopac-study"
code = "mopac-code"
architecture = "mopac-code"
review = "mopac-review"
summarize = "mopac-review"
writeback = "mopac-review"
vision = "mopac-vision"
primary = "mopac-primary"
# Exec tool: allow-listed bash. Org preset: deny-first, read-leaning allow
# list, no sudo/ssh/network exfil. Compound commands are checked segment by
# segment; command substitution and subshells are always denied.
[tools.bash]
enabled = true
timeout_secs = 60
max_output_bytes = 100000
default = "deny"
deny = [
"sudo *",
"ssh *",
"scp *",
"nc *",
"curl *",
"wget *",
"rm -rf *",
]
allow = [
"pwd",
"ls *",
"cat *",
"head *",
"tail *",
"grep *",
"find *",
"wc *",
"echo *",
"env",
"git status",
"git diff *",
"git log *",
"git show *",
"go version",
"go build *",
"go vet *",
"go test *",
]
# MVP demo (Charles, 2026-08-28 ~19:00): `harness once --demo` runs this
# issue through LiteLLM; the GLM self-description lands as the REPORT.
[demo]
id = "demo-1"
subject = "MVP demo: GLM self-description"
prompt = "tell me about yourself"
class = "primary"
# EVENTS: the `harness events` webhook receiver (Redmine/Discourse/Gitea
# punch the harness; DESIGN "Events are V1 scope"). Secrets are refs only,
# resolved at startup, never logged. At least one secret_ref must resolve
# or the receiver refuses to start.
[events]
listen = ":4100" # bind address; publish on the LAN via docker -p
state_dir = "state/events" # append-only events.jsonl + dedup index
[events.redmine]
secret_ref = "env:HARNESS_REDMINE_WEBHOOK_SECRET"
# secret_header = "X-Redmine-Webhook-Secret" # default; match your plugin
[events.discourse]
secret_ref = "env:HARNESS_DISCOURSE_WEBHOOK_SECRET"
# secret_header = "X-Discourse-Webhook-Secret" # default
[events.gitea]
secret_ref = "env:HARNESS_GITEA_WEBHOOK_SECRET"
# Gitea always verifies via HMAC-SHA256 in X-Gitea-Signature; the
# secret_header override does not apply to it.