Skip to content

Docs Updater Workflow Design

Workflow and domain design for the docs-updater loop (on-loop-docs-updater.yaml).

Layer Document
Platform Multi-Branch Loops Design
Caller shell Loop Caller Workflows Design
Invariants Loop Engineering Design

Artifacts: on-loop-docs-updater.yaml · skill docs-updater · docs-updater/scripts/detect_changes.sh

Shared caller keys: Loop Caller Inputs Reference.

Purpose

Detect documentation drift from code changes on integration branches and open fix PRs after the docs-updater skill runs.

Supported use cases

  • Cron scan of integration branches for git-diff facts (changed_files, affected_docs, …)
  • Semantic review and fix of high-priority stale references or missing doc content
  • Open an L2 review PR to the watch integration branch
  • Coordinate with peer loops via workflow concurrency when multiple loops target the same branch

Out of scope

  • PR head healing (pr_enabled default off)
  • Creating documentation from scratch; non-documentation file edits
  • Loop state and detect script management

docs-updater dual paths

Path Trigger Input
Interactive / hook Pre-commit, user-invoked scripts/detect_changes.sh JSON (mechanical facts)
Loop on-loop-docs-updater.yaml Same detect script facts in prompt; skill builds findings[] in Execute

Both paths share docs-updater/scripts/detect_changes.sh for mechanical facts only. The entry skill (Execute) builds semantic findings[] — detect and the caller do not emit semantic classifications.

Detect scope axis (normative)

Normative cross-skill definition: Detect scope axis and interactive discovery.

Path --scope Notes
Loop (state cursor) range --since <sha> Unchanged — detect limits to <since>..HEAD changes
git hook / pre-commit staged Index diff only; untracked files are not visible until added
Interactive free-form all Breaking (2026-08-10): full candidate-doc enumeration — not git diff HEAD + untracked

Loop callers must not rely on --scope all for worktree sync; use staged (hook) or range (automation).

Detect → findings pipeline (loop domain)

  1. Detect script emits mechanical facts: changed_files, deleted_files, renamed_files, affected_docs, commit_range, skip.
  2. Execute agent (docs-updater on the automation path) maps facts into findings[] with file, reason, and source_commit, then classifies and patches per skill checklists.
  3. Field semantics and ## Constraints edit gate: common-loop-triage-format.md and skill references/category-input-schema.md / category-automation-envelope.md (automation path only).

Modes

Mode Default Behavior
integration on Detect on watch branch → fix PR to same branch
pull_request off not supported for this loop

Caller inputs

Keys are passed in on-loop-docs-updater.yaml via with: on ci-loop-caller.yaml (alphabetically ordered). Multiline values (agent_checker_instructions, agent_maker_instructions) are defined inline in the caller workflow.

Shared semantics: Loop Caller Inputs Reference. Platform branch/finalize caps: canonical table.

Input / JSON key Description Dogfood value
agent_maker_max_turns Max maker agent turns per loop attempt (one Agent→Verify cycle). 100
agent_maker_model Maker model ID. Cursor: agent --list-models. claude-sonnet-5
agent_maker_effort Maker reasoning effort. Only engines with an effort flag (claude) consume it medium
agent_loop_max_attempts Max Agent→Verify retry cycles before finalize records failure. 3
agent_checker_instructions Checker APPROVE/REJECT rubric. Doc-only edits; factual consistency; no sensitive data. Inline in caller workflow
agent_checker_max_turns Max checker agent turns per verification. 100
agent_checker_model Checker model ID. Cursor: agent --list-models. claude-opus-5
agent_checker_effort Checker reasoning effort. Only engines with an effort flag (claude) consume it medium
allowlist Comma-separated globs the maker may modify. Must align with docs-updater scope. docs/**/*.md,README.md,mkdocs.yml
branch_match Comma-separated integration branch patterns to watch for doc drift. main
branch_state Branch for .loop/* persistence, state migration, and watch fallback. main
budget_max_runs_per_day Daily run cap keyed by loop_name. Caller input; .loop/loop-budget.json overrides when present. 1
budget_max_tokens_per_day Daily aggregated token cap across loops. 1000000
detect_script Domain detect script path (shared with docs-updater hook path). .agents/skills/docs-updater/scripts/detect_changes.sh
engine AI engine (claude, copilot, codex, cursor). Maps AGENT_TOKEN to engine env. claude
delivery Platform delivery after APPROVE (open_pr for dogfood). open_pr
infer_files_pattern Extended regex to infer file paths from checker text. See caller workflow
level Autonomy level (L1, L2, L3). L2 opens review PR. L2
loop_name Loop identifier; state file .loop/state-docs-updater.json. docs-updater
max_targets_per_schedule Max targets per cron tick after priority filters. 3
may_edit Agent worktree edit gate (true for dogfood). true
no_changes_verdict APPROVE or REJECT when maker produces no file diff. REJECT
pr_body Optional static prefix (dogfood: ""). loop-finalize composes agent Overview/Summary + mechanical sections. See Loop PR Body Readable Design. ""
pr_title PR title when finalize strategy is open_pr. chore(docs-updater): automated documentation update (loop-docs-updater)
agent_maker_instructions Domain instructions: run docs-updater automation path; address documented findings. Inline in caller workflow
pr_enabled Enumerate open PR heads. docs-updater uses integration branches only. false
agent_maker_skill_name Skill package to invoke. docs-updater

Domain detect environment (detect_domain_env_json)

JSON key Description Dogfood value
DOCS_UPDATER_DOC_GLOBS Comma-separated doc file globs for git-diff analysis docs/**/*.md,README.md
DOCS_UPDATER_EXTRA_FILES Additional non-glob paths mkdocs.yml

