BOARD_AGENT_COMMANDS is the one setting a headless agent cannot work around, and since the install stopped asking for it a project the detector does not recognise starts with it empty — correctly, but silently, until a run ended with an agent explaining it could not verify its work. Say it twice, in the two places it is learnable: a quiet `no agent commands` chip in the header (`--idle`, like the drive's "no driver", never `--alarm` — nothing is failing, something is unconfigured), and a note appended to the ticker line of the launches that would have run those commands, work and act-pr. Neither blocks anything: an agent that only edits files is still useful. What counts as empty is answered once, by `config.agent_commands()`, which splits exactly as the adapters' own `split_commands()` does — so whitespace and a lone comma are nothing configured on the board as well as at the launch, and the page reads the server's boolean rather than the raw setting.
151 lines
7.5 KiB
Bash
151 lines
7.5 KiB
Bash
# Task manager settings — copy to manager/local/.env (gitignored) and edit.
|
|
# Precedence: process environment > local/.env > these defaults.
|
|
#
|
|
# A first run of install.py with no local/.env writes this file there for
|
|
# you, asking only what it cannot guess (solo or team, which agent
|
|
# adapter, the project's test command) and leaving every other key at the
|
|
# default below. `install.py --setup` asks again later; nothing else ever
|
|
# rewrites your copy, so new keys added here by an update are yours to
|
|
# adopt by hand.
|
|
|
|
# Port the board serves on. Pinned by default so the URL is bookmarkable;
|
|
# adapters and drivers read the same value, so changing it here changes it
|
|
# everywhere at once.
|
|
BOARD_PORT=26071
|
|
|
|
# What the tab calls this project: the title is "<project> · bench", so two
|
|
# benches side by side are told apart at tab-bar width. Empty = the repo
|
|
# directory's name, which is the right answer unless every checkout on this
|
|
# machine is called "app".
|
|
BOARD_TITLE=
|
|
|
|
# Which agent adapter runs headless jobs (core/adapters/<name>, overridable
|
|
# in local/adapters/<name>). Ships with: claude, opencode.
|
|
BOARD_AGENT_ADAPTER=claude
|
|
|
|
# The binary each adapter launches jobs with. Point them at stub scripts
|
|
# to test the board's plumbing without spending tokens.
|
|
BOARD_CLAUDE_BIN=claude
|
|
BOARD_OPENCODE_BIN=opencode
|
|
|
|
# The model headless agents run on — an opaque vendor-native name the
|
|
# adapter passes through untranslated (claude: a model name or alias for
|
|
# --model; opencode: the "provider/model-id" config key). Empty = inherit
|
|
# the vendor's own default, i.e. whatever the CLI on this machine would
|
|
# pick anyway. The per-intent settings beat the general one for their
|
|
# intent only; _REVIEW covers both PR reviews and relevance checks. Work
|
|
# agents write code; reviews just read and judge — they can ride a
|
|
# cheaper, faster model.
|
|
BOARD_AGENT_MODEL=
|
|
BOARD_AGENT_MODEL_WORK=
|
|
BOARD_AGENT_MODEL_ACT_PR=
|
|
BOARD_AGENT_MODEL_REVIEW=
|
|
|
|
# Command prefixes headless agents may run in their worktree — the
|
|
# project's test/check commands, comma-separated, in plain neutral form
|
|
# (each adapter renders them into its vendor's permission rules; the
|
|
# git/gh grants per launch intent are built in). Headless runs have no
|
|
# human at a permission prompt, so a test runner missing from this list
|
|
# is a test the work agent cannot run. Left empty — or holding only
|
|
# whitespace or a lone comma — the board says so: a quiet `no agent
|
|
# commands` chip in the header, and a note on every work launch.
|
|
BOARD_AGENT_COMMANDS=python3 -m unittest
|
|
|
|
# What counts as a definition-of-done check (the Focus view's CHECKS
|
|
# panel) is a file, not an env var: core/checks ships a generic default,
|
|
# and a `checks` file in manager/local/ replaces it wholesale. Format
|
|
# (`<label>: <command regex>`) is documented in the default file itself.
|
|
|
|
# Where work-agent worktrees are created, relative to the repo root.
|
|
BOARD_WORKTREES=.worktrees
|
|
|
|
# GitHub plumbing. The gh CLI used for PRs (stub-able like claude); the git
|
|
# remote this board's work goes to (empty = the repo's first remote) — PRs
|
|
# and BOARD_SYNC both ride it, and a name set here is used as named, never
|
|
# swapped for another remote; and how often to poll open PRs of cards
|
|
# sitting in review/ for reviews and checks.
|
|
BOARD_GH_BIN=gh
|
|
BOARD_GIT_REMOTE=
|
|
BOARD_PR_POLL_INTERVAL=60
|
|
|
|
# Seconds a work-agent launch waits for `git fetch origin main` before
|
|
# giving up and branching from local HEAD. Fresh launches branch from
|
|
# origin/main when the fetch succeeds; no remote or a dead network just
|
|
# means today's behaviour, never a blocked launch.
|
|
BOARD_FETCH_TIMEOUT=10
|
|
|
|
# Claim on move, and commit it. On: a board-made move out of backlog/ or
|
|
# to-do/ writes **Assignee:** <git user.name> into the task file (first
|
|
# claim only — an existing assignee is preserved), walking a card back to
|
|
# backlog/ clears it, and each move commits itself — the move and the claim
|
|
# in one commit touching only that task file, messaged
|
|
# `board: <number> → <stage> (<name>)`. Nothing is pushed. Off (the
|
|
# default) means moves neither write nor clear the assignee and never
|
|
# commit — today's behaviour exactly, tasks/ committed by hand. An
|
|
# assignee added to a file by hand is still read and shown either way;
|
|
# the gate only governs whether a move writes it. Anything but
|
|
# empty/0/false/no/off turns it on.
|
|
#
|
|
# It is also what makes the claim mean something: on, ▸ start work refuses
|
|
# a card someone else holds (▸ take over is the deliberate way in) and
|
|
# claims an unheld one, and board-made edits to a card in place — the
|
|
# **PR:** line — commit themselves too. Off, nothing writes an assignee,
|
|
# so nothing reads one as a lock.
|
|
BOARD_COMMIT_MOVES=
|
|
|
|
# Sync boards through origin/main: the second half of team mode, and off
|
|
# by default. On, it implies BOARD_COMMIT_MOVES above (a move that never
|
|
# commits has nothing to publish) and: each board commit is pushed as it
|
|
# is made; a beat fetches and fast-forwards every BOARD_SYNC_INTERVAL
|
|
# seconds and once at startup; moves that arrive are narrated with their
|
|
# commit author's name; and a card someone else moved first wins the race
|
|
# — the local move is dropped with a toast naming who took it.
|
|
#
|
|
# Two things it will never do. It never publishes a commit the board did
|
|
# not make: one local-ahead commit on main without the `board: ` prefix
|
|
# stops the push and says which. And it never merges past a divergence or
|
|
# into a checkout with uncommitted changes — it says so and waits for a
|
|
# human. Both assume the discipline bench already has: code work lives in
|
|
# worktrees and PRs, so local main advances only through the board and
|
|
# origin.
|
|
#
|
|
# State syncs; reactions don't. A move that arrives over origin renders
|
|
# and narrates on every board but triggers nothing — opening a PR belongs
|
|
# to the board whose user made the move, and a review card left without
|
|
# one carries an explicit ↑ open PR action instead of N boards guessing.
|
|
# The same discipline moves merges to origin: merge & clean up runs
|
|
# `gh pr merge` and lets the beat deliver the result, so local main only
|
|
# ever fast-forwards. Whoever clicks needs merge rights on the repo.
|
|
#
|
|
# One board fetches twice a minute at the default interval; raise it on a
|
|
# rate-limited or metered remote. Sync rides one remote and `main` only —
|
|
# the remote BOARD_GIT_REMOTE names, or the checkout's first one, exactly
|
|
# as PRs do. Nothing to ride (no remote, or a BOARD_GIT_REMOTE naming one
|
|
# this checkout does not have) is a `sync stalled` chip and a ticker line,
|
|
# never a board that looks healthy while syncing nothing.
|
|
BOARD_SYNC=
|
|
BOARD_SYNC_INTERVAL=30
|
|
|
|
# Seconds between passes of the phase runner: a phase card being run
|
|
# (**Type:** Phase, in in-progress/) has its list worked into its own
|
|
# `phase/<stem>` branch one card at a time. Each pass recomputes what the
|
|
# phase needs from the cards and from git and does the one next thing, so
|
|
# raising this only makes a phase slower to notice, never wrong. Nothing
|
|
# runs at all while no phase is being run.
|
|
BOARD_PHASE_INTERVAL=30
|
|
|
|
# Seconds between disk polls of the stage directories.
|
|
BOARD_WATCH_INTERVAL=2
|
|
|
|
# In-memory caps: events kept per session, and board-level history
|
|
# (moves + agent lifecycle). Full logs always persist to local/state/.
|
|
BOARD_EVENTS_CAP=800
|
|
BOARD_HISTORY_CAP=300
|
|
|
|
# Where update.sh fetches the task-manager's releases from (owner/repo, or
|
|
# any GitHub URL). Normally unset: the shipped update.sh is stamped at
|
|
# build time with the repo it came from, and this overrides the stamp.
|
|
# Updates replace manager/core/ and the top-level scripts; they never touch
|
|
# tasks/, plans/, reference/ or manager/local/.
|
|
BENCH_SOURCE=
|