Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
3d299b3
Update template to be bare on `install` and work with Poetry and pip.
rxdt Jul 31, 2026
ea146dc
Adds mutmut and pip-audit to pyproject.toml
rxdt Aug 2, 2026
e0dfd29
Adds preferences test for when an AST parser doesn't report line number
rxdt Aug 2, 2026
4f7dd96
Make universal hash for new repo, aka empty tree, a global constant i…
rxdt Aug 2, 2026
fb7f5ec
Adds proof that Mutmut will run in this directory
rxdt Aug 2, 2026
05f3dbe
Make pylint Ignore worktrees
rxdt Aug 2, 2026
d47b203
Add .gitattributes to FORBIDDEN FILES
rxdt Aug 2, 2026
2e2ef8f
Move all git repo fixtures to
rxdt Aug 3, 2026
49606d1
Adds diff size check
rxdt Aug 4, 2026
029949c
Merge feat/loc-diff-size-gate into main
rxdt Aug 4, 2026
f0f5a34
Tests for diff size warn
rxdt Aug 6, 2026
612d2d3
Refactor gate to frozen class
rxdt Aug 6, 2026
bb931b6
Updates to not block humans from committing if hanress code is broken
rxdt Aug 6, 2026
e725b7e
Refactor gate to class
rxdt Aug 6, 2026
149f4df
TEST
rxdt Aug 6, 2026
6877b5d
Update tests to new Gate class private methods
rxdt Aug 6, 2026
aee8eca
Update Mutmut to save weekly json CI/CD files and error if score < 60
rxdt Aug 6, 2026
d3afca9
Update README.template
rxdt Aug 8, 2026
ad61809
Should work with python 3.10
rxdt Aug 8, 2026
75c6050
Should work with python 3.10
rxdt Aug 8, 2026
399cc48
Adds test lines to work with Windows env
rxdt Aug 8, 2026
1c97692
Adds test lines to work with Windows env
rxdt Aug 8, 2026
3669889
docs: add mutmut mutation testing badge
rxdt Aug 11, 2026
5d2aadc
test: follow configured mutation threshold
rxdt Aug 11, 2026
64e6163
docs: refresh mutation score badge
rxdt Aug 11, 2026
05c5811
Save console color conditional on agant
rxdt Aug 11, 2026
958ebd9
docs: publish verified mutation score
Aug 11, 2026
83063f5
docs: point mutation badge at published score
Aug 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 15 additions & 6 deletions .githooks/_resolve
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,26 @@
# $HARNESS is the path recorded by `record_harness`.
#
# Then, git hook does not require `uv` or `pip` or any specific environment layout.
#
# if is-agent-in-loop, check harness executable found via harness-path
[ "${RALPH_LOOP:-0}" = "1" ] || exit 0

recorded="$(git rev-parse --path-format=absolute --git-common-dir)/harness-path"
if [ ! -r "$recorded" ]; then
echo "loopgate: hooks are not installed. Run 'harness install' in this repo." >&2
exit 1
HARNESS=""

if [ -r "$recorded" ]; then
HARNESS="$(cat "$recorded")"
fi

HARNESS="$(cat "$recorded")"
if [ ! -x "$HARNESS" ]; then
echo "loopgate: recorded harness '$HARNESS' is gone. Re-run 'harness install'." >&2
exit 1
HARNESS="$(command -v harness 2>/dev/null || true)"
if [ ! -x "$HARNESS" ]; then
echo "loopgate: hooks are not installed. Run 'harness install' in this repo." >&2
exit 1
fi

echo "loopgate: harness installed but record of path '$HARNESS' is gone. Re-adding file 'harness-path'." >&2
printf '%s\n' "$HARNESS" > "$recorded"
fi

export PATH="$(dirname "$HARNESS")${PATH:+:$PATH}"
9 changes: 6 additions & 3 deletions .github/workflows/mutation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ jobs:

steps:
- name: Checkout Code
uses: actions/checkout@v6
uses: actions/checkout@v7

- name: Install uv
uses: astral-sh/setup-uv@v6
uses: astral-sh/setup-uv@v7
with:
enable-cache: true

Expand All @@ -38,7 +38,7 @@ jobs:
run: uv run --no-sync harness gate # need tests for Mutmut to target

- name: Run Mutmut
run: uv run --no-sync mutmut run || true
run: uv run --no-sync mutmut run

- name: Export CI/CD Stats
run: uv run --no-sync mutmut export-cicd-stats
Expand All @@ -48,3 +48,6 @@ jobs:
with:
name: mutmut-json-report
path: mutants/mutmut-cicd-stats.json

- name: Check Mutation Score
run: uv run --no-sync python mutation/check_mutmut.py
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ __pycache__/
docs/launch.md
test-results/
**/node_modules/
harness-path

.env
.env.*
Expand Down
126 changes: 60 additions & 66 deletions README.md

Large diffs are not rendered by default.

