# Dev Cycle

> Full implementation cycle pipeline. Takes the highest-RICE action from the action queue and implements it through a structured test → implement → verify workflow. Primary skill for the implementation domain — invoked by evolve when implementation is selected.

- **Type:** Skill
- **Install:** `agentstack add skill-mataeil-ooda-loop-dev-cycle`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [mataeil](https://agentstack.voostack.com/s/mataeil)
- **Installs:** 0
- **Category:** [Cloud & Infrastructure](https://agentstack.voostack.com/c/cloud-infrastructure)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [mataeil](https://github.com/mataeil)
- **Source:** https://github.com/mataeil/OODA-loop/tree/main/skills/dev-cycle

## Install

```sh
agentstack add skill-mataeil-ooda-loop-dev-cycle
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# dev-cycle: Full Implementation Cycle Pipeline

The "builder" of the harness. Takes the highest-priority action from the action
queue, implements it in a dedicated branch, verifies it passes tests, and
creates a Draft PR for human review.

dev-cycle is the primary skill for the implementation domain. When evolve's
Orient step selects implementation as the winning domain, it calls dev-cycle.
All changes go through branch + PR — dev-cycle never commits directly to main.

- Creates **Draft** PRs by default — human review is mandatory for implementation
- Creates a **ready** (non-draft) PR ONLY when the change is auto-merge-eligible
  (see "Auto-merge eligibility" below) AND the operator has opted in via
  `config.safety.enable_auto_merge`. Default behavior is Draft / human merge.
- NEVER uses `git add -A` — only explicit file staging to prevent secret leaks
- evolve (4-C) is the final merge authority — it re-checks every gate before any
  auto-merge; dev-cycle only chooses draft vs ready.

---

## Safety Rules

1. **HALT file** — Mandatory first check. If present, print reason and stop.
2. **Level gate** — Requires `progressive_complexity >= 3` or direct user invocation. Below Level 3, exit cleanly.
3. **PR size limits** — Respect `config.safety.max_files_per_pr` and `config.safety.max_lines_per_pr`. Exceeding either triggers a partial PR.
4. **Protected paths** — Any change touching `config.safety.protected_paths` forces Risk Tier 3 (already enforced — Draft only).
5. **Explicit staging** — `git add {file}` per file. `git add -A` is forbidden.
6. **Test retry cap** — Maximum 3 fix attempts after a test failure. Beyond that, mark action as `"blocked"` and exit.

---

## Step 0: Safety

### 0-A: HALT Check

```
if file exists at config.safety.halt_file:
  Print "[HALT] dev-cycle stopped. Reason: {file_content}"
  Print "Remove to resume: rm {config.safety.halt_file}"
  EXIT immediately.
```

### 0-B: Level Gate

```
Read config.json → progressive_complexity.current_level  (authoritative source)
Also check config.json → implementation.enabled
if implementation.enabled == false AND not manually invoked by user:
  Print "Implementation domain is disabled. Enable it: set implementation.enabled=true in config.json (done automatically by /ooda-config level 3)"
  EXIT cleanly (not an error).
if progressive_complexity.current_level  **Why this exists.** The f1 dogfood proved the loop can "iterate without
> improving" — a maze/local-optimum — when generation is anchored to the model's
> own priors instead of to external ground truth. The fix (AlphaCodium
> arXiv:2401.08500, which raised pass@5 19%→44% with a structured pre-generation
> stage; AutoCodeRover; Simon Willison's "concrete examples beat abstract
> requirements"): **ground every non-trivial change in an external reference
> BEFORE writing code.** This is Boyd's Observe extended to the world's knowledge,
> not just local state.

For any leap / quality-improving / "make it better" action (skip for a trivial
mechanical edit), BEFORE writing code:

1. **Resolve a reference.** Read `config.references` (and `agent/state/research/*`
   if present — a researched, cited playbook). Pick the reference target for this
   technique/domain (e.g. a named real-product level, a reference implementation
   URL, or a specific playbook move with its concrete API/parameters).
2. **Fetch the concrete block.** WebFetch / curl the *specific* reference snippet
   (the 30–50 lines that matter — the exact API calls, parameter values, order of
   operations), not the whole repo. If a research playbook already contains the
   cited concrete spec, use that.
3. **Derive acceptance criteria** from the reference: "the implementation MUST
   (a) call X with params Y, (b) produce effect Z visible at camera/probe C,
   (c) not break the gate." Record them in the cycle's outcome as
   `reference_block` + `acceptance_criteria`.
4. **Only then generate** — implement the cited technique, adapting names to the
   real code. The PR/outcome records WHICH reference grounded it (`grounded_in`).

A leap with no `grounded_in` reference is a red flag for the maze: prefer
researching a concrete approach over reaching for the model's first idea.

Analyze what needs to change based on the action title, source report, **and the
resolved reference block**, then implement the changes (write and/or edit files).

**Protected paths enforcement:**

Before writing any file, check against `config.safety.protected_paths`.
This prevents dev-cycle from modifying safety-critical files that could
compromise the framework's integrity (self-modification prevention).

```
protected = config.safety.protected_paths    -- e.g., ["agent/safety/*", "skills/evolve/*", "agent/contracts/*"]

before writing or editing any file:
  for each pattern in protected:
    if file path matches glob pattern:
      Print "BLOCKED: {file} matches protected path '{pattern}'. Skipping."
      Print "Protected paths cannot be modified by dev-cycle, even at Level 3."
      Add to PR body notes: "⚠ Protected path {file} was NOT modified (blocked by safety policy)."
      Set protected_blocked = true   -- forces Draft / Risk Tier 3 below (#35)
      DO NOT write/edit this file — continue to next file.
```

If ALL planned files are protected, mark the action as "blocked" with memo
"All target files are protected paths" and EXIT cleanly.

If `protected_blocked` is true (some — not all — target files were protected and
skipped), the PR is **never auto-merge-eligible** even if the remaining diff is
small and green: a partial change with safety-critical files silently dropped may
be incomplete or incoherent, so a human must review it (#35).

**Size limit enforcement:**

Track changes as you write. After each file edit, run `git diff --stat` on
the working tree to get authoritative counts (do not estimate):
```
files_changed = 0
lines_changed = 0  # counted as (additions + deletions) from git diff --numstat
```

Before writing each file:
```
if files_changed >= config.safety.max_files_per_pr:
  Print "PR size limit reached ({max_files_per_pr} files). Creating partial PR."
  Print "Remaining work noted in action-queue memos."
  Add memo to action-queue: "Partial implementation — {files_changed} files changed."
  GOTO Step 4 (verify what was done so far)

if lines_changed + estimated_lines_for_this_file > config.safety.max_lines_per_pr:
  Print "PR line limit reached ({max_lines_per_pr} lines). Creating partial PR."
  GOTO Step 4
```

When partial: create a NEW pending action for the unfinished scope (same
source_domain, title "{original title} (remainder)", rice_score inherited) and
note the split in the original action's `memos` field. The original action then
proceeds to "proposed" like any other PR — the remainder is independently
selectable next cycle and cannot be silently lost with the original stuck
in_progress.

---

## Step 4: Verify

> **Gate integrity (v1.10.1 — earned by the f1 probe).** A static check is
> necessary but NOT sufficient, and a sub-agent's *self-reported* gate result is
> not trustworthy — the orchestrator must verify from facts. Two real misses the
> f1 overnight run surfaced, BOTH caught only by loading the artifact in its real
> runtime, never by the unit gate:
> 1. `node --check` exits 0 on a same-scope `const` REDECLARATION that the browser
>    ES-module parser rejects — the game wouldn't boot, yet the cycle's
>    `node --check + smoke` gate "passed". For an ES-module/browser artifact, also
>    do a **module-load check** (import the changed modules in their module system,
>    e.g. `node --input-type=module -e 'import("./src/x.js")'`, or load the page)
>    — that catches what `node --check` cannot.
> 2. A cumulative **visual regression** (over-exposed-to-white frame) passed every
>    unit gate; only a **rendered critique** caught it.
> Rule: for rich-runtime artifacts (browser/UI/graphics/game), the verification
> MUST load the artifact the way its runtime does (module-load + render/screenshot
> critique, i.e. evolve Step 5-G), and evolve re-checks the gate from recorded
> facts — it does NOT take the build skill's word for "tests passed".

**If `config.test_command` is not configured or is empty:**
```
Print "No test_command configured. Skipping tests."
test_status = "skipped"
GOTO Step 5
```

**If configured**, run tests with timeout enforcement:
```bash
timeout {config.test_timeout_seconds or 300}s {config.test_command}
```

If the test command exceeds the timeout, treat as failure:
```
if exit_code == 124 (timeout):
  Print "ERROR: Test command timed out after {timeout}s. Treating as failure."
  test_output = "Test timeout after {timeout}s"
```

Track attempts:
```
attempt = 1
max_attempts = 3
timeout = config.test_timeout_seconds or 300

while attempt = 3
AND no changed file matches config.safety.protected_paths
AND protected_blocked == false                     -- no protected file was skipped (#35)
AND changed_files_count <= config.safety.auto_merge_max_files   -- default 5
AND changed_lines_count <= config.safety.auto_merge_max_lines   -- default 100
AND test_status == "passed"                        -- the CANONICAL Step-4 value;
                                                   -- "skipped" (no test_command)
                                                   -- is NOT eligible — auto-merge
                                                   -- requires actually-green tests
```
If NOT eligible (the default), create the PR as **Draft**. If eligible, create it
**ready** (omit `--draft`) and stamp `auto_merge_eligible=true` in the meta
comment so evolve 4-C can recognize it — evolve still independently re-checks
every gate before merging (defense in depth).

Create the PR (`--draft` UNLESS auto-merge-eligible):
```bash
gh pr create \
  --title "{selected.title}" \
  $([ "$auto_merge_eligible" = true ] || echo --draft) \
  --body "$(cat <<'EOF'

## Source
- **Domain**: {selected.source_domain}
- **RICE Score**: {selected.effective_rice}
- **Action ID**: {selected.id}

## Changes
| File | Description |
|------|-------------|
| `{file1}` | {one-line description} |

## Test Results
- **Status**: {test_status}
- **Command**: `{config.test_command}`
- **Attempts**: {attempt}/{max_attempts}
- **Output** (last run): `{last 5 lines of test output or "tests skipped"}`

## Notes
{any partial PR notes, size limit warnings, or protected-path flags}

---
Generated by OODA-loop dev-cycle v1.0.0
EOF
)"
```

(`--draft` is added by the conditional on the `gh pr create` line above — present
unless the change is auto-merge-eligible.)

If `gh` is not available:
```
Print "gh (GitHub CLI) not found. PR creation skipped."
Print "Push the branch and create a PR manually:"
Print "  git push origin {branch_name}"
Print "  gh pr create --draft --title \"{selected.title}\""
pr_number = null
```

Update `action_queue.json`:
```json
{
  "status": "proposed",
  "pr_number": {number or null},
  "pr_url": "{url or null}",
  "proposed_at": "{ISO 8601}"
}
```

---

## Step 6: Report

Print the final summary:

```
dev-cycle complete — {ISO timestamp}
Action  : {selected.title} (RICE: {selected.effective_rice})
Branch  : auto/dev-cycle/{slug}
PR      : #{pr_number} ({Draft|ready})  |  {pr_url}
Files   : {files_changed} changed
Lines   : {lines_changed} changed
Tests   : {test_status}
Status  : proposed
pr_created : {true|false}
```

`pr_created` is a REQUIRED report variable (true iff a PR was actually opened
this run) — it is what evolve's 4-B evaluates for this skill's chain trigger
(`pr_created == true`). Report variables are the evaluation source for skills
whose contract output file (here `action_queue.json`) doesn't carry the
condition fields at top level.

If PR was not created (gh unavailable):
```
PR      : not created — push branch and create manually
```

---

## Graceful Degradation

| Scenario | Behavior |
|---|---|
| HALT file present | Print reason, exit immediately |
| Level < 3, not manual | Print level message, exit cleanly |
| action_queue.json missing | Print "Action queue not found at agent/state/evolve/action_queue.json", exit cleanly |
| No pending actions | Print "No pending actions", exit cleanly |
| Branch already exists | Append suffix (`-2`, `-3`), continue |
| PR size limit hit | Create partial PR, note remaining scope in action memos |
| Tests fail after 3 tries | Mark action "blocked", stash changes, exit non-zero |
| `git push` fails | Record error in memos, print manual instructions, exit non-zero |
| `gh` not installed | Skip PR creation, print manual instructions, exit 0 |
| `test_command` not configured | Skip tests, record "skipped", continue to PR |
| `related_files` missing/empty | Proceed with action title and source report only |
| Protected path changed | Already in Draft mode — note in PR body as protected-path change |
| Merge conflict on push | Abort push, mark action `"blocked"` with memo `"merge conflict with main"`, stash changes, exit non-zero |
| `action_queue.json` malformed | Print parse error, exit cleanly |
| Branch suffix exhausted (`-9`) | Print error, mark action `"blocked"`, exit non-zero |

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [mataeil](https://github.com/mataeil)
- **Source:** [mataeil/OODA-loop](https://github.com/mataeil/OODA-loop)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-mataeil-ooda-loop-dev-cycle
- Seller: https://agentstack.voostack.com/s/mataeil
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
