Skip to content

Latest commit

 

History

History
71 lines (55 loc) · 5.39 KB

controller.md

File metadata and controls

71 lines (55 loc) · 5.39 KB

Label-only controller

Status: built, dry run by default. Part of autonomous-dev.md (Phase 1, PR C). .github/workflows/controller.yml runs .github/scripts/controller.mjs every 30 minutes and on demand. It uses only the built-in GITHUB_TOKEN: no LLM, no secrets, no GitHub App, no stored token.

What it does

It manages labels and nothing else. It never merges, approves, comments on, edits or closes anything, and it never checks out or runs a PR or an issue. Issue and PR text is read as data (a regex for Fixes #N); the changed files of a PR are read through the API and judged by the same rules as the risk gate (.github/agent/risk-rules.json).

Rule Effect
Every open PR (50 most recently updated, not hold) risk:T0..risk:T3 from the risk gate, replacing a stale risk:T*. If the files cannot be read, it changes nothing
An agent's PR adds agent-pr. A PR is an agent's when its author is in agentAuthors, or its branch in this repository starts with an agentBranchPrefixes entry (agent/), or a branch in this repository says Fixes #N for an issue that is agent-ready or agent-working. A fork PR counts by author only. The label is never removed
An issue labeled agent-ready or agent-working removes agent-ready and agent-working when the last agent-ready was set by someone who is not a maintainer, or when someone who is not a maintainer edited the text or title after it. Re-labeling by a maintainer re-approves it
A claim (agent-working) removes agent-working when it is older than claimTtlHours (6) and no open PR that says Fixes #N has a commit or was opened within that time
hold on the issue or PR everything is left alone
A label that does not exist in the repository the add is skipped and reported, never created (the API would create it with a default color). Removals still happen

Maintainers are the list in .github/agent/controller.json (Birfy, hsliuustc0106); editing it is T3. An editor GitHub cannot name (a deleted account) is not a maintainer. The controller can never add agent-ready or agent-working: validatePlan refuses it, and so does anything else outside the table above.

Modes and switches

Switch Where Effect
(default) nothing set dry run: the plan job reads (read-only token) and writes the proposed changes to the job summary; nothing is changed, and the apply job does not run
CONTROLLER_LIVE = true repository variable (Settings, Secrets and variables, Actions, Variables) live: the apply job adds and removes the labels. Any other value, including TRUE or 1, stays dry run
AGENT_PAUSE = true repository variable stops it completely: nothing is read, proposed or changed. The same variable is meant for the agents' scheduler
disable or delete the workflow Actions tab, or delete controller.yml off

This PR sets no variable. To go live: a maintainer runs node .github/scripts/sync-labels.mjs --repo ThinkFlowLab/FlyBot --apply (creates risk:T0..T3), reads a few dry-run summaries (Actions, Controller, run, summary; or workflow_dispatch one), and then sets CONTROLLER_LIVE=true.

Permissions (least per job)

Job GITHUB_TOKEN permissions When
plan contents: read, issues: read, pull-requests: read always
apply contents: read, issues: write, pull-requests: write only when CONTROLLER_LIVE is true and the plan has operations

Workflow-level permissions are {}. pull-requests: write is there because labeling a PR goes through the issues API and GitHub accepts either permission for it; the script calls only these writes: POST .../issues/N/labels and DELETE .../issues/N/labels/NAME (the tests check that the source has no other write, no merge, review, comment or close endpoint, no eval, no network access besides gh). Whether issues: write alone is enough for a PR was not testable without going live; if the first live run answers 403 on a PR, that is the line to look at.

The plan job passes the plan to apply as a job output (numbers, fixed label names and fixed reason codes only). The apply job validates it again, re-reads each target, and skips it if it is closed, has hold, or is already as planned. Nothing from an issue or PR reaches a shell: the workflow has no ${{ }} in a run: line and passes everything by env. The script and controller.json come from the default branch (checkout of default_branch, no credentials kept).

Limits

  • It cannot see an edit older than the last 50 body revisions or the last 100 label/rename events of an issue; if it cannot find when agent-ready was set it leaves the issue alone and says so in the summary.
  • Labels only: it leaves no comment, so the reason for a removal is in the job summary (the timeline shows github-actions removed the label).
  • Events caused by GITHUB_TOKEN start no workflows, so nothing chains from its labels; it runs on the schedule.
  • GitHub stops scheduled workflows of a public repository after 60 days without repository activity.
  • 50 PRs and 50 issues per label per run (controller.json); about 3 API calls per PR per run.

Try it by hand (read-only)

GH_REPO=ThinkFlowLab/FlyBot node .github/scripts/controller.mjs plan   # prints the plan; changes nothing
node --test .github/scripts/controller.test.mjs