Skip to content

Git Completion Contract (Mandatory)

Standard ID: ES-GITCC Date: 2026-07-19 Updated: 2026-09-10 Authority: Engineering Standard — Bluefly Agent Platform Scope: All agent-executed tasks that produce code, configuration, or documentation changes in a Git repository. Docs agents are in scope. Chat reports are not completion.

This contract is the hard completion law. It supersedes any weaker reading that treated a local commit, a green test run, a pushed branch, or an open MR as done.

Related: AGENTS.md, git-discipline.md, git-standard.md, factory-operating-contract.md, blucity-operator-contract.md, beads-work-ownership-contract.md.


Axiom

Work on disk is not done. A commit is not done. A pushed branch is not done. An open MR is not done. A green MR is not done.

An agent is not finished because code exists in a worktree.

An agent is not finished because tests pass.

An agent is not finished because it reported a result in chat.

An agent is not finished because it pushed a branch.

An agent is finished only when valid completed work is durable in GitLab and integrated into release/v0.1.x, unless an explicit external blocker prevents that.

DONE (feature / fix / chore)
=
implemented
+ tested
+ committed
+ pushed
+ MR to release/v0.N.x
+ CI passed
+ merged into release/v0.N.x
+ merge verified
+ development package published (when the project produces an artifact)
+ verified
+ worktree removed
+ bead reconciled

Feature work does not wait for release/v0.N.x → main. That is a separate promotion lifecycle.

FEATURE_BEAD_CLOSES_AFTER_RELEASE_INTEGRATION=YES
FEATURE_BEAD_WAITS_FOR_MAIN=NO
THOMAS_FEATURE_MERGE_REQUIRED=NO
FEATURE_TO_RELEASE_AUTOMATIC=YES
RELEASE_TO_MAIN_AUTO_MERGE=NO
RELEASE_TO_MAIN_HUMAN_GATE=YES

Never knowingly leave finished valid work uncommitted.

That last rule exists because the estate already contains this defect class: a “polecat-done handoff push-step gap” where Refinery was handed unpushed branches, plus WIP that was uncommitted and had no authorizing bead.


HARD LAW: NEVER LEAVE VALID WORK UNCOMMITTED

VALID_COMPLETED_WORK + UNCOMMITTED = FAILURE

VALID_COMPLETED_WORK + UNPUSHED = FAILURE

VALID_COMPLETED_WORK + NO_MR = FAILURE

GREEN_MERGEABLE_MR + NOT_MERGED = FAILURE

MERGED_MR + ABANDONED_WORKTREE = CLEANUP_FAILURE

Do not end a session with valid completed work sitting only on disk.

If you modified tracked source and the change is valid:

YOU MUST COMMIT IT.

If you committed valid work:

YOU MUST PUSH IT.

If you pushed a feature branch:

YOU MUST OPEN OR UPDATE AN MR TO release/v0.1.x.

If the MR is green, approved as required, conflict-free, and acceptance criteria pass:

YOU MUST MERGE IT TO release/v0.1.x.

Do not merely report that it is “ready to merge.”

Do not ask Thomas:

Should I merge this feature into release?

If acceptance criteria are satisfied and policy permits merge: merge it. Thomas is not the feature merge-queue operator. Thomas owns only whether release/v0.N.x is ready to promote to main.

If policy or permissions prevent the agent from performing the merge, report that as an explicit blocker:

BLOCKED_BY=MERGE_PERMISSION_OR_OPERATOR_GATE

and do not claim completion.

A weekly limit, context limit, provider interruption, handoff, or session restart does not turn local filesystem state into completion.

Before loss of session capacity, preserve work:

commit → push → update MR → update bead/handoff

at minimum.


Required lifecycle

claim bead
→ create/use feature branch + isolated worktree
  (CANONICAL_ENGINEERING_WORKTREE_ROOT=[WORKSPACE-ROOT]/worktrees/<task>;
   FORBIDDEN=[WORKSPACE-ROOT]/BluCity/.gc/worktrees)
→ implement
→ test
→ commit
→ push
→ open MR to release/v0.1.x
→ fix CI / review findings
→ merge to release/v0.1.x
→ shared CI publishes the next development package (artifact projects)
→ verify branch is contained in release
→ remove completed worktree
→ remove merged local branch
→ close/update the **feature** bead with evidence

Do not close a development bead merely because implementation is complete locally. Close or finalize a feature bead only after:

DONE=YES requires:
MR_MERGED=YES
DEPLOYED=YES
RUNTIME_VERIFIED=YES
BEAD_CLOSED=YES
WORKTREE_DEREGISTERED=YES
WORKTREE_REMOVED=YES

RECEIPT MUST INCLUDE:
WORKTREE_PATH=
WORKTREE_REMOVED=YES

