mirror of
https://github.com/boshu2/agentops.git
synced 2026-09-14 15:08:13 +08:00
docs: establish lean AgentOps product boundary
Implements: age-agentops-lean-loop-direct-cut-rp16f.1
This commit is contained in:
@@ -1,228 +1,123 @@
|
||||
# Operating Discipline — the rules every agent factory runs on
|
||||
# Operating Discipline — Rules for an Agent Software Factory
|
||||
|
||||
> **What this is.** The general, substrate-neutral operating rules for running a fleet of
|
||||
> AI coding agents: admission control, independent validation, close discipline, and
|
||||
> multi-lane coordination. Distilled from the mt-olympus *triangulated kernel* (D1–D16,
|
||||
> three independent model distillations reconciled to consensus) and **folded into AgentOps
|
||||
> as the surviving factory** — because AgentOps is now the one self-contained factory and the
|
||||
> operating rules should live where the work runs.
|
||||
>
|
||||
> **Adapted, not blind-copied.** The load-bearing gate invariants — fail-closed (exit 5 on any
|
||||
> non-CONFIRMED verdict), author≠reviewer by context identity, and evidence-*presence* binding —
|
||||
> are **already embodied** in the shipped ratchet pawl-gate, each cited below to the exact
|
||||
> mechanism. Others are weaker than the kernel's wording: single-writer is a workflow convention
|
||||
> (the script doesn't check the caller), command-citation is aspiration (the gate checks evidence
|
||||
> presence, not transcript content), and the auto-redo/breaker economy is orchestrator-loop
|
||||
> behavior, not gate-script code — each is labeled honestly per rule. The rules that were *about the cut cathedral*
|
||||
> (an OS-account privilege floor, peercred kernel identity, a daemon, a Rust gate spec) are
|
||||
> intentionally **dropped** — the ratchet pawl-gate ([`pawls.md`](../contracts/pawls.md))
|
||||
> embodies them in AgentOps terms, and re-importing the floor as live doctrine would resurrect
|
||||
> the cathedral. This is a reference doc, not a cathedral.
|
||||
> The detailed transition model lives in the
|
||||
> [Operating Loop](../architecture/operating-loop.md). This document keeps the
|
||||
> substrate-neutral engineering rules. It does not define a second gate,
|
||||
> retry controller, delivery system, or tracker.
|
||||
|
||||
## The doctrine in one line
|
||||
## Doctrine in one line
|
||||
|
||||
**Nothing ships on a lie while you're not looking**: nothing is real until it is admitted to
|
||||
the tracker; "done" is a claim until an independent, fresh-context reviewer verifies it against
|
||||
the live commit with real evidence; one writer closes; everything ambiguous fails toward a HOLD;
|
||||
destructive writes reconcile or refuse — and the whole machine exists to give the operator's
|
||||
attention back.
|
||||
Shape one behavior, let one writer build it, prove facts for one frozen
|
||||
candidate, obtain one immutable verdict from fresh context, Learn once, and let
|
||||
the repository deliver it.
|
||||
|
||||
## How the gate embodies the load-bearing rules
|
||||
## The kernel rules
|
||||
|
||||
The shipped ratchet is the enforcement surface. Read it as: **chaos between pawls, a fail-closed
|
||||
gate at each one-way door.**
|
||||
### D1 — Admission before mutation
|
||||
|
||||
- **The pawls** ([`docs/contracts/pawls.md`](../contracts/pawls.md)) — the short static list of
|
||||
irreversible actions (mutate-shared-trunk · delete · external-send · schema/contract change ·
|
||||
credential change · spend). Everything *not* on the list is ungated chaos.
|
||||
- **The verdict** ([`scripts/pawl-verdict.sh`](../../scripts/pawl-verdict.sh),
|
||||
schema [`schemas/pawl-verdict.v1.schema.json`](../../schemas/pawl-verdict.v1.schema.json)) — an
|
||||
evidence-bound, commit-bound verdict that requires a real reviewer run: `disposition` ∈
|
||||
{CONFIRMED, REFUTED, ESCALATE, HOLD}, an `author_context_id`, ≥1 refuter with a distinct
|
||||
`context_id`, non-empty reviewer evidence, roster-validated families.
|
||||
- **The merge path** ([`scripts/reconcile-pr.sh`](../../scripts/reconcile-pr.sh)) — green CI is
|
||||
necessary but **never sufficient**: a CONFIRMED verdict tied to this bead+PR with `head_sha` ==
|
||||
the PR's live head must exist, or the merge is refused (`exit 5` HOLD). A new commit after review
|
||||
→ STALE → HOLD. Lookup failure → HOLD. Fail-closed throughout.
|
||||
Tracked work starts with one accepted behavior, one owner, one exact write
|
||||
scope, one rollback, and one proof boundary. A goal or epic is demand, not WIP.
|
||||
|
||||
## The kernel rules (D1–D16) and their disposition
|
||||
### D2 — Completion is a claim
|
||||
|
||||
Each rule: one-line statement, then **disposition** — *embodied-in-gate* (with citation),
|
||||
*doctrine* (advisory; no single mechanism yet), or *dropped-as-cathedral* (floor-specific, not
|
||||
imported as live doctrine).
|
||||
An agent saying “done” is input to validation. Completion requires acceptance
|
||||
evidence and an author-distinct verdict bound to the exact candidate.
|
||||
|
||||
### D1 — Admission first
|
||||
No work exists until it is admitted and persisted in the tracker. Chat can propose; it cannot
|
||||
admit. "Admit first, then work" — never "do work, then file."
|
||||
**Doctrine** (operating rule). Embodied operationally by the beads tracker (`br`/`bd`): a bead is
|
||||
the unit of admitted work; the pawl-verdict and merge path are keyed by `bead_id`, so an
|
||||
un-admitted change has nothing to close against.
|
||||
### D3 — Author is not judge
|
||||
|
||||
### D2 — Completion is a claim, not a state
|
||||
A worker's "done" is an event, not a transition; only an independent typed verdict produces a
|
||||
verified close. The gate is what makes "don't watch" safe.
|
||||
**Embodied-in-gate.** `reconcile-pr.sh` refuses to close on a worker's say-so — it requires a
|
||||
CONFIRMED verdict from `pawl-verdict.sh check`; absent it, exit 5 (HOLD).
|
||||
The context that created a candidate cannot issue its binding verdict. A fresh
|
||||
same-family context is sufficient by default; a council is an optional risk
|
||||
tier, not a universal lifecycle.
|
||||
|
||||
### D3 — Author ≠ judge, by context identity
|
||||
The context that produced the work never validates it; a close needs ≥1 distinct non-author
|
||||
reviewer context, blind to authorship. Self-grade exclusion is by **context identity**, not model
|
||||
family (cross-family is a strengthening mode, not the floor).
|
||||
**Embodied-in-gate.** `pawl-verdict.sh` default `fresh-context` mode requires ≥1 refuter whose
|
||||
`context_id` != `author_context_id` (model-agnostic). `multi-model` mode (≥2 roster-validated
|
||||
families) is the opt-in strengthener for the highest-irreversibility doors — exactly the
|
||||
context-vs-family resolution the kernel's DISPUTED-1 settled.
|
||||
### D4 — One writer per leaf
|
||||
|
||||
### D4 — Single writer
|
||||
One decision, one binding artifact, one writer. Workers propose and never close; reviewers verify
|
||||
and never close; only the orchestrator writes the close, and only on verified PASS.
|
||||
**Doctrine** (workflow convention). The close is funneled through a *single* mechanism —
|
||||
`reconcile-pr.sh` is the one reconcile step that merges and then closes the bead — so there is one
|
||||
binding write path, not competing writers. But the script does **not** verify *who* invoked it: it
|
||||
performs no caller-identity check (no author/orchestrator distinction, no `whoami`). "Only the
|
||||
orchestrator runs it, and the implementer subagents never do" is an operating convention of the
|
||||
ship-beads/reconcile discipline, not something the gate enforces. The gate-enforced grain is
|
||||
narrower (the verdict's `author_context_id` != refuter `context_id`, checked by `pawl-verdict.sh`);
|
||||
single-*writer* itself is convention.
|
||||
One writer owns one active leaf. Parallel writers require disjoint checked
|
||||
scopes, separate worktrees, and one integration owner.
|
||||
|
||||
### D5 — Evidence or it didn't happen
|
||||
Every close cites a proof surface. A verdict with no cited evidence is rejected as unverified.
|
||||
**Embodied-in-gate as evidence *presence*.** `pawl-verdict.sh check` requires real, **non-empty**
|
||||
reviewer evidence: every per-refuter evidence path that exists must point at a non-empty file, and
|
||||
there must be at least one non-empty evidence file or a non-empty `council_artifact`, or the verdict
|
||||
fails closed (HOLD). What the gate enforces is that *a review actually ran and left a non-empty
|
||||
surface* — it does **not** parse or prove the *content* of that evidence (it does not verify the
|
||||
transcript records the specific commands run, nor that those commands match the work). Green CI is
|
||||
recorded but is not the proof — the reviewer evidence is. **Doctrine** rider: "every verdict carries
|
||||
the commands it ran" is the aspiration for *what belongs in* that evidence file; the gate checks
|
||||
presence and non-emptiness, not command-citation.
|
||||
### D5 — Evidence or it did not happen
|
||||
|
||||
### D6 — Fail closed
|
||||
Genuine uncertainty defaults to FAIL. Ties, thin councils, missing minimums → HOLD/escalate; the
|
||||
resolver never synthesizes a winner. A self-grade — the **author's own context** grading the
|
||||
author's own work — never counts as a verdict. (Note: a self-grade is author≠refuter *by context*,
|
||||
not a head-count. A single **fresh-context** refuter — one whose `context_id` differs from the
|
||||
author's — is **not** a self-grade and is the gate's accepted floor under D3; multi-model is the
|
||||
opt-in strengthener, not the minimum.)
|
||||
**Embodied-in-gate.** Every non-CONFIRMED disposition (REFUTED/ESCALATE/HOLD), a STALE head, an
|
||||
unresolvable head, a missing verdict, missing reviewer evidence, or a fresh-context floor that is
|
||||
unmet (zero refuters with a distinct `context_id`) all exit 5 (HOLD: no merge, no close) in
|
||||
`reconcile-pr.sh`. Non-convergence never auto-lands.
|
||||
Deterministic checks record facts for exact inputs. Validate cites those facts
|
||||
and the acceptance claims it judged. Chat confidence is not evidence.
|
||||
|
||||
### D7 — Identity is attested, not asserted
|
||||
**Dropped-as-cathedral** (mostly). The kernel's D7 was anchored to the OS privilege floor —
|
||||
kernel peercred, a separate OS account, `provision-accounts.sh`. That floor is the cut cathedral;
|
||||
do **not** import it as live doctrine. The *surviving* grain: a reviewer's `context_id`/`family`
|
||||
in the pawl verdict is validated against a known roster (off-roster families are rejected so
|
||||
"≥2 distinct families" can't be gamed) — but the threat model is explicitly a *sloppy* agent that
|
||||
self-stamps, **not** a cryptographic forger (single-operator trusted loop; see the pawls.md scope
|
||||
note). No peercred, no signatures, no OS writer-separation.
|
||||
### D6 — Fail closed on meaning, not ceremony
|
||||
|
||||
Missing or failed required proof prevents completion. Cosmetic, pre-existing,
|
||||
theoretical, and out-of-scope findings are NOTE and never block.
|
||||
|
||||
### D7 — Identity is recorded
|
||||
|
||||
Candidate base, commit, tree, owned blobs or deletions, commands, registries,
|
||||
toolchains, environments, author, and validator identities are explicit.
|
||||
|
||||
### D8 — No self-greening
|
||||
A gate and the thing it checks are adversaries; a pass derives from observed behavior, never a
|
||||
self-declared status; tightening/loosening a gate is its own reviewed change, never bundled with
|
||||
the work.
|
||||
**Embodied-in-gate.** The pawl gate cannot be satisfied by the author — it requires an external
|
||||
fresh-context refuter and live `head_sha` binding. **Doctrine** rider: gate changes (editing the
|
||||
pawl list, the verdict schema, or `reconcile-pr.sh`) ship as their own reviewed change — never in
|
||||
the same PR as work they would have caught.
|
||||
|
||||
### D9 — One source of truth
|
||||
Every declared capability has exactly one mechanical source of truth; "done" means the mechanical
|
||||
check is green, not that a doc says so.
|
||||
**Embodied-in-gate** + **doctrine.** AgentOps' `make regen-check` is this rule for derived
|
||||
artifacts: the registry/codex/context-map are generated, never hand-asserted, and drift fails the
|
||||
gate. This doc is itself an instance: it is "done" because regen-check is green, not because this
|
||||
sentence claims it.
|
||||
A worker may run deterministic checks but cannot convert its own semantic claim
|
||||
into PASS. Any candidate edit invalidates the prior verdict.
|
||||
|
||||
### D10 — Typed state transitions, not narrative persuasion
|
||||
Components publish and consume contract surfaces (tracker, reservations, evidence/verdict files)
|
||||
and act; a decision is real only when it appears as the required state transition.
|
||||
**Embodied-in-gate.** The pawl verdict is a typed JSON artifact against
|
||||
`pawl-verdict.v1.schema.json`; the merge path reads *that file*, not a chat assertion. Agent
|
||||
coordination rides Agent Mail locks/reservations, not narrative.
|
||||
### D9 — One source of truth per concern
|
||||
|
||||
### D11 — Policy is executable; roles are structure
|
||||
Policy is versioned, testable, default-deny, hard-reject code that travels with the repo; roles
|
||||
carry duty contracts (reviewer read-only; worker write-scoped; orchestrator coordinates and never
|
||||
labors).
|
||||
**Embodied-in-gate** + **doctrine.** The pawl list + verdict schema + `reconcile-pr.sh` are
|
||||
executable, repo-resident admission policy. The role split (worker proposes / reviewer verifies /
|
||||
orchestrator closes) is the ship-beads/reconcile discipline; the orchestrator-doesn't-labor rule
|
||||
is advisory doctrine for swarm runs.
|
||||
Executable behavior and generated projections outrank narrative docs. Tracker,
|
||||
candidate, verdict, Learn, and delivery records each have one owner; do not
|
||||
mirror them into a second mutable state machine.
|
||||
|
||||
### D12 — Inference mines and codifies; deterministic code reconciles forever
|
||||
The steady-state control loop is deterministic and cheap; inference lives in the learning loop
|
||||
(mine → codify into controllers), never inside the control loop it is meant to make reliable.
|
||||
**Doctrine** — and the core AgentOps shape: the knowledge flywheel (`/curate` — retired, folded into `/post-mortem`; `ao
|
||||
lookup`) is the learning loop; the deterministic gates/scripts are the control loop. Keep models
|
||||
out of the reconcile path; let them propose new deterministic checks, not run inside the gate.
|
||||
### D10 — Typed transitions
|
||||
|
||||
### D13 — Atomic lease-bounded claims; idempotent ticks; precise state words
|
||||
Claiming work is an atomic lock with a visible TTL lease that expired-reaps a dead worker; every
|
||||
tick reads state first and does only the next undone increment; NO_READY ≠ CONVERGED.
|
||||
**Doctrine.** Operating rule for the loop/swarm substrate (beads claim + Agent Mail reservations
|
||||
approximate the lease; evolve/crank ticks are read-state-first). No daemon-level lease reaper is
|
||||
imported — that was floor machinery.
|
||||
Use READY, ACTIVE, FROZEN, VALIDATED or REFUTED, LEARNED, DELIVERED,
|
||||
REMOTE_VERIFIED, and REPORTED. Use NOTE, REPAIR, REPLAN, HOLD, and ANDON for
|
||||
orchestrator decisions. Narrative labels do not create transitions.
|
||||
|
||||
### D11 — Roles are structure
|
||||
|
||||
Discovery shapes, Crank builds, Validate judges, Learn records consequence, and
|
||||
the repository delivers. An adapter may automate mechanics but cannot inherit a
|
||||
role's semantic authority.
|
||||
|
||||
### D12 — Inference proposes; deterministic code repeats
|
||||
|
||||
Models discover and judge meaning. Stable repeated defects may become proposed
|
||||
tests or checks, but enforcement requires runnable positives, negative controls,
|
||||
an owner, rollback, and expiry.
|
||||
|
||||
### D13 — Pull one leaf; make ticks idempotent
|
||||
|
||||
Read durable state before acting and perform only the next legal transition. A
|
||||
retry count is not a budget and an empty ready queue is not convergence.
|
||||
|
||||
### D14 — Destructive writes reconcile or refuse
|
||||
Any write that would replace existing state merges against current reality or fails closed; a
|
||||
close is not durable until merged to trunk.
|
||||
**Embodied-in-gate.** `reconcile-pr.sh` is the named reconcile step; the STALE-head check (a new
|
||||
commit after review invalidates the verdict) is exactly "reconcile against current reality or
|
||||
refuse." "Mutate shared trunk" is the first pawl. **Doctrine** rider: same root applies to
|
||||
tracker/notes/snapshot writes — merge, don't clobber.
|
||||
|
||||
### D15 — The operator's attention is the constraint
|
||||
The scarcest resource is the human's attention; babysitting burns it because an unverified "done"
|
||||
must be personally checked. The system subordinates everything to that constraint and spends
|
||||
attention only where the human is irreplaceable (intent, acceptance, one-way doors).
|
||||
**Embodied-in-gate** (the HOLD) + **doctrine** (the escalation economy). What the *scripts* enforce
|
||||
is the fail-closed HOLD: on any non-CONFIRMED verdict, `reconcile-pr.sh` exits 5 — it does not merge
|
||||
and does not close, so an unverified "done" can never silently land while the human is away.
|
||||
`pawl-verdict.sh`/`reconcile-pr.sh` contain **no** auto-redo loop and **no** circuit breakers; they
|
||||
just hold. The auto-redo-on-REFUTED loop and the tunable circuit breakers (max-attempts, time/cost
|
||||
budget, oscillation, explicit-judgment-flag) are **doctrine / orchestrator-loop behavior** —
|
||||
described in [`pawls.md` §Escalation](../contracts/pawls.md) and carried by the evolve loop and its
|
||||
`scripts/evolve/halt-check.sh`, not by the reconcile/verdict scripts. The andon ("Hey! Listen!") is
|
||||
rare and earned, never the default — but that economy lives in the loop above the gate, not inside
|
||||
the gate script.
|
||||
Before mutation, compare the expected identity with current reality. Changed
|
||||
dependencies or overlaps return to the earliest invalidated move. Never clobber
|
||||
foreign work.
|
||||
|
||||
### D16 — Mechanisms stay general; policy lives in its bounded context; layers meet through ports
|
||||
A shared mechanism never has a context's law welded into it — the context configures it via a mode
|
||||
plus a pointer to its enforcing gate; the factory layer calls the worker layer only through
|
||||
external ports and never bypasses its local gates or rewrites its evidence.
|
||||
**Doctrine** — and the architectural reason this fold is legitimate: the operating rules are the
|
||||
*general mechanism*; the ratchet pawl-gate is AgentOps' *enforcing gate*. The per-pawl `mode`
|
||||
(fresh-context vs multi-model) is exactly "the context configures the mechanism via a mode." See
|
||||
[`architecture/ports-and-adapters.md`](../architecture/ports-and-adapters.md).
|
||||
### D15 — Operator attention is the constraint
|
||||
|
||||
## What was dropped (and why)
|
||||
Ordinary REFUTED work auto-routes to one consolidated REPAIR or REPLAN. A run
|
||||
governor may enter HOLD and consult one bounded helper. Only genuine human
|
||||
authority or a spent hard ceiling earns ANDON.
|
||||
|
||||
These were real in mt-olympus but are **floor/cathedral-specific** — not imported as live AgentOps
|
||||
doctrine:
|
||||
### D16 — Mechanisms stay general; policy stays bounded
|
||||
|
||||
- **The OS privilege floor** — separate OS account, kernel peercred identity,
|
||||
`provision-accounts.sh --check`, the `olympusd` daemon as sole writer. The ratchet pawl-gate is
|
||||
the AgentOps embodiment of "single writer / attested reviewer"; the OS floor is the cut cathedral.
|
||||
- **The 55-case Rust gate spec / typestate `Accepted`** — a specific implementation of "the gate
|
||||
is the only door," not a substrate-neutral rule. AgentOps' door is `reconcile-pr.sh` + the pawl
|
||||
verdict.
|
||||
- **Host-policy instances** (e.g. the `claude -p` LAW 0 ban) — real, mechanically enforced, but a
|
||||
*host-policy instance* of D11 (forbidden-pattern admission), not a method invariant. (LAW 0 still
|
||||
holds operationally; it just isn't kernel doctrine.)
|
||||
- **3-family quorum / Gemini-benched specifics** — operational policy-mode detail of a particular
|
||||
fleet, superseded here by the per-pawl `mode` and the context-identity floor.
|
||||
AgentOps owns intent, independent judgment, evidence, and learning. Runtimes,
|
||||
trackers, local shells, cloud agents, Git providers, CI systems, and release
|
||||
pipelines connect through ports and remain replaceable.
|
||||
|
||||
## Delivery boundary
|
||||
|
||||
Validation and Git delivery are separate. Direct push, PR, hosted CI, or a
|
||||
dedicated merge service may consume the same exact candidate and proof. Delivery
|
||||
does not invoke another model, upgrade the verdict, or replay an unchanged full
|
||||
suite. AgentOps records the resulting identity; the repository owns the action.
|
||||
|
||||
## What was dropped
|
||||
|
||||
The former one-way-door review lifecycle, model-driving Git checks, queue
|
||||
admission, nested retry budgets, and semantic push-hook enforcement are retired.
|
||||
They duplicated the four umbrellas and turned validation into a CI product.
|
||||
Executable owners disappear through the checked K7/K9 direct-cut leaves; this
|
||||
authority change does not pretend that code has already been removed.
|
||||
|
||||
## Provenance
|
||||
|
||||
- Source kernel: `mt-olympus/docs/doctrine/fleet-operating-discipline/corpus/specs/triangulated_kernel.md`
|
||||
(D1–D16, three-model triangulation, evidence anchors `Q-<SRC>-<n>`).
|
||||
- Enforcement surface in this repo: [`docs/contracts/pawls.md`](../contracts/pawls.md),
|
||||
[`scripts/pawl-verdict.sh`](../../scripts/pawl-verdict.sh),
|
||||
[`scripts/reconcile-pr.sh`](../../scripts/reconcile-pr.sh),
|
||||
[`schemas/pawl-verdict.v1.schema.json`](../../schemas/pawl-verdict.v1.schema.json).
|
||||
- The structural-corpus validators (`validate-corpus.py`, `check-doctrine-drift.py`) were
|
||||
**not ported** — see the note at the bottom of this fold's task record; they validate the
|
||||
mt-olympus marker-bounded corpus (anchors, distillations, vendor-drift), which this single
|
||||
adapted reference doc does not carry.
|
||||
This doctrine distills the earlier D1–D16 corpus while replacing its repository
|
||||
gate embodiment with the lean operating loop. Git history preserves the prior
|
||||
mapping for forensic use.
|
||||
|
||||
Reference in New Issue
Block a user