43 changes: 31 additions & 12 deletions README.template.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

Now that you have the template locally:

1. `uv sync` OR `poetry install` OR ` pip install -r requirements.txt`, then `harness install <your-project-name>`
1. `uv sync` OR `poetry install` OR ` pip install -r requirements.txt`, then `harness install <your-project-name>
git add . && git commit`
2. Write your project goal in [docs/plan.md](docs/plan.md)
3. `harness run <agent=claude|codex|agy|copilot> [max_iterations] [max_minutes]`
4. Not what you wanted? Refine [`docs/plan.md`](docs/plan.md) / [`docs/PROMPT.md`](docs/PROMPT.md) and re-run
Expand All @@ -13,26 +14,30 @@ Now that you have the template locally:

> [!IMPORTANT]
> Default configurations In [`pyproject.toml`](pyproject.toml) Update tool settings, add agent calls, remove or include checks... or leave as is.
> If you don't like _ANYTHING_ in this framework, remove it.

> [!TIP]
> If you don't like _ANYTHING_ in this framework, [update it](#expanding-your-harness).

### Start a project

```sh
uv sync
source .venv/bin/activate
harness install <your-project-name>
git add . && git commit
harness gate
harness run <agent>>

poetry install
poetry run harness install <your-project-name>
git add . && git commit
poetry run harness gate
poetry run harness <agent>

python -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txt -e .
harness install <your-project-name>
harness install <your-project-name> && git add . && git commit
harness gate
harness run <agent>
```
Expand Down Expand Up @@ -157,12 +162,27 @@ The gate bounds what any **commit** may touch, but the worker itself is **not**

## Expanding your harness </summary>

