simplicio-loop 1.0.2__tar.gz → 1.0.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {simplicio_loop-1.0.2 → simplicio_loop-1.0.4}/MANIFEST.in +3 -3
- {simplicio_loop-1.0.2/simplicio_loop.egg-info → simplicio_loop-1.0.4}/PKG-INFO +3 -1
- {simplicio_loop-1.0.2 → simplicio_loop-1.0.4}/PYPI.md +52 -52
- {simplicio_loop-1.0.2 → simplicio_loop-1.0.4}/pyproject.toml +45 -38
- {simplicio_loop-1.0.2 → simplicio_loop-1.0.4}/simplicio_loop/__init__.py +8 -8
- simplicio_loop-1.0.4/simplicio_loop/_bundle/skills/simplicio-loop/SKILL.md +182 -0
- {simplicio_loop-1.0.2 → simplicio_loop-1.0.4}/simplicio_loop/_bundle/skills/simplicio-tasks/SKILL.md +6 -0
- {simplicio_loop-1.0.2 → simplicio_loop-1.0.4}/simplicio_loop/_bundle/skills/simplicio-tasks/references/extension-points.md +14 -0
- {simplicio_loop-1.0.2 → simplicio_loop-1.0.4}/simplicio_loop/cli.py +76 -76
- {simplicio_loop-1.0.2 → simplicio_loop-1.0.4/simplicio_loop.egg-info}/PKG-INFO +3 -1
- {simplicio_loop-1.0.2 → simplicio_loop-1.0.4}/simplicio_loop.egg-info/SOURCES.txt +1 -0
- simplicio_loop-1.0.4/simplicio_loop.egg-info/requires.txt +2 -0
- simplicio_loop-1.0.2/simplicio_loop/_bundle/skills/simplicio-loop/SKILL.md +0 -108
- {simplicio_loop-1.0.2 → simplicio_loop-1.0.4}/LICENSE +0 -0
- {simplicio_loop-1.0.2 → simplicio_loop-1.0.4}/README.md +0 -0
- {simplicio_loop-1.0.2 → simplicio_loop-1.0.4}/setup.cfg +0 -0
- {simplicio_loop-1.0.2 → simplicio_loop-1.0.4}/simplicio_loop/_bundle/hooks/hooks.claude.json +0 -0
- {simplicio_loop-1.0.2 → simplicio_loop-1.0.4}/simplicio_loop/_bundle/hooks/hooks.json +0 -0
- {simplicio_loop-1.0.2 → simplicio_loop-1.0.4}/simplicio_loop/_bundle/hooks/learn_stop.py +0 -0
- {simplicio_loop-1.0.2 → simplicio_loop-1.0.4}/simplicio_loop/_bundle/hooks/loop_capture.py +0 -0
- {simplicio_loop-1.0.2 → simplicio_loop-1.0.4}/simplicio_loop/_bundle/hooks/loop_stop.py +0 -0
- {simplicio_loop-1.0.2 → simplicio_loop-1.0.4}/simplicio_loop/_bundle/hooks/orient_clamp.py +0 -0
- {simplicio_loop-1.0.2 → simplicio_loop-1.0.4}/simplicio_loop/_bundle/hooks/orient_rewrite.py +0 -0
- {simplicio_loop-1.0.2 → simplicio_loop-1.0.4}/simplicio_loop/_bundle/skills/simplicio-compress/SKILL.md +0 -0
- {simplicio_loop-1.0.2 → simplicio_loop-1.0.4}/simplicio_loop/_bundle/skills/simplicio-learn/SKILL.md +0 -0
- {simplicio_loop-1.0.2 → simplicio_loop-1.0.4}/simplicio_loop/_bundle/skills/simplicio-orient/SKILL.md +0 -0
- {simplicio_loop-1.0.2 → simplicio_loop-1.0.4}/simplicio_loop/_bundle/skills/simplicio-review/SKILL.md +0 -0
- {simplicio_loop-1.0.2 → simplicio_loop-1.0.4}/simplicio_loop/_bundle/skills/simplicio-tasks/references/azure-devops-adapter.md +0 -0
- {simplicio_loop-1.0.2 → simplicio_loop-1.0.4}/simplicio_loop/_bundle/skills/simplicio-tasks/references/orchestration.md +0 -0
- {simplicio_loop-1.0.2 → simplicio_loop-1.0.4}/simplicio_loop/_bundle/skills/simplicio-tasks/references/quality-safety-delivery.md +0 -0
- {simplicio_loop-1.0.2 → simplicio_loop-1.0.4}/simplicio_loop/_bundle/skills/simplicio-tasks/references/standing-loop-247.md +0 -0
- {simplicio_loop-1.0.2 → simplicio_loop-1.0.4}/simplicio_loop/_bundle/skills/simplicio-tasks/references/token-economy.md +0 -0
- {simplicio_loop-1.0.2 → simplicio_loop-1.0.4}/simplicio_loop/_bundle/skills/simplicio-tasks/references/web-evidence.md +0 -0
- {simplicio_loop-1.0.2 → simplicio_loop-1.0.4}/simplicio_loop.egg-info/dependency_links.txt +0 -0
- {simplicio_loop-1.0.2 → simplicio_loop-1.0.4}/simplicio_loop.egg-info/entry_points.txt +0 -0
- {simplicio_loop-1.0.2 → simplicio_loop-1.0.4}/simplicio_loop.egg-info/top_level.txt +0 -0
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
include PYPI.md
|
|
2
|
-
include LICENSE
|
|
3
|
-
recursive-include simplicio_loop/_bundle *
|
|
1
|
+
include PYPI.md
|
|
2
|
+
include LICENSE
|
|
3
|
+
recursive-include simplicio_loop/_bundle *
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: simplicio-loop
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.4
|
|
4
4
|
Summary: The Universal Looping AI Orchestrator — a runtime-agnostic super-plugin (6 skills) that drains any queue of work end-to-end on any LLM/runtime.
|
|
5
5
|
Author-email: Wesley Simplicio <wesleybob4@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -19,6 +19,8 @@ Classifier: Operating System :: OS Independent
|
|
|
19
19
|
Requires-Python: >=3.8
|
|
20
20
|
Description-Content-Type: text/markdown
|
|
21
21
|
License-File: LICENSE
|
|
22
|
+
Requires-Dist: simplicio-mapper
|
|
23
|
+
Requires-Dist: simplicio-cli
|
|
22
24
|
Dynamic: license-file
|
|
23
25
|
|
|
24
26
|
# simplicio-loop
|
|
@@ -1,52 +1,52 @@
|
|
|
1
|
-
# simplicio-loop
|
|
2
|
-
|
|
3
|
-
**The Universal Looping AI Orchestrator** — a runtime-agnostic **super-plugin** (6 skills) that
|
|
4
|
-
drains any queue of work end-to-end on **any LLM / runtime**:
|
|
5
|
-
`discover → implement → verify → merge → close → watch 24/7`, behind safety gates and a hard cost
|
|
6
|
-
kill-switch, at up to **96% fewer tokens**. Not a chatbot. A worker.
|
|
7
|
-
|
|
8
|
-

