sloppatrol 0.1.1 → 0.1.2
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.
- package/README.md +111 -160
- package/dist/census/index.js +4 -2
- package/dist/census/index.js.map +1 -1
- package/dist/census/lib/guardrails.js +38 -9
- package/dist/census/lib/guardrails.js.map +1 -1
- package/dist/census/lib/stack.d.ts +2 -1
- package/dist/census/lib/stack.js +8 -4
- package/dist/census/lib/stack.js.map +1 -1
- package/dist/cli/index.js +20 -4
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/lib/browser.d.ts +2 -0
- package/dist/cli/lib/browser.js +13 -0
- package/dist/cli/lib/browser.js.map +1 -0
- package/dist/cli/lib/usage.d.ts +1 -1
- package/dist/cli/lib/usage.js +4 -3
- package/dist/cli/lib/usage.js.map +1 -1
- package/dist/config/lib/schema.d.ts +30 -0
- package/dist/config/lib/schema.js +16 -0
- package/dist/config/lib/schema.js.map +1 -1
- package/dist/dashboard/index.d.ts +4 -0
- package/dist/dashboard/index.js +6 -2
- package/dist/dashboard/index.js.map +1 -1
- package/dist/dashboard/lib/snapshot.d.ts +168 -30
- package/dist/dashboard/lib/snapshot.js +104 -37
- package/dist/dashboard/lib/snapshot.js.map +1 -1
- package/dist/dashboard/lib/summary.d.ts +230 -0
- package/dist/dashboard/lib/summary.js +398 -0
- package/dist/dashboard/lib/summary.js.map +1 -0
- package/dist/domain/index.d.ts +2 -0
- package/dist/domain/index.js +1 -0
- package/dist/domain/index.js.map +1 -1
- package/dist/domain/lib/cycle.d.ts +17 -0
- package/dist/domain/lib/cycle.js +2 -0
- package/dist/domain/lib/cycle.js.map +1 -0
- package/dist/{patrol → domain}/lib/pick.d.ts +2 -1
- package/dist/{patrol → domain}/lib/pick.js.map +1 -1
- package/dist/domain/lib/refactor.d.ts +2 -0
- package/dist/gate/index.d.ts +7 -0
- package/dist/gate/index.js +15 -0
- package/dist/gate/index.js.map +1 -1
- package/dist/patrol/lib/attempt.js +10 -2
- package/dist/patrol/lib/attempt.js.map +1 -1
- package/dist/patrol/lib/base.d.ts +10 -3
- package/dist/patrol/lib/base.js +14 -8
- package/dist/patrol/lib/base.js.map +1 -1
- package/dist/patrol/lib/cycle.d.ts +1 -1
- package/dist/patrol/lib/cycle.js +32 -1
- package/dist/patrol/lib/cycle.js.map +1 -1
- package/dist/patrol/lib/recover.d.ts +2 -1
- package/dist/patrol/lib/recover.js +16 -1
- package/dist/patrol/lib/recover.js.map +1 -1
- package/dist/patrol/lib/scorecard.js +12 -4
- package/dist/patrol/lib/scorecard.js.map +1 -1
- package/dist/patrol/lib/steps.d.ts +5 -2
- package/dist/patrol/lib/steps.js +9 -6
- package/dist/patrol/lib/steps.js.map +1 -1
- package/dist/playbook/index.js +3 -3
- package/dist/roles/lib/prompts.d.ts +1 -0
- package/dist/roles/lib/prompts.js +6 -0
- package/dist/roles/lib/prompts.js.map +1 -1
- package/dist/roles/lib/refactorer.d.ts +1 -0
- package/dist/roles/lib/refactorer.js +24 -6
- package/dist/roles/lib/refactorer.js.map +1 -1
- package/dist/roles/lib/scorecard-text.js +1 -1
- package/dist/roles/lib/scorecard-text.js.map +1 -1
- package/dist/store/index.d.ts +4 -1
- package/dist/store/index.js +7 -0
- package/dist/store/index.js.map +1 -1
- package/package.json +1 -1
- package/ui/app.js +1236 -324
- package/ui/index.html +35 -13
- package/ui/style.css +1063 -340
- /package/dist/{patrol → domain}/lib/pick.js +0 -0
package/README.md
CHANGED
|
@@ -1,206 +1,157 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="assets/banner.png" alt="Sloppatrol: AI agents that clean up your code, and prove nothing broke." width="100%">
|
|
3
|
+
</p>
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
<p align="center">
|
|
6
|
+
<a href="https://www.npmjs.com/package/sloppatrol"><img src="https://img.shields.io/npm/v/sloppatrol?color=22d3ee&label=npm" alt="npm version"></a>
|
|
7
|
+
<a href="https://github.com/agent-labs-dev/sloppatrol/actions/workflows/ci.yml"><img src="https://github.com/agent-labs-dev/sloppatrol/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
|
|
8
|
+
<a href="LICENSE"><img src="https://img.shields.io/badge/license-Apache--2.0-blue" alt="License: Apache-2.0"></a>
|
|
9
|
+
</p>
|
|
4
10
|
|
|
5
|
-
|
|
11
|
+
Sloppatrol is a team of agents that patrols your repo and makes the code cleaner, one small pull request at a time. It never changes what the code does, and each pull request carries the proof.
|
|
6
12
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
- The **gate** is code, not a model. It
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
|
|
13
|
+
- A **surveyor** agent reads the code and records opportunities: shallow modules, mixed concerns, hidden dependencies, tests that mock your own code.
|
|
14
|
+
- A **refactorer** agent makes one opportunity real, in its own git worktree.
|
|
15
|
+
- The **gate** is code, not a model. It keeps a refactor only when your checks pass and a planted bug turns a test red.
|
|
16
|
+
- Three blind **assessor** agents score the code before and after, on seven quality metrics. The target metrics must go up.
|
|
17
|
+
- A **reviewer** agent reads the change against your repo's rules. It can only reject.
|
|
18
|
+
|
|
19
|
+
It is the code-quality sibling of [Bugpatrol](https://github.com/agent-labs-dev/bugpatrol) and [Speedpatrol](https://github.com/agent-labs-dev/speedpatrol).
|
|
13
20
|
|
|
14
21
|
```bash
|
|
15
|
-
npx sloppatrol init
|
|
16
22
|
npx sloppatrol
|
|
17
23
|
```
|
|
18
24
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
An agent proposes; code decides. A refactor is kept only when every step below passes, and no agent can overrule one.
|
|
22
|
-
|
|
23
|
-
| Step | What it checks |
|
|
24
|
-
| --- | --- |
|
|
25
|
-
| One side | A **source** refactor changes no test file, so your existing tests prove the behaviour held. A **tests** refactor changes no source file, so the unchanged source proves the new tests right. |
|
|
26
|
-
| Frozen files | No manifest, lockfile, tool config, CI file, snapshot or `.env` changes. No path in `ignore`. |
|
|
27
|
-
| No suppression | No added `@ts-ignore`, `eslint-disable`, `# type: ignore`, `as any`, coverage exclusion, or skipped or focused test. A suppression that moves with its code is fine. |
|
|
28
|
-
| Tests kept | The diff removes no test case, and changes no test file that no check runs (`uncheckedTests`). |
|
|
29
|
-
| Size | At most `guards.maxFiles` files and `guards.maxLines` lines. |
|
|
30
|
-
| Checks | Every command in `checks` passes, as it passes on `main`. Sloppatrol does no work while `main` is red. |
|
|
31
|
-
| Review | A reviewer agent reads the diff against the playbook, and rejects when in doubt. |
|
|
25
|
+
`npx sloppatrol` runs the patrol: survey, refactor, gate, prove, review, and publish, again and again. Verified refactors wait for `sloppatrol publish` until you turn on GitHub.
|
|
32
26
|
|
|
33
|
-
|
|
34
|
-
| Improvement | The assessor scores the changed files before and after, blind. The target metrics must go up; no other metric may drop. |
|
|
27
|
+
### How the patrol runs
|
|
35
28
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
29
|
+
```mermaid
|
|
30
|
+
flowchart TB
|
|
31
|
+
start(["npx sloppatrol"]) --> pull["Pull main, run your checks, score more files"]
|
|
32
|
+
pull -->|green| survey["1 · Survey<br/>LLM · Surveyor records opportunities"]
|
|
33
|
+
survey --> refactor["2 · Refactor<br/>LLM · Refactorer edits a worktree"]
|
|
34
|
+
refactor --> gate["3 · Gate<br/>Code · guards, your checks, a planted bug"]
|
|
35
|
+
gate --> assess["4 · Prove the gain<br/>LLM · 3 blind assessors score before and after"]
|
|
36
|
+
assess --> review["5 · Review<br/>LLM · Reviewer, veto only"]
|
|
37
|
+
review --> publish["6 · Publish<br/>Code · a draft PR with its proof"]
|
|
38
|
+
publish --> wait["Wait for the next cycle"]
|
|
39
|
+
wait -->|"next cycle"| pull
|
|
40
|
+
|
|
41
|
+
subgraph legend ["Legend"]
|
|
42
|
+
direction LR
|
|
43
|
+
l1["LLM agent"] ~~~ l3["Code, no model"] ~~~ l4["Off by default"]
|
|
44
|
+
end
|
|
45
|
+
wait ~~~ legend
|
|
39
46
|
|
|
40
|
-
|
|
47
|
+
classDef llm fill:#312e81,stroke:#a5b4fc,color:#ffffff
|
|
48
|
+
classDef code fill:#1e293b,stroke:#64748b,color:#e2e8f0
|
|
49
|
+
classDef opt fill:#1e293b,stroke:#64748b,color:#e2e8f0,stroke-width:2px,stroke-dasharray:6 4
|
|
50
|
+
class survey,refactor,assess,review,l1 llm
|
|
51
|
+
class start,pull,gate,wait,l3 code
|
|
52
|
+
class publish,l4 opt
|
|
53
|
+
style legend fill:transparent,stroke:#64748b
|
|
54
|
+
```
|
|
41
55
|
|
|
42
|
-
|
|
43
|
-
| --- | --- |
|
|
44
|
-
| Simplicity | Can a reader follow each function without holding much in their head? |
|
|
45
|
-
| Modularity | Does the file own one concept, behind a small interface, apart from other concerns? |
|
|
46
|
-
| Injection | Does the code receive what it depends on, or reach out for it? |
|
|
47
|
-
| Purity | How much of the logic lives in pure functions (same input, same output, no side effects), with state and effects kept small and at the edge? |
|
|
48
|
-
| Test quality | Do the tests prove behaviour through the interface, and would they fail if it broke? |
|
|
49
|
-
| Clarity | Does every name, comment and abstraction earn its place? |
|
|
50
|
-
| Agent-friendliness | How hard is it for an agent to change this file wrong, and is it a pattern worth copying? |
|
|
56
|
+
[How it works](docs/how-it-works.md) shows each step of the gate, and the proof on each pull request.
|
|
51
57
|
|
|
52
|
-
|
|
58
|
+
## Score your codebase
|
|
53
59
|
|
|
54
|
-
|
|
60
|
+
Sloppatrol can score your code without the patrol. It changes no code and runs none of your checks, so it works on any repo.
|
|
55
61
|
|
|
56
|
-
|
|
62
|
+
<p align="center">
|
|
63
|
+
<img src="assets/scorecard.png" alt="The scorecard of a demo project: an overall score of 81 in a green ring, a bar for each of the seven metrics, the repo guardrails, and the command npx sloppatrol score." width="100%">
|
|
64
|
+
</p>
|
|
57
65
|
|
|
58
|
-
|
|
66
|
+
1. Log in to Claude Code, Codex or opencode. Sloppatrol uses the agent that you have.
|
|
67
|
+
2. Go to the root of your repo, and create the config:
|
|
59
68
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
69
|
+
```bash
|
|
70
|
+
npx sloppatrol init
|
|
71
|
+
```
|
|
63
72
|
|
|
64
|
-
|
|
73
|
+
3. Optional: add your generated code to `ignore` in `.sloppatrol/sloppatrol.yml`. A tool writes that code, so it must not change your score.
|
|
65
74
|
|
|
66
|
-
|
|
75
|
+
```yaml
|
|
76
|
+
ignore: [src/generated/**]
|
|
77
|
+
```
|
|
67
78
|
|
|
68
|
-
|
|
79
|
+
4. Score each file:
|
|
69
80
|
|
|
70
|
-
|
|
81
|
+
```bash
|
|
82
|
+
npx sloppatrol score
|
|
83
|
+
```
|
|
71
84
|
|
|
72
|
-
|
|
73
|
-
- [Testing](playbook/testing.md): test through the interface; fakes injected through a seam, never a mocking library for your own code.
|
|
74
|
-
- [Smells](playbook/smells.md) and [Safety](playbook/safety.md): what to look for, and the behaviour a refactor must keep.
|
|
75
|
-
- One page per stack, picked from what the census detects: [TypeScript](playbook/stacks/typescript.md), [React and React Native](playbook/stacks/react.md), [Node backends](playbook/stacks/node-backend.md), [Python](playbook/stacks/python.md), [Go](playbook/stacks/go.md), [Swift](playbook/stacks/swift.md), [Kotlin](playbook/stacks/kotlin.md), [Rust](playbook/stacks/rust.md).
|
|
85
|
+
An assessor agent scores each file on the [seven metrics](docs/metrics.md), from 0 (worst) to 100 (best). Then Sloppatrol opens the scorecard in your browser. Click **Download PNG** or **Copy image**, and post it.
|
|
76
86
|
|
|
77
|
-
|
|
87
|
+
Sloppatrol scores the last commit on `origin/main`, not your local changes. The first run can take some minutes on a large repo. Sloppatrol keeps each score, so the next run scores only the files that changed. `--files <n>` scores at most `n` files in one run.
|
|
78
88
|
|
|
79
|
-
##
|
|
89
|
+
## The dashboard
|
|
80
90
|
|
|
81
|
-
|
|
82
|
-
Start
|
|
83
|
-
sloppatrol init Create .sloppatrol/ with a guess at your checks
|
|
84
|
-
sloppatrol doctor Show the config, the agent each role runs on, and what is missing
|
|
85
|
-
|
|
86
|
-
Run
|
|
87
|
-
sloppatrol Patrol all day: a cycle every patrol.intervalMinutes, with the dashboard
|
|
88
|
-
sloppatrol --once One cycle, then stop
|
|
89
|
-
sloppatrol dashboard Only the dashboard (http://127.0.0.1:4322)
|
|
90
|
-
|
|
91
|
-
One step at a time
|
|
92
|
-
sloppatrol check Run your checks on the patrolled commit (the oracle)
|
|
93
|
-
sloppatrol survey Let the surveyor record opportunities now
|
|
94
|
-
sloppatrol refactor [id] Attempt one opportunity now: the best open one, or <id>
|
|
95
|
-
sloppatrol score Score the repo now: the metrics of the panel of files
|
|
96
|
-
sloppatrol publish Open pull requests for verified refactors (--dry-run)
|
|
97
|
-
|
|
98
|
-
Read
|
|
99
|
-
sloppatrol status The opportunities, the refactors and the agents
|
|
100
|
-
sloppatrol census What the surveyor sees: stack, large files, mocks, churn
|
|
101
|
-
sloppatrol dismiss <id> Never propose this opportunity again (--reason "...")
|
|
102
|
-
```
|
|
91
|
+
`npx sloppatrol` serves a live dashboard on http://127.0.0.1:4322. The **Overview** tells you at a glance if the patrol is healthy: the checks on main, what waits for your decision, the code quality and its change, and the last cycle. Then it lists what needs attention, with the command to run next.
|
|
103
92
|
|
|
104
|
-
|
|
93
|
+
<p align="center">
|
|
94
|
+
<img src="assets/dashboard.png" alt="The Overview of the dashboard on a demo project: a status band, the items that need attention with their commands, the agents, the code quality per metric, and the refactor results." width="100%">
|
|
95
|
+
</p>
|
|
105
96
|
|
|
106
|
-
|
|
107
|
-
flowchart TB
|
|
108
|
-
start(["sloppatrol"]) --> pull["Resolve origin/main, check it out"]
|
|
109
|
-
pull --> base{{"Checks on main<br/>(code)"}}
|
|
110
|
-
base -->|red| wait
|
|
111
|
-
base -->|green| survey["Survey, when the backlog is low<br/>LLM · surveyor"]
|
|
112
|
-
survey --> pick["Pick the strongest opportunity<br/>no file overlap with open PRs"]
|
|
113
|
-
pick --> refactor["Refactor in a worktree<br/>LLM · refactorer"]
|
|
114
|
-
refactor --> guards{{"Guards on the diff<br/>(code)"}}
|
|
115
|
-
guards -->|pass| checks{{"Your checks<br/>(code)"}}
|
|
116
|
-
checks -->|pass| review["Review<br/>LLM · reviewer, veto only"]
|
|
117
|
-
review -->|approve| pr["Draft pull request"]
|
|
118
|
-
guards -->|fail| reject["Rejected: worktree removed"]
|
|
119
|
-
checks -->|fail| reject
|
|
120
|
-
review -->|reject| reject
|
|
121
|
-
pr --> wait["Wait patrol.intervalMinutes"]
|
|
122
|
-
reject --> wait
|
|
123
|
-
wait --> pull
|
|
97
|
+
The other pages show each refactor as a pipeline with its proof, the scorecard of each file, every check run, the backlog in the order the refactorer picks it, and every agent session. [The dashboard](docs/dashboard.md) tells more.
|
|
124
98
|
|
|
125
|
-
|
|
126
|
-
classDef code fill:#1e293b,stroke:#64748b,color:#e2e8f0
|
|
127
|
-
class survey,refactor,review llm
|
|
128
|
-
class start,pull,base,pick,guards,checks,pr,reject,wait code
|
|
129
|
-
```
|
|
99
|
+
## Set up with your agent
|
|
130
100
|
|
|
131
|
-
|
|
132
|
-
- At most `github.maxOpen` pull requests wait at once, and two never touch the same file.
|
|
133
|
-
- An opportunity that fails the gate `maxAttempts` times is exhausted.
|
|
101
|
+
1. Install the Sloppatrol skill in your repo:
|
|
134
102
|
|
|
135
|
-
|
|
103
|
+
```bash
|
|
104
|
+
npx skills add agent-labs-dev/sloppatrol
|
|
105
|
+
```
|
|
136
106
|
|
|
137
|
-
|
|
107
|
+
The [skills CLI](https://github.com/vercel-labs/skills) installs the skill for Claude Code, Codex, Cursor, and many other agents. It also writes `skills-lock.json` at the repo root. Commit both, so your team gets the skill too.
|
|
138
108
|
|
|
139
|
-
|
|
140
|
-
- **Refactors**: each attempt as a pipeline (refactorer → guards → checks → mutation → metrics → review → pull request), with its full proof.
|
|
141
|
-
- **Scorecard**: each metric's score and trend over commits, and every file of the panel with the evidence behind its scores.
|
|
142
|
-
- **Checks**: every check run on `main`, on each refactor, and each run the refactorer starts itself, with the output of each check.
|
|
143
|
-
- **Backlog**: the opportunities by status, with the problem, the change and the files.
|
|
144
|
-
- **Sessions**: every agent session as a timeline of its tool calls.
|
|
109
|
+
2. Give this prompt to your agent:
|
|
145
110
|
|
|
146
|
-
|
|
111
|
+
```text
|
|
112
|
+
Set up Sloppatrol for this repo.
|
|
113
|
+
```
|
|
147
114
|
|
|
148
|
-
|
|
115
|
+
The [skill](skills/sloppatrol/SKILL.md) tells the agent what Sloppatrol does, how to configure the checks of your repo, how to run it, and how to read the results.
|
|
149
116
|
|
|
150
|
-
|
|
151
|
-
agent: auto # or claude | codex | opencode
|
|
152
|
-
agents:
|
|
153
|
-
reviewer: { use: codex } # a second opinion from another agent
|
|
154
|
-
surveyor:
|
|
155
|
-
use: { runtime: model, via: openrouter, model: anthropic/claude-opus-5.5 }
|
|
156
|
-
```
|
|
117
|
+
If your agent cannot install skills, give it the skill URL:
|
|
157
118
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
## Configuration
|
|
161
|
-
|
|
162
|
-
```yaml
|
|
163
|
-
# .sloppatrol/sloppatrol.yml
|
|
164
|
-
agent: auto
|
|
165
|
-
prepare: [pnpm install --frozen-lockfile] # each fresh checkout and worktree
|
|
166
|
-
checks: # the oracle
|
|
167
|
-
- { name: typecheck, run: pnpm typecheck }
|
|
168
|
-
- { name: lint, run: pnpm lint }
|
|
169
|
-
- { name: test, run: pnpm test, tests: true } # tests: true marks the checks a planted bug must turn red
|
|
170
|
-
focus: [src/**] # where the surveyor looks (default: everywhere)
|
|
171
|
-
ignore: [src/generated/**] # what no agent may change
|
|
172
|
-
uncheckedTests: [tests/e2e/**] # tests no check runs: no refactor may change them
|
|
173
|
-
guards: { maxFiles: 12, maxLines: 600 }
|
|
174
|
-
metrics: { enabled: true, panel: 100, tolerance: 0.5, judges: 3 } # panel: files newly scored per cycle
|
|
175
|
-
agents:
|
|
176
|
-
surveyor: { minBacklog: 3, maxPerSurvey: 8 }
|
|
177
|
-
refactorer: { maxPerCycle: 1, maxAttempts: 2 }
|
|
178
|
-
reviewer: { enabled: true }
|
|
179
|
-
github: { enabled: true, draft: true, maxOpen: 3, labels: [sloppatrol] }
|
|
180
|
-
patrol: { intervalMinutes: 60, pull: origin/main }
|
|
119
|
+
```text
|
|
120
|
+
Read https://raw.githubusercontent.com/agent-labs-dev/sloppatrol/main/skills/sloppatrol/SKILL.md and set up Sloppatrol for this repo.
|
|
181
121
|
```
|
|
182
122
|
|
|
183
|
-
|
|
123
|
+
To set it up by hand, read [Getting started](docs/getting-started.md).
|
|
184
124
|
|
|
185
|
-
|
|
125
|
+
## What is supported
|
|
186
126
|
|
|
187
|
-
|
|
127
|
+
| Area | Supported |
|
|
128
|
+
| --- | --- |
|
|
129
|
+
| Languages | Any language with checks that you can run from a shell. The playbook has pages for TypeScript, React and React Native, Node backends, Python, Go, Swift, Kotlin and Rust. |
|
|
130
|
+
| Agents | Claude Code, Codex or opencode, with your existing login (`agent: auto` picks the installed one). Or an API key for Anthropic, OpenAI, OpenRouter, or a custom endpoint. |
|
|
131
|
+
| Repo rules | `AGENTS.md`, `CLAUDE.md` and their `@` imports, `CONTRIBUTING.md`, `GLOSSARY.md`, and your decision records |
|
|
132
|
+
| GitHub | Draft pull requests through the `gh` CLI |
|
|
133
|
+
| Output | A local dashboard, GitHub pull requests, and JSON files under `.sloppatrol/runs/` |
|
|
188
134
|
|
|
189
|
-
|
|
190
|
-
- [Decisions](docs/adr/): why it works this way.
|
|
135
|
+
## Documentation
|
|
191
136
|
|
|
192
|
-
|
|
137
|
+
| Page | What it covers |
|
|
138
|
+
| --- | --- |
|
|
139
|
+
| [Getting started](docs/getting-started.md) | Add Sloppatrol to your repo, step by step |
|
|
140
|
+
| [How it works](docs/how-it-works.md) | The cycle, the gate, the proof, your repo's rules, and the playbook |
|
|
141
|
+
| [The metrics](docs/metrics.md) | The seven metrics, the rubric, and how the scorecard grows |
|
|
142
|
+
| [Commands](docs/commands.md) | All the CLI commands |
|
|
143
|
+
| [Configuration](docs/configuration.md) | All the settings in `.sloppatrol/sloppatrol.yml` |
|
|
144
|
+
| [Agents and models](docs/models.md) | The agent of each role, and the model providers |
|
|
145
|
+
| [The dashboard](docs/dashboard.md) | What each page shows |
|
|
146
|
+
| [Playbook](playbook/principles.md) | The engineering practice that the agents follow |
|
|
147
|
+
| [Glossary](GLOSSARY.md) | The words Sloppatrol uses, with one meaning each |
|
|
148
|
+
| [Decisions](docs/adr/) | Why Sloppatrol works this way |
|
|
149
|
+
| [Contributing](CONTRIBUTING.md) | Build Sloppatrol from source, the shape of the code, and releases |
|
|
193
150
|
|
|
194
|
-
|
|
195
|
-
pnpm install
|
|
196
|
-
pnpm build
|
|
197
|
-
pnpm test
|
|
198
|
-
pnpm check # Biome, module boundaries (dependency-cruiser), types
|
|
199
|
-
pnpm knip
|
|
200
|
-
```
|
|
151
|
+
## License
|
|
201
152
|
|
|
202
|
-
|
|
153
|
+
[Apache-2.0](LICENSE)
|
|
203
154
|
|
|
204
|
-
|
|
155
|
+
---
|
|
205
156
|
|
|
206
|
-
|
|
157
|
+
<p align="center">Made with ❤️ by the <a href="https://nebula.gg">Nebula</a> team.</p>
|
package/dist/census/index.js
CHANGED
|
@@ -9,10 +9,12 @@ export async function takeCensus(root, scope) {
|
|
|
9
9
|
!matchesAny(path, scope.ignore) &&
|
|
10
10
|
(scope.focus.length === 0 || matchesAny(path, scope.focus));
|
|
11
11
|
const code = all.filter(inScope);
|
|
12
|
+
// Generated files can outnumber the real code, so they do not decide the main language.
|
|
13
|
+
const kept = all.filter((path) => !matchesAny(path, scope.ignore));
|
|
12
14
|
const tests = code.filter((path) => matchesAny(path, scope.tests));
|
|
13
15
|
const sources = code.filter((path) => !matchesAny(path, scope.tests));
|
|
14
16
|
const [stack, measured, hot] = await Promise.all([
|
|
15
|
-
detectStack(root,
|
|
17
|
+
detectStack(root, kept),
|
|
16
18
|
measureFiles(root, sources, tests),
|
|
17
19
|
churn(root, inScope),
|
|
18
20
|
]);
|
|
@@ -32,7 +34,7 @@ export function censusMarkdown(census) {
|
|
|
32
34
|
const list = (items, line) => (items.length ? items.map(line).join('\n') : '- none');
|
|
33
35
|
return [
|
|
34
36
|
'# Census',
|
|
35
|
-
`Languages: ${stack.languages.map((l) => `${l.name} (${l.files} files)`).join(', ') || 'none found'}`,
|
|
37
|
+
`Languages: ${stack.languages.map((l) => `${l.name} (${l.files} files, ${l.lines} lines)`).join(', ') || 'none found'}`,
|
|
36
38
|
`Frameworks: ${stack.frameworks.join(', ') || 'none found'}`,
|
|
37
39
|
`Project kind: ${stack.kinds.join(', ')}`,
|
|
38
40
|
`Files: ${census.sourceFiles} source, ${census.testFiles} test`,
|
package/dist/census/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/census/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAc,KAAK,EAA+B,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChG,OAAO,EAAE,WAAW,EAAE,UAAU,EAAc,MAAM,gBAAgB,CAAC;AAmBrE,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAY,EAAE,KAAkB;IAC/D,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,OAAO,GAAG,CAAC,IAAY,EAAE,EAAE,CAC/B,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QACzB,CAAC,UAAU,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC;QAC/B,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,UAAU,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IAC9D,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACjC,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IACnE,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IACtE,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC/C,WAAW,CAAC,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/census/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,7 +5,43 @@ async function read(root, file) {
|
|
|
5
5
|
const path = join(root, file);
|
|
6
6
|
return existsSync(path) ? readFile(path, 'utf8').catch(() => '') : '';
|
|
7
7
|
}
|
|
8
|
-
|
|
8
|
+
/** The compiler of each of these rejects a wrong type. JavaScript has no compiler check, so it is not here. */
|
|
9
|
+
const STATIC_LANGUAGES = ['typescript', 'go', 'rust', 'swift', 'kotlin', 'java', 'csharp'];
|
|
10
|
+
/** A language with this share of the code lines or more needs its own type check. */
|
|
11
|
+
const MAIN_SHARE = 0.1;
|
|
12
|
+
/** Evidence that a check rejects a wrong type in each language, keyed by language. */
|
|
13
|
+
async function typeChecks(root, files) {
|
|
14
|
+
let python = files.find((f) => /(^|\/)(mypy\.ini|pyrightconfig\.json)$/.test(f));
|
|
15
|
+
for (const file of files.filter((f) => /(^|\/)(pyproject\.toml|setup\.cfg)$/.test(f))) {
|
|
16
|
+
if (python)
|
|
17
|
+
break;
|
|
18
|
+
if (/\[(tool\.(mypy|pyright|ty)|mypy)\]/.test(await read(root, file)))
|
|
19
|
+
python = `${file}: a type checker is configured`;
|
|
20
|
+
}
|
|
21
|
+
return {
|
|
22
|
+
python,
|
|
23
|
+
...Object.fromEntries(STATIC_LANGUAGES.map((name) => [name, `${name}: the compiler checks types`])),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Strict types are present when each main language of the repo has a type check.
|
|
28
|
+
* A repo can mix languages, such as a Rust server with a JavaScript UI.
|
|
29
|
+
*/
|
|
30
|
+
async function strictTypes(root, files, stack) {
|
|
31
|
+
const total = stack.languages.reduce((sum, l) => sum + l.lines, 0);
|
|
32
|
+
const main = stack.languages.filter((l, i) => i === 0 || l.lines >= total * MAIN_SHARE).map((l) => l.name);
|
|
33
|
+
const checks = await typeChecks(root, files);
|
|
34
|
+
const missing = main.filter((name) => !checks[name]);
|
|
35
|
+
return {
|
|
36
|
+
name: 'Strict types',
|
|
37
|
+
present: main.length > 0 && missing.length === 0,
|
|
38
|
+
evidence: main.length === 0
|
|
39
|
+
? 'No code found.'
|
|
40
|
+
: missing.length === 0
|
|
41
|
+
? main.map((name) => checks[name]).join('; ')
|
|
42
|
+
: `No strict type check for ${missing.join(', ')}: a wrong type reaches run time.`,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
9
45
|
/**
|
|
10
46
|
* The repo-wide guardrails that keep an agent from changing code wrong,
|
|
11
47
|
* found from files alone. Each one turns a wrong edit into a failed check.
|
|
@@ -14,27 +50,20 @@ export async function detectGuardrails(root, files, stack, testFiles) {
|
|
|
14
50
|
const has = (pattern) => files.find((f) => pattern.test(f));
|
|
15
51
|
const pyproject = await read(root, 'pyproject.toml');
|
|
16
52
|
const pkg = await read(root, 'package.json');
|
|
17
|
-
const tsconfig = await read(root, 'tsconfig.json');
|
|
18
|
-
const main = stack.languages[0]?.name;
|
|
19
53
|
const found = (name, evidence, why) => ({
|
|
20
54
|
name,
|
|
21
55
|
present: Boolean(evidence),
|
|
22
56
|
evidence: evidence ?? why,
|
|
23
57
|
});
|
|
24
|
-
const strict = (/"strict"\s*:\s*true/.test(tsconfig) && 'tsconfig.json: strict') ||
|
|
25
|
-
(/\[tool\.(mypy|pyright|ty)\]/.test(pyproject) && 'pyproject.toml: a type checker is configured') ||
|
|
26
|
-
has(/(^|\/)(mypy\.ini|pyrightconfig\.json)$/) ||
|
|
27
|
-
(main && STATIC_LANGUAGES.includes(main) ? `${main} is statically typed` : undefined);
|
|
28
58
|
return [
|
|
29
59
|
found('Agent guide', has(/^(AGENTS|CLAUDE)\.md$/), 'No AGENTS.md or CLAUDE.md at the root: agents learn the rules by trial.'),
|
|
30
|
-
|
|
60
|
+
await strictTypes(root, files, stack),
|
|
31
61
|
found('Linter', has(/(^|\/)(biome\.jsonc?|eslint\.config\.\w+|\.eslintrc(\.\w+)?|ruff\.toml|\.golangci\.\w+|\.swiftlint\.yml|detekt\.yml)$/) || (/\[tool\.ruff/.test(pyproject) ? 'pyproject.toml: ruff' : undefined), 'No linter config.'),
|
|
32
62
|
found('Module boundaries', has(/(^|\/)\.dependency-cruiser\.\w+$|(^|\/)\.importlinter$/) ||
|
|
33
63
|
(/\[tool\.importlinter\]/.test(pyproject) ? 'pyproject.toml: import-linter' : undefined) ||
|
|
34
64
|
(/eslint-plugin-boundaries|@nx\/enforce-module-boundaries/.test(pkg)
|
|
35
65
|
? 'package.json: boundary lint'
|
|
36
66
|
: undefined), 'Nothing stops a deep import across modules.'),
|
|
37
|
-
found('Pre-commit hook', has(/^(\.husky\/|\.pre-commit-config\.yaml$|lefthook\.ya?ml$|\.githooks\/)/), 'No hook: a broken change reaches a commit.'),
|
|
38
67
|
found('CI', has(/^(\.github\/workflows\/|\.gitlab-ci\.yml$|\.circleci\/)/), 'No CI config found.'),
|
|
39
68
|
found('Tests', testFiles > 0 ? `${testFiles} test files` : undefined, 'No test files: nothing pins behaviour.'),
|
|
40
69
|
];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guardrails.js","sourceRoot":"","sources":["../../../src/census/lib/guardrails.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAIjC,KAAK,UAAU,IAAI,CAAC,IAAY,EAAE,IAAY;IAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC9B,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AACxE,CAAC;AAED,MAAM,gBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"guardrails.js","sourceRoot":"","sources":["../../../src/census/lib/guardrails.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
export type Stack = {
|
|
2
|
-
/** Languages by
|
|
2
|
+
/** Languages by line count, most first. Many small files, such as configs, do not make a main language. */
|
|
3
3
|
languages: {
|
|
4
4
|
name: string;
|
|
5
5
|
files: number;
|
|
6
|
+
lines: number;
|
|
6
7
|
}[];
|
|
7
8
|
frameworks: string[];
|
|
8
9
|
/** What the project is: it decides which playbook pages apply. */
|
package/dist/census/lib/stack.js
CHANGED
|
@@ -49,11 +49,15 @@ async function nodeDependencies(root, files) {
|
|
|
49
49
|
export async function detectStack(root, files) {
|
|
50
50
|
const counts = new Map();
|
|
51
51
|
for (const file of files) {
|
|
52
|
-
const
|
|
53
|
-
if (
|
|
54
|
-
|
|
52
|
+
const name = languageOf(file);
|
|
53
|
+
if (!name)
|
|
54
|
+
continue;
|
|
55
|
+
const count = counts.get(name) ?? { name, files: 0, lines: 0 };
|
|
56
|
+
count.files += 1;
|
|
57
|
+
count.lines += (await read(root, file).catch(() => '')).split('\n').length;
|
|
58
|
+
counts.set(name, count);
|
|
55
59
|
}
|
|
56
|
-
const languages = [...counts
|
|
60
|
+
const languages = [...counts.values()].sort((a, b) => b.lines - a.lines);
|
|
57
61
|
const { deps, bin } = await nodeDependencies(root, files);
|
|
58
62
|
const python = (await Promise.all(['pyproject.toml', 'requirements.txt'].map((f) => read(root, f)))).join('\n');
|
|
59
63
|
for (const name of ['django', 'fastapi', 'flask'])
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stack.js","sourceRoot":"","sources":["../../../src/census/lib/stack.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAU1C,MAAM,SAAS,GAA2B;IACxC,KAAK,EAAE,YAAY;IACnB,MAAM,EAAE,YAAY;IACpB,MAAM,EAAE,YAAY;IACpB,MAAM,EAAE,YAAY;IACpB,KAAK,EAAE,YAAY;IACnB,MAAM,EAAE,YAAY;IACpB,MAAM,EAAE,YAAY;IACpB,MAAM,EAAE,YAAY;IACpB,KAAK,EAAE,QAAQ;IACf,KAAK,EAAE,IAAI;IACX,KAAK,EAAE,MAAM;IACb,QAAQ,EAAE,OAAO;IACjB,KAAK,EAAE,QAAQ;IACf,MAAM,EAAE,QAAQ;IAChB,OAAO,EAAE,MAAM;IACf,KAAK,EAAE,MAAM;IACb,KAAK,EAAE,QAAQ;CAChB,CAAC;AAEF,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,OAAO,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;AAClC,CAAC;AAED,MAAM,MAAM,GAAG,CAAC,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;AACvH,MAAM,OAAO,GAAG,CAAC,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;AAEpH,KAAK,UAAU,IAAI,CAAC,IAAY,EAAE,IAAY;IAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC9B,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AACxD,CAAC;AAED,KAAK,UAAU,gBAAgB,CAAC,IAAY,EAAE,KAAe;IAC3D,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,IAAI,GAAG,GAAG,KAAK,CAAC;IAChB,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;QAC/G,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAA4B,CAAC;YAC1E,KAAK,MAAM,GAAG,IAAI,CAAC,cAAc,EAAE,iBAAiB,EAAE,kBAAkB,CAAC;gBACvE,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAE,GAAG,CAAC,GAAG,CAAwC,IAAI,EAAE,CAAC;oBAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACzG,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC3B,CAAC;QAAC,MAAM,CAAC;YACP,oDAAoD;QACtD,CAAC;IACH,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;AACvB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAY,EAAE,KAAe;IAC7D,MAAM,MAAM,GAAG,IAAI,GAAG,
|
|
1
|
+
{"version":3,"file":"stack.js","sourceRoot":"","sources":["../../../src/census/lib/stack.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/index.js
CHANGED
|
@@ -12,6 +12,7 @@ import { stopAll } from '../processes/index.js';
|
|
|
12
12
|
import { scorecardMarkdown } from '../roles/index.js';
|
|
13
13
|
import { Store } from '../store/index.js';
|
|
14
14
|
import { intFlag, parseArgv, strFlag } from './lib/argv.js';
|
|
15
|
+
import { openInBrowser } from './lib/browser.js';
|
|
15
16
|
import { doctor } from './lib/doctor.js';
|
|
16
17
|
import { init } from './lib/init.js';
|
|
17
18
|
import { status } from './lib/status.js';
|
|
@@ -45,10 +46,11 @@ async function dashboard(store, project, port) {
|
|
|
45
46
|
return startDashboard({ store, project, port: 0 });
|
|
46
47
|
}
|
|
47
48
|
}
|
|
49
|
+
const SIGNALS = ['SIGINT', 'SIGTERM', 'SIGHUP'];
|
|
48
50
|
/**
|
|
49
51
|
* Ctrl-C or a SIGTERM stops every check and agent CLI Sloppatrol started,
|
|
50
52
|
* marks the running agents stopped, and exits. The next patrol cleans up
|
|
51
|
-
* the interrupted refactor.
|
|
53
|
+
* the interrupted refactor. Returns a function that removes the handlers.
|
|
52
54
|
*/
|
|
53
55
|
function stopOnSignal(store) {
|
|
54
56
|
const stop = async (signal) => {
|
|
@@ -59,8 +61,12 @@ function stopOnSignal(store) {
|
|
|
59
61
|
await store.setStatus({ role: status.role, state: 'idle', detail: 'Stopped.' });
|
|
60
62
|
process.exit(130);
|
|
61
63
|
};
|
|
62
|
-
for (const signal of
|
|
63
|
-
process.once(signal,
|
|
64
|
+
for (const signal of SIGNALS)
|
|
65
|
+
process.once(signal, stop);
|
|
66
|
+
return () => {
|
|
67
|
+
for (const signal of SIGNALS)
|
|
68
|
+
process.off(signal, stop);
|
|
69
|
+
};
|
|
64
70
|
}
|
|
65
71
|
function untilSigint() {
|
|
66
72
|
return new Promise((done) => process.once('SIGINT', () => done()));
|
|
@@ -121,8 +127,18 @@ async function main(args) {
|
|
|
121
127
|
return refactor.status === 'verified' ? EXIT.ok : EXIT.failed;
|
|
122
128
|
}
|
|
123
129
|
case 'score': {
|
|
124
|
-
stopOnSignal(store);
|
|
130
|
+
const unwatch = stopOnSignal(store);
|
|
125
131
|
out(scorecardMarkdown(await scoreNow(loaded, deps, intFlag(flags, 'files'))));
|
|
132
|
+
unwatch();
|
|
133
|
+
if (flags.dashboard === false)
|
|
134
|
+
return EXIT.ok;
|
|
135
|
+
const server = await dashboard(store, loaded.config.project.name, intFlag(flags, 'port'));
|
|
136
|
+
const page = `${server.url}/#share`;
|
|
137
|
+
out(`\nThe scorecard, ready to share: ${page}\nCtrl-C stops the dashboard.`);
|
|
138
|
+
if (flags.open !== false)
|
|
139
|
+
openInBrowser(page);
|
|
140
|
+
await untilSigint();
|
|
141
|
+
await server.close();
|
|
126
142
|
return EXIT.ok;
|
|
127
143
|
}
|
|
128
144
|
case 'status':
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|