feat(pre-commit): stamp a standing git-workflow authorization into every AGENTS.md #1157

Merged
coilysiren merged 2 commits from feat/git-workflow-stamp into main 2026-08-20 08:52:48 +00:00
Member

Closes #1150.

What

Replaces the hand-written one-line **Git workflow** - stamp under ## Agent rules with a generated, marker-delimited managed block that states the repo's landing lane as a standing authorization.

The old stamp named the lane without ever saying the lane is permission, so agents kept stopping to ask before a commit, a branch, a push, or a pull request. A turn that stops there ends with the work stranded in a dirty worktree, which is the loss vector this issue records.

Lane semantics (corrected in bdf4817)

A slug names what the author agent does. This PR's first two drafts got it backwards, and the correction is the substance of the second commit:

  • merge-remote-main - the author commits and pushes straight to main.
  • pull-request-and-merge - the author opens a pull request and merges it itself once green. The fully autonomous lane. The PR is the record and the CI gate, not a wait state.
  • pull-request - the author opens the pull request and stops. The director merge lane picks it up from there. It has no -and-merge for exactly that reason.
  • remote-branch-only - the author pushes a branch and stops.

Draft 1 read -and-merge as "a human merges it later". Draft 2 moved it to "the director merges it". Both invert the pair against pull-request. The block now states the direction outright, and the tests reject the inverted phrasings rather than pinning wording.

Ward currently disagrees. agent_director_merge.go gates director merges on pull-request-and-merge and says "pull-request still needs a human", the inverse of the above. Filed as ward#1677 - worth an answer before the fleet sweep, since the block asserts these semantics in every repo.

Shipped

  • agentic_os/generators/generate_git_workflow.py - pure renderer plus check_drift, mirroring generate_agents_pointer. Lane comes from ward.workflow in the file's own frontmatter.
  • agentic_os/pre_commit/check_git_workflow.py - the git-workflow hook. Regenerates offline, fails on drift, a missing block, a block that no longer matches the declared lane, or a legacy stamp beside it.
  • scripts/apply-git-workflow.py - the applier. Idempotent, needs no per-repo argument.
  • Hook wired into .pre-commit-hooks.yaml and dogfooded in .pre-commit-config.yaml.
  • Corrected the same inversion in the coding-core-git-workflow skill, and added a lane check to the lane-blind merge mechanics in coding-core-git/references/merging.md.
  • 26 tests, docs section, FEATURES entry, AGENTS.md stamped.

The block

Details both fleet lanes, names the one this repo is on, and states the pre-authorization in MUST / ALWAYS / NEVER terms, while holding the two genuine walls - --no-verify and force-push - closed in the same breath. A repo declaring no lane gets the pull-request variant, which neither pushes main nor merges.

Org-agnostic with no base repo exempt: a lane binds in the base as it does in a consumer.

Rollout

DEFAULT_HOOK_IDS in scripts/apply-agentic-os-hooks.py is deliberately unchanged - the guard in test_apply_agentic_os_hooks.py requires a tagged aos-precommit release carrying the hook first. Fleet rollout order once that release lands: apply-git-workflow stamps the block, then the rollout enables the hook. Reversed, every commit breaks until the block arrives. A dry run across the workspace resolves 12 repos correctly by declared lane. Tracked at #1158.

Verification

  • pre-commit run --all-files green.
  • just test on the affected files green (83 passed). The 32 unrelated failures on this host (shell, gpg, git-identity, dev-base, statusline) reproduce with the change stashed.

🤖 Generated with Claude Code

