# Allegro Burn-Mode Validator Rules

**Epic:** #842 M7 — Autonomous Burn-Mode Hardening
**Issue:** #242
**Source:** `allegro/cycle_guard.py`

Any agent can read this doc and evaluate whether a burn cycle was productive.

---

## Cycle Lifecycle

```
start_cycle(target)
  → start_slice("clone") → end_slice(artifact="repo cloned")
  → start_slice("implement") → end_slice(artifact="PR #42")
  → commit_cycle(proof={...})
```

A cycle has three terminal states:
- **complete** — `commit_cycle()` called with proof
- **aborted** — `abort_cycle(reason)` called, reason recorded
- **stale** — crashed or hung; auto-aborted by `resume_or_abort()` after 30 min

---

## 1. Tangible Artifact Criteria

A cycle is **productive** if at least one slice produces a tangible artifact.

### What Counts as Tangible

| Artifact Type | Example | Valid |
|---|---|---|
| Git commit | `abc1234 — fix: resolve import collision` | ✅ |
| Pull request | `PR #42: https://forge.../pulls/42` | ✅ |
| Issue closure | `Closed #17 with comment explaining resolution` | ✅ |
| Test file | `tests/test_new_feature.py — 5 passing` | ✅ |
| Report | `reports/2026-04-15-audit.md` committed to repo | ✅ |
| Config change | Modified `config.yaml`, pushed to branch | ✅ |
| Documentation | New or updated `.md` file committed | ✅ |
| Skill created | `skill_manage(create)` with SKILL.md | ✅ |
| Memory updated | Facts saved via `memory()` tool | ✅ |

### What Does NOT Count

| Non-Artifact | Why | Invalid |
|---|---|---|
| Log output only | Ephemeral, not durable | ❌ |
| "I analyzed the code" | No file touched, no commit made | ❌ |
| Conversation summary | Not a repo artifact | ❌ |
| Plan without execution | Intent without delivery | ❌ |
| Duplicate of existing work | No new value produced | ❌ |
| Deleted work with no record | Net-zero artifact | ❌ |

### Rule

> **Every cycle must produce at least one tangible artifact or a documented abort reason.**
> A cycle that ends with `status: complete` but `proof: null` and zero commits is **invalid**.

---

## 2. Stop Compliance Checks

The cycle guard enforces time discipline via `cycle_guard.py`.

### Slice Timeout (10-minute rule)

- Each slice has a 10-minute default max (`check_slice_timeout(max_minutes=10)`)
- If a slice exceeds 10 minutes, the agent should either:
  - End it with a partial artifact and start a new slice
  - Abort with reason: `"slice timeout — {description}"`

### Crash Recovery (30-minute rule)

- `resume_or_abort()` auto-aborts cycles stuck for >30 minutes
- If `cycle_guard.py resume` returns `aborted`, the agent must not continue the old cycle
- Start a fresh cycle instead

### Stop Signals

An agent MUST stop and abort when:

| Signal | Action |
|---|---|
| `check_slice_timeout` returns `True` | End slice, start new or abort |
| `resume_or_abort` returns `aborted` | Do not resume; start fresh |
| Issue already closed/implemented | Abort: `"already resolved"` |
| Authentication failure | Abort: `"auth failure — {detail}"` |
| Clone timeout > 120s | Abort: `"clone timeout"` |
| Unresolvable merge conflict | Abort: `"merge conflict — manual intervention needed"` |
| Human says stop | Abort: `"human override"` |

### Lane Boundary Checks

Agents must stay in their lane:

| Agent | Lane | Out-of-Bounds |
|---|---|---|
| Allegro | Dispatch, reporting, infra, docs | Direct model training, UI changes |
| Claude | Architecture, complex bugs | Simple config edits (use Gemini) |
| Gemini | Issue burn, simple fixes | Architecture decisions |
| Codex | Code generation, test writing | Operational dispatch |
| Ezra | Analysis, pattern recognition | Implementation |

If an agent detects it's working out-of-lane:
```
abort_cycle("out-of-lane — {what} should be done by {correct_agent}")
```

---

## 3. Proof Structure

The `proof` field in `commit_cycle()` should contain:

```json
{
  "artifacts": [
    {
      "type": "pr",
      "number": 42,
      "url": "https://forge.../pulls/42",
      "repo": "Timmy_Foundation/timmy-config"
    }
  ],
  "commits": ["abc1234", "def5678"],
  "files_changed": ["allegro/burn-mode-validator.md"],
  "summary": "Documented burn-loop validator rules per #242"
}
```

