19 KiB
AGENTS-WORKFLOW.md — How work flows from bead to merge
Sibling of
AGENTS.md(orientation),AGENTS-CI.md(gate detail),AGENTS-CODEX.md(parity rules),AGENTS-RUNTIME.md(runtime constraints). Split out of the monolithic AGENTS.md at 580 lines per soc-vuu6.3.
Workflow
This repository currently chooses direct push to main after deterministic
checks. That is a repository delivery policy, not an AgentOps lifecycle rule.
The Go gate (ao gate check --fast) is the local deterministic check for this
repo; another repository may choose a PR or user-owned CI. Discovery, Crank,
Validate, and Learn end at evidence and receipts. Delivery may consume that
immutable proof but does not require another LLM landing verdict, and AgentOps
does not own a global Git queue. Keep each change a coherent, independently
revertible bead arc; on remote rejection, update against the moving target and
retry the repository-selected delivery command.
Autonomous-session scope (sister rule to coherent-arc). Coherent-arc governs the shape of one shipped arc; session-scope governs the count of consecutive arcs. Default: 2-4 arcs per autonomous session. At >=5 shipped or in-flight arcs in one session, stop and run a postmortem before continuing. The old PR-count signal is now interpreted as arc count because the repo no longer uses PRs as the normal landing path. Derivation: the 2026-05-19 cron-loop session shipped 6 PRs with 3 self-corrections; items #5-#6 each fixed fallout from #1-3. Mechanical enforcement is the mandatory /evolve postmortem checkpoint (council-gated, cannot be bypassed; skills/evolve/references/postmortem-checkpoint.md). That checkpoint is a re-plan point, not just stop/continue — it may refactor, reorder, drop, or add to the remaining arcs from what the session taught (/rpi's Agile Re-Plan Loop; --auto pivots without an operator prompt). (soc-waxr, ag-o5xp)
Tracker = br (beads_rust) + bv, as of 2026-06-11. Issue tracking is br — offline, git-JSONL-backed (_beads/issues.jsonl + a local SQLite cache; br sync never runs git). The private ledger lives in the canonical checkout, not in every linked worktree. Resolve it with ao beads dir and invoke as BEADS_DIR="$(ao beads dir)" br <cmd>; do not rely on $PWD/_beads from linked worktrees. For write commands (create/update/close/dep), resolution must fail closed — an empty or wrong BEADS_DIR lets br silently write the wrong tracker (age-gstf). Guarded write shape: BEADS_DIR="$(ao beads dir --require)" && export BEADS_DIR && br close <id> -r "Done" (--require exits non-zero, printing nothing, unless the resolved directory holds a real ledger). Triage with bv (bv --robot-insights, --robot-plan, --robot-priority). Two-store truth (age-gc-adoption-u0he): br is AgentOps' own repo tracker; bd/Dolt is the gascity SUBSTRATE store — first-class and embraced, the native store a gas-city factory runs on. They are different layers, not competitors. AgentOps moved its OWN tracking to br for offline/local-first reasons (the earlier all-in bet on the agentic-flywheel stack coupled delivery to a remote single-host Dolt server — a SPOF with no offline lane; circuit breaker observed open in the 2026-06-11 recon, docs/audits/codebase-skills-2026-06-11/codebase-risk-audit.md), so do not run bd for this repo's tracking — but bd/dolt is legitimate as the gascity substrate. The pre-br .beads/ bd/Dolt data for this repo is preserved pending reconciliation; migration record: .agents/swarm/results/br-migration.json.
Phases
- Claim.
BEADS_DIR="$(ao beads dir)" br ready --json→ pick a bead →BEADS_DIR="$(ao beads dir)" br update <id> --claim --json. No bead, no push. If the work is genuinely new,BEADS_DIR="$(ao beads dir)" br create "Title" -t task -p 2 --body "..." --jsonfirst (deps:--deps blocks:<id>orBEADS_DIR="$(ao beads dir)" br dep add <child> <parent>). - Scope. Read the live bead body with
BEADS_DIR="$(ao beads dir)" br show <id> --jsonbefore editing. Its acceptance is the contract: a.featurefile (canonical when present) or an embedded## Scenariosblock in the bead description. Free-text acceptance is invalid — promote it to scenarios before work begins. Default: one coherent arc per push — bundle scenarios that ship-or-revert together; split scenarios with independent rollback. The direct-main commit range is the atomic revert unit. Carve-out:type=chorewith#triviallabel for tiny work. - Ship.
git worktree add wt-<bead-id> -b <type>/<bead-id>-<scenario-token>-<short-slug>— worktree-mandatory; do not edit in the shared checkout (canonical-root rules:AGENTS-RUNTIME.md). Implement, commit the bead's code as HEAD. Runao gate check --fast --scope headto fail fast before you land. - Deliver. Run the repository-selected deterministic adapter. In this repo,
fetch current
main, integrate if needed, rerun the scoped deterministic check when the payload changes, andgit push origin HEAD:main. Other repos may open a PR or use their own CI. Close tracker state only after separately confirming the selected delivery succeeded.
Branch + Direct-Main Shape
| Element | Format |
|---|---|
| Branch | <type>/<bead-id>-<scenario-token>-<short-slug> · ≤80 chars · <scenario-token> = full slug if it fits, else <slug-prefix>-<hash8> |
| Commit title | <type>(<scope>): <subject> (<bead-id>) |
| Required evidence | bead id in commit message or close reason · local gate output path or summary · bounded context when relevant |
| Delivery | Repository-selected adapter. This repo uses ordinary direct push; PR and user-owned CI remain valid elsewhere. |
| Gate | Deterministic repository checks. AgentOps lifecycle proof is not a Git authorization token. |
Multi-agent discipline (shared checkout)
The host ~/dev/agentops is contended. Agents do not edit it directly. Use
git worktree add <name> -b <branch> for every change. Git's remote update is
the serialization point for direct push; an operator may add repository-owned
coordination, but AgentOps does not create a global merge queue. Foreign
uncommitted files are quarantined: identify the owner, attach them to a bead,
and move them into a worktree.
Provenance
Source of truth: append-only JSONL at docs/provenance/ledger.jsonl (schema agentops-sdlc-provenance.v1). Tracker state (br issue fields, notes, comments) is a derived projection — ledger wins on disagreement. The ledger is append-only: concurrent writers append events, never rewrite (the old --set-metadata/dolt-advisory-lock machinery is retired with bd). claude-code-review verdicts are first-class ledger events.
Doctrine altitudes
- Spine:
docs/architecture/operating-loop.md— 7-move agent doctrine. Primary navigation. - One turn's executor:
/rpiskill. NOT primary. - Architecture: 6 Bounded Contexts (BC1 Corpus → BC6 Orchestration). Where code lives.
- Consumer metaphor: "CDLC" — the compounding Knowledge Flywheel framing.
Source layer — three axis owners, generated or schema-gated; NEVER hand-edited inventory maps
- DDD (vocabulary):
skills/domain/references/— BC names + ubiquitous language. - Hex (structure):
skills/*/SKILL.mdfrontmatter (hexagonal_role,consumes,produces,context_rel) → generated todocs/contracts/context-map.md. CI gate:validate-context-map-drift. - Gherkin (acceptance):
skills/*/references/*.feature+ bead-embedded## Scenarios. CI gate:scenario-hash-stability.
Helper extractions ship a ratchet
Every helper/library extraction ships a shrink-only OBSERVATIONAL ratchet gate in the same arc — scripts/lib/ratchet.sh makes that a detector function + a pinned grandfather file (worked example: scripts/check-atomic-write-ratchet.sh, age-ratchet-lib-extraction-bv7d.9). The ratchet claims observation, not enforcement: consolidation without a guard accretes new hand-rolled copies (the 07-01 writeJSONAtomic escape re-rolled a helper fsync-less a week after it landed), and a ratchet graduates to blocking only via a separately-earned precision detector, never by default.
CI tiers (no "advisory")
- T0 (≤30s) required gates · T1 (≤5min) verification · T2 (≤15min) quality — all required.
- I0 informational; runs and reports artifact but does NOT appear as a PR check.
Local Pre-Push Checklist
Run ao gate check --fast --scope head for the smart conditional Go gate that only checks what changed, or ao gate check --full --workflow-coverage --require-workflow-parity for full local release evidence. Use AGENTOPS_GATE_BASH=1 only as the documented legacy fallback. Or run individual checks below.
# Recommended: smart conditional gate
ao gate check --fast --scope head
# One-command local development bootstrap
bash scripts/install.sh --dev
# Or individual checks:
# 1. Skill integrity (most common failure)
bash skills/heal-skill/scripts/heal.sh --strict
# 2. Doc-release gate (skill counts, link validation)
./tests/docs/validate-doc-release.sh
# 3. ShellCheck
find . -name "*.sh" -type f -not -path "./.git/*" -print0 | xargs -0 shellcheck --severity=error
# 4. Markdownlint
git ls-files '*.md' | xargs markdownlint
# 5. Go build + tests (if cli/ changed)
cd cli && make build && make test
# 6. Contract compatibility
./scripts/check-contract-compatibility.sh
# 7. CI policy/docs parity
bash scripts/validate-ci-policy-parity.sh
# 8. Worktree disposition
bash scripts/check-worktree-disposition.sh
# 9. Plugin structure (symlinks, manifests)
./scripts/validate-manifests.sh --repo-root .
find skills -type l # must be empty — zero symlinks allowed
# 10. Headless runtime skill smoke (local Claude/Codex sessions; skips missing CLIs)
bash scripts/validate-headless-runtime-skills.sh
# 11. Codex-first override coverage (full skill catalog is classified and covered)
bash scripts/validate-codex-override-coverage.sh
# 12. Codex RPI contract and lifecycle guard checks
bash scripts/validate-codex-rpi-contract.sh
bash scripts/validate-codex-lifecycle-guards.sh
# 13. Codex semantic parity audit (generated skills still match Codex-native tool/runtime semantics)
bash scripts/audit-codex-parity.sh
# 14. AgentOps contract canaries (official deterministic test gate)
scripts/test-agentops-contract-canaries.sh
# 15. Installed-binary smoke (USER-FACING CLI CHANGES ONLY): the `ao` on PATH
# must match the just-built binary, else UAT/closeout exercises the STALE
# product path (a same-version binary can still differ in content until
# `make install` refreshes it). Run before declaring the product path
# usable. Local-only — needs an installed ao, so it is not a CI gate. (age-6sg.3)
cd cli && make build && cd .. && bash scripts/preflight-uat-binary.sh
# Full gate (runs everything above and more):
scripts/ci-local-release.sh
Releasing
Is a release due? Run scripts/check-release-due.sh (also surfaced by scripts/release-cadence-check.sh) — a non-blocking nudge that reports commits + days since the last vX.Y.Z tag and flags when a release looks overdue (defaults: 50 commits / 14 days; override with RELEASE_DUE_COMMITS / RELEASE_DUE_DAYS). It only surfaces the signal — distribution stays pull-based; nothing auto-releases.
Standard release flow:
- Validate. For a routine pre-tag sanity pass use the fast lane
scripts/ci-local-release.sh --quick(<5min, code-correctness subset); run the fullscripts/ci-local-release.sh(~78min) only for the actual tag. - Tag and push:
git tag v2.X.0 && git push origin v2.X.0 - GitHub Actions runs GoReleaser — builds binaries, creates release, updates Homebrew tap
- Upgrade locally:
brew update && brew upgrade agentops
For retagging (rolling post-tag commits into an existing release):
scripts/retag-release.sh v2.13.0
This moves the tag to HEAD, pushes, rebuilds the GitHub release, updates the Homebrew tap, and upgrades locally. One command, no manual steps.
Landing the Plane (Session Completion)
When ending a work session, you MUST complete ALL steps below. Work is NOT complete until git push succeeds.
MANDATORY WORKFLOW:
- File issues for remaining work - Create issues for anything that needs follow-up
- Run quality gates (if code changed) - Tests, linters, builds. For user-facing CLI changes, also run the installed-binary smoke (
cd cli && make build && cd .. && bash scripts/preflight-uat-binary.sh) so the closeout proves the installedaomatches the build — not the stale product path — before declaring it usable. - Update issue status - Close finished work, update in-progress items
- DELIVER WITH REPOSITORY POLICY - this repo uses a deterministic gate and
direct push. A Validate proof may be cited, but no additional LLM verdict is
required. Then sync the private tracker independently:
ao gate check --fast --scope head git fetch origin main git push origin HEAD:main BEADS_DIR="$(ao beads dir)" br sync --flush-only # export DB → _beads JSONL (br never runs git itself) git -C "$(ao beads dir)" add -A && git -C "$(ao beads dir)" commit -m "tracker: <summary>" && git -C "$(ao beads dir)" push # if tracker changes are pending git status # MUST show "up to date with origin" - Clean up - Clear stashes, prune remote branches, and validate worktree disposition
- Verify - All changes committed AND pushed
- Hand off - Provide context for next session
CRITICAL RULES:
- Work is NOT complete until
git pushsucceeds - NEVER stop before pushing - that leaves work stranded locally
- NEVER say "ready to push when you are" - YOU must push
- If push fails, resolve and retry until it succeeds
- NEVER leave a foreign branch-attached worktree without a recorded disposition
- Keep the canonical root clean and attached to
main. - Run
bash scripts/check-worktree-disposition.shbefore push and session close. - The tracker ledger is a PRIVATE nested git repo (
_beads/→boshu2/agentops-beads), gitignored by this PUBLIC repo — bead bodies carry private fleet/client context and must NEVER land on the public remote.git -C "$(ao beads dir)" pushIS the tracker sync. IfBEADS_DIR="$(ao beads dir)" br sync --flush-onlyreports nothing to export, that is fine; continue with the mandatory git push.
Issue Tracking with br (beads_rust)
IMPORTANT: This project tracks its OWN issues with br (beads_rust). Do NOT use markdown TODOs, task lists, other tracking methods — or bd (which is the gascity substrate store, a different layer, not this repo's tracker).
Linked worktrees intentionally do not contain their own _beads directory. Run ao beads dir at session start and use that value for BEADS_DIR on every direct br invocation. ao session bootstrap prints the same path as tracker: BEADS_DIR=....
Why br?
- Dependency-aware: Track blockers and relationships between issues
- Git-native: SQLite cache +
_beads/issues.jsonlledger committed in its own private repo — offline, no server, no SPOF, no public leak - Agent-optimized: JSON output, ready work detection, discovered-from links,
br robot-docs guide - Prevents duplicate tracking systems and confusion
Quick Start
Check for ready work:
BEADS_DIR="$(ao beads dir)" br ready --json
Create new issues:
BEADS_DIR="$(ao beads dir)" br create "Issue title" --body "Detailed context" -t bug|feature|task -p 0-4 --json
BEADS_DIR="$(ao beads dir)" br create "Issue title" --body "What this issue is about" -p 1 --deps discovered-from:<parent-id> --json
Claim and update:
BEADS_DIR="$(ao beads dir)" br update <id> --claim --json
BEADS_DIR="$(ao beads dir)" br update <id> --priority 1 --json
Complete tracker work after repository delivery is independently confirmed:
BEADS_DIR="$(ao beads dir)" br close <id> --reason "Completed" --json
Issue Types
bug- Something brokenfeature- New functionalitytask- Work item (tests, docs, refactoring)epic- Large feature with subtaskschore- Maintenance (dependencies, tooling)
Priorities
0- Critical (security, data loss, broken builds)1- High (major features, important bugs)2- Medium (default, nice-to-have)3- Low (polish, optimization)4- Backlog (future ideas)
Workflow for AI Agents
- Check ready work:
BEADS_DIR="$(ao beads dir)" br ready --jsonshows unblocked issues (graph triage:bv --robot-insights/bv --robot-plan) - Claim your task atomically:
BEADS_DIR="$(ao beads dir)" br update <id> --claim --json - Work on it: Implement, test, document
- Discover new work? Create linked issue:
BEADS_DIR="$(ao beads dir)" br create "Found bug" --body "Details about what was found" -p 1 --deps discovered-from:<parent-id> --json
- Complete: after the repository-selected delivery succeeds,
BEADS_DIR="$(ao beads dir)" br close <id> --reason "Done" --json
Quality
- Use
br update <id> --acceptance-criteria "..."and--design "..."to fill structured fields - Use
br lintto check issues for missing template sections
Lifecycle
br defer <id>/br undefer <id>for schedulingbr stale/br orphans/br lintfor hygienebr epicfor epic management,br dep tree <id>/br dep cyclesfor graph health
Auto-Sync
br syncs through git, not a server:
- Each write auto-flushes the SQLite DB to
_beads/issues.jsonl(disable with--no-auto-flush) BEADS_DIR="$(ao beads dir)" br sync --flush-only/--import-only/--statusfor explicit control; br NEVER runs git commands itself- Remote sync =
git -C "$(ao beads dir)" add -A && git -C "$(ao beads dir)" commit && git -C "$(ao beads dir)" push(private remoteboshu2/agentops-beads)
Important Rules
- ✅ Use br for ALL task tracking
- ✅ Always use
--jsonflag for programmatic use - ✅ Link discovered work with
discovered-fromdependencies - ✅ Check
BEADS_DIR="$(ao beads dir)" br ready --jsonbefore asking "what should I work on?" - ❌ Do NOT create markdown TODO lists
- ❌ Do NOT use external issue trackers
- ❌ Do NOT duplicate tracking systems
- ❌ Do NOT run
bdfor this repo's tracking — br is AgentOps' own tracker (its Dolt server was a single-host SPOF; see the tracker note atop this file). bd/dolt itself is the gascity substrate store — legitimate there, just not this repo's tracker.
For more details, see README.md and docs/newcomer-guide.md.
Session Completion
Covered in full by Landing the Plane (Session Completion) above — one canonical checklist; this section exists only so older links to it still resolve.