Closes #1150. ## What Replaces the hand-written one-line `**Git workflow** -` stamp under `## Agent rules` with a generated, marker-delimited managed block that states the repo's landing lane **as a standing authorization**. The old stamp named the lane without ever saying the lane *is* permission, so agents kept stopping to ask before a commit, a branch, a push, or a pull request. A turn that stops there ends with the work stranded in a dirty worktree, which is the loss vector this issue records. ## Lane semantics (corrected in bdf4817) A slug names what the **author agent** does. This PR's first two drafts got it backwards, and the correction is the substance of the second commit: - `merge-remote-main` - the author commits and pushes straight to `main`. - `pull-request-and-merge` - the author opens a pull request and **merges it itself** once green. The fully autonomous lane. The PR is the record and the CI gate, not a wait state. - `pull-request` - the author opens the pull request and **stops**. The director merge lane picks it up from there. It has no `-and-merge` for exactly that reason. - `remote-branch-only` - the author pushes a branch and stops. Draft 1 read `-and-merge` as "a human merges it later". Draft 2 moved it to "the director merges it". Both invert the pair against `pull-request`. The block now states the direction outright, and the tests reject the inverted phrasings rather than pinning wording. **Ward currently disagrees.** `agent_director_merge.go` gates director merges on `pull-request-and-merge` and says "pull-request still needs a human", the inverse of the above. Filed as ward#1677 - worth an answer before the fleet sweep, since the block asserts these semantics in every repo. ## Shipped - `agentic_os/generators/generate_git_workflow.py` - pure renderer plus `check_drift`, mirroring `generate_agents_pointer`. Lane comes from `ward.workflow` in the file's own frontmatter. - `agentic_os/pre_commit/check_git_workflow.py` - the `git-workflow` hook. Regenerates offline, fails on drift, a missing block, a block that no longer matches the declared lane, or a legacy stamp beside it. - `scripts/apply-git-workflow.py` - the applier. Idempotent, needs no per-repo argument. - Hook wired into `.pre-commit-hooks.yaml` and dogfooded in `.pre-commit-config.yaml`. - Corrected the same inversion in the `coding-core-git-workflow` skill, and added a lane check to the lane-blind merge mechanics in `coding-core-git/references/merging.md`. - 26 tests, docs section, FEATURES entry, `AGENTS.md` stamped. ## The block Details both fleet lanes, names the one this repo is on, and states the pre-authorization in MUST / ALWAYS / NEVER terms, while holding the two genuine walls - `--no-verify` and force-push - closed in the same breath. A repo declaring no lane gets the `pull-request` variant, which neither pushes `main` nor merges. Org-agnostic with no base repo exempt: a lane binds in the base as it does in a consumer. ## Rollout `DEFAULT_HOOK_IDS` in `scripts/apply-agentic-os-hooks.py` is deliberately unchanged - the guard in `test_apply_agentic_os_hooks.py` requires a tagged `aos-precommit` release carrying the hook first. Fleet rollout order once that release lands: `apply-git-workflow` stamps the block, then the rollout enables the hook. Reversed, every commit breaks until the block arrives. A dry run across the workspace resolves 12 repos correctly by declared lane. Tracked at #1158. ## Verification - `pre-commit run --all-files` green. - `just test` on the affected files green (83 passed). The 32 unrelated failures on this host (shell, gpg, git-identity, dev-base, statusline) reproduce with the change stashed. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat(pre-commit): stamp a standing git-workflow authorization into every AGENTS.md
All checks were successful
ci / aos-cli-tests (pull_request) Successful in 18s
ci / ward-doctor (pull_request) Successful in 13s
ci / aos-eval-tests (pull_request) Successful in 42s
ci / gate (pull_request) Successful in 1m47s
0660f9d064
Each repo declared its landing lane once as `ward.workflow` frontmatter and
restated it by hand as a one-line `**Git workflow** -` stamp. The stamp named
the lane without ever saying the lane IS a standing authorization, so agents
kept treating a commit, a branch, a push, or a pull request as an action worth
stopping to ask about. A turn that stops there ends with the work stranded in a
dirty worktree.

Adds `generate_git_workflow`, the pure renderer and drift check, the
`git-workflow` pre-commit hook, and `scripts/apply-git-workflow.py`. The
generated block details both fleet lanes, names the one the file declares, and
states the pre-authorization in MUST / ALWAYS / NEVER terms while holding
`--no-verify` and force-push closed. Org-agnostic with no base repo exempt, and
a repo declaring no lane gets the undeclared variant rather than a guessed push
to `main`.

Fleet rollout waits on a tagged release carrying the hook, so `apply-git-workflow`
is authored here and DEFAULT_HOOK_IDS stays unchanged for now.

closes #1150

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
fix(pre-commit): a lane slug names what the author agent does, not someone else
All checks were successful
ci / aos-cli-tests (pull_request) Successful in 16s
ci / aos-eval-tests (pull_request) Successful in 6s
ci / ward-doctor (pull_request) Successful in 12s
ci / gate (pull_request) Successful in 1m32s
bdf4817c96
The first stamp read `pull-request-and-merge` as "opened by the agent, merged
by a human" and `pull-request` as the human-gated one. Both halves were wrong,
and the second draft only moved the merge from a human to the director.

The slug names the AUTHOR's own behavior. `pull-request-and-merge` carries the
merge because the agent that wrote the code merges its own pull request once it
is green, which makes it the fully autonomous lane. `pull-request` drops
`-and-merge` because the author stops at the pull request and the director
merge lane takes over.

Corrects the generated block, the `coding-core-git-workflow` skill, the
lane-blind merge mechanics in `coding-core-git`, and the docs. Tests now pin the
direction rather than the wording, and reject the inverted phrasings outright.
The undeclared variant renders `pull-request`, the lane that neither pushes
`main` nor merges.

Ward's `agent_director_merge` still gates director merges on
`pull-request-and-merge`, the opposite slug, so its behavior contradicts this
doctrine until someone reconciles it. Filed separately.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
coilysiren deleted branch feat/git-workflow-stamp 2026-08-20 08:52:49 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-flight-deck/agentic-os!1157
No description provided.