Minimal valid proof (single commit, no PR):
```json
{
  "commits": ["abc1234"],
  "summary": "Fixed import collision in scripts/ci_automation_gate.py"
}
```

Invalid proof (empty):
```json
null
```
A cycle with `proof: null` and no commits is **invalid** — it should have been aborted.

---

## 4. Validation Examples

### PASS: Productive Cycle

```json
{
  "cycle_id": "2026-04-21T14:00:00+00:00",
  "status": "complete",
  "target": "timmy-config issue #242",
  "slices": [
    {"name": "clone", "status": "complete", "artifact": "repo cloned"},
    {"name": "implement", "status": "complete", "artifact": "PR #301"},
    {"name": "verify", "status": "complete", "artifact": "tests passing"}
  ],
  "proof": {"commits": ["abc1234"], "summary": "Documented validator rules"}
}
```
**Verdict: PASS** — Three slices, each with artifact, proof present, committed.

### PASS: Productive Abort

```json
{
  "cycle_id": "2026-04-21T14:00:00+00:00",
  "status": "aborted",
  "target": "hermes-agent issue #999",
  "slices": [
    {"name": "clone", "status": "complete", "artifact": "repo cloned"},
    {"name": "investigate", "status": "aborted", "artifact": null}
  ],
  "abort_reason": "already resolved — PR #888 merged this fix yesterday"
}
```
**Verdict: PASS** — Legitimate abort with clear reason. Investigation was productive (discovered duplicate).

### FAIL: Empty Cycle

```json
{
  "cycle_id": "2026-04-21T14:00:00+00:00",
  "status": "complete",
  "target": "timmy-config issue #123",
  "slices": [],
  "proof": null
}
```
**Verdict: FAIL** — No slices, no artifacts, no proof. Agent started but produced nothing.

### FAIL: Log-Only Cycle

```json
{
  "cycle_id": "2026-04-21T14:00:00+00:00",
  "status": "complete",
  "target": "timmy-config issue #456",
  "slices": [
    {"name": "analyze", "status": "complete", "artifact": "analysis output to stdout"}
  ],
  "proof": {"summary": "Analyzed the codebase and identified 3 patterns"}
}
```
**Verdict: FAIL** — Analysis produced no durable artifact. Should have written findings to a file or created an issue.

### FAIL: Stale Cycle (Auto-Aborted)

```json
{
  "cycle_id": "2026-04-21T14:00:00+00:00",
  "status": "aborted",
  "target": "timmy-config issue #789",
  "slices": [
    {"name": "clone", "status": "in_progress", "artifact": null}
  ],
  "abort_reason": "crash recovery — stale cycle detected (45m old)"
}
```
**Verdict: FAIL** — Clone hung or agent crashed. `resume_or_abort()` caught it. Start fresh.

---

## 5. Integration Points

### In Burn-Loop Prompts

Add to dispatch prompts:
```
Before starting: python3 allegro/cycle_guard.py resume
After each slice: python3 allegro/cycle_guard.py end --artifact "description"
After all work: python3 allegro/cycle_guard.py commit --proof '{"commits":["..."],"summary":"..."}'
If stuck: python3 allegro/cycle_guard.py abort "reason"
```

### In Reporting

Morning reports should include cycle validation:
```
Cycles last night: 12
- Complete with proof: 9
- Productive aborts: 2
- Failed (empty/stale): 1  ← RCA filed
```

### In Metrics

Track as fleet health metric:
- **Cycle completion rate:** complete / total cycles
- **Artifact density:** artifacts per cycle (target: ≥1)
- **Abort quality:** % of aborts with descriptive reasons
- **Stale detection rate:** auto-aborted / total cycles (target: <5%)

---

## Quick Reference

```
# Start
python3 allegro/cycle_guard.py start "timmy-config #242"

# Work slices
python3 allegro/cycle_guard.py slice "clone"
# ... do work ...
python3 allegro/cycle_guard.py end --artifact "repo cloned"

python3 allegro/cycle_guard.py slice "implement"
# ... do work ...
python3 allegro/cycle_guard.py end --artifact "PR #301"

# Finish
python3 allegro/cycle_guard.py commit --proof '{"commits":["abc1234"],"summary":"Done"}'

# Or abort
python3 allegro/cycle_guard.py abort "already resolved"

# Recovery check
python3 allegro/cycle_guard.py resume
```
