Install
$ agentstack add skill-mataeil-ooda-loop-dev-cycle ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →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
- HALT file — Mandatory first check. If present, print reason and stop.
- Level gate — Requires
progressive_complexity >= 3or direct user invocation. Below Level 3, exit cleanly. - PR size limits — Respect
config.safety.max_files_per_prandconfig.safety.max_lines_per_pr. Exceeding either triggers a partial PR. - Protected paths — Any change touching
config.safety.protected_pathsforces Risk Tier 3 (already enforced — Draft only). - Explicit staging —
git add {file}per file.git add -Ais forbidden. - 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):
fileschanged = 0 lineschanged = 0 # counted as (additions + deletions) from git diff --numstat
Before writing each file:
if fileschanged >= config.safety.maxfilesperpr: Print "PR size limit reached ({maxfilesperpr} files). Creating partial PR." Print "Remaining work noted in action-queue memos." Add memo to action-queue: "Partial implementation — {fileschanged} files changed." GOTO Step 4 (verify what was done so far)
if lineschanged + estimatedlinesforthisfile > config.safety.maxlinesperpr: Print "PR line limit reached ({maxlinesper_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 testcommand configured. Skipping tests." teststatus = "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):
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:
{
"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 | | actionqueue.json missing | Print "Action queue not found at agent/state/evolve/actionqueue.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
- Source: mataeil/OODA-loop
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.