ci(decisions): reconcile the Current Decisions pages with a scheduled job

MI
7h ago
+328-0

Add a GitHub Actions job that keeps the Current Decisions pages (docs/decisions/) up to date. It ports chainloop-dev/platform#7115 to this repository, with the fixes of chainloop-dev/platform#7178 and chainloop-dev/platform#7194.

The job runs the eng-adr reconcile skill of chainloop-dev/brain with claude-code-action, in the skill's scheduled mode: it asks no questions, writes only the changes that need no person, and lists the open questions in the PR body. When the pages change, it opens or updates one draft PR on the decisions-reconcile-scheduled branch. When nothing changes, it opens no PR. The PR has the title adr: update YYYY-MM-DD (UTC date of the run) and the labels automated and skip-ai-session.

The job runs at 05:00 UTC from Monday to Friday, and can be started manually with an optional area. A manual run is a dry run by default: it uploads the diff and the PR body as an artifact.

  • Claude authenticates with workload identity federation (no Anthropic API key).
  • Claude gets read-only GitHub tokens. It reads the states of the GitHub issues of the specs through the collector, with the job token. The job fails when Claude changes a file outside docs/decisions/ and CLAUDE.md.
  • The chainloop-eng GitHub App commits, pushes and opens the PR.

The job fails, and never reports "no change", when the run is not complete:

  • "Check sources" runs before Claude. It reads one issue and the pull requests of the repository with the job token, checks that the brain plugin has skills/eng-adr/SKILL.md, and runs the collector decisions.py on the checkout.
  • Claude stops and writes source-error.txt when a call to GitHub or the collector fails or is refused. "Check Claude run" fails when that file exists.
  • Subagents run in the foreground (CLAUDE_CODE_DISABLE_BACKGROUND_TASKS=1). A headless run ends with Claude's turn, so a background subagent's result is lost. Claude writes done.txt as its last action, and "Check Claude run" fails without it.
  • The Claude output is uploaded after each run, to show what a run did.

The prompt names the skill steps by title, and lists the changes that need no person and the changes that need a person.

Differences from the platform version:

  • The job runs only on chainloop-dev/chainloop, not on forks.
  • The federation rule ID comes from the repository variable ANTHROPIC_FEDERATION_RULE_ID, because the platform rule is restricted to the platform repository.
  • No Linear. The specs of this repository use GitHub issues.
  • The workflow grants permissions per job (with issues: read), and the write token is limited to this repository.
  • The bot commits are signed (sign-commits) and carry an Assisted-by: Claude Code trailer, as this repository requires.

Setup before the first run:

  • Create a federation rule restricted to repo:chainloop-dev/chainloop:ref:refs/heads/main and set its ID in the variable ANTHROPIC_FEDERATION_RULE_ID.
  • Add the secret CHAINLOOP_ENG_APP_PRIVATE_KEY.
  • Install the chainloop-eng app on chainloop (contents and pull requests: write) and brain (contents: read).

AI disclosure: this change was written with Claude Code.