crewforth 3.1.1 → 3.2.0-rc.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/CHANGELOG.md +171 -0
- package/README.md +4 -3
- package/VERSION +1 -1
- package/adopt.sh +56 -5
- package/kit/AGENT_TEMPLATE.md +2 -1
- package/kit/CLAUDE.md +14 -13
- package/kit/agents/crew-commit-agent.md +7 -2
- package/kit/agents/crew-docs-agent.md +71 -0
- package/kit/agents/crew-planner.md +2 -0
- package/kit/agents/crew-refuter.md +77 -0
- package/kit/agents/crew-security-expert.md +3 -1
- package/kit/agents/crew-session-manager.md +11 -9
- package/kit/eval/doctor.sh +117 -6
- package/kit/eval/golden-routing.txt +9 -0
- package/kit/eval/lib/crew-map/crew-map.sh +26 -0
- package/kit/eval/lib/crew-map/detect.mjs +238 -0
- package/kit/eval/lib/crew-map/narrative.mjs +98 -0
- package/kit/eval/lib/crew-map/parse.mjs +305 -0
- package/kit/eval/lib/crew-map/project.mjs +163 -0
- package/kit/eval/lib/crew-map/rules/names.json +38 -0
- package/kit/eval/lib/crew-map/rules/packages.json +142 -0
- package/kit/eval/lib/crew-map/rules/python-stdlib.json +197 -0
- package/kit/eval/lib/crew-map/scan.mjs +214 -0
- package/kit/eval/lib/crew-map/stacks.mjs +441 -0
- package/kit/eval/lib/crew-map/surface.mjs +457 -0
- package/kit/eval/lib/findings/findings.mjs +410 -0
- package/kit/eval/lib/findings/findings.schema.json +122 -0
- package/kit/eval/lib/findings/findings.sh +29 -0
- package/kit/eval/lib/settings-default.sh +36 -0
- package/kit/eval/lib/settings-json.awk +15 -4
- package/kit/eval/lib/star.sh +23 -7
- package/kit/eval/lib/statusline.settings.json +6 -0
- package/kit/eval/lib/statusline.sh +100 -0
- package/kit/eval/lib/version.sh +41 -0
- package/kit/eval/smoke-test.sh +576 -41
- package/kit/hooks/agent-outcome.sh +26 -12
- package/kit/hooks/guard-agent-model.sh +109 -9
- package/kit/hooks/guard-bash.sh +240 -182
- package/kit/hooks/guard-question.sh +73 -0
- package/kit/hooks/guard-write.sh +21 -0
- package/kit/hooks/prompt-approval.sh +320 -103
- package/kit/hooks/refuter-ledger.sh +80 -0
- package/kit/hooks/session-update-check.sh +9 -8
- package/kit/owned-blobs.tsv +4 -4
- package/kit/settings.json +33 -0
- package/kit/skills/crew-approve/SKILL.md +7 -0
- package/kit/skills/crew-doctor/SKILL.md +5 -1
- package/kit/skills/crew-handoff/SKILL.md +3 -2
- package/kit/skills/crew-map/SKILL.md +44 -0
- package/kit/skills/crew-review/SKILL.md +2 -0
- package/kit/skills/crew-update/SKILL.md +1 -1
- package/kit/skills/incident-runbook/SKILL.md +2 -2
- package/kit/skills/security-scan/references/verify.md +6 -3
- package/kit/studio/README.md +12 -0
- package/kit/studio/server/index.js +125 -11
- package/kit/studio/server/lib/code-stamp.js +35 -0
- package/kit/studio/server/lib/crew-map.js +113 -0
- package/kit/studio/server/lib/model-outcomes.js +130 -15
- package/kit/studio/server/lib/owned-stream.js +56 -0
- package/kit/studio/server/lib/pricing.js +3 -0
- package/kit/studio/server/lib/projects.js +11 -4
- package/kit/studio/server/lib/remote.js +99 -0
- package/kit/studio/server/lib/usage.js +74 -14
- package/kit/studio/web/app.js +223 -15
- package/kit/studio/web/canvas.js +44 -120
- package/kit/studio/web/chat.js +82 -17
- package/kit/studio/web/graph-plan.js +10 -4
- package/kit/studio/web/index.html +10 -5
- package/kit/studio/web/liveness.js +14 -0
- package/kit/studio/web/map-plan.js +341 -0
- package/kit/studio/web/map.js +503 -0
- package/kit/studio/web/models-plan.js +61 -7
- package/kit/studio/web/models.js +19 -3
- package/kit/studio/web/style.css +131 -0
- package/kit/studio/web/usage.js +12 -0
- package/kit/studio/web/viewport.js +160 -0
- package/package.json +6 -5
- package/start.sh +10 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,177 @@ Crewforth was named Claude Starter Kit until 3.0.0.
|
|
|
5
5
|
Notable changes to this project are recorded here. Format follows [Keep a Changelog](https://keepachangelog.com/en/),
|
|
6
6
|
versioning follows [SemVer](https://semver.org/).
|
|
7
7
|
|
|
8
|
+
## [Unreleased] — 3.2.0
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **In `auto`, approve a commit or a push with one click.** The refusal now also offers a fixed question, asked with
|
|
13
|
+
AskUserQuestion: Commit only, Commit + push, Push only, No. A new gate, `guard-question.sh`, answers `ask` on it,
|
|
14
|
+
so a hook that fills in the answer cannot answer it for you (measured in 34 runs and by hand in the terminal), and
|
|
15
|
+
`prompt-approval.sh` records your click exactly as it records `/crew-approve`: tied to what is staged, `HEAD`, the
|
|
16
|
+
session, for 30 minutes.
|
|
17
|
+
Any other wording, a question with answers already in it, or an answer the hook did not ask for records nothing.
|
|
18
|
+
- **Studio's Models view shows normal work that ran above the table's model.** The gate holds a floor, not a
|
|
19
|
+
ceiling, so this is shown and nothing is blocked: the classes of normal work that ran higher than Sonnet and than
|
|
20
|
+
the floor the gate held them to, with what they cost as run and the same tokens at Sonnet's list price. That
|
|
21
|
+
Sonnet is enough for a class is said only when its last ten verified calls on Sonnet all passed first time, the
|
|
22
|
+
test a held class is offered for lowering by; otherwise the view says it is not measured.
|
|
23
|
+
- **Studio draws a project's crew map.** The Map view (`p`, or **Map** under a project in the navigator, beside its
|
|
24
|
+
number of findings) reads `.crewforth/crew-map.json` and scans nothing. Modules sit in bands from the clients down
|
|
25
|
+
to the external resources, and a module the map does not place goes to Unplaced. Lines are solid where a file
|
|
26
|
+
proves them, dotted where inferred, and marked where the model proposed them. The pane pans and zooms with the
|
|
27
|
+
graph's own code; a card placed by hand stays placed for the project, and modules sharing a folder fold into one
|
|
28
|
+
card. The findings are listed proven first, with the scanner's hidden rules counted until asked for. The inspector
|
|
29
|
+
copies any `file:line` and copies a finding as a task. Compare with matches another project's calls against this
|
|
30
|
+
one's endpoints. On a phone, the findings and a list of the modules stand in for the pane.
|
|
31
|
+
- **A crew map of the project.** `bash .claude/eval/lib/crew-map/crew-map.sh` reads the modules (Node and TypeScript,
|
|
32
|
+
Python, Go, .NET, Java and Kotlin), the external resources they touch, the endpoints they provide and call, and
|
|
33
|
+
writes `.crewforth/crew-map.json`. Every module, line and finding cites the `file:line` it was read from, the same
|
|
34
|
+
tree gives the same bytes (`--check` holds it in CI), and a configuration value is read only to name its kind. Ten
|
|
35
|
+
gap rules: five proven by the lines they cite, five concluded from absence and hidden until their false-positive
|
|
36
|
+
rate is measured.
|
|
37
|
+
- **Findings are held to the lines they cite.** The findings core (`.claude/eval/lib/findings/findings.sh`) checks
|
|
38
|
+
every citation: the file is inside the project, the lines exist, and they are still the lines that were read. A
|
|
39
|
+
document that does not verify is reported entry by entry and never written.
|
|
40
|
+
- **A finding is verified by an agent that tries to refute it.** `crew-refuter` gets one claim and its cited lines,
|
|
41
|
+
not the reasoning, and works on one lens. `refuter-ledger.sh` records its verdict from the agent's own task and
|
|
42
|
+
answer in `.claude/state/crew-refuter.tsv`. With `--verified`, a `medium` finding needs one verdict and a `high` or
|
|
43
|
+
`critical` one three, each a line of that ledger.
|
|
44
|
+
- **`crew-docs-agent` writes the text.** README, guides, release notes, legal and privacy texts and store listings had
|
|
45
|
+
no owner and ran outside model routing. Legal, privacy, consent and terms paths and store metadata are critical
|
|
46
|
+
paths, so that text runs on the critical tier and a legal or privacy text is audited by `crew-privacy-agent` before
|
|
47
|
+
it closes.
|
|
48
|
+
- **Doctor names three more things, none of which changes its verdict.** Both editions enabled at once (every hook
|
|
49
|
+
would run twice), read from `claude plugin list --json`; the advisor, whether it is on, on what and from which
|
|
50
|
+
settings file, or turned off; and, before any update check has run, the published version, said as not measured
|
|
51
|
+
instead of nothing.
|
|
52
|
+
- **Studio shows why work was critical, and says when an agent is outside routing.** The gate records its reason
|
|
53
|
+
(`risk_why`, a new last column of `model-outcomes.tsv`) and the inspector shows it under the task card; an older
|
|
54
|
+
line shows none rather than a guessed one. An agent that is not `crew-*` gets a Model routing note: the gate leaves
|
|
55
|
+
it alone, so it has no card.
|
|
56
|
+
- **Studio counts the advisor in what a session cost.** An advisor call is billed at the advisor model's rates and the
|
|
57
|
+
API keeps it out of a response's top-level usage; Studio now reads it from `usage.iterations` and prices it at its
|
|
58
|
+
own model. The session table has an Advisor line (calls, tokens, cost) when a call is recorded. Measured on a real
|
|
59
|
+
session: Studio read $0.0567 before, $0.2110 after, the same as Claude Code's own figure.
|
|
60
|
+
- **Studio's Models view marks the classes whose agents consulted the advisor.** The cost cell carries an advisor tag
|
|
61
|
+
whose hover says how many calls and how much of the cost they were, already included; a class whose agents consulted
|
|
62
|
+
none has no tag.
|
|
63
|
+
- **Read-only remote viewers for Studio.** The Machines tab makes a viewer link that only reads, lists each viewer
|
|
64
|
+
with its last request, and revokes it. The server still binds to `127.0.0.1`; watching from another device goes
|
|
65
|
+
through a tunnel you run (`ssh -L`, Tailscale).
|
|
66
|
+
- **A visible way to the repository.** `/crew-doctor` now shows the star line once per version under its own marker,
|
|
67
|
+
so a line already shown at install no longer silences it, and a plugin install shows it too, with the plugin's
|
|
68
|
+
version. `/crew-update` keeps it to one line per update. The READMEs and the site's home page have a Star on GitHub
|
|
69
|
+
button.
|
|
70
|
+
- **A status line.** One line under the prompt: the gate's last word in this session, a commit or push approval that
|
|
71
|
+
still holds, the crew agents still running, the measured context fill and the session's cost. The installers set it
|
|
72
|
+
only where no status line is set, in the project or in your own settings, and `/crew-doctor` says which one is in
|
|
73
|
+
use.
|
|
74
|
+
- **`/crew-map`.** It runs the scanner, then has the model describe what it found: at most two sentences per module on
|
|
75
|
+
what it is for, and a short overview, each citing lines the scan itself read. `crew-map.sh --validate` refuses a
|
|
76
|
+
description that cites anything else or nothing, or a scanner field changed by hand; a scan again keeps the
|
|
77
|
+
descriptions that still hold and drops the rest. Studio's Map shows them, and `crew-planner` reads the map on an
|
|
78
|
+
unfamiliar project.
|
|
79
|
+
|
|
80
|
+
### Changed
|
|
81
|
+
|
|
82
|
+
- **A model is chosen to cost what the work needs.** Measured on a real project: 186 crew tasks, 0 on haiku, 73 (39%)
|
|
83
|
+
above their card's floor, and no verify command ever passing, so the cheaper path never opened. Now:
|
|
84
|
+
- the card's model is the default: a call above it runs on it (the gate rewrites the call's model), unless the
|
|
85
|
+
card adds `above: <why>`;
|
|
86
|
+
- outside the crew, a call asking for opus or fable runs on sonnet, and so does a general-purpose call that names
|
|
87
|
+
no model in a session that is not on haiku (it took the session's model; measured on Claude Code 2.1.299, the
|
|
88
|
+
project's settings `env` could not change that, so the gate does);
|
|
89
|
+
- a verify command in a sub-folder (`cd apps/x && <command>`, 41 of 71 refusals) is run in that folder;
|
|
90
|
+
`none (why)` is none; and `/crew-doctor` lists the commands that were never allowed to run, with the line that
|
|
91
|
+
allows each.
|
|
92
|
+
|
|
93
|
+
- **A commit's command is read by one reader.** `guard-bash.sh` paired quotes in three places: the reader of a call,
|
|
94
|
+
an older walk that looks for a path or `-a` in a commit, and the check of a call the user's approval covers. The
|
|
95
|
+
last two now take their text from the first, and keep only their own question. What a call the user approved may
|
|
96
|
+
hold is unchanged. The older walk read a here-document's body and a comment as arguments of the commit; it no
|
|
97
|
+
longer does, so a call that only holds the words of a commit inside a here-document body, or `-a` after a `#`,
|
|
98
|
+
asks as any other commit does instead of being refused.
|
|
99
|
+
- **npm releases are published over OIDC.** The release job proves its identity with a short-lived GitHub Actions
|
|
100
|
+
token (npm Trusted Publishing); the repository holds no npm token, and each version carries a provenance statement.
|
|
101
|
+
- **The session line shows the measured fill.** The last line of a reply was `🔋 Session: low fill · …`: the template
|
|
102
|
+
had no number, so the figure the hook measures every turn stayed out of sight. It is now `🔋 Session %NN → low fill ·
|
|
103
|
+
…`, the hook's own figure, never an estimate.
|
|
104
|
+
- **Studio keeps cards for a longer session.** At Auto density a picture may now run up to half again past the pane
|
|
105
|
+
before its cards become chips; it opens at the zoom cards are read at, from its top, and Fit still shows all of it.
|
|
106
|
+
A compact group card says how its agents went as well as their models (`5 done · 3 Sonnet · 2 Opus`).
|
|
107
|
+
- **The session's own write to a critical path is recorded.** Agents not on Opus are refused a critical path; the
|
|
108
|
+
session's own writes were not looked at at all. They are still not refused (the choice is yours), but each one now
|
|
109
|
+
leaves a NOTE line in the gate log with the path and the rule that made it critical, which Studio's Gates tab and
|
|
110
|
+
the status line show.
|
|
111
|
+
|
|
112
|
+
### Security
|
|
113
|
+
|
|
114
|
+
- **A `PermissionRequest` hook could approve a commit with nobody at the keyboard.** Such a hook answers a
|
|
115
|
+
permission prompt before the person does, and the answer cannot be told from a click: measured, it approved the
|
|
116
|
+
Bash prompt `guard-bash.sh` raises for a commit in `default`, and it answered the new question too. Before it
|
|
117
|
+
asks, the gate now looks for one in every source it can read (user, project and local settings, the
|
|
118
|
+
managed-settings files, skill, agent and command front matter, installed plugins). Where one may be wired the
|
|
119
|
+
question closes, and so does the gate's own prompt in `default` and `acceptEdits`: `/crew-approve`, which no hook
|
|
120
|
+
can type, is the approval left. The limit: settings passed with `--settings` and managed settings delivered by a
|
|
121
|
+
server cannot be read.
|
|
122
|
+
- **`crewforth.hookschain` is guarded the way `core.hooksPath` is.** The key holds the path of a project hook chain
|
|
123
|
+
the shim reads on every commit, and `git config crewforth.hookschain …` passed. A write is now refused in every form
|
|
124
|
+
`core.hooksPath` is (a value, `--unset`, `-c`, `--config-env`, `GIT_CONFIG_` variables); reading it still passes.
|
|
125
|
+
|
|
126
|
+
### Fixed
|
|
127
|
+
|
|
128
|
+
- **Studio keeps answering with many conversations open.** Each conversation pane held its own stream, and a
|
|
129
|
+
browser opens six connections to one host: at five panes a message sent and every request the page made waited
|
|
130
|
+
for a pane to close (on Windows a send did not arrive in 35 s; on macOS the page's own request timed out at 4 s).
|
|
131
|
+
Every open conversation now shares one stream, resumed from each session's last event when it reconnects.
|
|
132
|
+
- **Studio finds sessions under a moved config dir.** It read `~/.claude/projects` only, so sessions under
|
|
133
|
+
`CLAUDE_CONFIG_DIR` were not listed and read a cost of 0. It now reads `projects` there, as Claude Code writes.
|
|
134
|
+
- **Studio says when it needs a restart.** A running server keeps the code it started with, and an update
|
|
135
|
+
replaces the files the page is read from: on a real project the Map view of the new page asked a server from
|
|
136
|
+
before it and showed "Not read — HTTP 404". The server now says whether its code changed on disk since it
|
|
137
|
+
started; a page that hears so, or talks to a server too old to say, shows a note to restart it, and Map says the
|
|
138
|
+
same instead of the 404.
|
|
139
|
+
- **Two agents starting together no longer share one model record on Windows.** A record was taken by renaming
|
|
140
|
+
it, which is a lock on macOS and Linux; on Windows two hook processes both reported the rename as done (seen
|
|
141
|
+
twice on the Windows CI). Each record is now locked first with an exclusive create, a shell builtin that costs no
|
|
142
|
+
process, and only the hook that made the lock takes it.
|
|
143
|
+
- **An rc says it is one, and its final is offered.** A release candidate installed `.claude/VERSION` as the final's
|
|
144
|
+
number (3.2.0 for 3.2.0-rc.1), so the update check, doctor and the refresh's "what's new" all read it as the final,
|
|
145
|
+
and someone who tried the rc was never told the final shipped. The rc's archive and npm package now carry its own
|
|
146
|
+
version, and one definition (`eval/lib/version.sh`) orders an rc before its final. A version off the network is
|
|
147
|
+
still held to X.Y.Z.
|
|
148
|
+
- **`adopt.sh --help` prints its usage.** It ran the project detection instead; the usage now comes in English and
|
|
149
|
+
Turkish, before anything is read.
|
|
150
|
+
- **The crew map reads what two real projects showed it missing.** Scanned before release, they put three rules
|
|
151
|
+
well over a 20% false-positive rate, and one scan refused its own document. Read now: a route with an empty path,
|
|
152
|
+
a decorator whose path is on the next line, `api.get<T>(` and a call split over lines, a client made in one file
|
|
153
|
+
and called in another (it had read as a server), an import ending in a comment, twelve more import names, and a
|
|
154
|
+
string in a test that looks like an import. A call with a run-time host is matched but never reported missing. A
|
|
155
|
+
route a healthcheck or a Kubernetes probe calls has a caller, and a package that works without an import (a
|
|
156
|
+
server started from the command line, a database driver named in a URL, a pytest plugin) is not unused.
|
|
157
|
+
Source in a language the scanner has no reader for, and routes registered with a variable path, are listed in
|
|
158
|
+
`notMeasured` instead of being silently absent. On the Python project the proven `endpoint-missing` went from 2
|
|
159
|
+
real out of 10 to 4 out of 4.
|
|
160
|
+
- **Studio's cards no longer flicker while a window is resized.** At Auto density, an edge dragged across the limit
|
|
161
|
+
between cards and chips redrew every card on every frame (measured: 57 times in 60 frames with 43 agents). The view
|
|
162
|
+
still follows the edge at once; the choice between cards and chips is made once the window has stopped for 150 ms.
|
|
163
|
+
- **`crew-commit-agent` and `crew-session-manager` are called.** Both were exempt from the delegation cue and nothing
|
|
164
|
+
pulled them, so the main thread wrote every commit message and handover itself. The discipline and `/crew-handoff`
|
|
165
|
+
now call them, and smoke fails when a chain-step agent has no caller.
|
|
166
|
+
- **Doctor names the 2.x plugin enabled beside a 3.x install.** The 2.x plugin, under its old name, wires the same
|
|
167
|
+
hooks; the check looked for `crewforth@…` only and said one edition while every hook ran twice.
|
|
168
|
+
- **The crew map no longer reads a regex literal as an import.** `from '[^']*…` inside a regular expression was
|
|
169
|
+
reported as a proven undeclared dependency named `[^`; a specifier counts as a package only when it is named the way
|
|
170
|
+
npm names one.
|
|
171
|
+
- **A cache write the usage split leaves out is counted.** Studio dropped cache writes that the top-level split of a
|
|
172
|
+
response did not account for; they are now the five-minute kind, which is how they were billed.
|
|
173
|
+
- **Doctor's advisor lines match how Claude Code attaches it.** An advisor below the model it would advise is not
|
|
174
|
+
attached at all, so critical work runs without one; the warning said it would advise a stronger model.
|
|
175
|
+
- **`incident-runbook` is picked for an outage that keeps coming back.** Its description named only a production that
|
|
176
|
+
is degraded or broken; a request about a recurring outage picked it in none of three held-out eval runs before, and
|
|
177
|
+
in two of three after.
|
|
178
|
+
|
|
8
179
|
## [3.1.1] — 2026-10-12
|
|
9
180
|
|
|
10
181
|
### Fixed
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<p align="center"><img src="https://raw.githubusercontent.com/Crewforth/crewforth/main/assets/logo.svg" alt="Crewforth" width="420"></p>
|
|
2
2
|
|
|
3
|
-
**Crewforth is your engineering crew for Claude Code.** It adds subagents, skills, commands and hooks to Claude Code:
|
|
3
|
+
**Crewforth is your engineering crew for Claude Code.** It adds subagents, skills, commands and hooks to Claude Code: 14 specialist agents that each own a domain, 40 skills that hold the method, 13 commands you start with `/crew-…`, and hooks that enforce the rules that matter.
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
6
|
npx crewforth init # set up a new project
|
|
@@ -13,6 +13,7 @@ Then open Claude Code and run `/crew-doctor` to confirm the setup. Requires bash
|
|
|
13
13
|
|
|
14
14
|
[](https://www.npmjs.com/package/crewforth)
|
|
15
15
|
[](https://github.com/Crewforth/crewforth/blob/main/LICENSE)
|
|
16
|
+
[](https://github.com/Crewforth/crewforth)
|
|
16
17
|
|
|
17
18
|
<picture>
|
|
18
19
|
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/Crewforth/crewforth/main/assets/flow-en-dark.svg">
|
|
@@ -28,9 +29,9 @@ Then open Claude Code and run `/crew-doctor` to confirm the setup. Requires bash
|
|
|
28
29
|
|
|
29
30
|
## What you get
|
|
30
31
|
|
|
31
|
-
- **
|
|
32
|
+
- **14 specialist agents**, from `crew-planner` to `crew-commit-agent`, each owning one domain.
|
|
32
33
|
- **40 skills** holding the method: testing, migrations, API contracts, observability, accessibility, deployment.
|
|
33
|
-
- **
|
|
34
|
+
- **13 commands**, each started with its `/crew-…` name: `/crew-plan`, `/crew-review`, `/crew-ship`, `/crew-handoff`, `/crew-brainstorm`, `/crew-update`, `/crew-doctor`, `/crew-gates`, `/crew-skill`, `/crew-studio`, `/crew-approve`, `/crew-loosen`, `/crew-map`.
|
|
34
35
|
- In `auto` mode a commit or a push waits for you: type `/crew-approve` and what was just refused is approved, tied to what is staged.
|
|
35
36
|
- **Safe adoption.** `adopt` lands everything on a branch, staged and uncommitted; `main` is never touched.
|
|
36
37
|
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.
|
|
1
|
+
3.2.0-rc.2
|
package/adopt.sh
CHANGED
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
set -uo pipefail
|
|
12
12
|
# The 2.x names of the variables a user can set still work (one helper: eval/lib/crew-env.sh).
|
|
13
13
|
_crew_d="${BASH_SOURCE%/*}"; [ "$_crew_d" = "${BASH_SOURCE}" ] && _crew_d=.
|
|
14
|
-
[ -f "$_crew_d/kit/eval/lib/crew-env.sh" ] && . "$_crew_d/kit/eval/lib/crew-env.sh"
|
|
14
|
+
[ -f "$_crew_d/kit/eval/lib/crew-env.sh" ] && . "$_crew_d/kit/eval/lib/crew-env.sh"
|
|
15
|
+
[ -f "$_crew_d/kit/eval/lib/version.sh" ] && . "$_crew_d/kit/eval/lib/version.sh"; unset _crew_d # an rc orders before its final
|
|
15
16
|
HERE="$(CDPATH= cd "$(dirname "$0")" && pwd)"
|
|
16
17
|
|
|
17
18
|
# --version (or -v) is answered first, before the payload check below: it reads only VERSION, so it works
|
|
@@ -23,6 +24,44 @@ for _a in "$@"; do
|
|
|
23
24
|
fi
|
|
24
25
|
done
|
|
25
26
|
|
|
27
|
+
# --help (or -h) is answered here too, before anything is read: an unknown flag is ignored further down, so without
|
|
28
|
+
# this `adopt.sh --help` ran the detection instead of saying what the script does. The language comes from --lang or
|
|
29
|
+
# CREW_LANG; the rest of the script asks for it later, which is too late for a help text.
|
|
30
|
+
_hl="${CREW_LANG:-}"; _hh=0; _ht=0
|
|
31
|
+
for _a in "$@"; do
|
|
32
|
+
if [ "$_ht" = 1 ]; then _ht=0; _hl="$_a"; continue; fi
|
|
33
|
+
case "$_a" in -h|--help) _hh=1 ;; --lang) _ht=1 ;; --lang=*) _hl="${_a#--lang=}" ;; esac
|
|
34
|
+
done
|
|
35
|
+
if [ "$_hh" = 1 ]; then
|
|
36
|
+
if [ "$_hl" = tr ]; then
|
|
37
|
+
cat <<'USAGE_TR'
|
|
38
|
+
Kullanım: bash adopt.sh [SEÇENEKLER] (ya da: npx crewforth adopt [SEÇENEKLER])
|
|
39
|
+
Crewforth'u MEVCUT bir projeye kurar ya da kurulu olanı yeniler. Önce projeyi okur ve ne yapacağını gösterir;
|
|
40
|
+
projenin kendi dosyalarına, hook'larına ve status line'ına dokunmaz. Değişiklikleri hazırlar (stage), commit atmaz.
|
|
41
|
+
--here değişiklikleri şu anki dalda yap
|
|
42
|
+
--new-branch değişiklikleri yeni bir inceleme dalında yap (ilk kurulumda varsayılan)
|
|
43
|
+
--yes, -y her soruya evet de (gözetimsiz kurulum)
|
|
44
|
+
--lang tr|en dil (verilmezse sorulur)
|
|
45
|
+
--version, -v Crewforth sürümünü yazdırıp çık
|
|
46
|
+
--help, -h bu metni yazdırıp çık
|
|
47
|
+
USAGE_TR
|
|
48
|
+
else
|
|
49
|
+
cat <<'USAGE'
|
|
50
|
+
Usage: bash adopt.sh [OPTIONS] (or: npx crewforth adopt [OPTIONS])
|
|
51
|
+
Installs Crewforth into an EXISTING project, or refreshes an install. It reads the project first and shows what it
|
|
52
|
+
will do; the project's own files, hooks and status line are left alone. Changes are staged, never committed.
|
|
53
|
+
--here make the changes on the current branch
|
|
54
|
+
--new-branch make the changes on a fresh review branch (the default for a first adopt)
|
|
55
|
+
--yes, -y answer yes at every gate (unattended)
|
|
56
|
+
--lang tr|en language (asked when not given)
|
|
57
|
+
--version, -v print Crewforth's version and exit
|
|
58
|
+
--help, -h print this text and exit
|
|
59
|
+
USAGE
|
|
60
|
+
fi
|
|
61
|
+
exit 0
|
|
62
|
+
fi
|
|
63
|
+
unset _hl _hh _ht
|
|
64
|
+
|
|
26
65
|
SRC="$HERE/kit"
|
|
27
66
|
[ -d "$SRC" ] || { echo "ERROR: kit/ not found (must be in the same directory as adopt.sh)."; exit 1; }
|
|
28
67
|
|
|
@@ -273,6 +312,8 @@ _mt() { # $1 = English text (the key); further args fill %s; result in _M
|
|
|
273
312
|
"custom hooks and every other permission PRESERVED") s="özel hook'lar ve diğer tüm izinler KORUNDU" ;;
|
|
274
313
|
"custom hooks/permissions PRESERVED") s="özel hook'lar ve izinler KORUNDU" ;;
|
|
275
314
|
"settings.json: was missing in the project -> Crewforth's was installed") s="settings.json: projede yoktu -> Crewforth'unki kuruldu" ;;
|
|
315
|
+
"Status line: Crewforth's (the gate's last word, a standing approval, crew agents, fill, cost).") s="Durum satırı: Crewforth'unki (kapının son sözü, geçerli onay, crew ajanları, doluluk, maliyet)." ;;
|
|
316
|
+
"Status line: yours is kept; Crewforth's is one command away (see /crew-doctor).") s="Durum satırı: seninki korundu; Crewforth'unki tek komutla açılır (/crew-doctor'a bak)." ;;
|
|
276
317
|
"settings.json: hook-aware MERGE (Crewforth hooks refreshed - %s)") s="settings.json: hook'ları gözeten BİRLEŞTİRME (Crewforth hook'ları yenilendi - %s)" ;;
|
|
277
318
|
"settings.json: %s") s='settings.json: %s' ;;
|
|
278
319
|
"merge failed -> project setting PRESERVED (not overwritten)") s='birleştirme başarısız -> proje ayarı KORUNDU (üzerine yazılmadı)' ;;
|
|
@@ -1538,14 +1579,15 @@ fi
|
|
|
1538
1579
|
# A fresh adopt has no "before", so it gets no file (and a stale one from an earlier update is removed).
|
|
1539
1580
|
rm -f .claude/.state/whats-new.md 2>/dev/null
|
|
1540
1581
|
_kv="$(printf '%s' "$KIT_VER" | tr -d '\r')"
|
|
1541
|
-
|
|
1582
|
+
_kv="$(crew_local_version "$_kv" 2>/dev/null)" || _kv="" # an odd old version compares as 0.0.0 — every section would look new
|
|
1542
1583
|
if [ "$KIT_PRESENT" = 1 ] && [ -n "$_kv" ] && [ -f "$HERE/CHANGELOG.md" ] && [ -f "$HERE/VERSION" ]; then
|
|
1543
1584
|
mkdir -p .claude/.state 2>/dev/null
|
|
1544
|
-
|
|
1545
|
-
|
|
1585
|
+
# The upper bound is the target's X.Y.Z: an rc's notes are its final's section ("[Unreleased] — 3.2.0").
|
|
1586
|
+
awk -v from="$_kv" -v to="$(head -1 "$HERE/VERSION" | tr -d '\r')" "${CREW_VCMP_AWK:-}"'
|
|
1587
|
+
BEGIN { sub(/-.*/, "", to) }
|
|
1546
1588
|
/^## \[/ { v=$0; sub(/^## \[/,"",v); w=v; sub(/\].*/,"",v)
|
|
1547
1589
|
if (v=="Unreleased") { v=w; sub(/^[^—]*— */,"",v); sub(/[^0-9.].*/,"",v) }
|
|
1548
|
-
keep = (v ~ /^[0-9]+\.[0-9]+\.[0-9]+$/ &&
|
|
1590
|
+
keep = (v ~ /^[0-9]+\.[0-9]+\.[0-9]+$/ && vcmp(v,from)>0 && vcmp(v,to)<=0) }
|
|
1549
1591
|
keep' "$HERE/CHANGELOG.md" | tr -d '\r' > .claude/.state/whats-new.md 2>/dev/null
|
|
1550
1592
|
[ -s .claude/.state/whats-new.md ] || rm -f .claude/.state/whats-new.md
|
|
1551
1593
|
fi
|
|
@@ -1673,6 +1715,15 @@ if [ -n "$SET_NOTE" ]; then HAND_SET="NOT merged — ${SET_NOTE%.}"
|
|
|
1673
1715
|
elif [ "$SET_FRESH" = 1 ]; then HAND_SET="Crewforth's settings.json installed (the project had none, so nothing was merged)"
|
|
1674
1716
|
else HAND_SET="hook-aware merge (Crewforth hooks REFRESHED to current — new events + timeouts land; your own custom hooks/permissions PRESERVED${RET_GONE:+, except the retired §4.4 ask rule(s) REMOVED: $RET_GONE — guard-bash.sh asks for these itself})"; fi
|
|
1675
1717
|
|
|
1718
|
+
# The status line, only where none is set (a user's own would lose to the project's setting, so it is never
|
|
1719
|
+
# replaced). eval/lib/statusline.sh --install decides and writes; this only says what it did.
|
|
1720
|
+
if [ -f .claude/eval/lib/statusline.sh ]; then
|
|
1721
|
+
case "$(bash .claude/eval/lib/statusline.sh --install 2>/dev/null)" in
|
|
1722
|
+
installed) say "Status line: Crewforth's (the gate's last word, a standing approval, crew agents, fill, cost)." ;;
|
|
1723
|
+
kept) say "Status line: yours is kept; Crewforth's is one command away (see /crew-doctor)." ;;
|
|
1724
|
+
esac
|
|
1725
|
+
fi
|
|
1726
|
+
|
|
1676
1727
|
# ============ [STAGE 4] GIT-HOOK ARMING (SHIM) + PROOF ============
|
|
1677
1728
|
h1m 'Stage 4 — arm the git gates (SHIM via husky) + PROOF'
|
|
1678
1729
|
|
package/kit/AGENT_TEMPLATE.md
CHANGED
|
@@ -49,7 +49,8 @@ verify: npm test -- orders
|
|
|
49
49
|
`architecture` · `test-run` · `test-write` · `audit`. `verify` is the command that proves the work, or `none`.
|
|
50
50
|
|
|
51
51
|
**Risk class.** `critical` when the change is `migration`, `security`, `architecture` or `fix-unknown`, or a file is
|
|
52
|
-
on a critical path (auth, payments, billing, migrations, security, crypto, secrets,
|
|
52
|
+
on a critical path (auth, payments, billing, migrations, security, crypto, secrets, legal, privacy, consent, terms,
|
|
53
|
+
`*.sql`, `schema.prisma`, store-listing text under `store/` or `fastlane/metadata/`; the
|
|
53
54
|
project's own are listed in `.claude/state/crew-critical-paths.auto`, and `.claude/crew-model-rules` adds or removes).
|
|
54
55
|
Otherwise `normal`.
|
|
55
56
|
|
package/kit/CLAUDE.md
CHANGED
|
@@ -34,12 +34,13 @@ recommend, with the rationale.**
|
|
|
34
34
|
code — RISK decides, not size: behaviour changes and a subagent's diff review go to the owner.
|
|
35
35
|
|
|
36
36
|
**Classify before the first tool call:** name the DOMAIN in your own words, then read its owner from
|
|
37
|
-
`.claude/agents/`. Classify *intent*,
|
|
37
|
+
`.claude/agents/`. Classify *intent*, not wording, in any language.
|
|
38
38
|
What the user sees → **crew-frontend-expert** · server behaviour → **crew-backend-expert** · stored data →
|
|
39
39
|
**crew-database-expert** · run/deploy/CI → **crew-devops-expert** · **crew-security-expert** ·
|
|
40
|
-
**crew-privacy-agent** (personal data) · **crew-test-expert** · **crew-performance-expert** ·
|
|
40
|
+
**crew-privacy-agent** (personal data) · **crew-test-expert** · **crew-performance-expert** · docs/legal/store
|
|
41
|
+
text → **crew-docs-agent** · what to build →
|
|
41
42
|
**crew-planner** · unknown cause → **general-purpose** + `systematic-debugging`. Two domains → delegate in
|
|
42
|
-
sequence.
|
|
43
|
+
sequence. All are installed: "no owner" is an `ls`.
|
|
43
44
|
|
|
44
45
|
1. **Diagnose, then plan** — unknown cause → `systematic-debugging` first; unclear scope → **crew-planner** (`/crew-plan`).
|
|
45
46
|
2. **Produce** — the domain owner above.
|
|
@@ -49,21 +50,21 @@ sequence. Every agent above is installed; "no owner" is an `ls`, not a default.
|
|
|
49
50
|
A finding or a red test goes back to the owner that wrote the code, and after the fix **all of them run
|
|
50
51
|
again**: the diff they cleared no longer exists.
|
|
51
52
|
4. **Close — only once 3 is clean.** DoD → **crew-review-agent** (LAST, never first) clean → **crew-commit-agent**
|
|
52
|
-
|
|
53
|
-
5. **Hand off** — phase boundary or
|
|
53
|
+
writes the message, not you; waits for approval (`/crew-ship`); held items close here.
|
|
54
|
+
5. **Hand off** — phase boundary or 🔋 ≥ medium → **crew-session-manager** → `handoff` → `/clear` (`/crew-handoff`).
|
|
54
55
|
|
|
55
56
|
**Model per call — RISK decides, not size.** A `crew-*` task opens with its card, and the call names `model`:
|
|
56
57
|
`files:` files/globs · `change:` text|feature|fix-known|fix-unknown|refactor|migration|security|architecture|test-run|test-write|audit
|
|
57
|
-
· `verify:` the command that proves it, or `none`. **crew-planner** writes the card
|
|
58
|
+
· `verify:` the command that proves it, or `none`. **crew-planner** writes the card, or you do.
|
|
58
59
|
|
|
59
|
-
| `model` | the card |
|
|
60
|
+
| `model` (`guard-agent-model.sh`: floor = default; `above: <why>` for more) | the card |
|
|
60
61
|
|---|---|
|
|
61
|
-
| `haiku` | text, test-run, mechanical work — only with
|
|
62
|
+
| `haiku` | text, test-run, mechanical work — only with `verify:` |
|
|
62
63
|
| `sonnet` | feature, fix-known, refactor, test-write, audit, review; anything with `verify: none` |
|
|
63
|
-
| `opus` | **critical**: migration, security, architecture, fix-unknown, or a
|
|
64
|
+
| `opus` | **critical**: migration, security, architecture, fix-unknown, or a critical-path file (auth, payments, migrations…) — its test-write, audit, review too |
|
|
64
65
|
|
|
65
66
|
The referee follows the RISK, not the author's model. Verify fails → the agent fixes once; again → re-run ONCE one
|
|
66
|
-
model up; again → AskUserQuestion. The same for a report that ends `confidence: low`.
|
|
67
|
+
model up; again → AskUserQuestion. The same for a report that ends `confidence: low`.
|
|
67
68
|
|
|
68
69
|
**Naming an agent in prose is a hope; `@agent-<name>` is a guarantee** — measured here: 0/3 vs 3/3. Use that form
|
|
69
70
|
whenever an agent must run, and tell the user they can too.
|
|
@@ -126,9 +127,9 @@ more tokens, because each one re-pays for its own context — plan for that.
|
|
|
126
127
|
> **Honest boundary.** Measuring fill **is a gate** (`context-usage.sh` + `session-guard.sh`). The four bullets above
|
|
127
128
|
> are **model discipline** — no exit code can judge a delegate-or-not call, so they rest on your reasoning.
|
|
128
129
|
|
|
129
|
-
## Session
|
|
130
|
-
Last line of a reply, after the next step: `🔋 Session
|
|
131
|
-
— **only
|
|
130
|
+
## Session status line
|
|
131
|
+
Last line of a reply, after the next step: `🔋 Session %NN → [low/medium/high] fill · Recommendation: [continue / handoff+clear / new session]`
|
|
132
|
+
— **only with a reading** (%NN is its measured figure); with none, omit the line.
|
|
132
133
|
|
|
133
134
|
**Never guess the fill.** You cannot run `/context`; the `UserPromptSubmit` hook injects the measured line
|
|
134
135
|
`🔋 Session %NN.N → level` every turn (`input + cache_read + cache_creation` = the `/context` figure). Use it. Exact
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
name: crew-commit-agent
|
|
3
3
|
color: cyan
|
|
4
4
|
description: |
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
Use immediately after the DoD is clean, before any git commit: proposes the Conventional Commits message
|
|
6
|
+
from the staged diff (`commit-message`). Commits only with user approval.
|
|
7
7
|
tools: Read, Grep, Glob, Bash, PowerShell
|
|
8
8
|
model: haiku
|
|
9
9
|
metadata:
|
|
@@ -102,6 +102,11 @@ write is refused because the file is on a critical path, do not reach it another
|
|
|
102
102
|
`/crew-approve push` or `/crew-approve commit+push`. The user approves by sending
|
|
103
103
|
that command alone; a sentence that says yes is not an approval, and you cannot run `/crew-approve` for them. It covers what is staged on that HEAD. If the gate says the approval path is closed in this session (the
|
|
104
104
|
recording hook is not wired), say so and offer Shift+Tab or their own terminal instead.
|
|
105
|
+
In `auto` the refusal may also offer the approval question: show the message, then call AskUserQuestion with
|
|
106
|
+
exactly the input the refusal prints (the fixed question and its four answers, no answers of your own). The
|
|
107
|
+
user's click is recorded the same way; read the line Crewforth adds and run what it names. Where a
|
|
108
|
+
`PermissionRequest` hook may be wired the gate closes the question, and in `default` / `acceptEdits` its own
|
|
109
|
+
prompt too, because such a hook can answer either before the user does: then `/crew-approve` is the way.
|
|
105
110
|
Then run `git commit -m '…'` alone in its call (single-quoted, or from a here-document with a quoted delimiter),
|
|
106
111
|
and a push as `git push <remote> <branch>`. Never write that message yourself. Under `plan` and
|
|
107
112
|
`bypassPermissions` the gate fails closed; there the user must switch modes or pre-authorise with
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: crew-docs-agent
|
|
3
|
+
color: yellow
|
|
4
|
+
description: |
|
|
5
|
+
Use proactively for docs: README, guides, release notes, legal, privacy and store texts. Writes no code.
|
|
6
|
+
tools: Read, Grep, Glob, Edit, Write
|
|
7
|
+
metadata:
|
|
8
|
+
stage: produce
|
|
9
|
+
skills: [docs-writer, i18n-integrity]
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Docs Agent
|
|
13
|
+
|
|
14
|
+
<!-- routing-eval reads the next line; why it sits in the body: AGENT_TEMPLATE.md -->
|
|
15
|
+
Trigger phrases: "readme", "user guide", "release notes", "changelog entry", "privacy policy", "terms of service", "terms of use", "cookie notice", "consent text", "legal text", "store listing", "app store description", "play store description", "documentation page"
|
|
16
|
+
|
|
17
|
+
Writes the text; the `docs-writer` skill holds how. Code is someone else's: a sentence inside a component goes to its
|
|
18
|
+
owner, a document beside it comes here.
|
|
19
|
+
|
|
20
|
+
## Expertise stance (technical writer who has been sued once)
|
|
21
|
+
- **Every claim is checkable.** A number, a flag, a behaviour is read from the code or the tool's own documentation
|
|
22
|
+
before it is written; what could not be checked is written as not checked, or left out.
|
|
23
|
+
- **The reader acts on it.** Lead with what they do, then why; one idea per paragraph, no history in a guide.
|
|
24
|
+
- **Legal and privacy text is not paraphrased into a promise.** It says what the product does, measured from the code
|
|
25
|
+
and the data flow, and nothing the product does not do. Anything that reads as a legal commitment the code does
|
|
26
|
+
not back goes to the user before it is written.
|
|
27
|
+
- **Both languages or neither.** A text the project ships in two languages changes in both in the same change
|
|
28
|
+
(`i18n-integrity`).
|
|
29
|
+
|
|
30
|
+
## When
|
|
31
|
+
README, guides, docs pages, release notes and CHANGELOG, legal and privacy texts (`legal/`, `privacy*`, `terms*`,
|
|
32
|
+
`consent*`), store listings (`fastlane/metadata/`, `store/`, `store-listing/`, `metadata/android|ios/`).
|
|
33
|
+
|
|
34
|
+
## How (follow its skill)
|
|
35
|
+
`docs-writer`: structure, what a README states and what it does not, the voice. `i18n-integrity` when the text has a
|
|
36
|
+
translation. The model follows the RISK: legal, privacy and store texts are critical paths, so their card runs on
|
|
37
|
+
the critical tier and the write itself is refused on a lower model.
|
|
38
|
+
|
|
39
|
+
## Coordination (cross-agent)
|
|
40
|
+
- A legal or privacy text is audited by **crew-privacy-agent** before it closes: what the text says against what the
|
|
41
|
+
code collects, keeps and shares.
|
|
42
|
+
- A sentence about behaviour the code does not have goes to the owner of that code first, not into the text.
|
|
43
|
+
|
|
44
|
+
## DoD
|
|
45
|
+
Every checkable statement checked; translations in step; the audit above clean for a legal or privacy text.
|
|
46
|
+
|
|
47
|
+
## Output & context (token)
|
|
48
|
+
To the main thread: what changed, in which files, and every statement that could not be checked. Not the text itself.
|
|
49
|
+
|
|
50
|
+
## Errors/escalation
|
|
51
|
+
A claim the code contradicts, or a legal commitment nobody has decided: stop and report it, do not soften it into
|
|
52
|
+
the text.
|
|
53
|
+
|
|
54
|
+
## Example delegation
|
|
55
|
+
- ✅ "update the privacy policy for the new retention period"
|
|
56
|
+
- ❌ "add a consent checkbox to the signup form" (UI: crew-frontend-expert)
|
|
57
|
+
|
|
58
|
+
## Confidence
|
|
59
|
+
The LAST line of every report is exactly `confidence: high` or exactly `confidence: low`: lower case, nothing else
|
|
60
|
+
on the line, nothing after it. `low` when you guessed, could not verify, or the task was above the model this run
|
|
61
|
+
was given; the caller then repeats it once, one model up. Your task opens with a card (`files:`, `change:`,
|
|
62
|
+
`verify:`): the `verify` command is run when you stop, and if it fails you are asked once to fix the work. If a
|
|
63
|
+
write is refused because the file is on a critical path, do not reach it another way: stop, and put
|
|
64
|
+
`escalate: <the file>` on the line before `confidence: low`.
|
|
65
|
+
|
|
66
|
+
## Constraints
|
|
67
|
+
- Writes text files only; no source, no configuration, no build files.
|
|
68
|
+
- Does not invent a policy: what the product does is read from the code, what it should do is the user's decision.
|
|
69
|
+
|
|
70
|
+
## Prohibitions (absolute)
|
|
71
|
+
CLAUDE.md §4 applies: no AI trace, no third-party template name, nothing under `docs/` named in a shipped text.
|
|
@@ -33,6 +33,8 @@ before planning. You are read-only: when it ends at "ask", return its questions
|
|
|
33
33
|
decision — the main thread asks and records the answer.
|
|
34
34
|
|
|
35
35
|
## How (applies the `spec-planning` skill)
|
|
36
|
+
- On an unfamiliar project, read `.crewforth/crew-map.json` first when it exists (its modules, what they touch,
|
|
37
|
+
the gaps, each with the lines it rests on); with none, `/crew-map` writes one, and that is the user's call.
|
|
36
38
|
- Define the problem in a single sentence; clarify what is in scope and out of scope.
|
|
37
39
|
- Break tasks into atomic steps; derive the dependency order.
|
|
38
40
|
- For each step, write acceptance criteria (how "done" is judged).
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: crew-refuter
|
|
3
|
+
color: gray
|
|
4
|
+
description: |
|
|
5
|
+
Use proactively on each medium+ finding before it is reported: given one claim and its file:line, refutes it.
|
|
6
|
+
tools: Read, Grep, Glob
|
|
7
|
+
metadata:
|
|
8
|
+
stage: audit
|
|
9
|
+
skills: [security-scan]
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Refuter
|
|
13
|
+
|
|
14
|
+
<!-- routing-eval reads the next line; why it sits in the body: AGENT_TEMPLATE.md -->
|
|
15
|
+
Trigger phrases: "refute this finding", "disprove this claim", "try to prove it wrong", "verify this finding independently", "is this finding a false positive"
|
|
16
|
+
|
|
17
|
+
Read-only. A fresh context is the point: it has not seen the reasoning that produced the finding, so it cannot
|
|
18
|
+
inherit its blind spot. The method is `security-scan` → `references/verify.md`.
|
|
19
|
+
|
|
20
|
+
## When
|
|
21
|
+
After discovery, before a finding is written to a report or a findings document. Every finding of `medium` or
|
|
22
|
+
higher severity goes through it; `critical` and `high` through three calls, each on a different lens.
|
|
23
|
+
|
|
24
|
+
## Expertise stance (the colleague whose job is to find the hole in your argument)
|
|
25
|
+
- **Starts from the cited lines, never from the summary.** Reads the code at `cite:` first and only then the claim.
|
|
26
|
+
- **Hunts for why the claim is false**: unreachable input, a guard on every path, a test or dead file, a control
|
|
27
|
+
the claim did not look for. Agreement is what is left when that search fails, not where it starts.
|
|
28
|
+
- **One lens, held to it**: reachability, protection, reproduction, exclusion or blast-radius — the one it is given.
|
|
29
|
+
- **Names the missing fact** instead of guessing: a verdict it cannot reach from the repository is CANNOT_VERIFY.
|
|
30
|
+
|
|
31
|
+
## How (follow its skill)
|
|
32
|
+
`security-scan` → `references/verify.md`: the verifier stance, the lens, the three verdicts and the exclusion
|
|
33
|
+
rules. The task it is given is exactly this, and nothing of the caller's reasoning. It opens with the card every
|
|
34
|
+
crew agent is called with (`change: audit`, so the model follows the risk of the cited file):
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
files: <the cited file>
|
|
38
|
+
change: audit
|
|
39
|
+
verify: none
|
|
40
|
+
finding: <the finding's id in the findings document>
|
|
41
|
+
lens: reachability | protection | reproduction | exclusion | blast-radius
|
|
42
|
+
cite: <file>:<line>
|
|
43
|
+
claim: <one sentence>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Output & context (token)
|
|
47
|
+
Its last lines are read by `hooks/refuter-ledger.sh`, which records the verdict against the finding and lens of
|
|
48
|
+
the task it was given, so they are exactly:
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
FINDING: <id>
|
|
52
|
+
LENS: <lens>
|
|
53
|
+
VERDICT: TRUE_POSITIVE | FALSE_POSITIVE | CANNOT_VERIFY
|
|
54
|
+
REASON: <one or two sentences, citing file:line>
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Confidence
|
|
58
|
+
The LAST line of every report is exactly `confidence: high` or exactly `confidence: low`: lower case, nothing else
|
|
59
|
+
on the line, nothing after it. `low` when you guessed or could not read what the claim needs; the caller then
|
|
60
|
+
repeats the call once, one model up. Your task opens with a card (`files:`, `change: audit`, `verify: none`), so
|
|
61
|
+
nothing is run when you stop. The `FINDING`, `LENS`, `VERDICT` and `REASON` lines come before it.
|
|
62
|
+
|
|
63
|
+
## Errors/escalation
|
|
64
|
+
A task without `finding:`, `lens:` and `cite:` is answered with `VERDICT: CANNOT_VERIFY` and the reason, never
|
|
65
|
+
with a guess; the ledger records nothing for it.
|
|
66
|
+
|
|
67
|
+
## Example delegation
|
|
68
|
+
- ✅ "finding: sec-idor-orders · lens: protection · cite: src/orders.ts:88 · claim: any user can read any order"
|
|
69
|
+
- ❌ "audit the orders module for security issues" (discovery: crew-security-expert)
|
|
70
|
+
|
|
71
|
+
## Constraints
|
|
72
|
+
- Read-only: no Edit, no Write, no Bash, and no `Agent`, so it cannot hand the question to a context that has
|
|
73
|
+
seen more than it should.
|
|
74
|
+
- One claim per call. The caller runs the calls of one finding in parallel, never in one context.
|
|
75
|
+
- HONEST SCOPE: what keeps the record true is the hook writing the ledger from this agent's own task and answer;
|
|
76
|
+
what keeps the answer independent is that the caller gave it the claim and not the reasoning, which is model
|
|
77
|
+
discipline.
|
|
@@ -27,7 +27,7 @@ Read-only auditor. The relevant expert (backend/database) makes the fix; this ag
|
|
|
27
27
|
- **Prove** each finding: how it's exploited + impact + fix; not a theoretical warning.
|
|
28
28
|
- Assign a **severity** to every finding; high-impact first — **derived from preconditions × access, not the category** ("real" is not "critical").
|
|
29
29
|
- **Defense in depth**: don't rely on a single control; add layers.
|
|
30
|
-
- **Signal, not noise**: every candidate goes through the **adversarial verify pass** (N independent verifiers that start from the code and hunt for why it's *wrong* → TRUE_POSITIVE / FALSE_POSITIVE / CANNOT_VERIFY). See `security-scan` → `references/verify.md`.
|
|
30
|
+
- **Signal, not noise**: every candidate goes through the **adversarial verify pass** (N independent verifiers that start from the code and hunt for why it's *wrong* → TRUE_POSITIVE / FALSE_POSITIVE / CANNOT_VERIFY). See `security-scan` → `references/verify.md`. This agent has no `Agent` tool: it returns the candidates, and the session runs one **crew-refuter** per finding and lens.
|
|
31
31
|
|
|
32
32
|
## When
|
|
33
33
|
On changes touching auth, token/credential, externally exposed endpoints, or sensitive data.
|
|
@@ -52,6 +52,8 @@ Each finding: `file:line · risk · suggested fix`, or a "clean on this axis" ra
|
|
|
52
52
|
|
|
53
53
|
## Output & context (token)
|
|
54
54
|
To the main thread: a **severity-ranked findings summary** (area · severity · fix). Full scan output → `docs/SECURITY_FINDINGS.md`, returns a summary + count.
|
|
55
|
+
The candidates also go out as a findings document (`kit/eval/lib/findings`, one `id` and `file:line` evidence each) for the session to verify; the
|
|
56
|
+
verified one is stored with `findings.sh write --verified security <file>` (`eval/lib/findings/` in either edition), which refuses a `medium`-or-higher finding without its refuters.
|
|
55
57
|
|
|
56
58
|
## Errors/escalation
|
|
57
59
|
On an exploitable CRITICAL finding, **warn clearly**; don't report a finding you're unsure of as 'certain', add a verifiability note.
|