|
|
9
|
-
|
|
10
|
-
## Install
|
|
11
|
-
|
|
12
|
-
```bash
|
|
13
|
-
pip install simplicio-loop
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
Then drop the skills + hooks into your project (or globally):
|
|
17
|
-
|
|
18
|
-
```bash
|
|
19
|
-
simplicio-loop install # into ./.claude of the current project
|
|
20
|
-
simplicio-loop install --global # into ~/.claude (all projects)
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
Now invoke it from your agent runtime (Claude Code, Cursor, Codex, Gemini, …):
|
|
24
|
-
|
|
25
|
-
```
|
|
26
|
-
/simplicio-tasks finish all the open issues
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
## What you get — 6 skills
|
|
30
|
-
|
|
31
|
-
| Skill | What it does |
|
|
32
|
-
|---|---|
|
|
33
|
-
| `simplicio-tasks` | The orchestrator loop: discover → implement → verify → merge → close → watch 24/7. |
|
|
34
|
-
| `simplicio-loop` | Hardened Ralph loop — re-feed the goal until an evidence-gated `<promise>` or a cap. |
|
|
35
|
-
| `simplicio-orient` | Terminal-first token economy — output-reduction catalog, tee-cache, signatures-read. |
|
|
36
|
-
| `simplicio-review` | Adversarial review — parallel subagents on distinct rubrics, deduped into one verdict. |
|
|
37
|
-
| `simplicio-compress` | Output + memory compression, byte-preserving identifiers. |
|
|
38
|
-
| `simplicio-learn` | Retrospective — durable, deduped lessons written back to memory. |
|
|
39
|
-
|
|
40
|
-
## Highlights
|
|
41
|
-
|
|
42
|
-
- **11 runtimes, one protocol** — Claude Code, Codex, VS Code/Copilot, Cursor, Antigravity, Kiro,
|
|
43
|
-
OpenCode, Gemini, Aider, Hermes, OpenClaw.
|
|
44
|
-
- **Evidence-gated completion** — never a false "done"; exits only on a verified `<promise>` or a
|
|
45
|
-
cap / budget / STOP.
|
|
46
|
-
- **Token economy** — honest "answer concisely" baseline; savings credited only on verified-correct
|
|
47
|
-
outcomes.
|
|
48
|
-
|
|
49
|
-
Requires Python 3.8+. The skills, hooks, and installer are pure cross-platform Python.
|
|
50
|
-
|
|
51
|
-
MIT — part of the [Simplicio](https://github.com/wesleysimplicio) ecosystem.
|
|
52
|
-
Full docs: <https://github.com/wesleysimplicio/simplicio-loop>
|
|
1
|
+
# simplicio-loop
|
|
2
|
+
|
|
3
|
+
**The Universal Looping AI Orchestrator** — a runtime-agnostic **super-plugin** (6 skills) that
|
|
4
|
+
drains any queue of work end-to-end on **any LLM / runtime**:
|
|
5
|
+
`discover → implement → verify → merge → close → watch 24/7`, behind safety gates and a hard cost
|
|
6
|
+
kill-switch, at up to **96% fewer tokens**. Not a chatbot. A worker.
|
|
7
|
+
|
|
8
|
+

|
|
9
|
+
|
|
10
|
+
## Install
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
pip install simplicio-loop
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Then drop the skills + hooks into your project (or globally):
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
simplicio-loop install # into ./.claude of the current project
|
|
20
|
+
simplicio-loop install --global # into ~/.claude (all projects)
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Now invoke it from your agent runtime (Claude Code, Cursor, Codex, Gemini, …):
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
/simplicio-tasks finish all the open issues
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## What you get — 6 skills
|
|
30
|
+
|
|
31
|
+
| Skill | What it does |
|
|
32
|
+
|---|---|
|
|
33
|
+
| `simplicio-tasks` | The orchestrator loop: discover → implement → verify → merge → close → watch 24/7. |
|
|
34
|
+
| `simplicio-loop` | Hardened Ralph loop — re-feed the goal until an evidence-gated `<promise>` or a cap. |
|
|
35
|
+
| `simplicio-orient` | Terminal-first token economy — output-reduction catalog, tee-cache, signatures-read. |
|
|
36
|
+
| `simplicio-review` | Adversarial review — parallel subagents on distinct rubrics, deduped into one verdict. |
|
|
37
|
+
| `simplicio-compress` | Output + memory compression, byte-preserving identifiers. |
|
|
38
|
+
| `simplicio-learn` | Retrospective — durable, deduped lessons written back to memory. |
|
|
39
|
+
|
|
40
|
+
## Highlights
|
|
41
|
+
|
|
42
|
+
- **11 runtimes, one protocol** — Claude Code, Codex, VS Code/Copilot, Cursor, Antigravity, Kiro,
|
|
43
|
+
OpenCode, Gemini, Aider, Hermes, OpenClaw.
|
|
44
|
+
- **Evidence-gated completion** — never a false "done"; exits only on a verified `<promise>` or a
|
|
45
|
+
cap / budget / STOP.
|
|
46
|
+
- **Token economy** — honest "answer concisely" baseline; savings credited only on verified-correct
|
|
47
|
+
outcomes.
|
|
48
|
+
|
|
49
|
+
Requires Python 3.8+. The skills, hooks, and installer are pure cross-platform Python.
|
|
50
|
+
|
|
51
|
+
MIT — part of the [Simplicio](https://github.com/wesleysimplicio) ecosystem.
|
|
52
|
+
Full docs: <https://github.com/wesleysimplicio/simplicio-loop>
|
|
@@ -1,38 +1,45 @@
|
|
|
1
|
-
[build-system]
|
|
2
|
-
requires = ["setuptools>=68", "wheel"]
|
|
3
|
-
build-backend = "setuptools.build_meta"
|
|
4
|
-
|
|
5
|
-
[project]
|
|
6
|
-
name = "simplicio-loop"
|
|
7
|
-
version = "1.0.
|
|
8
|
-
description = "The Universal Looping AI Orchestrator — a runtime-agnostic super-plugin (6 skills) that drains any queue of work end-to-end on any LLM/runtime."
|
|
9
|
-
readme = "PYPI.md"
|
|
10
|
-
requires-python = ">=3.8"
|
|
11
|
-
license = { text = "MIT" }
|
|
12
|
-
authors = [{ name = "Wesley Simplicio", email = "wesleybob4@gmail.com" }]
|
|
13
|
-
keywords = ["ai", "agent", "orchestrator", "llm", "claude", "cursor", "automation", "ralph-loop", "token-economy", "cli"]
|
|
14
|
-
classifiers = [
|
|
15
|
-
"Development Status :: 4 - Beta",
|
|
16
|
-
"Intended Audience :: Developers",
|
|
17
|
-
"License :: OSI Approved :: MIT License",
|
|
18
|
-
"Programming Language :: Python :: 3",
|
|
19
|
-
"Programming Language :: Python :: 3 :: Only",
|
|
20
|
-
"Topic :: Software Development :: Build Tools",
|
|
21
|
-
"Topic :: Utilities",
|
|
22
|
-
"Operating System :: OS Independent",
|
|
23
|
-
]
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
[
|
|
38
|
-
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "simplicio-loop"
|
|
7
|
+
version = "1.0.4"
|
|
8
|
+
description = "The Universal Looping AI Orchestrator — a runtime-agnostic super-plugin (6 skills) that drains any queue of work end-to-end on any LLM/runtime."
|
|
9
|
+
readme = "PYPI.md"
|
|
10
|
+
requires-python = ">=3.8"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "Wesley Simplicio", email = "wesleybob4@gmail.com" }]
|
|
13
|
+
keywords = ["ai", "agent", "orchestrator", "llm", "claude", "cursor", "automation", "ralph-loop", "token-economy", "cli"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 4 - Beta",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
20
|
+
"Topic :: Software Development :: Build Tools",
|
|
21
|
+
"Topic :: Utilities",
|
|
22
|
+
"Operating System :: OS Independent",
|
|
23
|
+
]
|
|
24
|
+
# The simplicio-loop drive REQUIRES two operators (see .claude/skills/simplicio-loop/SKILL.md):
|
|
25
|
+
# simplicio-mapper -> the repo-survey step (binds `orient`)
|
|
26
|
+
# simplicio-cli -> the operator that applies+verifies changes (binds `execute`/`deterministic_edit`)
|
|
27
|
+
dependencies = [
|
|
28
|
+
"simplicio-mapper",
|
|
29
|
+
"simplicio-cli",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[project.urls]
|
|
33
|
+
Homepage = "https://github.com/wesleysimplicio/simplicio-loop"
|
|
34
|
+
Repository = "https://github.com/wesleysimplicio/simplicio-loop"
|
|
35
|
+
Issues = "https://github.com/wesleysimplicio/simplicio-loop/issues"
|
|
36
|
+
|
|
37
|
+
[project.scripts]
|
|
38
|
+
simplicio-loop = "simplicio_loop.cli:main"
|
|
39
|
+
|
|
40
|
+
[tool.setuptools]
|
|
41
|
+
packages = ["simplicio_loop"]
|
|
42
|
+
include-package-data = true
|
|
43
|
+
|
|
44
|
+
[tool.setuptools.package-data]
|
|
45
|
+
simplicio_loop = ["_bundle/**/*"]
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
"""simplicio-loop — The Universal Looping AI Orchestrator.
|
|
2
|
-
|
|
3
|
-
A runtime-agnostic super-plugin (6 skills + loop/token hooks) that drains any
|
|
4
|
-
queue of work end-to-end on any LLM/runtime. This package ships the skills and
|
|
5
|
-
hooks and installs them into a runtime's skills location.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
__version__ = "1.0.
|
|
1
|
+
"""simplicio-loop — The Universal Looping AI Orchestrator.
|
|
2
|
+
|
|
3
|
+
A runtime-agnostic super-plugin (6 skills + loop/token hooks) that drains any
|
|
4
|
+
queue of work end-to-end on any LLM/runtime. This package ships the skills and
|
|
5
|
+
hooks and installs them into a runtime's skills location.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
__version__ = "1.0.3"
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: simplicio-loop
|
|
3
|
+
description: Iterate on a task autonomously until a typed completion-promise is genuinely true or a max-iteration cap is hit — the Ralph Wiggum loop, hardened. Use when the user says "ralph loop", "keep iterating until done", "loop on this until it passes", or when simplicio-tasks needs a self-referential drive that re-feeds the same goal each turn and sees its own prior work. Runtime-agnostic: binds a real stop-hook where the host supports hooks (Claude, Cursor); otherwise self-paces via the host scheduler. Never escapes the loop with a false promise.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# simplicio-loop — the hardened Ralph loop
|
|
7
|
+
|
|
8
|
+
A self-referential iteration primitive: the SAME goal is fed back after every turn, so
|
|
9
|
+
the agent sees its own prior edits and converges. It exits ONLY when a **typed
|
|
10
|
+
completion-promise** is genuinely true, or a hard `max_iterations` cap fires. This is the
|
|
11
|
+
drive underneath `simplicio-tasks`' 24/7 watcher (Step 3b/7) extracted as a reusable,
|
|
12
|
+
inspectable, cancellable skill.
|
|
13
|
+
|
|
14
|
+
Credit: the technique is Ralph Wiggum / cursor `ralph-loop`. We keep its best parts —
|
|
15
|
+
single human-readable state file, exact-match promise sentinel, two-hook split — and add
|
|
16
|
+
the simplicio safety spine (evidence-gated promise, budget kill-switch, cross-platform hook).
|
|
17
|
+
|
|
18
|
+
## When to use
|
|
19
|
+
|
|
20
|
+
- "run a ralph loop on X", "iterate until the tests pass", "keep going until done".
|
|
21
|
+
- As the engine for `simplicio-tasks` when it must drain a queue unattended.
|
|
22
|
+
- NOT for a one-shot edit — use the host's normal flow.
|
|
23
|
+
|
|
24
|
+
## Bound operators (REQUIRED): survey + operate
|
|
25
|
+
|
|
26
|
+
This loop does NOT survey the repo with the LLM, and it does NOT hand-edit files with the LLM.
|
|
27
|
+
Two installed CLIs are the operators; the model only DECIDES, the operators DO. Both ship as
|
|
28
|
+
hard dependencies of the `simplicio-loop` package (`pip install simplicio-loop` pulls them):
|
|
29
|
+
|
|
30
|
+
| Operator | CLI (binary) | Binds | Role in the loop |
|
|
31
|
+
|---|---|---|---|
|
|
32
|
+
| **simplicio-mapper** | `simplicio-mapper` | `orient` / `recall` | **Survey** — maps the repo(s) into `.simplicio/*.json` (project-map, precedent-index, symbol-index, call-graph, docs). This survey, not an ad-hoc LLM read, is what feeds the goal each turn. |
|
|
33
|
+
| **simplicio-dev-cli** | `simplicio-dev-cli` | `execute` / `deterministic_edit` / `validate` / `diagnostics` | **Operate** — applies a DECIDED change through its 6-layer contract (mapper context → precedent → prompt → diff → test → verify, ≤3 retries). The CLI edits and verifies; the AI does not hand-write the diff. |
|
|
34
|
+
|
|
35
|
+
**Preflight (MANDATORY, BLOCKING).** Before iteration 1, confirm both operators are on PATH:
|
|
36
|
+
```bash
|
|
37
|
+
simplicio-mapper --version # survey operator
|
|
38
|
+
simplicio-dev-cli --help # action operator (pkg simplicio-cli; exposes `simplicio-dev-cli`)
|
|
39
|
+
```
|
|
40
|
+
The action binary is `simplicio-dev-cli` (from `pip install simplicio-cli`) — NOT the bare
|
|
41
|
+
`simplicio`, which is reserved for the compiled Rust `simplicio-runtime` and is not what this loop
|
|
42
|
+
binds. `simplicio-dev-cli` has no `--version` subcommand; `--help` exiting 0 is the readiness
|
|
43
|
+
proof. If either operator is missing, do NOT fall back to LLM survey/editing — STOP and emit
|
|
44
|
+
`simplicio-loop: BLOCKED — missing operator <name>; run: pip install simplicio-loop` (the install
|
|
45
|
+
re-pulls `simplicio-mapper` + `simplicio-cli`). This requirement is scoped to the loop drive.
|
|
46
|
+
|
|
47
|
+
**Survey step (each loop start + on any structural change).** Run
|
|
48
|
+
`simplicio-mapper index . --json` (add `--watch` for long runs) to (re)build `.simplicio/`. Read
|
|
49
|
+
the survey artifacts — never re-scan the tree by hand when a fresh map exists. For a multi-repo
|
|
50
|
+
levantamento, run the mapper per repo root and aggregate the JSON.
|
|
51
|
+
|
|
52
|
+
**Operate step (every turn that mutates code).** Once the AC and the change are DECIDED, delegate
|
|
53
|
+
the mutation to the operator, one decided change at a time:
|
|
54
|
+
```bash
|
|
55
|
+
simplicio-dev-cli task "<the decided, AC-scoped change>" --target <file> [--json]
|
|
56
|
+
```
|
|
57
|
+
The operator applies the diff, runs the tests, and self-corrects up to 3× — its passing
|
|
58
|
+
verification IS the in-turn evidence the promise gate needs (below). The AI never edits the file
|
|
59
|
+
directly inside the loop; if `simplicio-dev-cli` cannot complete a change after its retries, treat that
|
|
60
|
+
as a genuine blocker to investigate, not a reason to hand-edit around it.
|
|
61
|
+
|
|
62
|
+
**Where each operator fires.** The AI only DECIDES (triage, AC extraction, choosing the change,
|
|
63
|
+
merge/close gates); the operators do survey + apply:
|
|
64
|
+
|
|
65
|
+
| Phase | Operator | Command |
|
|
66
|
+
|---|---|---|
|
|
67
|
+
| Preflight (before iteration 1) | both | `simplicio-mapper --version` · `simplicio-dev-cli --help` → BLOCK if missing |
|
|
68
|
+
| Survey (loop start; multi-repo: per root) | mapper | `simplicio-mapper index . --json` → `.simplicio/*.json` |
|
|
69
|
+
| Loop contract step 2 — Triage (every turn) | mapper | re-read `.simplicio/*.json`; `simplicio-mapper index . --json` to refresh if the tree changed |
|
|
70
|
+
| Loop contract step 3 — Work the goal | dev-cli | `simplicio-dev-cli task "<decided change>" --target <file> [--json]` |
|
|
71
|
+
| Evidence-gated `<promise>` / `simplicio-tasks` Step 4b | dev-cli | the operator's passing test+verify pass = in-turn evidence |
|
|
72
|
+
|
|
73
|
+
One turn: `preflight → survey (mapper) → triage (re-read survey) → DECIDE (AI) → operate
|
|
74
|
+
(simplicio-dev-cli task: apply+test+retry ≤3×) → <promise> only if the operator's gate passed`.
|
|
75
|
+
|
|
76
|
+
## State file (single source of truth)
|
|
77
|
+
|
|
78
|
+
`.orchestrator/loop/scratchpad.md` — human-readable, trivially editable/cancellable:
|
|
79
|
+
|
|
80
|
+
```markdown
|
|
81
|
+
---
|
|
82
|
+
iteration: 1
|
|
83
|
+
max_iterations: <N or 0> # 0 = unlimited (pair with a budget ceiling, never alone)
|
|
84
|
+
completion_promise: "<EXACT TEXT>" | null
|
|
85
|
+
evidence_required: true # promise is rejected unless backed by a passing gate
|
|
86
|
+
started_at: "<ISO-8601>"
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
<the task goal, verbatim — this body is re-fed every turn>
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
A sibling flag file `.orchestrator/loop/done` is `touch`ed only when the promise is verified.
|
|
93
|
+
|
|
94
|
+
## The loop contract
|
|
95
|
+
|
|
96
|
+
1. **Write the scratchpad** with the goal, the cap, and the promise text. Always recommend a
|
|
97
|
+
`max_iterations` safety net even when the user wants "unlimited" — pair unlimited with the
|
|
98
|
+
`.orchestrator/loop-budget.json` $ kill-switch (see `simplicio-tasks` Step 1a/7).
|
|
99
|
+
2. **Triage the live state FIRST (mandatory).** Before any action each turn, re-read the ground
|
|
100
|
+
truth — the **`simplicio-mapper` survey** (`.simplicio/*.json`; refresh it with
|
|
101
|
+
`simplicio-mapper index . --json` if the tree changed), `git status`/`git diff`, the working
|
|
102
|
+
tree, the scratchpad notes, AND the source of record (re-query the open issues/PRs, existing
|
|
103
|
+
branches, the `.orchestrator/loop/done` flag). Act only on what is still genuinely open; never
|
|
104
|
+
redo done work or act on a stale picture (idempotency).
|
|
105
|
+
3. **Work the goal** each turn as if fresh, against that triaged state. The model DECIDES the
|
|
106
|
+
AC-scoped change; the **`simplicio-dev-cli` operator APPLIES and verifies it**
|
|
107
|
+
(`simplicio-dev-cli task "<change>" --target <file>`) — do not hand-edit inside the loop. End EVERY
|
|
108
|
+
iteration with a short, concrete verification — the operator's passing test run, or one gate /
|
|
109
|
+
command / `file:line` receipt. Keep iterations small and verifiable: a turn that only edits
|
|
110
|
+
without verifying is incomplete.
|
|
111
|
+
4. **Re-feed** happens at turn end via the stop-hook (below). Each re-fed turn is prefixed
|
|
112
|
+
`[simplicio-loop iteration N. To finish: output <promise>TEXT</promise> ONLY when genuinely true.]`.
|
|
113
|
+
5. **Exit** by emitting the sentinel `<promise>EXACT TEXT</promise>` — and ONLY when every
|
|
114
|
+
acceptance criterion is met AND a real gate passed **in the SAME turn** (`evidence_required`).
|
|
115
|
+
|
|
116
|
+
## The promise is evidence-gated (the simplicio hardening)
|
|
117
|
+
|
|
118
|
+
The classic Ralph loop trusts the model to be honest. We do not. A `<promise>` is accepted
|
|
119
|
+
only if, in the SAME turn, there is concrete evidence the work is truly done:
|
|
120
|
+
|
|
121
|
+
- the run-verification gate passed ("works, not just compiles" — `simplicio-tasks` Step 4b) —
|
|
122
|
+
the `simplicio-dev-cli` operator's passing test+verify pass (its contract step 5/6) satisfies this, or
|
|
123
|
+
- the named acceptance criteria are each checked with a `file:line` or command-output receipt, or
|
|
124
|
+
- for a queue, the source re-query confirms the items are actually closed/merged.
|
|
125
|
+
|
|
126
|
+
A `<promise>` with no evidence in-turn is a **contract violation** — the capture hook ignores
|
|
127
|
+
it (does not raise `done`) and the loop continues. **Never output a false promise to escape
|
|
128
|
+
the loop.** This wires the loop directly into the repo's hard rule: *never close work without a
|
|
129
|
+
merged PR or concrete evidence.*
|
|
130
|
+
|
|
131
|
+
**Closing is evidence-gated too (no false positives).** Declaring an item done — or closing an
|
|
132
|
+
issue — requires BOTH a live source re-query (the item is actually still open right now) AND
|
|
133
|
+
concrete evidence in the code or a linked/merged PR. A self-reported "done" with no live state
|
|
134
|
+
and no artifact is a false positive and is rejected, exactly like a bare promise.
|
|
135
|
+
|
|
136
|
+
## Binding the hook (deterministic, near-zero token)
|
|
137
|
+
|
|
138
|
+
Where the host runtime supports lifecycle hooks, bind the two cross-platform hooks shipped in
|
|
139
|
+
`hooks/` (Python, so they run identically on Windows/macOS/Linux — see `hooks/hooks.json`):
|
|
140
|
+
|
|
141
|
+
| Hook | Fires | Job |
|
|
142
|
+
|---|---|---|
|
|
143
|
+
| `afterAgentResponse` → `loop_capture.py` | after every turn | extract `<promise>…</promise>`; if it exactly equals `completion_promise` AND in-turn evidence exists → `touch .orchestrator/loop/done`. Fire-and-forget, `exit 0`. Never stops the loop itself. |
|
|
144
|
+
| `stop` → `loop_stop.py` | when the turn ends | guard clauses, each ends the loop cleanly (remove state, `exit 0`): (1) no scratchpad → stop; (2) corrupt frontmatter → stop; (3) `done` flag present → stop (promise fulfilled); (4) `iteration >= max_iterations > 0` → stop (cap); (5) budget halted → stop; else increment `iteration` in place and emit `{"followup_message": "<header>\n\n<goal body>"}` to re-feed. |
|
|
145
|
+
|
|
146
|
+
Detection (`capture`) and termination (`stop`) are split on purpose — neither parses the
|
|
147
|
+
other's inline state. Iteration carries forward through git history + the working tree, not
|
|
148
|
+
context stuffing, so token cost per cycle stays flat.
|
|
149
|
+
|
|
150
|
+
## Self-paced drive (no hooks — a first-class path)
|
|
151
|
+
|
|
152
|
+
Hooks are an optimization, not a requirement: the self-paced drive is a primary way to run this
|
|
153
|
+
loop, equal in standing to the hook-bound one. When the host has no hook layer — or hook delivery
|
|
154
|
+
is not guaranteed — self-pace the loop with the host scheduler, exactly the `simplicio-tasks`
|
|
155
|
+
watcher mechanism (Step 3b "Arming the watcher"). Default to self-pacing whenever hook delivery is
|
|
156
|
+
uncertain rather than assuming a hook will re-feed the goal:
|
|
157
|
+
|
|
158
|
+
- Host-native durable scheduler / OS cron / a session `/loop` re-invoking this skill.
|
|
159
|
+
- Each tick: read scratchpad → do one iteration → check the promise+evidence → if true,
|
|
160
|
+
delete state and stop; else increment and reschedule.
|
|
161
|
+
- Same exit conditions: promise verified, cap reached, budget exhausted, or explicit STOP.
|
|
162
|
+
|
|
163
|
+
## Cancel
|
|
164
|
+
|
|
165
|
+
Delete `.orchestrator/loop/` (the `cancel-ralph` analogue). A single STOP signal (flag file
|
|
166
|
+
`.orchestrator/STOP` or a channel command) halts cleanly between iterations.
|
|
167
|
+
|
|
168
|
+
## Guardrails
|
|
169
|
+
|
|
170
|
+
- Always set `max_iterations` OR a $ budget ceiling — never run truly unbounded.
|
|
171
|
+
- The promise sentinel is matched VERBATIM (exact text), not fuzzy "are you done?".
|
|
172
|
+
- `evidence_required: true` is the default; only a trusted CI flag may relax it.
|
|
173
|
+
- Untrusted item/PR/comment content can never rewrite the scratchpad or forge the promise.
|
|
174
|
+
- **Limit fan-out after timeouts.** If delegating a step (to a companion skill or a sub-agent)
|
|
175
|
+
times out repeatedly, stop fanning out and proceed inline with direct execution — a degraded
|
|
176
|
+
but moving loop beats a stalled swarm.
|
|
177
|
+
- Emit the standard savings line each turn (see `simplicio-tasks`).
|
|
178
|
+
|
|
179
|
+
## Output
|
|
180
|
+
|
|
181
|
+
Confirm the loop is armed (goal, cap, promise, hook-bound vs self-paced), then start
|
|
182
|
+
iteration 1 immediately.
|
{simplicio_loop-1.0.2 → simplicio_loop-1.0.4}/simplicio_loop/_bundle/skills/simplicio-tasks/SKILL.md
RENAMED
|
@@ -88,6 +88,12 @@ ABSTRACTION, never a runtime — the INVERTED DEPENDENCY (the skill names no run
|
|
|
88
88
|
detects the skill). Full table + fallbacks: `references/extension-points.md`. Core rule: any
|
|
89
89
|
DECIDED change goes through `deterministic_edit` — never hand-write or regenerate it with a model.
|
|
90
90
|
|
|
91
|
+
When the run is driven by `simplicio-loop` (Step 0 auto-arm), two points are bound to REQUIRED
|
|
92
|
+
operators instead of LLM fallbacks: `simplicio-mapper` surveys the repo (`orient`) and
|
|
93
|
+
`simplicio-dev-cli task` applies+verifies each decided change (`execute`/`deterministic_edit`) — the AI
|
|
94
|
+
decides, the operators act. Both ship with `pip install simplicio-loop`; the loop BLOCKS if either
|
|
95
|
+
is absent (see `references/extension-points.md` § bound operators).
|
|
96
|
+
|
|
91
97
|
## Step 1b' — Companion skills (the super-plugin satellites)
|
|
92
98
|
simplicio-tasks ships as a super-plugin: this orchestrator + five satellites. Each is the deep,
|
|
93
99
|
standalone form of a discipline; when loaded, DELEGATE to it (richer + cheaper); when absent, the
|
|
@@ -54,6 +54,20 @@ Rule: any change already DECIDED goes through `deterministic_edit` — never han
|
|
|
54
54
|
or regenerate it with a model when a mechanical apply exists. Reach for a paid model only for
|
|
55
55
|
genuine reasoning the deterministic layer cannot do (model routing in orchestration.md).
|
|
56
56
|
|
|
57
|
+
## simplicio-loop's bound operators (REQUIRED for the loop drive)
|
|
58
|
+
|
|
59
|
+
The `simplicio-loop` companion skill is NOT runtime-optional about two of these points — it binds
|
|
60
|
+
them to two installed CLIs (hard deps of `pip install simplicio-loop`) and BLOCKS if absent:
|
|
61
|
+
|
|
62
|
+
| Point(s) | Bound CLI | What replaces the LLM fallback |
|
|
63
|
+
|---|---|---|
|
|
64
|
+
| `orient` / `recall` | `simplicio-mapper` (`simplicio-mapper index . --json`) | the repo SURVEY — `.simplicio/*.json` (project-map, precedent-index, symbol-index, call-graph) instead of ad-hoc LLM reads |
|
|
65
|
+
| `execute` / `deterministic_edit` / `validate` / `diagnostics` | `simplicio-dev-cli task` (binary `simplicio-dev-cli`, pkg `simplicio-cli`) | the OPERATOR — applies a decided change via its 6-layer contract (mapper→precedent→prompt→diff→test→verify, ≤3 retries); the AI never hand-writes the diff inside the loop |
|
|
66
|
+
|
|
67
|
+
This is the one place the abstraction is realized by a REQUIRED binding rather than an optional
|
|
68
|
+
one. Everywhere else the inverted-dependency rule below still holds. See
|
|
69
|
+
`.claude/skills/simplicio-loop/SKILL.md` (§ Bound operators).
|
|
70
|
+
|
|
57
71
|
A host runtime MAY detect that this skill is running (by name) and auto-bind its native commands
|
|
58
72
|
to these points — transparently, at near-zero token cost — without the skill ever naming that
|
|
59
73
|
runtime. The binding lives in the host runtime, not here. This is the INVERTED DEPENDENCY: the
|
|
@@ -1,76 +1,76 @@
|
|
|
1
|
-
"""CLI for simplicio-loop: install the bundled skills + hooks into a runtime."""
|
|
2
|
-
from __future__ import annotations
|
|
3
|
-
|
|
4
|
-
import argparse
|
|
5
|
-
import shutil
|
|
6
|
-
from pathlib import Path
|
|
7
|
-
|
|
8
|
-
from . import __version__
|
|
9
|
-
|
|
10
|
-
BUNDLE = Path(__file__).resolve().parent / "_bundle"
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def _copy_tree(src: Path, dst: Path) -> int:
|
|
14
|
-
"""Copy every file under src into dst, preserving structure. Returns file count."""
|
|
15
|
-
count = 0
|
|
16
|
-
for item in src.rglob("*"):
|
|
17
|
-
if item.is_file():
|
|
18
|
-
out = dst / item.relative_to(src)
|
|
19
|
-
out.parent.mkdir(parents=True, exist_ok=True)
|
|
20
|
-
shutil.copy2(item, out)
|
|
21
|
-
count += 1
|
|
22
|
-
return count
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
def install(target: Path, globally: bool) -> int:
|
|
26
|
-
base = (Path.home() / ".claude") if globally else (target / ".claude")
|
|
27
|
-
skills_dst = base / "skills"
|
|
28
|
-
hooks_dst = (base / "hooks") if globally else (target / "hooks")
|
|
29
|
-
|
|
30
|
-
if not (BUNDLE / "skills").is_dir():
|
|
31
|
-
print("error: bundled skills not found in the installed package.", flush=True)
|
|
32
|
-
return 1
|
|
33
|
-
|
|
34
|
-
n_skills = _copy_tree(BUNDLE / "skills", skills_dst)
|
|
35
|
-
n_hooks = _copy_tree(BUNDLE / "hooks", hooks_dst)
|
|
36
|
-
|
|
37
|
-
print(f"simplicio-loop {__version__} installed:")
|
|
38
|
-
print(f" skills -> {skills_dst} ({n_skills} files)")
|
|
39
|
-
print(f" hooks -> {hooks_dst} ({n_hooks} files)")
|
|
40
|
-
print("")
|
|
41
|
-
print("Use it in your agent runtime (Claude Code, Cursor, ...):")
|
|
42
|
-
print(" /simplicio-tasks finish all the open issues")
|
|
43
|
-
return 0
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
def main(argv=None) -> int:
|
|
47
|
-
parser = argparse.ArgumentParser(
|
|
48
|
-
prog="simplicio-loop",
|
|
49
|
-
description=(
|
|
50
|
-
"Install the simplicio-loop super-plugin (6 AI-orchestration skills + "
|
|
51
|
-
"loop/token-economy hooks) into a runtime's skills location."
|
|
52
|
-
),
|
|
53
|
-
)
|
|
54
|
-
parser.add_argument(
|
|
55
|
-
"command", nargs="?", default="install", choices=["install"],
|
|
56
|
-
help="action to run (default: install)",
|
|
57
|
-
)
|
|
58
|
-
parser.add_argument(
|
|
59
|
-
"--target", default=".",
|
|
60
|
-
help="project directory to install into (default: current directory)",
|
|
61
|
-
)
|
|
62
|
-
parser.add_argument(
|
|
63
|
-
"--global", dest="globally", action="store_true",
|
|
64
|
-
help="install into ~/.claude instead of the project",
|
|
65
|
-
)
|
|
66
|
-
parser.add_argument(
|
|
67
|
-
"-V", "--version", action="version", version=f"simplicio-loop {__version__}",
|
|
68
|
-
)
|
|
69
|
-
args = parser.parse_args(argv)
|
|
70
|
-
if args.command == "install":
|
|
71
|
-
return install(Path(args.target).resolve(), args.globally)
|
|
72
|
-
return 0
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
if __name__ == "__main__":
|
|
76
|
-
raise SystemExit(main())
|
|
1
|
+
"""CLI for simplicio-loop: install the bundled skills + hooks into a runtime."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import argparse
|
|
5
|
+
import shutil
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
from . import __version__
|
|
9
|
+
|
|
10
|
+
BUNDLE = Path(__file__).resolve().parent / "_bundle"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _copy_tree(src: Path, dst: Path) -> int:
|
|
14
|
+
"""Copy every file under src into dst, preserving structure. Returns file count."""
|
|
15
|
+
count = 0
|
|
16
|
+
for item in src.rglob("*"):
|
|
17
|
+
if item.is_file():
|
|
18
|
+
out = dst / item.relative_to(src)
|
|
19
|
+
out.parent.mkdir(parents=True, exist_ok=True)
|
|
20
|
+
shutil.copy2(item, out)
|
|
21
|
+
count += 1
|
|
22
|
+
return count
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def install(target: Path, globally: bool) -> int:
|
|
26
|
+
base = (Path.home() / ".claude") if globally else (target / ".claude")
|
|
27
|
+
skills_dst = base / "skills"
|
|
28
|
+
hooks_dst = (base / "hooks") if globally else (target / "hooks")
|
|
29
|
+
|
|
30
|
+
if not (BUNDLE / "skills").is_dir():
|
|
31
|
+
print("error: bundled skills not found in the installed package.", flush=True)
|
|
32
|
+
return 1
|
|
33
|
+
|
|
34
|
+
n_skills = _copy_tree(BUNDLE / "skills", skills_dst)
|
|
35
|
+
n_hooks = _copy_tree(BUNDLE / "hooks", hooks_dst)
|
|
36
|
+
|
|
37
|
+
print(f"simplicio-loop {__version__} installed:")
|
|
38
|
+
print(f" skills -> {skills_dst} ({n_skills} files)")
|
|
39
|
+
print(f" hooks -> {hooks_dst} ({n_hooks} files)")
|
|
40
|
+
print("")
|
|
41
|
+
print("Use it in your agent runtime (Claude Code, Cursor, ...):")
|
|
42
|
+
print(" /simplicio-tasks finish all the open issues")
|
|
43
|
+
return 0
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def main(argv=None) -> int:
|
|
47
|
+
parser = argparse.ArgumentParser(
|
|
48
|
+
prog="simplicio-loop",
|
|
49
|
+
description=(
|
|
50
|
+
"Install the simplicio-loop super-plugin (6 AI-orchestration skills + "
|
|
51
|
+
"loop/token-economy hooks) into a runtime's skills location."
|
|
52
|
+
),
|
|
53
|
+
)
|
|
54
|
+
parser.add_argument(
|
|
55
|
+
"command", nargs="?", default="install", choices=["install"],
|
|
56
|
+
help="action to run (default: install)",
|
|
57
|
+
)
|
|
58
|
+
parser.add_argument(
|
|
59
|
+
"--target", default=".",
|
|
60
|
+
help="project directory to install into (default: current directory)",
|
|
61
|
+
)
|
|
62
|
+
parser.add_argument(
|
|
63
|
+
"--global", dest="globally", action="store_true",
|
|
64
|
+
help="install into ~/.claude instead of the project",
|
|
65
|
+
)
|
|
66
|
+
parser.add_argument(
|
|
67
|
+
"-V", "--version", action="version", version=f"simplicio-loop {__version__}",
|
|
68
|
+
)
|
|
69
|
+
args = parser.parse_args(argv)
|
|
70
|
+
if args.command == "install":
|
|
71
|
+
return install(Path(args.target).resolve(), args.globally)
|
|
72
|
+
return 0
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
if __name__ == "__main__":
|
|
76
|
+
raise SystemExit(main())
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: simplicio-loop
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.4
|
|
4
4
|
Summary: The Universal Looping AI Orchestrator — a runtime-agnostic super-plugin (6 skills) that drains any queue of work end-to-end on any LLM/runtime.
|
|
5
5
|
Author-email: Wesley Simplicio <wesleybob4@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -19,6 +19,8 @@ Classifier: Operating System :: OS Independent
|
|
|
19
19
|
Requires-Python: >=3.8
|
|
20
20
|
Description-Content-Type: text/markdown
|
|
21
21
|
License-File: LICENSE
|
|
22
|
+
Requires-Dist: simplicio-mapper
|
|
23
|
+
Requires-Dist: simplicio-cli
|
|
22
24
|
Dynamic: license-file
|
|
23
25
|
|
|
24
26
|
# simplicio-loop
|
|
@@ -9,6 +9,7 @@ simplicio_loop.egg-info/PKG-INFO
|
|
|
9
9
|
simplicio_loop.egg-info/SOURCES.txt
|
|
10
10
|
simplicio_loop.egg-info/dependency_links.txt
|
|
11
11
|
simplicio_loop.egg-info/entry_points.txt
|
|
12
|
+
simplicio_loop.egg-info/requires.txt
|
|
12
13
|
simplicio_loop.egg-info/top_level.txt
|
|
13
14
|
simplicio_loop/_bundle/hooks/hooks.claude.json
|
|
14
15
|
simplicio_loop/_bundle/hooks/hooks.json
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: simplicio-loop
|
|
3
|
-
description: Iterate on a task autonomously until a typed completion-promise is genuinely true or a max-iteration cap is hit — the Ralph Wiggum loop, hardened. Use when the user says "ralph loop", "keep iterating until done", "loop on this until it passes", or when simplicio-tasks needs a self-referential drive that re-feeds the same goal each turn and sees its own prior work. Runtime-agnostic: binds a real stop-hook where the host supports hooks (Claude, Cursor); otherwise self-paces via the host scheduler. Never escapes the loop with a false promise.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# simplicio-loop — the hardened Ralph loop
|
|
7
|
-
|
|
8
|
-
A self-referential iteration primitive: the SAME goal is fed back after every turn, so
|
|
9
|
-
the agent sees its own prior edits and converges. It exits ONLY when a **typed
|
|
10
|
-
completion-promise** is genuinely true, or a hard `max_iterations` cap fires. This is the
|
|
11
|
-
drive underneath `simplicio-tasks`' 24/7 watcher (Step 3b/7) extracted as a reusable,
|
|
12
|
-
inspectable, cancellable skill.
|
|
13
|
-
|
|
14
|
-
Credit: the technique is Ralph Wiggum / cursor `ralph-loop`. We keep its best parts —
|
|
15
|
-
single human-readable state file, exact-match promise sentinel, two-hook split — and add
|
|
16
|
-
the simplicio safety spine (evidence-gated promise, budget kill-switch, cross-platform hook).
|
|
17
|
-
|
|
18
|
-
## When to use
|
|
19
|
-
|
|
20
|
-
- "run a ralph loop on X", "iterate until the tests pass", "keep going until done".
|
|
21
|
-
- As the engine for `simplicio-tasks` when it must drain a queue unattended.
|
|
22
|
-
- NOT for a one-shot edit — use the host's normal flow.
|
|
23
|
-
|
|
24
|
-
## State file (single source of truth)
|
|
25
|
-
|
|
26
|
-
`.orchestrator/loop/scratchpad.md` — human-readable, trivially editable/cancellable:
|
|
27
|
-
|
|
28
|
-
```markdown
|
|
29
|
-
---
|
|
30
|
-
iteration: 1
|
|
31
|
-
max_iterations: <N or 0> # 0 = unlimited (pair with a budget ceiling, never alone)
|
|
32
|
-
completion_promise: "<EXACT TEXT>" | null
|
|
33
|
-
evidence_required: true # promise is rejected unless backed by a passing gate
|
|
34
|
-
started_at: "<ISO-8601>"
|
|
35
|
-
---
|
|
36
|
-
|
|
37
|
-
<the task goal, verbatim — this body is re-fed every turn>
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
A sibling flag file `.orchestrator/loop/done` is `touch`ed only when the promise is verified.
|
|
41
|
-
|
|
42
|
-
## The loop contract
|
|
43
|
-
|
|
44
|
-
1. **Write the scratchpad** with the goal, the cap, and the promise text. Always recommend a
|
|
45
|
-
`max_iterations` safety net even when the user wants "unlimited" — pair unlimited with the
|
|
46
|
-
`.orchestrator/loop-budget.json` $ kill-switch (see `simplicio-tasks` Step 1a/7).
|
|
47
|
-
2. **Work the goal** each turn as if fresh, but READ your own prior output (git diff, the
|
|
48
|
-
working tree, the scratchpad notes) first — do not redo done work (idempotency).
|
|
49
|
-
3. **Re-feed** happens at turn end via the stop-hook (below). Each re-fed turn is prefixed
|
|
50
|
-
`[simplicio-loop iteration N. To finish: output <promise>TEXT</promise> ONLY when genuinely true.]`.
|
|
51
|
-
4. **Exit** by emitting the sentinel `<promise>EXACT TEXT</promise>` — and ONLY when every
|
|
52
|
-
acceptance criterion is met AND a real gate passed (`evidence_required`).
|
|
53
|
-
|
|
54
|
-
## The promise is evidence-gated (the simplicio hardening)
|
|
55
|
-
|
|
56
|
-
The classic Ralph loop trusts the model to be honest. We do not. A `<promise>` is accepted
|
|
57
|
-
only if, in the SAME turn, there is concrete evidence the work is truly done:
|
|
58
|
-
|
|
59
|
-
- the run-verification gate passed ("works, not just compiles" — `simplicio-tasks` Step 4b), or
|
|
60
|
-
- the named acceptance criteria are each checked with a `file:line` or command-output receipt, or
|
|
61
|
-
- for a queue, the source re-query confirms the items are actually closed/merged.
|
|
62
|
-
|
|
63
|
-
A `<promise>` with no evidence in-turn is a **contract violation** — the capture hook ignores
|
|
64
|
-
it (does not raise `done`) and the loop continues. **Never output a false promise to escape
|
|
65
|
-
the loop.** This wires the loop directly into the repo's hard rule: *never close work without a
|
|
66
|
-
merged PR or concrete evidence.*
|
|
67
|
-
|
|
68
|
-
## Binding the hook (deterministic, near-zero token)
|
|
69
|
-
|
|
70
|
-
Where the host runtime supports lifecycle hooks, bind the two cross-platform hooks shipped in
|
|
71
|
-
`hooks/` (Python, so they run identically on Windows/macOS/Linux — see `hooks/hooks.json`):
|
|
72
|
-
|
|
73
|
-
| Hook | Fires | Job |
|
|
74
|
-
|---|---|---|
|
|
75
|
-
| `afterAgentResponse` → `loop_capture.py` | after every turn | extract `<promise>…</promise>`; if it exactly equals `completion_promise` AND in-turn evidence exists → `touch .orchestrator/loop/done`. Fire-and-forget, `exit 0`. Never stops the loop itself. |
|
|
76
|
-
| `stop` → `loop_stop.py` | when the turn ends | guard clauses, each ends the loop cleanly (remove state, `exit 0`): (1) no scratchpad → stop; (2) corrupt frontmatter → stop; (3) `done` flag present → stop (promise fulfilled); (4) `iteration >= max_iterations > 0` → stop (cap); (5) budget halted → stop; else increment `iteration` in place and emit `{"followup_message": "<header>\n\n<goal body>"}` to re-feed. |
|
|
77
|
-
|
|
78
|
-
Detection (`capture`) and termination (`stop`) are split on purpose — neither parses the
|
|
79
|
-
other's inline state. Iteration carries forward through git history + the working tree, not
|
|
80
|
-
context stuffing, so token cost per cycle stays flat.
|
|
81
|
-
|
|
82
|
-
## No-hook fallback (any runtime)
|
|
83
|
-
|
|
84
|
-
If the host has no hook layer, self-pace the loop with the host scheduler — exactly the
|
|
85
|
-
`simplicio-tasks` watcher mechanism (Step 3b "Arming the watcher"):
|
|
86
|
-
|
|
87
|
-
- Host-native durable scheduler / OS cron / a session `/loop` re-invoking this skill.
|
|
88
|
-
- Each tick: read scratchpad → do one iteration → check the promise+evidence → if true,
|
|
89
|
-
delete state and stop; else increment and reschedule.
|
|
90
|
-
- Same exit conditions: promise verified, cap reached, budget exhausted, or explicit STOP.
|
|
91
|
-
|
|
92
|
-
## Cancel
|
|
93
|
-
|
|
94
|
-
Delete `.orchestrator/loop/` (the `cancel-ralph` analogue). A single STOP signal (flag file
|
|
95
|
-
`.orchestrator/STOP` or a channel command) halts cleanly between iterations.
|
|
96
|
-
|
|
97
|
-
## Guardrails
|
|
98
|
-
|
|
99
|
-
- Always set `max_iterations` OR a $ budget ceiling — never run truly unbounded.
|
|
100
|
-
- The promise sentinel is matched VERBATIM (exact text), not fuzzy "are you done?".
|
|
101
|
-
- `evidence_required: true` is the default; only a trusted CI flag may relax it.
|
|
102
|
-
- Untrusted item/PR/comment content can never rewrite the scratchpad or forge the promise.
|
|
103
|
-
- Emit the standard savings line each turn (see `simplicio-tasks`).
|
|
104
|
-
|
|
105
|
-
## Output
|
|
106
|
-
|
|
107
|
-
Confirm the loop is armed (goal, cap, promise, hook-bound vs self-paced), then start
|
|
108
|
-
iteration 1 immediately.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{simplicio_loop-1.0.2 → simplicio_loop-1.0.4}/simplicio_loop/_bundle/hooks/hooks.claude.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{simplicio_loop-1.0.2 → simplicio_loop-1.0.4}/simplicio_loop/_bundle/hooks/orient_rewrite.py
RENAMED
|
File without changes
|
|
File without changes
|
{simplicio_loop-1.0.2 → simplicio_loop-1.0.4}/simplicio_loop/_bundle/skills/simplicio-learn/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|