Do not keep the feature bead open waiting for promotion to main. Maintain one promotion bead per project/release line for the release/v0.N.x → main MR, target patch, readiness, and promotion verification. Feature beads may link to it; they are not blocked by it after they land in release.

Record the MR/commit/verification receipt in the Bead before final closure where the workflow supports it. If an MR cannot be merged because of an external gate, keep the Bead open/blocked with the exact blocker.


Branch law

Normal engineering work flows:

feature/fix/chore branch
→ release/v0.1.x
→ main only through the separate governed promotion process

Never:

feature → main
main → release/v0.1.x

Do not modify the separate release→main promotion workflow during a convergence sweep. Those MRs targeting main from release/v0.N.x are not feature work and must not be retargeted or auto-merged as if they were.

There must be exactly one active promotion MR per project for the active release branch. If none exists after the first release-branch change, create it. If one exists, update it — do not open a duplicate.

Automation may create/update the promotion MR, run CI, calculate the stable patch, generate notes, and mark ready. It must not merge it unless Thomas explicitly authorizes that promotion.

PROMOTION_MR_AUTO_CREATE=YES
PROMOTION_MR_AUTO_UPDATE=YES
PROMOTION_MR_DUPLICATES=0
AUTO_MERGE_RELEASE_TO_MAIN=NO

Versioning (patch-only automation, development sequence, shared gitlab_components owner) lives in git-standard.md.

Remotes use git@gitlab-bluefly:blueflyio/... — never [email protected]:.


Sweep every Rig

For every registered Rig, inspect:

  1. Dirty worktrees.
  2. Untracked files that appear to be implementation work.
  3. Local branches.
  4. Local-only commits.
  5. Remote feature branches.
  6. Pushed branches with no MR.
  7. Open MRs.
  8. MRs targeting the wrong branch.
  9. Failed pipelines.
  10. Mergeable green MRs that agents abandoned before merge.
  11. Branches already merged into release/v0.1.x.
  12. Worktrees belonging to already-merged branches.
  13. Beads marked complete whose Git lifecycle was never completed.
  14. Beads still open even though their corresponding MR is merged.

Do not assume age means disposable. Do not delete unexplained work.


Classification

Every discovered or in-flight work unit must be assigned exactly one state:

UNCOMMITTED
UNPUSHED
PUSHED_NO_MR
MR_OPEN
MR_WRONG_TARGET
MR_BLOCKED
MR_CI_FAILED
READY_TO_MERGE
MERGED_CLEANUP_PENDING
COMPLETE
ABANDONED_REQUIRES_REVIEW

Record:

RIG=
BEAD=
WORKTREE=
BRANCH=
DIRTY_FILES=
LOCAL_ONLY_COMMITS=
REMOTE_BRANCH=
MR=
MR_TARGET=
CI=
STATE=
BLOCKER=
NEXT_ACTION=

Do not assume age means disposable. Do not delete unexplained work. Unclear ownership is ABANDONED_REQUIRES_REVIEW, not a clean-tree license.


Execute — do not stop at inventory

UNCOMMITTED

Inspect the diff and determine whether it belongs to an authorized work unit.

If valid: run required tests → commit → push → open/update MR.

Never discard valid work just to obtain a clean tree.

UNPUSHED

Verify the commits, then push the branch and open/update an MR to release/v0.1.x.

PUSHED_NO_MR

Inspect branch intent and diff. If valid, open MR with TARGET=release/v0.1.x.

MR_WRONG_TARGET

If ordinary feature work incorrectly targets main, retarget it to release/v0.1.x provided doing so preserves the intended history and policy. Do not retarget a governed release/v0.1.x → main promotion MR.

MR_CI_FAILED

Investigate and fix the root cause. If the failure belongs to shared CI, fix blueflyio/gitlab_components. Do not introduce one-off consumer CI to bypass the shared component. Push the fix, rerun the pipeline, continue until PASS or genuinely blocked.

READY_TO_MERGE

When all of these hold:

CI=PASS
CONFLICTS=NO
TARGET=release/v0.1.x
ACCEPTANCE=PASS
REQUIRED_REVIEW=PASS

then merge the MR. The expected terminal state is MR_MERGED=YES, not MR_READY=YES. Do not ask Thomas whether to merge ordinary feature work into release/v0.N.x. Do not auto-merge a release/v0.N.x → main promotion MR.

MERGED_CLEANUP_PENDING

First prove containment:

git fetch origin
git merge-base --is-ancestor <branch-sha> origin/release/v0.1.x

Only after success: remove the worktree, remove the merged local branch, prune stale worktree metadata.

Use trash for filesystem deletion. Never shell rm. Never use git clean, git reset --hard, or git stash to hide unresolved work.


