Improve Mikado process: cycle discipline, reset rigor, --resume enhancements (#261)
## Summary - **End-of-cycle prompting:** After closing a leaf node and pushing, the agent should prompt the user to review and suggest ending the session rather than rushing into the next leaf - **Reset rigor:** Reinforced that errors during impl should trigger a branch reset + plan update (not fix-forward). Documented the `git log --oneline --not main` → `git reset --hard` → `git cherry-pick` pattern with clear threshold guidance - **`--resume` shows PR number:** Queries the Forgejo API for open PRs matching the branch, displays number/title/URL and a hint to run `pr-comments` - **`--resume` checks git stash:** Shows stash entries as a non-presumptive hint — informs without assuming they apply ## Test plan - [ ] `mise run docs-mikado --resume` runs without errors (no active chains case) - [ ] On a mikado branch with an open PR, verify PR info is shown - [ ] With stashed work, verify stash entries are displayed - [ ] Review agent-change-process.md for clarity 🤖 Generated with [Claude Code](https://claude.com/claude-code) Reviewed-on: https://forge.ops.eblu.me/eblume/blumeops/pulls/261
This commit is contained in:
parent
d05d2fbaff
commit
9b4951bf94
3 changed files with 110 additions and 20 deletions
1
docs/changelog.d/mikado-process-improvements.ai.md
Normal file
1
docs/changelog.d/mikado-process-improvements.ai.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
Improved Mikado C2 process: end-of-cycle session prompts, rigorous reset discipline with documented git patterns, and `--resume` now shows PR number and stash hints.
|
||||
|
|
@ -165,18 +165,35 @@ The `mikado-branch-invariant-check` commit-msg hook validates this convention an
|
|||
- **Verify the change works** (deploy from branch, run tests, etc.) before closing
|
||||
- Commit the card closure (`C2(<chain>): close ...`) — 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 --resume`
|
||||
4. **End the cycle** — after pushing a closed leaf node, prompt the user to review the PR and suggest ending the session. Each closed leaf is a natural stopping point; the chain is designed to be resumed later. Don't rush into the next leaf without the user's go-ahead.
|
||||
5. **Repeat** until the chain is complete
|
||||
6. **New agent sessions** pick up state by running `mise run docs-mikado --resume`
|
||||
|
||||
### Discovering new prerequisites
|
||||
### Discovering new prerequisites or errors
|
||||
|
||||
When you discover a new prerequisite during code work, you must restore the Mikado Branch Invariant:
|
||||
When you discover a new prerequisite **or encounter an error** during code work, do not fix forward. The Mikado method's power comes from rigorous resets that keep the plan honest. You must restore the Mikado Branch Invariant:
|
||||
|
||||
1. **Reset the branch** back to the top of the Mikado commit stack — the last `C2(<chain>): plan` or `C2(<chain>): close` commit before your current `impl` commits
|
||||
2. **Add a new commit** (`C2(<chain>): plan ...`) 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. **Stash or note any in-progress work** you want to preserve
|
||||
2. **Identify the reset point** — the last `plan` or `close` commit before your current `impl` commits:
|
||||
```bash
|
||||
git log --oneline mikado/<chain-stem> --not main
|
||||
```
|
||||
3. **Reset the branch** to that commit:
|
||||
```bash
|
||||
git reset --hard <reset-point-sha>
|
||||
```
|
||||
4. **Update the plan** — add a `plan` commit that captures what you learned:
|
||||
- If you discovered a new prerequisite: add a new card and update `requires`
|
||||
- If you hit an error: update the relevant card with what you learned, or introduce a new prerequisite card that addresses the root cause
|
||||
5. **Replay valid work** by cherry-picking commits that still apply:
|
||||
```bash
|
||||
git cherry-pick <sha1> <sha2> ...
|
||||
```
|
||||
6. **Resume the Mikado process** from the new state of the card stack
|
||||
|
||||
**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.
|
||||
**When to reset vs. fix forward:** If an `impl` commit introduces a bug that's a simple typo or one-liner, another `impl` commit is fine. But if the error reveals a gap in understanding, a missing prerequisite, or requires rethinking the approach — reset. The threshold is: "does this error teach us something that should be in the plan?" If yes, reset.
|
||||
|
||||
**Saving work across resets:** It is acceptable to cherry-pick code commits from before the reset back onto the branch after adding the new card. Use `git stash` for uncommitted work. 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.
|
||||
|
||||
### Completing a chain
|
||||
|
||||
|
|
@ -199,8 +216,10 @@ When starting a new session to continue C2 work:
|
|||
2. Run `mise run docs-mikado --resume` — this will:
|
||||
- Detect the current branch and match it to an active chain
|
||||
- Show the chain state, ready leaf nodes, and current position in the invariant
|
||||
- Show the PR number and URL if an open PR exists for the branch
|
||||
- Warn about any stashed work in `git stash list`
|
||||
- If on main, list active chains and suggest which to resume
|
||||
3. Check PR comments with `mise run pr-comments <pr_number>`
|
||||
3. Check PR comments with `mise run pr-comments <pr_number>` — use the PR number from the `--resume` output above
|
||||
4. Pick the next ready leaf node and continue with a work cycle
|
||||
|
||||
### Build artifacts
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env -S uv run --script
|
||||
# /// script
|
||||
# requires-python = ">=3.12"
|
||||
# dependencies = ["pyyaml>=6.0", "rich>=13.0.0", "typer>=0.15.0"]
|
||||
# dependencies = ["httpx>=0.28.0", "pyyaml>=6.0", "rich>=13.0.0", "typer>=0.15.0"]
|
||||
# ///
|
||||
#MISE description="View active Mikado dependency chains for C2 changes"
|
||||
#USAGE arg "[card]" help="Card stem to show chain for"
|
||||
|
|
@ -238,6 +238,49 @@ def classify_branch_position(commits: list[dict]) -> str:
|
|||
return "unknown"
|
||||
|
||||
|
||||
FORGE_API = "https://forge.ops.eblu.me/api/v1"
|
||||
|
||||
|
||||
def find_pr_for_branch(branch: str) -> dict | None:
|
||||
"""Find an open PR for the given branch via the Forgejo API."""
|
||||
import httpx
|
||||
|
||||
try:
|
||||
resp = httpx.get(
|
||||
f"{FORGE_API}/repos/eblume/blumeops/pulls",
|
||||
params={"state": "open", "limit": 50},
|
||||
timeout=10,
|
||||
)
|
||||
if resp.status_code != 200:
|
||||
return None
|
||||
for pr in resp.json():
|
||||
if pr.get("head", {}).get("ref") == branch:
|
||||
return {
|
||||
"number": pr["number"],
|
||||
"title": pr["title"],
|
||||
"url": pr.get("html_url", ""),
|
||||
}
|
||||
except (httpx.HTTPError, KeyError):
|
||||
pass
|
||||
return None
|
||||
|
||||
|
||||
def get_stash_list() -> list[str]:
|
||||
"""Get the list of git stash entries."""
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["git", "stash", "list"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
cwd=REPO_DIR,
|
||||
)
|
||||
if result.returncode == 0 and result.stdout.strip():
|
||||
return result.stdout.strip().split("\n")
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
return []
|
||||
|
||||
|
||||
def show_resume(
|
||||
cards: dict[str, dict],
|
||||
console: Console,
|
||||
|
|
@ -350,13 +393,26 @@ def _show_chain_resume(
|
|||
branch = card.get("branch") or current_branch
|
||||
|
||||
console.print()
|
||||
console.print(
|
||||
Panel(
|
||||
f"[bold]{chain}[/bold] — {card['title']}\n"
|
||||
f"Branch: [green]{branch or 'not set'}[/green]",
|
||||
title="Resuming Mikado Chain",
|
||||
|
||||
# Look up PR for this branch
|
||||
pr_info = find_pr_for_branch(branch) if branch else None
|
||||
panel_lines = [
|
||||
f"[bold]{chain}[/bold] — {card['title']}",
|
||||
f"Branch: [green]{branch or 'not set'}[/green]",
|
||||
]
|
||||
if pr_info:
|
||||
panel_lines.append(
|
||||
f"PR: [cyan]#{pr_info['number']}[/cyan] — {pr_info['title']}"
|
||||
)
|
||||
if pr_info["url"]:
|
||||
panel_lines.append(f" {pr_info['url']}")
|
||||
|
||||
console.print(Panel("\n".join(panel_lines), title="Resuming Mikado Chain"))
|
||||
|
||||
if pr_info:
|
||||
console.print(
|
||||
f"[dim]Check PR comments: mise run pr-comments {pr_info['number']}[/dim]"
|
||||
)
|
||||
)
|
||||
|
||||
# Show branch position if we can read commits
|
||||
if branch and current_branch == branch:
|
||||
|
|
@ -405,6 +461,20 @@ def _show_chain_resume(
|
|||
else:
|
||||
console.print("\n[dim]No ready leaf nodes — all leaves have unmet dependencies[/dim]")
|
||||
|
||||
# Check for stashed work
|
||||
stashes = get_stash_list()
|
||||
if stashes:
|
||||
console.print(
|
||||
f"\n[yellow]Note: {len(stashes)} stash entr{'y' if len(stashes) == 1 else 'ies'} found:[/yellow]"
|
||||
)
|
||||
for entry in stashes[:5]:
|
||||
console.print(f" [dim]{entry}[/dim]")
|
||||
if len(stashes) > 5:
|
||||
console.print(f" [dim]... and {len(stashes) - 5} more[/dim]")
|
||||
console.print(
|
||||
"[dim]Review with: git stash list / git stash show[/dim]"
|
||||
)
|
||||
|
||||
console.print()
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue