loopgate 0.1.0__py3-none-any.whl

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.
harness/config.py ADDED
@@ -0,0 +1,203 @@
1
+ """Only hardcoded values go in here and only with explicit permission. This is a no-bloat zone."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from importlib.metadata import distribution, packages_distributions
6
+ from pathlib import Path
7
+ from typing import Any
8
+
9
+ from harness.gate import gates
10
+
11
+ distribution_name = packages_distributions()["harness"][0]
12
+ site_packages = Path(str(distribution(distribution_name).locate_file("")))
13
+ package_root = site_packages / "harness"
14
+ repo_root = gates().repo_root
15
+
16
+ CATEGORIES: dict[str, str] = {
17
+ "audit": "audit",
18
+ "complexity": "complexity",
19
+ "format": "ruff_format",
20
+ "lint": "ruff_lint",
21
+ "security": "security",
22
+ "test": "test",
23
+ "types": "types",
24
+ }
25
+
26
+ PHASES = (
27
+ ("agents", gates().agents),
28
+ ("preflight", gates().commit_checks),
29
+ ("gate", gates().gate_checks),
30
+ ("forbidden", gates().forbidden),
31
+ )
32
+
33
+ CODEX_RULES = """\
34
+ prefix_rule(
35
+ pattern = ["git", ["push", "commit"], ["--no-verify", "-n"]],
36
+ decision = "forbidden",
37
+ justification = "Run git commands without hook-bypass flags.",
38
+ )
39
+ prefix_rule(
40
+ pattern = [["unset", "unsetenv"], "RALPH_LOOP"],
41
+ decision = "forbidden",
42
+ justification = "Keep RALPH_LOOP=1 so harness containment remains active.",
43
+ )
44
+ prefix_rule(
45
+ pattern = ["env", "-u", "RALPH_LOOP"],
46
+ decision = "forbidden",
47
+ justification = "Keep RALPH_LOOP=1 so harness containment remains active.",
48
+ )
49
+ prefix_rule(
50
+ pattern = [
51
+ ["bash", "/bin/bash", "zsh", "/bin/zsh", "sh", "/bin/sh"],
52
+ ["-c", "-lc"],
53
+ ["RALPH_LOOP=0", "export RALPH_LOOP=0"],
54
+ ],
55
+ decision = "forbidden",
56
+ justification = "Keep RALPH_LOOP=1 so harness containment remains active.",
57
+ )
58
+ """
59
+
60
+ TOOLS: dict[str, dict[str, Any]] = {
61
+ "audit": {"category": "audit", "args": gates().gate_checks["audit"]},
62
+ "bandit": {
63
+ "category": "security",
64
+ "filenames": [".bandit"],
65
+ "pyproject": ["bandit"],
66
+ "args": ["bandit", "-r", ".", "-x", "build,tox,docs,tests,.venv,scratchpad,mutants,tests"],
67
+ },
68
+ "ruff_format": {
69
+ "category": "format",
70
+ "filenames": [".ruff.toml", "ruff.toml"],
71
+ "pyproject": ["ruff", "format"],
72
+ "args": gates().commit_checks["ruff_format"],
73
+ },
74
+ "ruff_lint": {
75
+ "category": "lint",
76
+ "filenames": [".ruff.toml", "ruff.toml"],
77
+ "pyproject": ["ruff", "lint"],
78
+ "args": gates().commit_checks["ruff_lint"],
79
+ },
80
+ "black": {"category": "format", "pyproject": ["black"], "args": ["black", "--check", "."]},
81
+ "coverage": {
82
+ "category": "test",
83
+ "filenames": [".coveragerc", ".coveragerc.toml"],
84
+ "pyproject": ["coverage"],
85
+ },
86
+ "flake8": {"category": "lint", "filenames": [".flake8"], "args": ["flake8", "."]},
87
+ "hypothesis": {"category": "test", "pyproject": ["hypothesis"]},
88
+ "lint": {"category": "lint", "pyproject": ["lint"]},
89
+ "pytest": {
90
+ "category": "test",
91
+ "filenames": ["pytest.toml", ".pytest.toml", "pytest.ini", ".pytest.ini"],
92
+ "pyproject": ["pytest", "ini_options"],
93
+ "args": gates().gate_checks["test"],
94
+ },
95
+ "pyright": {
96
+ "category": "types",
97
+ "filenames": ["pyrightconfig.json"],
98
+ "pyproject": ["pyright"],
99
+ "args": gates().gate_checks["types"],
100
+ },
101
+ "pylint": {
102
+ "category": "lint",
103
+ "filenames": ["pylintrc", "pylintrc.toml", ".pylintrc", ".pylintrc.toml"],
104
+ "pyproject": ["pylint"],
105
+ "args": gates().commit_checks["pylint"],
106
+ },
107
+ "mypy": {
108
+ "category": "types",
109
+ "filenames": ["mypy.ini", ".mypy.ini"],
110
+ "pyproject": ["mypy"],
111
+ "args": ["mypy", "."],
112
+ },
113
+ "mutmut": {"category": "test", "pyproject": ["mutmut"]},
114
+ "radon": {
115
+ "category": "complexity",
116
+ "filenames": ["radon.cfg"],
117
+ "pyproject": ["radon"],
118
+ "args": [
119
+ "radon",
120
+ "cc",
121
+ "-s",
122
+ "-a",
123
+ "-i",
124
+ "build,tox,docs,tests,.venv,scratchpad,mutants,tests",
125
+ "-e",
126
+ "**/__init__.py.",
127
+ ],
128
+ },
129
+ "safety": {"category": "audit", "args": ["safety", "scan"]},
130
+ "sonarqube": {
131
+ "category": "security",
132
+ "filenames": ["sonar-project.properties"],
133
+ "args": ["sonar-scanner", "-Dsonar.qualitygate.wait=true"],
134
+ },
135
+ "snyk": {"category": "security", "filenames": [".snyk"], "args": ["snyk", "test"]},
136
+ "ty": {
137
+ "category": "types",
138
+ "filenames": [
139
+ "ty.toml",
140
+ "~/.config/ty/ty.toml",
141
+ "$XDG_CONFIG_HOME/ty/ty.toml", # Linux/macOS
142
+ "%APPDATA%\\ty\\ty.toml", # Windows
143
+ ],
144
+ "pyproject": ["ty"],
145
+ "args": ["ty", "check"],
146
+ },
147
+ "complexipy": {
148
+ "category": "complexity",
149
+ "filenames": ["complexipy.toml", ".complexipy.toml"],
150
+ "pyproject": ["complexipy"],
151
+ "args": gates().commit_checks["complexity"],
152
+ },
153
+ "semgrep": {
154
+ "category": "security",
155
+ "filenames": [
156
+ ".semgrep.yml",
157
+ ".semgrep.yaml",
158
+ "semgrep.yml",
159
+ "semgrep.yaml",
160
+ "semgrep.config.yml",
161
+ "semgrep.config.yaml",
162
+ ],
163
+ "args": gates().gate_checks["security"],
164
+ },
165
+ "pyrefly": {
166
+ "category": "types",
167
+ "filenames": ["pyrefly.toml", ".pyrefly.toml"],
168
+ "pyproject": ["pyrefly"],
169
+ "args": ["pyrefly", "check"],
170
+ },
171
+ "xenon": {
172
+ "category": "complexity",
173
+ "filenames": [".xenon.yml"],
174
+ "args": ["xenon", "--max-absolute", "B", "--max-modules", "A", "--max-average", "A", "."],
175
+ },
176
+ "zuban": {
177
+ "category": "types",
178
+ "filenames": [".zuban.toml"],
179
+ "pyproject": ["zuban"],
180
+ "args": ["zuban", "check"],
181
+ },
182
+ }
183
+
184
+ CLAUDE_RULES: set[str] = {
185
+ "Bash(*git push*--no-verify*)",
186
+ "Bash(*git commit*--no-verify*)",
187
+ "Bash(*git push* -n*)",
188
+ "Bash(*git commit* -n*)",
189
+ "Bash(*unset RALPH_LOOP*)",
190
+ "Bash(*env -u RALPH_LOOP*)",
191
+ "Bash(*unsetenv RALPH_LOOP*)",
192
+ "Bash(*RALPH_LOOP=0*)",
193
+ "Bash(*export RALPH_LOOP=0*)",
194
+ }
195
+
196
+ ASSETS: dict[str, tuple[Path, Path]] = {
197
+ "docs": (package_root / "docs", repo_root / "docs"),
198
+ "githooks": (package_root / ".githooks", repo_root / ".githooks"),
199
+ "preferences": (site_packages / "preferences", repo_root / "preferences"),
200
+ "mutation": (site_packages / "mutation", repo_root / "mutation"),
201
+ "pref_tests": (package_root / "tests/preferences", repo_root / "tests/preferences"),
202
+ "mutation_tests": (package_root / "tests/mutation", repo_root / "tests/mutation"),
203
+ }
@@ -0,0 +1,38 @@
1
+ # Project Status
2
+
3
+ > Current truth of the repo. Keep it short and current < 100 lines. Human-agent interface document.
4
+
5
+ ## Current Focus
6
+
7
+ - Active spec + milestone: <e.g. docs/specs/base.md → Milestone 2>
8
+
9
+ ## Current State
10
+
11
+ - <current repo state>
12
+ - <current state of each feature described in plan.md>
13
+ - <current state of functionalities described in plan.md>
14
+ - <current remaining gap of repo and what is described in plan.md>
15
+
16
+ ## Checks
17
+
18
+ - `harness preflight` <status>
19
+ - `harness gate` <status>
20
+ - <another-check-to-use>
21
+ - <another-check-to-use>
22
+
23
+ ## Next
24
+
25
+ 1. <next concrete action>
26
+ 2. <next concrete action>
27
+ 3. <next concrete action>
28
+
29
+ ## Changelog
30
+
31
+ - <what a previous iteration tried, and enduring changes or failures (with the error/check) example>
32
+ - <what THIS iteration tried, and whether it worked or failures (with the error/check) example>
33
+
34
+ ## Blockers
35
+
36
+ - <known blocker, or None known>
37
+ - <known blocker, or None known>
38
+ - <known blocker, or None known>
harness/docs/PROMPT.md ADDED
@@ -0,0 +1,39 @@
1
+ You are a fresh-context iteration in a loop. The repo `src/` and `docs/` are your memory. Specs say what to build.
2
+ You decide what is the next most useful change.
3
+
4
+ 1. Read `docs/specs/*.md` and `docs/plan.md` and identify the most important unfinished items.
5
+ 2. If a spec is wrong or missing, add or update the spec using `plan.md` as a guide instead of guessing.
6
+ 3. Inspect the relevant code and tests before editing.
7
+ 4. Implement the scoped change that advances the specs.
8
+ 5. If you are blocked, report it in `docs/PROJECT_STATUS.md` and exit: do not waste your turn and tokens pretending to work.
9
+ 6. Verify existing 'blockers' before trusting them. Try to remove blockers.
10
+ 7. Add or update tests that prove behavior and challenge the source; use durable, behavior-focused names and docstrings.
11
+ 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.
12
+ 9. Periodically run `mutmut run` and kill mutants.
13
+ 10. Run `harness gate`. If `harness` is not on PATH, run `.venv/bin/harness gate`.
14
+ 11. Update the relevant spec and `docs/PROJECT_STATUS.md` to match what changed. Keep `docs/PROJECT_STATUS.md` uncluttered: persist only actionable items.
15
+ 12. Commit on the current branch.
16
+
17
+ Rules:
18
+
19
+ - Do not batch unrelated work.
20
+ - Keep history linear on the current branch: no branches or worktrees unless the human explicitly asked for them. Commit only relevant current-branch work.
21
+ - If forbidden paths block a commit, run `git restore --staged <path>` and leave those working-tree edits for human review.
22
+ - Never delete tests or assertions to make checks pass.
23
+ - Fix failures without weakening tests, coverage, typing, security checks, or the gate.
24
+ - Do not edit forbidden paths: `AGENTS.md`, `harness/`, `.githooks/`, `.github/`, `pyproject.toml`, `PROMPT.md`.
25
+ - Use tests for code output and contracts. Do not test for `.md` contents.
26
+ Commit message:
27
+
28
+ ```
29
+ One sentence summary
30
+
31
+ - concrete detail
32
+ - concrete detail
33
+ ...
34
+
35
+ <prefix><your-agent-id>-<spec-you-worked>-<RALPH_ITERATION> # e.g. `codex-0006-frontend_ui-6/7`
36
+ ```
37
+
38
+ Use the agent id the harness gave you (e.g. `0002-codex`); append the spec you worked and the
39
+ `RALPH_ITERATION` value. This makes commits traceable to their run log (`scratchpad/runs/<id>.jsonl`).
harness/docs/plan.md ADDED
@@ -0,0 +1,68 @@
1
+ # The human vision
2
+
3
+ Agents read this for direction; `docs/specs/` turns it into concrete, prioritized work. Humans start owning this file. Delete or comment out the `docs/plan.md` entry in `[tool.harness.gate] forbidden_files` at [pyproject.toml](../pyproject.toml) if you want agents to take over managing the vision.
4
+
5
+ Code will go in `src/`
6
+
7
+ ## Objective
8
+
9
+ Prose to describe the intended outcome, e.g. a one page web app that does X for Y users. e.g. email will always be clear of junk mail. Use affirmative phrasing in non-contradictory detail.
10
+
11
+ ## Features and functionality
12
+
13
+ Detail the objective outcome.
14
+
15
+ EXAMPLE:
16
+
17
+ - User experience is like {this}
18
+ - Data Storage {stores X like Y}
19
+ - Cost is kept to {#}
20
+ - Page X does Y, Page A does B
21
+ - Links to wireframes or mockups
22
+ - Schema contract
23
+ - Tests to include to enforce functionality
24
+ - Project will be deployed at {place}
25
+ - API integrations include {A}, {B}, {C}
26
+ - Local tasks are {X}, {Y}, {Z}
27
+
28
+ ## Approach
29
+
30
+ Describe the high-level steps for completing the project. Prefer concrete direction over vague quality words. For example, describe user experience deliverables, data flows, or things the project must avoid, in the ontext of timing.
31
+
32
+ EXAMPLE:
33
+
34
+ - User description
35
+ - Major technical choices
36
+ - Workflows
37
+ - Libraries and architecture
38
+ - Storage choices
39
+ - APIs
40
+ - Services
41
+ - Data sources
42
+ - Performanec targets
43
+ - UX expectations
44
+ - Compatibility requirements
45
+
46
+ EXAMPLE:
47
+
48
+ 1. Dependencies installed: FastAPI, Numpy, Requests, Supabase
49
+ 2. FastAPI Backend working with health endponit.
50
+ 3. User can see blank homepage.
51
+ 4. API `/data` endpoint reurns user info. React/Vite homepage shows raw html.
52
+ ...
53
+ {FINAL}. The one page web app is styled like mockup and ... (This item should be a mirror of the Objective at the top)
54
+
55
+ ## Milestones
56
+
57
+ Similar to 'Approach', with concrete deliverables in a timeline
58
+
59
+ 1. First major milestone and its concrete description
60
+ 2. Second major milestone and its concrete description
61
+ 3. Third major milestone and its concrete description
62
+ 4. {fill in additional milestones}
63
+ 5. Release or handoff milestone
64
+
65
+ ## Out of Scope
66
+
67
+ 1. {item the project will NOT do}
68
+ 2. {item the project will NOT do}
@@ -0,0 +1,56 @@
1
+ # Base Spec
2
+
3
+ > **PRIORITY <1|2|3>.** Replace with 1–2 sentence context outlining the core problem this spec solves.
4
+
5
+ ## Scope
6
+
7
+ Clear definitions of what the agent should focus on. Detail APIs, frameworks, data schemas, or libraries the agent must use.
8
+
9
+ ## Priorities
10
+
11
+ 1. Milestone <name>
12
+ - Description
13
+ - Link to which [docs/plan.md] **Milestone** this addresses
14
+ - Sub-tasks
15
+ - <sub-task-1>
16
+ - <sub-task-2>
17
+ - <additional sub-tasks>
18
+ - Files created or updated
19
+ - Definition of done: <command/test that exits 0 when met, e.g. `pytest tests/test_x.py::test_y`>
20
+
21
+ <fill in additional milestones>
22
+
23
+ ## Guardrails
24
+
25
+ Examples:
26
+ - Structure
27
+ - Style
28
+ - Behavioral tests
29
+ - Dependencies to use
30
+ - Compatibilities to support
31
+
32
+ ## Acceptance Criteria
33
+
34
+ Measurable criteria for success. Instead of vague quality terms like "should be fast," use verifiable metrics (e.g., "P95 latency < 100ms", or "npx prisma generate succeeds").
35
+
36
+ - <measurable criterion>
37
+ - <measurable criterion>
38
+ - <fill in additional criterion as needed>
39
+
40
+ ## Out of Scope
41
+ (Features/scope the agent must not start.)
42
+
43
+ - <explicit non-goal>
44
+ - <explicit non-goal>
45
+ - <fill in additional non-goals as needed>
46
+
47
+ ## Blockers
48
+
49
+ - <List specific item preventing completion of this spec>
50
+ - <List specific item preventing completion of this spec>
51
+ - <fill in additional blockers as needed>
52
+
53
+ ## Changelog
54
+
55
+ _Keep brief and to the latest items to keep spec < 100 lines_
56
+ - Each agent adds their name + iteration info, what the current agent tried, and what worked or did not work
@@ -0,0 +1,56 @@
1
+ # Base Spec
2
+
3
+ > **PRIORITY <1|2|3>.** Replace with 1–2 sentence context outlining the core problem this spec solves.
4
+
5
+ ## Scope
6
+
7
+ Clear definitions of what the agent should focus on. Detail APIs, frameworks, data schemas, or libraries the agent must use.
8
+
9
+ ## Priorities
10
+
11
+ 1. Milestone <name>
12
+ - Description
13
+ - Link to which [docs/plan.md] **Milestone** this addresses
14
+ - Sub-tasks
15
+ - <sub-task-1>
16
+ - <sub-task-2>
17
+ - <additional sub-tasks>
18
+ - Files created or updated
19
+ - Definition of done: <command/test that exits 0 when met, e.g. `pytest tests/test_x.py::test_y`>
20
+
21
+ <fill in additional milestones>
22
+
23
+ ## Guardrails
24
+
25
+ Examples:
26
+ - Structure
27
+ - Style
28
+ - Behavioral tests
29
+ - Dependencies to use
30
+ - Compatibilities to support
31
+
32
+ ## Acceptance Criteria
33
+
34
+ Measurable criteria for success. Instead of vague quality terms like "should be fast," use verifiable metrics (e.g., "P95 latency < 100ms", or "npx prisma generate succeeds").
35
+
36
+ - <measurable criterion>
37
+ - <measurable criterion>
38
+ - <fill in additional criterion as needed>
39
+
40
+ ## Out of Scope
41
+ (Features/scope the agent must not start.)
42
+
43
+ - <explicit non-goal>
44
+ - <explicit non-goal>
45
+ - <fill in additional non-goals as needed>
46
+
47
+ ## Blockers
48
+
49
+ - <List specific item preventing completion of this spec>
50
+ - <List specific item preventing completion of this spec>
51
+ - <fill in additional blockers as needed>
52
+
53
+ ## Changelog
54
+
55
+ _Keep brief and to the latest items to keep spec < 100 lines_
56
+ - Each agent adds their name + iteration info, what the current agent tried, and what worked or did not work