Session exit gate

Before any coding or docs agent stops, hands off, sleeps, or declares completion, it MUST run:

git status
git branch
git log for local-only commits
remote branch existence
MR existence/status
CI status
merge status
worktree cleanup status
bead status

The agent may exit normally only when:

UNCOMMITTED_VALID_WORK=0
UNPUSHED_COMMITS=0
PUSHED_BRANCH_WITHOUT_MR=0
GREEN_MERGEABLE_MR_LEFT_UNMERGED=0
MERGED_WORKTREE_LEFT_BEHIND=0

Otherwise continue executing.


Fleet sweep

When draining an estate, do not stop because one Rig is blocked.

record blocker → route blocker → continue to next work unit

The purpose is to drain existing valid engineering work into canonical GitLab state. Do not create unrelated feature work during a sweep.

Do not use:

rm
git clean
git reset --hard
git stash

to hide unresolved work.


Failure contract

If commit, push, MR creation, CI, or merge fails for a reason the agent cannot clear:

  • STOP that unit.
  • Report the exact error.
  • Set BLOCKER= to the named external authority or gate.
  • Do not claim completion.
  • Continue to the next independent work unit when sweeping a fleet.
STATUS: BLOCKED
BLOCKED_BY: <named gate>
Reason: <exact error>
Required operator action: <exact action>

The agent may never leave work in this state and report complete:

  • valid completed work uncommitted
  • committed locally and not pushed
  • pushed with no MR to release/v0.1.x
  • green mergeable MR left unmerged (unless BLOCKED_BY=MERGE_PERMISSION_OR_OPERATOR_GATE)
  • merged MR with an abandoned worktree

Final report (required)

Every completed task ends with:

Repository:
Branch:
Commit:
Remote:
Push: SUCCESS / FAILED
MR: URL
MR_TARGET: release/v0.1.x
CI: PASS / FAILED / BLOCKED
MR_MERGED: YES / NO
MERGE_VERIFIED: YES / NO
DEV_PACKAGE: YES / N/A / BLOCKED
WORKTREE_CLEANED: YES / NO / N/A
BEAD:
FEATURE_BEAD_WAITING_FOR_MAIN: NO
STATUS: COMPLETE / BLOCKED

A fleet sweep additionally returns:

RIGS_AUDITED=<n>

DIRTY_WORKTREES_FOUND=<n>
UNCOMMITTED_FOUND=<n>
UNCOMMITTED_COMMITTED=<n>

UNPUSHED_FOUND=<n>
UNPUSHED_PUSHED=<n>

PUSHED_NO_MR_FOUND=<n>
MRS_CREATED=<n>

WRONG_TARGET_MRS_FOUND=<n>
WRONG_TARGET_MRS_FIXED=<n>

FAILED_MRS_FOUND=<n>
FAILED_MRS_FIXED=<n>

READY_TO_MERGE_FOUND=<n>
MRS_MERGED_TO_RELEASE=<n>

MERGED_WORKTREES_FOUND=<n>
WORKTREES_REMOVED=<n>

MERGED_BRANCHES_FOUND=<n>
LOCAL_BRANCHES_REMOVED=<n>

BEADS_RECONCILED=<n>
BLOCKED_ITEMS=<n>
UNKNOWN_OR_UNSAFE_ITEMS=<n>

VALID_WORK_LEFT_UNCOMMITTED=0
VALID_COMMITS_LEFT_UNPUSHED=0
VALID_PUSHED_BRANCHES_WITHOUT_MR=0
GREEN_MERGEABLE_MRS_LEFT_UNMERGED=0
MERGED_WORKTREES_LEFT_BEHIND=0

FEATURE_TO_MAIN_MRS=0
MAIN_MERGED_INTO_RELEASE=NO
VALID_WORK_DISCARDED=0
RM_USED=NO

For anything remaining:

RIG | BEAD | BRANCH | WORKTREE | MR | STATE | BLOCKER | NEXT_ACTION

Exceptions

The operator may explicitly instruct an agent not to push or merge (local-only draft, staging for review). Document the exception and the reason. Absent that instruction, commit-only, push-only, and open-MR-only are incomplete.

Release→main promotion remains a separate governed workflow. This contract does not authorize merging release/v0.N.x to main. Versioning and the shared CI owner are git-standard.md.


artifact:
  owner:        BluCity-Docs
  consumer:     All agents performing Git operations, including docs agents
  purpose:      Prevents agents from claiming completion on uncommitted, unpushed, un-MRed, or unmerged valid work
  lifetime:     permanent
  authority:    BluCity-Docs
  replaces:     weaker ES-GITCC reading that treated remote push as completion
  enforcement:  agent-directive + operator sweep