- Edit rules at [pyproject.toml](pyproject.toml) for [ruff](https://docs.astral.sh/ruff/), [pylint](https://pypi.org/project/pylint/), [pydoclint](https://pypi.org/project/pydoclint/0.9.1/), [pyright](https://github.com/microsoft/pyright), [pytest](https://docs.pytest.org/en/stable/), [hypothesis](https://hypothesis.readthedocs.io/), [complexipy](https://github.com/rohaquinlop/complexipy)
- Add forbidden files, directories, or patterns in `[tool.harness.gate]` at [pyproject.toml](pyproject.toml)
- Add [Hypothesis](https://hypothesis.readthedocs.io/) tests when generated cases improve coverage beyond example-based tests. `tests/`
- [semgrep](https://docs.semgrep.dev/semgrep-ci/sample-ci-configs) has no repo config here. It uses registry configs plus Semgrep's built-in defaults which ignore tests.
- Edit `[tool.harness.gate.checks]` in [pyproject.toml](pyproject.toml). [ci.yml](.github/workflows/ci.yml) runs the same `harness gate`.
- Remove or add preferences not caught by Ruff, Pylint, etc. at [preferences.py](preferences/preferences.py).
- Edit rules at [pyproject.toml](pyproject.toml) for [ruff](https://docs.astral.sh/ruff/), [pylint](https://pypi.org/project/pylint/), [pydoclint](https://pypi.org/project/pydoclint/0.9.1/), [pyright](https://github.com/microsoft/pyright), [pytest](https://docs.pytest.org/en/stable/), [hypothesis](https://hypothesis.readthedocs.io/), [complexipy](https://github.com/rohaquinlop/complexipy), [mutmut](https://mutmut.readthedocs.io/)
- Add forbidden files, directories, or patterns in `[tool.harness]` at [pyproject.toml](pyproject.toml)
- Add [Hypothesis](https://hypothesis.readthedocs.io/) tests in any test directory, examples at [test_properties.py](tests/preferences/test_properties.py).
- Run [mutmut](https://mutmut.readthedocs.io/) by hand with `uv run mutmut run`, then `uv run mutmut browse`. A surviving mutant is a covered line no assertion checks. It is not a gate check: `mutmut run` exits 0 even with survivors and it should be run ~1x/week. Its mutants are cached in a JSON and should be used to identify weak tests. Example at [check_mutmut.py](https://github.com/rxdt/loopgate_harness/blob/main/mutation/check_mutmut.py).
- [semgrep](https://docs.semgrep.dev/semgrep-ci/sample-ci-configs) has no repo config here. It uses registry configs / Semgrep's built-in defaults which ignore tests.
- Update `[tool.harness.gate.checks]` in [pyproject.toml](pyproject.toml). [ci.yml](.github/workflows/ci.yml) runs those **same exact** `harness gate` checks.
- Add or remove coding preferences [preferences.py](preferences/preferences.py) that only agents in loops **must** respect. Current preferences:

```py
function_argument_assignment_has_star # agents use non-specific `def fun(*)`
function_argument_assignment_underscore_lead # agents love over-using underscore names `def _fun()`
hidden_signature_star_args # Complain when a function uses *args or **kwargs (it hides function signatures)
dynamic_star_call # Calls to def fun(*items) breaks when you can't tell how many arguments f is getting
pointless_class # ensure classes are added for good reasons (carry state, values, methods)
lazy_assert # enforce real assertions, stronger tests
objects_injected_into_runtime_memory # finds calls that manipulate global state (dangerous, tricky)
lambda_found # abolish lambdas, make agents keep their code simple
lazy_any_type_hints # abolish type `Any` used to bypass strict type-checking
chaotic_continue_statements # abolish unecessary nested continue statements, clean code
complex_comprehension # no needlessly dense list/set/dict comprehensions, prefer linear code
```

</details>

Expand Down Expand Up @@ -209,11 +229,10 @@ npm run --prefix harness/js-scaffold preflight
Spec claimed by agent: <unclaimed>
```

- **The agents:** paste this exact block into [PROMPT.md line 3](docs/PROMPT.md#L3):
- **This exact block** into [PROMPT.md line 3](docs/PROMPT.md#L3):

```
Other agents are working this repo. Before touching code, pick a spec whose claim line is
<unclaimed>, replace it with your name, and commit that claim first. Own that spec's file and its
Other agents are working this repo. Before touching code, pick a spec whose claim line is <unclaimed>, replace it with your exact name `<your-agent-id>-<spec-you-worked>-<RALPH_ITERATION>/<MAX_ITERATIONS>`, and commit that claim first. Own that spec's file and its
tests. Set the line back to <unclaimed> on your last commit.
```

Expand Down
32 changes: 17 additions & 15 deletions docs/PROMPT.md
Original file line number Diff line number Diff line change
@@ -1,36 +1,38 @@
You are a fresh-context iteration in a loop. The repo is your memory.
Specs say what to build. You decide what is the next most useful change.
You are a fresh-context iteration in a loop. The repo `src/` and `docs/` are your memory. Specs say what to build.
You decide what is the next most useful change.

1. Read `docs/specs/*.md` and `docs/plan.md` and identify the most important unfinished items.
2. If a spec is wrong or missing, add or update the spec using `plan.md` instead of guessing.
2. If a spec is wrong or missing, add or update the spec using `plan.md` as a guide instead of guessing.
3. Inspect the relevant code and tests before editing.
4. Implement the scoped change that advances the specs.
5. Add or update tests that prove behavior and challenge the source; use durable, behavior-focused names and docstrings.
6. A milestone is not DONE until a test executes the entry point end-to-end and asserts observable output and exit code. Unit-testing an internal function is not sufficient.
7. Run `harness gate`. If `harness` is not on PATH, run `.venv/bin/harness gate`.
8. Fix failures without weakening tests, coverage, typing, security checks, or the gate.
9. Update the relevant spec and `docs/PROJECT_STATUS.md` to match what changed.
10. Commit on the current branch.
11. Push the current branch so the iteration is saved remotely.
5. If you are blocked, report it in `docs/PROJECT_STATUS.md` and exit: do not waste your turn and tokens pretending to work.
6. Verify existing 'blockers' before trusting them. Try to remove blockers.
7. Add or update tests that prove behavior and challenge the source; use durable, behavior-focused names and docstrings.
8. A milestone is not DONE until a test executes the entry point end-to-end and asserts observable output and exit code. Unit-testing an internal function is not sufficient. Prefer `hypothesis` property tests when possible.
9. Periodically run `mutmut run` and kill mutants.
10. Run `harness gate`. If `harness` is not on PATH, run `.venv/bin/harness gate`.
11. Update the relevant spec and `docs/PROJECT_STATUS.md` to match what changed. Keep `docs/PROJECT_STATUS.md` uncluttered: persist only actionable items.
12. Commit on the current branch.

Rules:

- Do not batch unrelated work.
- Keep history linear on the current branch: no branches, worktrees, merges, or rebases unless the human explicitly asked for one; commit only relevant current-branch work.
- Keep history linear on the current branch: no branches or worktrees unless the human explicitly asked for them. Commit only relevant current-branch work.
- If forbidden paths block a commit, run `git restore --staged <path>` and leave those working-tree edits for human review.
- Never delete tests or assertions to make checks pass.
- Fix failures without weakening tests, coverage, typing, security checks, or the gate.
- Do not edit forbidden paths: `AGENTS.md`, `harness/`, `.githooks/`, `.github/`, `pyproject.toml`, `PROMPT.md`.
- Use tests for code behavior and API contracts. Do not test for `.md` contents.

Commit message:
- Use tests for code output and contracts. Do not test for `.md` contents.
Commit message:

```
One sentence summary

- concrete detail
- concrete detail
...

<your-agent-id>-<spec-you-worked>-<RALPH_ITERATION>
<prefix><your-agent-id>-<spec-you-worked>-<RALPH_ITERATION> # e.g. `codex-0006-frontend_ui-6/7`
```

Use the agent id the harness gave you (e.g. `0002-codex`); append the spec you worked and the
Expand Down
Loading
Loading