When DOCS_UPDATER_DOC_GLOBS is unset, detect falls back to a repository-wide *.md find with standard repo_paths pruning (excludes .agents/, generated trees, etc.). Production callers should set globs explicitly; the fallback is mainly for local runs and tests.

Hook / manual (appendix)

Not a loop caller; configure via environment when invoking detect_changes.sh outside defaults.

Env var Description Default
DOCS_UPDATER_DOCS_ROOT Documentation tree root docs
DOCS_UPDATER_SITE_CONFIG Site navigation config path mkdocs.yml

| write_target | Agent artifact when may_edit is true (fix for dogfood). | fix |

Detect

Integration mode only

Per watch branch, loop-detect checks out the branch and invokes detect_changes.sh with targets["integration:<branch>"].last_sha.

Detect script outputs facts (not semantic findings):

Field Role
changed_files, deleted_files, renamed_files Git diff summary
affected_docs Candidate doc paths for agent review
commit_range Passed through prompt context
skip true when no doc-impacting change

Skill (docs-updater automation path) builds findings[] with semantic reason from these facts.

loop-detect emits per-branch target_json:

  • from.ref = HEAD on watch branch
  • to.branch = watch branch
  • finalize = open_pr

Do not use ci-sweeper workflow-run / gh run list detect.

Stable filters (detect only)

  • Circuit breaker on targets[key].consecutive_failures
  • Budget (platform)

No infra/env classification — not applicable.

State fields (per target key)

Field Role
last_sha Scan cursor; advances when fix PR merges (on-loop-state-promote)
pending Written at finalize on open_pr; promoted to last_sha on merge
outcome pr-created, rejected, no-op, …
consecutive_failures Circuit breaker

No workflow_run_id / ci ledger.

Execute

  • Worktree from target.from on integration branch
  • Checker diff baseline: to.branch
  • verifier_context: detect fact summary (changed files, affected docs). Platform always wires; may be brief

Finalize

PR body is composed by loop-finalize from agent ## Overview / ## Summary (skill-owned) plus mechanical sections. Dogfood sets pr_body: "". See Loop PR Body Skill Contract.

Always open_pr to to.branch at L2. L3 push rarely appropriate for docs-updater; if enabled, requires explicit promotion review.

No domain_persistence_script.

Merge-gated cursor: Same platform rule as all L2 open_pr loops — pending at finalize, last_sha on fix PR merge via on-loop-state-promote.yaml. See State delivery philosophy.

State delivery

See State delivery philosophy for platform rules.

Target (dogfood): merge-gated pending + on-loop-state-promote — same as changelog.

Persistence: state-docs-updater.json on branch_state via finalize inside ci-loop-agent.

Implementation Checklist

Shared platform: Multi-Branch — Shared platform checklist.

Loop-specific

  • [x] docs-updater/scripts/detect_changes.sh (facts output)
  • [x] on-loop-docs-updater.yaml dogfood caller via ci-loop-caller
  • [x] verifier_context on execute path (build_verifier_context_from_result .affected_docs branch)
  • [x] docs-updater skill automation path + references
  • [x] Bats suite for detect script (TEST-00)

Cross-Loop Note

If ci-sweeper and docs-updater both target integration:main, workflow concurrency and separate concurrency groups apply. CI failure on main is ci-sweeper priority; doc-only drift is docs-updater.

References