From 9e39087a0a0e1ebd0e13bc18704690b2ede70904 Mon Sep 17 00:00:00 2001 From: Erich Blume Date: Mon, 23 Feb 2026 15:33:18 -0800 Subject: [PATCH] Formalize C0/C1/C2 change classification process Redefine the three change classes with clearer boundaries: - C0: direct-to-main commits for low-risk, fix-forward-safe changes - C1: feature branch + PR with docs-first workflow and branch deployment - C2: Mikado Branch Invariant enforcing strict commit ordering (card commits first, code progress, card closures) with branch resets on new prerequisite discovery Co-Authored-By: Claude Opus 4.6 --- CLAUDE.md | 24 +-- .../formalize-change-classification.doc.md | 1 + docs/how-to/agent-change-process.md | 153 ++++++++++++------ docs/how-to/how-to.md | 2 +- docs/tutorials/ai-assistance-guide.md | 15 +- mise-tasks/docs-mikado | 4 +- 6 files changed, 131 insertions(+), 68 deletions(-) create mode 100644 docs/changelog.d/formalize-change-classification.doc.md diff --git a/CLAUDE.md b/CLAUDE.md index f1ba123..d185575 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -15,25 +15,31 @@ blumeops is Erich Blume's GitOps repository for personal infrastructure, orchest 1. **Always run `mise run ai-docs -- --style=header --color=never --decorations=always` at session start** This will refresh your context with important information you will be assumed to know and follow. 2. **Always use `--context=minikube-indri` with kubectl** (or `--context=k3s-ringtail` for ringtail services) - work contexts must never be touched -3. **Feature branches only** - checkout main, pull, create branch, commit often -4. **Create PRs via `tea pr create`** - user reviews before deploy, merges after +3. **Classify the change as C0/C1/C2 before starting** (see below) — this determines branching and PR requirements +4. **Feature branches + PRs for C1/C2** - checkout main, pull, create branch, open PR via `tea pr create`. C0 goes direct to main. 5. **Check PR comments with `mise run pr-comments `** before proceeding 6. **Add changelog fragments** - `docs/changelog.d/..md` Types: `feature`, `bugfix`, `infra`, `doc`, `ai`, `misc` 7. **Test before applying** - dry runs (`--check --diff`), syntax checks, `ssh indri '...'` -8. **Wait for user review before deploying** -9. **Never merge PRs or push to main without explicit request** +8. **Wait for user review before deploying** (C1/C2) +9. **Never merge PRs or push to main without explicit request** (C0 commits to main are fine) 10. **Verify deployments** - `mise run services-check` ## Change Classification Before starting work, classify the change: -| Class | Scope | Process | -|-------|-------|---------| -| **C0** | Quick fix, single-file, obvious | Read `ai-docs`, implement directly | -| **C1** | Moderate, potential hidden complexity | Mikado method, single session, single PR | -| **C2** | Complex, multi-session | Mikado method, documentation-driven, single PR | +| Class | Name | When to use | Key trait | +|-------|------|-------------|-----------| +| **C0** | Quick Fix | Small, low-risk, fix-forward safe | Direct to main, no PR | +| **C1** | Human Review | Moderate complexity or risk | Feature branch + PR, docs-first | +| **C2** | Mikado Chain | Multi-phase, multi-session, high complexity | Mikado Branch Invariant | + +**C0** — commit directly to main. No branch or PR needed. Fix forward if problems arise. + +**C1** — feature branch with early PR. Search related docs first, write documentation changes before code, deploy from the unmerged branch (ArgoCD `--revision`, Ansible from checkout). Upgrade to C2 if complexity spirals. + +**C2** — feature branch governed by the Mikado Branch Invariant: all Mikado card commits come first, then code progress commits, then card-closing commits. Reset the branch when new prerequisites are discovered. See [[agent-change-process]] for the full methodology. diff --git a/docs/changelog.d/formalize-change-classification.doc.md b/docs/changelog.d/formalize-change-classification.doc.md new file mode 100644 index 0000000..f9d271b --- /dev/null +++ b/docs/changelog.d/formalize-change-classification.doc.md @@ -0,0 +1 @@ +Formalize C0/C1/C2 change classification: C0 allows direct-to-main commits, C1 adds docs-first workflow with branch deployment, C2 introduces the Mikado Branch Invariant for strict commit ordering on multi-phase changes. diff --git a/docs/how-to/agent-change-process.md b/docs/how-to/agent-change-process.md index 236d9d3..c36e14d 100644 --- a/docs/how-to/agent-change-process.md +++ b/docs/how-to/agent-change-process.md @@ -1,7 +1,7 @@ --- title: Agent Change Process -modified: 2026-02-20 -last-reviewed: 2026-02-22 +modified: 2026-02-23 +last-reviewed: 2026-02-23 tags: - how-to - ai @@ -15,71 +15,125 @@ How to classify and execute infrastructure changes, especially when working with Before starting work, classify the change: -| Class | Scope | Process | -|-------|-------|---------| -| **C0** | Quick fix, single-file, obvious | Read `ai-docs`, implement directly | -| **C1** | Moderate, potential hidden complexity | Mikado method, single session, single PR | -| **C2** | Complex, multi-session | Mikado method, documentation-driven, single PR | +| Class | Name | When to use | Key trait | +|-------|------|-------------|-----------| +| **C0** | Quick Fix | Small, low-risk, fix-forward safe | Direct to main, no PR | +| **C1** | Human Review | Moderate complexity or risk | Feature branch + PR, docs-first | +| **C2** | Mikado Chain | Multi-phase, multi-session, high complexity | Mikado Branch Invariant | + +When in doubt, start at C1. Upgrade to C2 if complexity spirals or the user requests it. ## C0 — Quick Fix -1. Run `mise run ai-docs` to load context -2. Implement the change directly -3. Commit, push, create PR - -Examples: fix a typo, bump a version, add a simple config value. - -## C1 — Guided Change (Single Session) - -Use the [Mikado method](https://mikadomethod.info/) within a single session: +A change where the risk is low enough that problems can be quickly fixed forward. 1. Run `mise run ai-docs` to load context -2. Attempt the change on a feature branch, amending a single commit as you iterate -3. **If it works:** push and create PR -4. **If it fails:** revert the broken change (`git revert`), then: - - Amend or add a commit with documentation updates noting what prerequisite was discovered - - Update frontmatter: add `requires: [prerequisite-card]` to the goal card - - Work the leaf nodes (prerequisites with no further dependencies) first - - Repeat until the goal succeeds +2. Implement the change directly on main +3. Commit and push -Single feature branch, squash-merge when complete. GitOps may require pushing to test — if a pushed commit breaks, revert it promptly. +No feature branch or PR required. If something goes wrong, fix forward with another commit. -## C2 — Documented Change (Multi-Session) +Examples: fix a typo, bump a version, add a simple config value, update a doc. -Like C1 but designed to survive agent context loss across sessions: +## C1 — Human Review + +A change with enough complexity or risk that a human should review it, but not so much that a formal multi-phase approach is needed. + +### Process + +1. Run `mise run ai-docs` to load context +2. **Search related docs** — read existing documentation, reference cards, and prior Mikado chains related to the change area +3. **Create a feature branch** and open a PR early (draft is fine) +4. **Documentation first** — commit doc changes reflecting the desired end state before writing code. This helps the reviewer understand intent and catches design issues early +5. **Implement** — commit code changes, pushing as you go. The PR gets updated along the way and the user can review and comment at any point +6. **Deploy from the branch** — do not wait for merge: + - **ArgoCD:** `argocd app set --revision && argocd app sync ` + - **Ansible:** run playbooks directly from the branch checkout + - **Workflows:** point workflow triggers at the branch if needed +7. After user review and successful deployment, the user merges the PR +8. **After merge:** reset ArgoCD revisions back to main, re-sync + +### Upgrading to C2 + +Upgrade to C2 if any of these happen during a C1 change: + +- You discover the change requires multiple prerequisite changes that must be sequenced +- The change is spiraling in complexity beyond a single session +- The user requests it +- During planning you realize this is a multi-phase project + +## C2 — Mikado Chain + +A complex, multi-session change managed through the [Mikado method](https://mikadomethod.info/) with a strict branch discipline called the **Mikado Branch Invariant**. + +### The Mikado Branch Invariant + +The invariant governs how commits are ordered on a C2 feature branch. The branch must always have this structure: + +``` +main ← [Mikado card commits] ← [code commits] ← [card-closing commits] + ^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^ + Planning layer Implementation Resolution + (cards only) (code only) (close leaf nodes) +``` + +**Rules:** + +1. The first N commits on the branch (after diverging from main) must ALL be commits that **only introduce or modify Mikado cards** — no code changes +2. After the card commits, a series of commits (preferably just one) make **code progress toward closing a leaf node** — these commits must NOT introduce or change Mikado cards +3. The code commits must be followed by one or more commits that **close Mikado leaf nodes** based on the work done +4. This pattern (code → close) repeats until the chain is complete + +**What is NOT allowed:** + +- Introducing a Mikado card in a commit that comes after code progress commits +- Closing a Mikado card before all cards it depends on have been introduced + +**The length-zero case:** It is valid for the "planning layer" to have zero commits on the branch — this happens when all Mikado cards were introduced in earlier sessions and are already in main's history. The invariant is satisfied. + +### Process 1. **Goal card:** Create a how-to doc in `docs/how-to/` describing the desired end state - Add `status: active` to frontmatter -2. **Attempt the change** — GitOps may require pushing code to test (e.g., ArgoCD sync). When the attempt fails: - - **First**, reset the failed code changes (the branch should not carry broken code forward) - - **Then**, create/update prerequisite cards as how-to docs with `status: active` - - Add `requires: [prerequisite-stem, ...]` to the goal card's frontmatter - - Commit only the doc updates (the documentation IS the Mikado graph) -3. **Work leaf nodes first** — cards with `status: active` and no unmet `requires` -4. **Re-attempt the goal** after leaf nodes are resolved — code from the attempt comes back here + - Create prerequisite cards discovered during planning, each with `status: active` + - Commit all cards together (or in a sequence of card-only commits) +2. **Open a PR** after the first card commits so the user can review the Mikado graph +3. **Work leaf nodes** — pick a leaf (a card with `status: active` and no unmet `requires`): + - Commit code changes that progress toward closing it + - Commit the card closure (remove `status: active`) + - Push to origin — this is the save point +4. **Repeat** until the chain is complete 5. **New agent sessions** pick up state by running `mise run docs-mikado` -6. When a card's change succeeds, remove `status: active` (or the entire field) from its frontmatter -Documentation IS the Mikado graph. Each card captures what was learned from failed attempts, so the next agent session doesn't repeat mistakes. +### Discovering new prerequisites -### Handling failed attempts +When you discover a new prerequisite during code work, you must restore the Mikado Branch Invariant: -When an attempt fails and you discover prerequisites, the branch must be cleaned up before documenting what you learned: +1. **Reset the branch** back to the top of the Mikado commit stack — the point where all card-introducing commits end and code commits begin +2. **Add a new commit** introducing the new prerequisite card (and updating `requires` on existing cards if needed) +3. **Replay the Mikado process** from the new state of the card stack -1. Reset to before the code attempt (`git reset --hard`) -2. Commit the new prerequisite cards and frontmatter updates -3. If you already committed docs mixed with code, cherry-pick the doc commits onto a clean base rather than reverting (avoids noisy add/revert history) +**Saving work across resets:** It is acceptable to cherry-pick or rebase code commits from before the reset back onto the branch after adding the new card. This is a pragmatic exception — use it only when you are confident the saved work is still valid given the new prerequisite. When in doubt, redo the work from scratch. -The branch between attempts should contain only documentation. Code returns when prerequisites are satisfied and the next attempt succeeds. +### Completing a chain + +When the final leaf node is closed and no `status: active` cards remain: + +1. **Rewrite all Mikado cards** to reflect their nature as historical documentation: + - Remove transient technical details (specific version numbers, temporary workarounds) that won't matter in the future + - Frame the content as "what to do if someone wanted to repeat this process" + - Add appropriate context about what was learned +2. **Add changelog information** in `docs/changelog.d/` +3. The user reviews and merges the PR ### Build artifacts Mikado resets apply to branch code, not build artifacts. Container images in the registry are independent of branch lifecycle: -- **Registry images** are build outputs cached in zot — tagged with commit SHAs, so each build is unique and traceable. -- **Automatic builds** trigger when container changes merge to main. Use `mise run container-build-and-release` for manual dispatch. -- **If a build succeeds but deployment fails**, the image is fine; the problem is elsewhere. Document what you learned and try again. -- **If a build fails in CI**, no image is pushed. Fix the nix/dockerfile and re-merge or re-dispatch. +- **Registry images** are build outputs cached in zot — tagged with commit SHAs, so each build is unique and traceable +- **Automatic builds** trigger when container changes merge to main. Use `mise run container-build-and-release` for manual dispatch +- **If a build succeeds but deployment fails**, the image is fine; the problem is elsewhere. Document what you learned and try again +- **If a build fails in CI**, no image is pushed. Fix the nix/dockerfile and re-merge or re-dispatch ## Card Conventions @@ -111,12 +165,11 @@ tags: ### Git Discipline -- Single feature branch per C1/C2 change -- **Create a PR early** — open a draft PR after the first doc commit so the user can review the Mikado graph as it evolves between iterations. -- **Push after every iteration** — after completing a leaf node or documenting a failed attempt, push to origin. This is the save point for multi-session work. -- Amend a single working commit as you iterate; keep the branch history clean +- **C0:** Commit directly to main +- **C1:** Single feature branch, PR early, push often +- **C2:** Single feature branch, Mikado Branch Invariant enforced, PR early, push after every leaf-node closure +- **Deploy from branches** — C1 and C2 changes deploy from the unmerged branch (ArgoCD `--revision`, Ansible from checkout, etc.). Reset to main after merge. - GitOps requires pushing to test — if a pushed commit breaks, revert it promptly -- Commit doc updates noting what was learned from failures ## Tools diff --git a/docs/how-to/how-to.md b/docs/how-to/how-to.md index 8ff7aeb..81483cd 100644 --- a/docs/how-to/how-to.md +++ b/docs/how-to/how-to.md @@ -35,7 +35,7 @@ Task-oriented instructions for common BlumeOps operations. These guides assume y |-------|-------------| | [[review-documentation]] | Periodically review and maintain documentation | | [[review-services]] | Periodically review services for version freshness | -| [[agent-change-process]] | C0/C1/C2 change classification and Mikado method for agents | +| [[agent-change-process]] | C0/C1/C2 change classification and Mikado Branch Invariant | ## Operations diff --git a/docs/tutorials/ai-assistance-guide.md b/docs/tutorials/ai-assistance-guide.md index a98fbbd..aceb52a 100644 --- a/docs/tutorials/ai-assistance-guide.md +++ b/docs/tutorials/ai-assistance-guide.md @@ -1,6 +1,6 @@ --- title: AI Assistance Guide -modified: 2026-02-09 +modified: 2026-02-23 tags: - tutorials - ai @@ -22,13 +22,16 @@ These are non-negotiable for AI agents working in this repo: 4. **Wait for user review before deploying** - Create PRs, don't auto-deploy 5. **Never merge PRs without explicit request** - The user merges after review -Full rules are in the repo's `CLAUDE.md`. See [[agent-change-process]] for the C0/C1/C2 change classification methodology. +Full rules are in the repo's `CLAUDE.md`. See [[agent-change-process]] for the C0/C1/C2 change classification methodology — C0 (direct to main), C1 (feature branch + PR), C2 (Mikado Branch Invariant). ## Workflow Conventions -### Feature Branches +### Branching -All work happens on feature branches: +Branching depends on change classification (see [[agent-change-process]]): + +- **C0 (Quick Fix):** Commit directly to main — no branch or PR needed +- **C1/C2:** Feature branch required: ```bash git checkout main && git pull git checkout -b feature/descriptive-name @@ -85,7 +88,7 @@ BlumeOps operations are driven by mise tasks. Run `mise tasks` to list all avail | Task | When to Use | |------|-------------| | `ai-docs` | At session start - review infrastructure documentation | -| `docs-mikado` | View active Mikado dependency chains for C1/C2 changes | +| `docs-mikado` | View active Mikado dependency chains for C2 changes | | `provision-indri` | Deploy changes to [[indri]]-hosted services via Ansible | | `services-check` | After deployments - verify all services are healthy | | `pr-comments` | Check unresolved PR comments during review | @@ -131,5 +134,5 @@ Credentials live in 1Password. Never retrieve them directly - use existing patte | Missing kubectl context | Always add `--context=minikube-indri` | | Deploying without review | Create PR first, wait for user approval | | Re-explaining reference material | Link to reference cards instead | -| Committing to main | Use feature branches | +| Committing to main without classifying | Classify as C0/C1/C2 first — only C0 goes to main | | Guessing at credentials | Ask user or check 1Password patterns | diff --git a/mise-tasks/docs-mikado b/mise-tasks/docs-mikado index cf091b1..eefa2e8 100755 --- a/mise-tasks/docs-mikado +++ b/mise-tasks/docs-mikado @@ -3,10 +3,10 @@ # requires-python = ">=3.12" # dependencies = ["pyyaml>=6.0", "rich>=13.0.0", "typer>=0.15.0"] # /// -#MISE description="View active Mikado dependency chains for C1/C2 changes" +#MISE description="View active Mikado dependency chains for C2 changes" #USAGE arg "[card]" help="Card stem to show chain for" #USAGE flag "--all" help="Show all cards in full, including complete ones" -"""View active Mikado dependency chains for C1/C2 changes. +"""View active Mikado dependency chains for C2 changes. Scans all markdown files in docs/ for YAML frontmatter with ``status: active`` and ``requires`` fields, then builds and displays the Mikado dependency graph.