crewforth 3.1.1 → 3.2.0-rc.10
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 +323 -0
- package/README.md +6 -3
- package/VERSION +1 -1
- package/adopt.sh +66 -6
- package/bin/cli.js +3 -2
- package/kit/AGENT_TEMPLATE.md +2 -1
- package/kit/CLAUDE.md +15 -14
- package/kit/agents/crew-commit-agent.md +11 -4
- 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-review-agent.md +2 -0
- package/kit/agents/crew-security-expert.md +3 -1
- package/kit/agents/crew-session-manager.md +11 -9
- package/kit/eval/doctor.sh +128 -6
- package/kit/eval/gate-report.sh +2 -0
- 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 +132 -0
- package/kit/eval/lib/crew-map/parse.mjs +305 -0
- package/kit/eval/lib/crew-map/project.mjs +164 -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/rules/tech.json +35 -0
- package/kit/eval/lib/crew-map/scan.mjs +266 -0
- package/kit/eval/lib/crew-map/stacks.mjs +547 -0
- package/kit/eval/lib/crew-map/surface.mjs +535 -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/gate-log.sh +52 -0
- package/kit/eval/lib/json-string.awk +27 -0
- package/kit/eval/lib/preset.sh +109 -0
- package/kit/eval/lib/presets/default.json +7 -0
- package/kit/eval/lib/presets/solo.json +7 -0
- package/kit/eval/lib/presets/strict.json +11 -0
- package/kit/eval/lib/preview.sh +150 -0
- package/kit/eval/lib/review-bench/bench.mjs +273 -0
- package/kit/eval/lib/review-prepass/prepass.mjs +203 -0
- package/kit/eval/lib/review-prepass/prepass.sh +23 -0
- package/kit/eval/lib/settings-default.sh +36 -0
- package/kit/eval/lib/settings-json.awk +19 -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/verify-cmd.sh +17 -0
- package/kit/eval/lib/version.sh +41 -0
- package/kit/eval/review-bench.sh +26 -0
- package/kit/eval/smoke-test.sh +878 -53
- package/kit/hooks/agent-outcome.sh +44 -12
- package/kit/hooks/board-sync.sh +2 -23
- package/kit/hooks/guard-agent-model.sh +177 -24
- package/kit/hooks/guard-bash.sh +295 -204
- package/kit/hooks/guard-commit-scan.sh +10 -2
- package/kit/hooks/guard-question.sh +73 -0
- package/kit/hooks/guard-write.sh +24 -7
- package/kit/hooks/precompact-snapshot.sh +75 -0
- package/kit/hooks/prompt-approval.sh +389 -103
- package/kit/hooks/refuter-ledger.sh +80 -0
- package/kit/hooks/session-rehydrate.sh +25 -2
- package/kit/hooks/session-update-check.sh +9 -8
- package/kit/hooks/trace-blocklist.txt +9 -0
- package/kit/owned-blobs.tsv +4 -4
- package/kit/settings.json +51 -0
- package/kit/skills/crew-approve/SKILL.md +7 -0
- package/kit/skills/crew-code-review/SKILL.md +16 -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 +55 -0
- package/kit/skills/crew-review/SKILL.md +4 -1
- package/kit/skills/crew-ship/SKILL.md +3 -1
- 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 +25 -2
- package/kit/studio/server/index.js +187 -21
- 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/graph.js +9 -1
- package/kit/studio/server/lib/kit-telemetry.js +30 -5
- package/kit/studio/server/lib/lan.js +87 -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/redact.js +60 -0
- package/kit/studio/server/lib/remote.js +185 -0
- package/kit/studio/server/lib/session.js +1 -1
- package/kit/studio/server/lib/terminal.js +51 -13
- package/kit/studio/server/lib/transcript.js +32 -0
- package/kit/studio/server/lib/usage.js +74 -14
- package/kit/studio/web/app.js +287 -17
- package/kit/studio/web/canvas.js +58 -122
- package/kit/studio/web/chat.js +114 -24
- package/kit/studio/web/graph-plan.js +13 -6
- package/kit/studio/web/index.html +10 -5
- package/kit/studio/web/liveness.js +14 -0
- package/kit/studio/web/map-plan.js +410 -0
- package/kit/studio/web/map.js +596 -0
- package/kit/studio/web/models-plan.js +61 -7
- package/kit/studio/web/models.js +19 -3
- package/kit/studio/web/qr.js +200 -0
- package/kit/studio/web/style.css +165 -0
- package/kit/studio/web/tokens.css +6 -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 +24 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,329 @@ 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
|
+
- **Watch Studio from a phone on the same Wi-Fi.** A viewer is a second token that only reads: the Machines tab makes
|
|
13
|
+
one, lists each with its last request, and revokes it. **Add viewer** shows its link as a QR code; a phone on
|
|
14
|
+
the same network scans it and the panel opens there, with no ssh and no tunnel. While a viewer is live the server
|
|
15
|
+
also listens on the machine's private Wi-Fi address, for viewer tokens only (the panel's own token gets `401` from
|
|
16
|
+
the network); with none, nothing listens beyond `127.0.0.1`. A viewer lasts eight hours, then the phone shows
|
|
17
|
+
Session expired; revoking it closes its stream at once, and the last one closes the Wi-Fi listener. Transcripts
|
|
18
|
+
are hidden by default: the server sends such a link no transcript text at all (an allow-list of fields, applied to
|
|
19
|
+
every answer and to the event stream), and shows them only for a link added with them ticked. Every viewer
|
|
20
|
+
connection and refusal is logged. Measured with an Android phone; the firewall asks once (macOS: allow `node`;
|
|
21
|
+
Windows: Private networks).
|
|
22
|
+
|
|
23
|
+
- **The advisor, measured.** `review-bench --advisor <model>` runs the agent arm with an advisor and reports each
|
|
24
|
+
run's cost by model and its advisor calls; a case of `kind: "task"` is an implementation graded by a check the
|
|
25
|
+
session never saw. Against Opus alone on five review cases and a task (24 runs), Sonnet with an Opus advisor
|
|
26
|
+
never called it: 6 of 6 defects caught against 5 of 6, for $1.06 against $2.23. No rule is added; the runs and
|
|
27
|
+
their numbers are in `packaging/advisor-bench/`.
|
|
28
|
+
|
|
29
|
+
- **An organisation preset.** `--preset <name|file>` on the installers (and `preset.sh --apply` later) writes an
|
|
30
|
+
organisation's critical paths, model floors, verify commands and language as one marked block at the top of
|
|
31
|
+
`.claude/crew-model-rules`; the project's own lines stay below it and win where the rules let them. Three ship:
|
|
32
|
+
`default`, `strict`, `solo`. An invalid preset is refused before anything is installed; `doctor` names the one
|
|
33
|
+
in force. It covers the surfaces the gates read today; which agents a project gets is not part of it.
|
|
34
|
+
|
|
35
|
+
- **Continue here says what it will do before it is pressed.** Studio continues a session it did not start as
|
|
36
|
+
that same session when nothing else holds it open, and starts a copy when something does; the read-only foot now
|
|
37
|
+
says which it will be before the press, from the check it acts on, and offers the command that opens the session
|
|
38
|
+
in the desktop app again (`claude --desktop --resume <id>`) to copy. Measured with a real session: its id stayed
|
|
39
|
+
the same from a terminal, through Studio, and back to a terminal, in one transcript.
|
|
40
|
+
On Windows the desktop command is a PowerShell line, and the terminal Studio opens runs `claude --resume <id>`
|
|
41
|
+
without single quotes, which cmd.exe handed to the program as part of the id. An id that is not a session id
|
|
42
|
+
builds no command at all.
|
|
43
|
+
The terminal Studio opens runs `claude --resume <id>` and nothing else: the route no longer takes a `command`
|
|
44
|
+
from the request, which it ran unchecked and the panel never sent.
|
|
45
|
+
|
|
46
|
+
- **A stopped command says what it would have touched.** When the shell gate stops `git reset --hard`,
|
|
47
|
+
`git clean -f`, `git push --force` or `rm -r`, or asks about a commit or a push, one line says what it would
|
|
48
|
+
have done: the uncommitted changes and commits it discards, the paths a dry run lists, the remote commits it
|
|
49
|
+
overwrites, the files under a target inside the project, what a commit takes and a push sends. Read only, after
|
|
50
|
+
the decision and in a subshell of its own, so a failing preview never changes the decision. The push question
|
|
51
|
+
became cheaper too: the branch is read from HEAD without a process.
|
|
52
|
+
|
|
53
|
+
- **What a compaction keeps is written down first.** A PreCompact hook writes the state of the work from the files
|
|
54
|
+
and the gates (branch, uncommitted files, the last gate refusal, the findings on record, a handover if there is
|
|
55
|
+
one) inside the repository's git directory, and SessionStart gives it back after the compaction, to the same
|
|
56
|
+
session only. It never blocks the compaction. Studio's session card adds how much of the context since the last
|
|
57
|
+
compaction is tool output, and how many times the session was compacted.
|
|
58
|
+
|
|
59
|
+
- **The Map reads like a project, not a graph.** Studio's Map draws modules in the layers `/crew-map` wrote (UI,
|
|
60
|
+
API, Service, Data, Infrastructure, Library, Tools), each card naming the module in full with its domain, up to
|
|
61
|
+
three of what it is built with and the outside services it calls folded into one line under it. A search dims
|
|
62
|
+
what it does not name; the tour `/crew-map` wrote steps through the map over the bottom of the pane; the
|
|
63
|
+
inspector shows the layer, the domain and what is inside a module (its entry point, its folders and their file
|
|
64
|
+
counts). A map with no layers is drawn in the bands the scan gives, as before.
|
|
65
|
+
|
|
66
|
+
- **The Crew Map says where each module sits, and how to read the project.** `/crew-map` now has the model add,
|
|
67
|
+
to each module, its layer (`ui`, `api`, `service`, `data`, `infra`, `tool`, `library`) and the part of the
|
|
68
|
+
business it serves, and to the map a tour of up to eight stops a newcomer reads in order. Each rests on lines
|
|
69
|
+
the scan read; `--validate` refuses a layer not on the list, a domain written as a sentence, a tour stop at no
|
|
70
|
+
node, citing another node's lines or visiting a node twice, and a scan again drops what no longer holds.
|
|
71
|
+
A module's README is read too: its first line of prose is a line a description may rest on (measured on a real
|
|
72
|
+
project, four of ten modules had nothing else to describe them by).
|
|
73
|
+
|
|
74
|
+
- **How right the review is, in numbers.** `eval/review-bench.sh` runs the review on labelled cases and reports
|
|
75
|
+
recall, precision and every false alarm by name; the pre-pass arm costs nothing, the agent arm runs Claude Code
|
|
76
|
+
headless as the review agent under a per-case and a per-run dollar cap, isolated from the user's own settings.
|
|
77
|
+
Crewforth's 27 cases come from its own history (a fix undone, its explanation left out) and 8 are held out; the
|
|
78
|
+
pre-pass's floor on them is a CI gate. Measured with Sonnet: 18 of 20 defects found, 34 of 49 findings about the defect, $1.62.
|
|
79
|
+
|
|
80
|
+
- **The review starts from a deterministic pre-pass.** `eval/lib/review-prepass/prepass.sh` reads the lines a
|
|
81
|
+
change adds (staged, or `--base <ref>` for a branch) and writes `.crewforth/review-prepass.json` in the findings
|
|
82
|
+
shape: a secret pattern (cited by hash), a debug call or a TODO comment left in code, shellcheck on shell files, a lock
|
|
83
|
+
file that moved without its manifest, a very large change. The review agent carries those over and writes its
|
|
84
|
+
own findings to `.crewforth/review.json`, blockers through the refuter. What it could not check (no shellcheck,
|
|
85
|
+
a file edited after staging, no Node) is said, never read as clean.
|
|
86
|
+
|
|
87
|
+
- **In `auto`, approve a commit or a push with one click.** A fixed question, asked with AskUserQuestion: Commit
|
|
88
|
+
only, Commit + push, Push only, No. It is handed to the session when `crew-commit-agent` is called, so `/crew-ship`
|
|
89
|
+
asks it with the message, and a refused commit offers it too (measured in real sessions: offered by the refusal
|
|
90
|
+
alone, it never came up, since the session asks before trying a commit). A new gate, `guard-question.sh`, answers `ask` on it,
|
|
91
|
+
so a hook that fills in the answer cannot answer it for you (measured in 34 runs and by hand in the terminal), and
|
|
92
|
+
`prompt-approval.sh` records your click exactly as it records `/crew-approve`: tied to what is staged, `HEAD`, the
|
|
93
|
+
session, for 30 minutes.
|
|
94
|
+
Any other wording, a question with answers already in it, or an answer the hook did not ask for records nothing.
|
|
95
|
+
- **Studio's Models view shows normal work that ran above the table's model.** The gate holds a floor, not a
|
|
96
|
+
ceiling, so this is shown and nothing is blocked: the classes of normal work that ran higher than Sonnet and than
|
|
97
|
+
the floor the gate held them to, with what they cost as run and the same tokens at Sonnet's list price. That
|
|
98
|
+
Sonnet is enough for a class is said only when its last ten verified calls on Sonnet all passed first time, the
|
|
99
|
+
test a held class is offered for lowering by; otherwise the view says it is not measured.
|
|
100
|
+
- **Studio draws a project's crew map.** The Map view (`p`, or **Map** under a project in the navigator, beside its
|
|
101
|
+
number of findings) reads `.crewforth/crew-map.json` and scans nothing. Modules sit in bands from the clients down
|
|
102
|
+
to the external resources, and a module the map does not place goes to Unplaced. Lines are solid where a file
|
|
103
|
+
proves them, dotted where inferred, and marked where the model proposed them. The pane pans and zooms with the
|
|
104
|
+
graph's own code; a card placed by hand stays placed for the project, and modules sharing a folder fold into one
|
|
105
|
+
card. The findings are listed proven first, with the scanner's hidden rules counted until asked for. The inspector
|
|
106
|
+
copies any `file:line` and copies a finding as a task. Compare with matches another project's calls against this
|
|
107
|
+
one's endpoints. On a phone, the findings and a list of the modules stand in for the pane.
|
|
108
|
+
- **A crew map of the project.** `bash .claude/eval/lib/crew-map/crew-map.sh` reads the modules (Node and TypeScript,
|
|
109
|
+
Python, Go, .NET, Java and Kotlin), the external resources they touch, the endpoints they provide and call, and
|
|
110
|
+
writes `.crewforth/crew-map.json`. Every module, line and finding cites the `file:line` it was read from, the same
|
|
111
|
+
tree gives the same bytes (`--check` holds it in CI), and a configuration value is read only to name its kind. Ten
|
|
112
|
+
gap rules: five proven by the lines they cite, five concluded from absence and hidden until their false-positive
|
|
113
|
+
rate is measured.
|
|
114
|
+
- **Findings are held to the lines they cite.** The findings core (`.claude/eval/lib/findings/findings.sh`) checks
|
|
115
|
+
every citation: the file is inside the project, the lines exist, and they are still the lines that were read. A
|
|
116
|
+
document that does not verify is reported entry by entry and never written.
|
|
117
|
+
- **A finding is verified by an agent that tries to refute it.** `crew-refuter` gets one claim and its cited lines,
|
|
118
|
+
not the reasoning, and works on one lens. `refuter-ledger.sh` records its verdict from the agent's own task and
|
|
119
|
+
answer in `.claude/state/crew-refuter.tsv`. With `--verified`, a `medium` finding needs one verdict and a `high` or
|
|
120
|
+
`critical` one three, each a line of that ledger.
|
|
121
|
+
- **`crew-docs-agent` writes the text.** README, guides, release notes, legal and privacy texts and store listings had
|
|
122
|
+
no owner and ran outside model routing. Legal, privacy, consent and terms paths and store metadata are critical
|
|
123
|
+
paths, so that text runs on the critical tier and a legal or privacy text is audited by `crew-privacy-agent` before
|
|
124
|
+
it closes.
|
|
125
|
+
- **Doctor names three more things, none of which changes its verdict.** Both editions enabled at once (every hook
|
|
126
|
+
would run twice), read from `claude plugin list --json`; the advisor, whether it is on, on what and from which
|
|
127
|
+
settings file, or turned off; and, before any update check has run, the published version, said as not measured
|
|
128
|
+
instead of nothing.
|
|
129
|
+
- **Studio shows why work was critical, and says when an agent is outside routing.** The gate records its reason
|
|
130
|
+
(`risk_why`, a new last column of `model-outcomes.tsv`) and the inspector shows it under the task card; an older
|
|
131
|
+
line shows none rather than a guessed one. An agent that is not `crew-*` gets a Model routing note: the gate leaves
|
|
132
|
+
it alone, so it has no card.
|
|
133
|
+
- **Studio counts the advisor in what a session cost.** An advisor call is billed at the advisor model's rates and the
|
|
134
|
+
API keeps it out of a response's top-level usage; Studio now reads it from `usage.iterations` and prices it at its
|
|
135
|
+
own model. The session table has an Advisor line (calls, tokens, cost) when a call is recorded. Measured on a real
|
|
136
|
+
session: Studio read $0.0567 before, $0.2110 after, the same as Claude Code's own figure.
|
|
137
|
+
- **Studio's Models view marks the classes whose agents consulted the advisor.** The cost cell carries an advisor tag
|
|
138
|
+
whose hover says how many calls and how much of the cost they were, already included; a class whose agents consulted
|
|
139
|
+
none has no tag.
|
|
140
|
+
- **A visible way to the repository.** `/crew-doctor` now shows the star line once per version under its own marker,
|
|
141
|
+
so a line already shown at install no longer silences it, and a plugin install shows it too, with the plugin's
|
|
142
|
+
version. `/crew-update` keeps it to one line per update. The READMEs and the site's home page have a Star on GitHub
|
|
143
|
+
button.
|
|
144
|
+
- **A status line.** One line under the prompt: the gate's last word in this session, a commit or push approval that
|
|
145
|
+
still holds, the crew agents still running, the measured context fill and the session's cost. The installers set it
|
|
146
|
+
only where no status line is set, in the project or in your own settings, and `/crew-doctor` says which one is in
|
|
147
|
+
use.
|
|
148
|
+
- **`/crew-map`.** It runs the scanner, then has the model describe what it found: at most two sentences per module on
|
|
149
|
+
what it is for, and a short overview, each citing lines the scan itself read. `crew-map.sh --validate` refuses a
|
|
150
|
+
description that cites anything else or nothing, or a scanner field changed by hand; a scan again keeps the
|
|
151
|
+
descriptions that still hold and drops the rest. Studio's Map shows them, and `crew-planner` reads the map on an
|
|
152
|
+
unfamiliar project.
|
|
153
|
+
|
|
154
|
+
### Changed
|
|
155
|
+
|
|
156
|
+
- **A typed approval is caught at the turn's end.** The one-click question reached the user only from a refused
|
|
157
|
+
commit or a call to the commit agent, and a session that wrote the message itself asked the user to type
|
|
158
|
+
`/crew-approve` without trying either: 9 of 18 typed asks in two real `auto` sessions. Now, when a reply asks for
|
|
159
|
+
`/crew-approve` in `auto` with the question open and it was not asked since the user's last message, the session
|
|
160
|
+
is told once to ask the click. It never blocks the turn; a question that was refused or dismissed leaves the typed
|
|
161
|
+
way, and a turn's end does not end an approval.
|
|
162
|
+
|
|
163
|
+
- **A refused commit asks one way.** In `auto`, with the approval question open, the refusal offered the click and
|
|
164
|
+
the typed `/crew-approve` side by side, and a session picked the typed one 7 times in 9. The click is now the way
|
|
165
|
+
to ask, and the typed command is only the fallback for a question that cannot be asked.
|
|
166
|
+
|
|
167
|
+
- **A task card on one line is read.** `files: … · change: … · verify: …` (with `;` or `|` too, after an optional
|
|
168
|
+
`Card:`, and `above:` on the same line) is read by its labels and held to the rules of the three-line card, and a
|
|
169
|
+
kind with a note in parentheses (`architecture (planning only)`) is that kind, on either form. Measured on one
|
|
170
|
+
machine's sessions: 37 calls had been refused for their card, every one followed by a second call; 17 of them now
|
|
171
|
+
pass on the first.
|
|
172
|
+
|
|
173
|
+
- **A model is chosen to cost what the work needs.** Measured on a real project: 186 crew tasks, 0 on haiku, 73 (39%)
|
|
174
|
+
above their card's floor, and no verify command ever passing, so the cheaper path never opened. Now:
|
|
175
|
+
- the card's model is the default: a call above it runs on it (the gate rewrites the call's model), unless the
|
|
176
|
+
card adds `above: <why>`;
|
|
177
|
+
- outside the crew, a call asking for opus or fable runs on sonnet, and so does a general-purpose call that names
|
|
178
|
+
no model in a session that is not on haiku (it took the session's model; measured on Claude Code 2.1.299, the
|
|
179
|
+
project's settings `env` could not change that, so the gate does);
|
|
180
|
+
- a verify command in a sub-folder (`cd apps/x && <command>`, 41 of 71 refusals) is run in that folder;
|
|
181
|
+
`none (why)` is none; and `/crew-doctor` lists the commands that were never allowed to run, with the line that
|
|
182
|
+
allows each.
|
|
183
|
+
|
|
184
|
+
- **A commit's command is read by one reader.** `guard-bash.sh` paired quotes in three places: the reader of a call,
|
|
185
|
+
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
|
|
186
|
+
last two now take their text from the first, and keep only their own question. What a call the user approved may
|
|
187
|
+
hold is unchanged. The older walk read a here-document's body and a comment as arguments of the commit; it no
|
|
188
|
+
longer does, so a call that only holds the words of a commit inside a here-document body, or `-a` after a `#`,
|
|
189
|
+
asks as any other commit does instead of being refused.
|
|
190
|
+
- **npm releases are published over OIDC.** The release job proves its identity with a short-lived GitHub Actions
|
|
191
|
+
token (npm Trusted Publishing); the repository holds no npm token, and each version carries a provenance statement.
|
|
192
|
+
- **The session line shows the measured fill.** The last line of a reply was `🔋 Session: low fill · …`: the template
|
|
193
|
+
had no number, so the figure the hook measures every turn stayed out of sight. It is now `🔋 Session %NN → low fill ·
|
|
194
|
+
…`, the hook's own figure, never an estimate.
|
|
195
|
+
- **Studio keeps cards for a longer session.** At Auto density a picture may now run up to half again past the pane
|
|
196
|
+
before its cards become chips; it opens at the zoom cards are read at, from its top, and Fit still shows all of it.
|
|
197
|
+
A compact group card says how its agents went as well as their models (`5 done · 3 Sonnet · 2 Opus`).
|
|
198
|
+
- **The session's own write to a critical path is recorded.** Agents not on Opus are refused a critical path; the
|
|
199
|
+
session's own writes were not looked at at all. They are still not refused (the choice is yours), but each one now
|
|
200
|
+
leaves a NOTE line in the gate log with the path and the rule that made it critical, which Studio's Gates tab and
|
|
201
|
+
the status line show.
|
|
202
|
+
|
|
203
|
+
### Security
|
|
204
|
+
|
|
205
|
+
- **The session-link trailer is a trace.** Claude Code asks the model to end a commit message with a line linking the
|
|
206
|
+
session on claude.ai; the trace scan had no pattern for it, and six commits of a project with Crewforth installed
|
|
207
|
+
carried it to a remote. The trailer and its address are both caught now, in the message and in staged files.
|
|
208
|
+
|
|
209
|
+
- **A `PermissionRequest` hook could approve a commit with nobody at the keyboard.** Such a hook answers a
|
|
210
|
+
permission prompt before the person does, and the answer cannot be told from a click: measured, it approved the
|
|
211
|
+
Bash prompt `guard-bash.sh` raises for a commit in `default`, and it answered the new question too. Before it
|
|
212
|
+
asks, the gate now looks for one in every source it can read (user, project and local settings, the
|
|
213
|
+
managed-settings files, skill, agent and command front matter, installed plugins). Where one may be wired the
|
|
214
|
+
question closes, and so does the gate's own prompt in `default` and `acceptEdits`: `/crew-approve`, which no hook
|
|
215
|
+
can type, is the approval left. The limit: settings passed with `--settings` and managed settings delivered by a
|
|
216
|
+
server cannot be read.
|
|
217
|
+
- **`crewforth.hookschain` is guarded the way `core.hooksPath` is.** The key holds the path of a project hook chain
|
|
218
|
+
the shim reads on every commit, and `git config crewforth.hookschain …` passed. A write is now refused in every form
|
|
219
|
+
`core.hooksPath` is (a value, `--unset`, `-c`, `--config-env`, `GIT_CONFIG_` variables); reading it still passes.
|
|
220
|
+
|
|
221
|
+
### Fixed
|
|
222
|
+
|
|
223
|
+
- **Crew Map reads a `fetch` call's method from its own options only.** The method was taken from the next four
|
|
224
|
+
lines, so in a file of one-line calls a `{ method: 'POST' }` on a later call was given to the earlier ones, and the
|
|
225
|
+
map reported `POST /api/products is called but no endpoint in this repo provides it` (endpoint-missing) for a
|
|
226
|
+
plain `fetch('/api/products')`. The scan now reads the call's arguments up to its own closing parenthesis, over
|
|
227
|
+
strings and nested brackets; a method on a later line of the same call is still read.
|
|
228
|
+
- **A push approval covers a tag on the approved commit.** `git push <remote> <tag>` had no way to be approved: the
|
|
229
|
+
click and `/crew-approve push` both record a push of the branch, and the tag push of a release was refused after
|
|
230
|
+
either, so the session handed the user the command to run. It now passes when the tag points at the commit the
|
|
231
|
+
approval covers (after a commit + push, the new one) and no branch has its name; a tag on another commit, a full
|
|
232
|
+
ref, a refspec and `--tags` are still refused.
|
|
233
|
+
- **`change: review` is read as `audit`.** The model table of the working rules names review with audit, and
|
|
234
|
+
`crew-review-agent` cards that said `change: review` were refused. It now takes the audit floor, on a critical path
|
|
235
|
+
too; a kind that is not on the list is still refused.
|
|
236
|
+
- **A commit refusal names a trace in the message even when the staged content also fails.** The content gate
|
|
237
|
+
scanned the `-m` message only when the staged change was clean, so a refusal for a silenced lint check said nothing about
|
|
238
|
+
the session-link trailer in the same message, and the session showed the user the traced message again. Both are
|
|
239
|
+
named in one refusal now, and a trace in the message adds that a harness reminder to end a message with a
|
|
240
|
+
trailer does not override §4.1. The git `commit-msg` hook still stops the trailer at the commit itself.
|
|
241
|
+
- **A one-line task card may open with `Kart`.** Sessions that write in Turkish lead the card with `Kart —` as
|
|
242
|
+
others write `Card —`, and the call was refused as having no card. The Turkish word is read like the English one;
|
|
243
|
+
the fields after it are held to the same rules.
|
|
244
|
+
- **`above:` is read anywhere among a task card's three lines.** A card with `above: <why>` between `change:` and
|
|
245
|
+
`verify:` was refused ("line 3 of the task is not one of files:, change:, verify:") and the call was sent again
|
|
246
|
+
with the line moved down. It is now read in any position and keeps the model as it does after the three; the three
|
|
247
|
+
are still all required.
|
|
248
|
+
- **A click on the approval question is recorded whatever order its keys come back in.** Claude Code hands the
|
|
249
|
+
answered question back either as it was asked or with its keys sorted, and the answer side matched it byte for
|
|
250
|
+
byte: in real `auto` sessions 30 of 30 answers in the asked order were recorded and 7 of 7 sorted ones refused
|
|
251
|
+
("the question answered is not the fixed one"), so the user clicked and was then told to type `/crew-approve`. The
|
|
252
|
+
answer side now checks each text of the fixed question wherever it sits; the exact match stays where the question
|
|
253
|
+
is asked, and the answer is still bound to that call.
|
|
254
|
+
|
|
255
|
+
- **The Crew Map says what a project is made of.** A Flutter project read as a pile of Gradle modules and its
|
|
256
|
+
server as an external API (seen on a real project). The scanner now reads Dart: one module per `pubspec.yaml`,
|
|
257
|
+
its packages and `path:` references, and a Flutter app's `android/` and `ios/` folders as platforms of the app.
|
|
258
|
+
Each module says what it is built with (Hono, Cloudflare Workers, Flutter, Riverpod…, from `rules/tech.json`)
|
|
259
|
+
and what is inside it (folders with file counts, tests apart). A module served at a host its wrangler routes or
|
|
260
|
+
`fly.toml` name is called, module to module, by any module that writes that host; a Dart call to that host or a
|
|
261
|
+
Dio call's relative path is matched to the endpoints provided. A `.dart` file no `pubspec.yaml` owns is listed
|
|
262
|
+
as not measured, as is Dart package usage: Flutter declares packages nothing imports.
|
|
263
|
+
|
|
264
|
+
- **A commit message and a reworded paragraph no longer go to the expensive model.** Two floors of the model gate
|
|
265
|
+
raised prose for no gain (seen on a real project): with no verify command a commit message was held to sonnet,
|
|
266
|
+
though the commit hook checks it, and a two-sentence fix under a critical path such as `legal/` was held to opus.
|
|
267
|
+
A text change now runs on haiku without a verify command, the commit agent too; on a critical path a text change
|
|
268
|
+
whose every file is prose (`.md`, `.txt`, `.rst`, `.adoc`) is written on sonnet, and the audit of it stays on opus.
|
|
269
|
+
One code file on the card keeps it on opus, and an agent on sonnet still writes no code there. A project that
|
|
270
|
+
wants opus for such text says so in `.claude/crew-model-rules` (`floor * text critical opus`).
|
|
271
|
+
- **The gate log is written in every project, and Studio shows a refused agent call.** A project that tracks
|
|
272
|
+
`.claude/` had no gate log at all: no record of a refusal, no 🛡 on the status line, no note of a model lowered to
|
|
273
|
+
its card's floor (seen on a real project). The log now goes inside the repository's own `.git` there
|
|
274
|
+
(`crewforth-gate-log.tsv`, never committed); one rule (`eval/lib/gate-log.sh`) serves every gate and reader. A
|
|
275
|
+
call the model gate refused starts no agent, so the canvas showed nothing while the session said "2 failed"; the
|
|
276
|
+
session's card now says how many calls were refused and not made again, with the gate's words on hover.
|
|
277
|
+
- **`/crew-doctor` offers a verify rule that works, in every mode.** For `cd sub && ./check.sh` it offered the line
|
|
278
|
+
with the `cd` in it, which allows nothing (the rule names the command alone), and in default mode it offered
|
|
279
|
+
nothing, because that refusal is worded differently. Measured on Windows.
|
|
280
|
+
- **Studio keeps answering with many conversations open.** Each conversation pane held its own stream, and a
|
|
281
|
+
browser opens six connections to one host: at five panes a message sent and every request the page made waited
|
|
282
|
+
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).
|
|
283
|
+
Every open conversation now shares one stream, resumed from each session's last event when it reconnects.
|
|
284
|
+
- **Studio finds sessions under a moved config dir.** It read `~/.claude/projects` only, so sessions under
|
|
285
|
+
`CLAUDE_CONFIG_DIR` were not listed and read a cost of 0. It now reads `projects` there, as Claude Code writes.
|
|
286
|
+
- **Studio says when it needs a restart.** A running server keeps the code it started with, and an update
|
|
287
|
+
replaces the files the page is read from: on a real project the Map view of the new page asked a server from
|
|
288
|
+
before it and showed "Not read — HTTP 404". The server now says whether its code changed on disk since it
|
|
289
|
+
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
|
|
290
|
+
same instead of the 404.
|
|
291
|
+
- **Two agents starting together no longer share one model record on Windows.** A record was taken by renaming
|
|
292
|
+
it, which is a lock on macOS and Linux; on Windows two hook processes both reported the rename as done (seen
|
|
293
|
+
twice on the Windows CI). Each record is now locked first with an exclusive create, a shell builtin that costs no
|
|
294
|
+
process, and only the hook that made the lock takes it.
|
|
295
|
+
- **An rc says it is one, and its final is offered.** A release candidate installed `.claude/VERSION` as the final's
|
|
296
|
+
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,
|
|
297
|
+
and someone who tried the rc was never told the final shipped. The rc's archive and npm package now carry its own
|
|
298
|
+
version, and one definition (`eval/lib/version.sh`) orders an rc before its final. A version off the network is
|
|
299
|
+
still held to X.Y.Z.
|
|
300
|
+
- **`adopt.sh --help` prints its usage.** It ran the project detection instead; the usage now comes in English and
|
|
301
|
+
Turkish, before anything is read.
|
|
302
|
+
- **The crew map reads what two real projects showed it missing.** Scanned before release, they put three rules
|
|
303
|
+
well over a 20% false-positive rate, and one scan refused its own document. Read now: a route with an empty path,
|
|
304
|
+
a decorator whose path is on the next line, `api.get<T>(` and a call split over lines, a client made in one file
|
|
305
|
+
and called in another (it had read as a server), an import ending in a comment, twelve more import names, and a
|
|
306
|
+
string in a test that looks like an import. A call with a run-time host is matched but never reported missing. A
|
|
307
|
+
route a healthcheck or a Kubernetes probe calls has a caller, and a package that works without an import (a
|
|
308
|
+
server started from the command line, a database driver named in a URL, a pytest plugin) is not unused.
|
|
309
|
+
Source in a language the scanner has no reader for, and routes registered with a variable path, are listed in
|
|
310
|
+
`notMeasured` instead of being silently absent. On the Python project the proven `endpoint-missing` went from 2
|
|
311
|
+
real out of 10 to 4 out of 4.
|
|
312
|
+
- **Studio's cards no longer flicker while a window is resized.** At Auto density, an edge dragged across the limit
|
|
313
|
+
between cards and chips redrew every card on every frame (measured: 57 times in 60 frames with 43 agents). The view
|
|
314
|
+
still follows the edge at once; the choice between cards and chips is made once the window has stopped for 150 ms.
|
|
315
|
+
- **`crew-commit-agent` and `crew-session-manager` are called.** Both were exempt from the delegation cue and nothing
|
|
316
|
+
pulled them, so the main thread wrote every commit message and handover itself. The discipline and `/crew-handoff`
|
|
317
|
+
now call them, and smoke fails when a chain-step agent has no caller.
|
|
318
|
+
- **Doctor names the 2.x plugin enabled beside a 3.x install.** The 2.x plugin, under its old name, wires the same
|
|
319
|
+
hooks; the check looked for `crewforth@…` only and said one edition while every hook ran twice.
|
|
320
|
+
- **The crew map no longer reads a regex literal as an import.** `from '[^']*…` inside a regular expression was
|
|
321
|
+
reported as a proven undeclared dependency named `[^`; a specifier counts as a package only when it is named the way
|
|
322
|
+
npm names one.
|
|
323
|
+
- **A cache write the usage split leaves out is counted.** Studio dropped cache writes that the top-level split of a
|
|
324
|
+
response did not account for; they are now the five-minute kind, which is how they were billed.
|
|
325
|
+
- **Doctor's advisor lines match how Claude Code attaches it.** An advisor below the model it would advise is not
|
|
326
|
+
attached at all, so critical work runs without one; the warning said it would advise a stronger model.
|
|
327
|
+
- **`incident-runbook` is picked for an outage that keeps coming back.** Its description named only a production that
|
|
328
|
+
is degraded or broken; a request about a recurring outage picked it in none of three held-out eval runs before, and
|
|
329
|
+
in two of three after.
|
|
330
|
+
|
|
8
331
|
## [3.1.1] — 2026-10-12
|
|
9
332
|
|
|
10
333
|
### 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,10 +29,12 @@ 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.
|
|
36
|
+
- A stopped destructive command says what it would have touched; a review starts from a deterministic pre-pass, and `crew-refuter` tries to refute each finding that blocks.
|
|
37
|
+
- **Organisation presets.** `npx crewforth init --preset strict` (or `solo`, or your own JSON file) carries critical paths, model floors and verify commands to every project.
|
|
35
38
|
- **Safe adoption.** `adopt` lands everything on a branch, staged and uncommitted; `main` is never touched.
|
|
36
39
|
|
|
37
40
|
## Updating
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.
|
|
1
|
+
3.2.0-rc.10
|
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,24 +24,68 @@ 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
|
|
|
29
68
|
# --- flags (B5 — where a refresh lands) --- --here: the current branch · --new-branch: a fresh review branch.
|
|
30
69
|
# Left empty, Stage 2 picks a smart default (first adopt -> new; update + untracked .claude -> here; update +
|
|
31
70
|
# tracked -> ask). Unknown flags are ignored here (start.sh owns --backend/--frontend/… ; adopt auto-detects shape).
|
|
32
|
-
BRANCH_MODE=""; ASSUME_YES=0
|
|
71
|
+
BRANCH_MODE=""; ASSUME_YES=0; PRESET=""; _preset_take=0
|
|
33
72
|
_lang_flag=""; _lang_take=0
|
|
34
73
|
for _a in "$@"; do
|
|
35
74
|
# `--lang` with no value must not swallow the next flag: `--lang --yes` is --yes with no language given.
|
|
36
75
|
if [ "$_lang_take" = 1 ]; then _lang_take=0; case "$_a" in -*) ;; *) _lang_flag="$_a"; continue ;; esac; fi
|
|
76
|
+
if [ "$_preset_take" = 1 ]; then _preset_take=0; PRESET="$_a"; continue; fi
|
|
37
77
|
case "$_a" in
|
|
78
|
+
--preset=*) PRESET="${_a#--preset=}" ;;
|
|
79
|
+
--preset) _preset_take=1 ;;
|
|
38
80
|
--here) BRANCH_MODE=here ;;
|
|
39
81
|
--new-branch) BRANCH_MODE=new ;;
|
|
40
82
|
--yes|-y) ASSUME_YES=1 ;; # assume "yes" at every gate — for agent-driven / CI updates (no TTY to prompt)
|
|
41
83
|
--lang=*) _lang_flag="${_a#--lang=}" ;;
|
|
42
84
|
--lang) _lang_take=1 ;;
|
|
43
85
|
esac; done
|
|
86
|
+
[ "$_preset_take" = 1 ] && { echo "ERROR: --preset needs a name or a file (default, strict, solo, or ./org.json)."; exit 1; }
|
|
87
|
+
# A preset is checked before anything is changed: one that is not valid stops the update here.
|
|
88
|
+
if [ -n "$PRESET" ]; then bash "$SRC/eval/lib/preset.sh" --check "$PRESET" || exit 1; fi
|
|
44
89
|
|
|
45
90
|
# ---- CREW-I18N (the twin of start.sh's; see the long note there for why the English string is the key) ----
|
|
46
91
|
# Short version, because the reasoning belongs in one place: `m 'text'` prints the translation of that text
|
|
@@ -273,6 +318,8 @@ _mt() { # $1 = English text (the key); further args fill %s; result in _M
|
|
|
273
318
|
"custom hooks and every other permission PRESERVED") s="özel hook'lar ve diğer tüm izinler KORUNDU" ;;
|
|
274
319
|
"custom hooks/permissions PRESERVED") s="özel hook'lar ve izinler KORUNDU" ;;
|
|
275
320
|
"settings.json: was missing in the project -> Crewforth's was installed") s="settings.json: projede yoktu -> Crewforth'unki kuruldu" ;;
|
|
321
|
+
"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)." ;;
|
|
322
|
+
"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
323
|
"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
324
|
"settings.json: %s") s='settings.json: %s' ;;
|
|
278
325
|
"merge failed -> project setting PRESERVED (not overwritten)") s='birleştirme başarısız -> proje ayarı KORUNDU (üzerine yazılmadı)' ;;
|
|
@@ -1533,19 +1580,23 @@ fi
|
|
|
1533
1580
|
# set up in Turkish to English from its first unattended update on.
|
|
1534
1581
|
[ "$_LANG_CHOSEN" = 1 ] && echo "lang=$CREW_LANG"
|
|
1535
1582
|
} > .claude/kit.conf
|
|
1583
|
+
# The organisation's preset (checked before anything was changed): a block at the top of crew-model-rules. Without
|
|
1584
|
+
# --preset an update leaves the block that is there, with the project's own lines, as they were.
|
|
1585
|
+
if [ -n "$PRESET" ]; then bash .claude/eval/lib/preset.sh --apply "$PRESET" || exit 1; fi
|
|
1536
1586
|
# What changed, for /crew-update to report: the package's own CHANGELOG sections newer than the version this
|
|
1537
1587
|
# project had, and no newer than the one being installed — read from the package on disk, never from the network.
|
|
1538
1588
|
# A fresh adopt has no "before", so it gets no file (and a stale one from an earlier update is removed).
|
|
1539
1589
|
rm -f .claude/.state/whats-new.md 2>/dev/null
|
|
1540
1590
|
_kv="$(printf '%s' "$KIT_VER" | tr -d '\r')"
|
|
1541
|
-
|
|
1591
|
+
_kv="$(crew_local_version "$_kv" 2>/dev/null)" || _kv="" # an odd old version compares as 0.0.0 — every section would look new
|
|
1542
1592
|
if [ "$KIT_PRESENT" = 1 ] && [ -n "$_kv" ] && [ -f "$HERE/CHANGELOG.md" ] && [ -f "$HERE/VERSION" ]; then
|
|
1543
1593
|
mkdir -p .claude/.state 2>/dev/null
|
|
1544
|
-
|
|
1545
|
-
|
|
1594
|
+
# The upper bound is the target's X.Y.Z: an rc's notes are its final's section ("[Unreleased] — 3.2.0").
|
|
1595
|
+
awk -v from="$_kv" -v to="$(head -1 "$HERE/VERSION" | tr -d '\r')" "${CREW_VCMP_AWK:-}"'
|
|
1596
|
+
BEGIN { sub(/-.*/, "", to) }
|
|
1546
1597
|
/^## \[/ { v=$0; sub(/^## \[/,"",v); w=v; sub(/\].*/,"",v)
|
|
1547
1598
|
if (v=="Unreleased") { v=w; sub(/^[^—]*— */,"",v); sub(/[^0-9.].*/,"",v) }
|
|
1548
|
-
keep = (v ~ /^[0-9]+\.[0-9]+\.[0-9]+$/ &&
|
|
1599
|
+
keep = (v ~ /^[0-9]+\.[0-9]+\.[0-9]+$/ && vcmp(v,from)>0 && vcmp(v,to)<=0) }
|
|
1549
1600
|
keep' "$HERE/CHANGELOG.md" | tr -d '\r' > .claude/.state/whats-new.md 2>/dev/null
|
|
1550
1601
|
[ -s .claude/.state/whats-new.md ] || rm -f .claude/.state/whats-new.md
|
|
1551
1602
|
fi
|
|
@@ -1673,6 +1724,15 @@ if [ -n "$SET_NOTE" ]; then HAND_SET="NOT merged — ${SET_NOTE%.}"
|
|
|
1673
1724
|
elif [ "$SET_FRESH" = 1 ]; then HAND_SET="Crewforth's settings.json installed (the project had none, so nothing was merged)"
|
|
1674
1725
|
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
1726
|
|
|
1727
|
+
# The status line, only where none is set (a user's own would lose to the project's setting, so it is never
|
|
1728
|
+
# replaced). eval/lib/statusline.sh --install decides and writes; this only says what it did.
|
|
1729
|
+
if [ -f .claude/eval/lib/statusline.sh ]; then
|
|
1730
|
+
case "$(bash .claude/eval/lib/statusline.sh --install 2>/dev/null)" in
|
|
1731
|
+
installed) say "Status line: Crewforth's (the gate's last word, a standing approval, crew agents, fill, cost)." ;;
|
|
1732
|
+
kept) say "Status line: yours is kept; Crewforth's is one command away (see /crew-doctor)." ;;
|
|
1733
|
+
esac
|
|
1734
|
+
fi
|
|
1735
|
+
|
|
1676
1736
|
# ============ [STAGE 4] GIT-HOOK ARMING (SHIM) + PROOF ============
|
|
1677
1737
|
h1m 'Stage 4 — arm the git gates (SHIM via husky) + PROOF'
|
|
1678
1738
|
|
package/bin/cli.js
CHANGED
|
@@ -18,12 +18,13 @@ if (sub === '--help' || sub === '-h' || sub === 'help') {
|
|
|
18
18
|
console.log(`Crewforth
|
|
19
19
|
|
|
20
20
|
Usage:
|
|
21
|
-
npx crewforth [init] [--private|--shared] [--yes]
|
|
21
|
+
npx crewforth [init] [--private|--shared] [--yes] [--preset <name|file.json>]
|
|
22
22
|
Set up Crewforth in a fresh project (start.sh wizard). Every install ships everything and
|
|
23
23
|
is stack-agnostic: the stack is recorded per project in CLAUDE.md ## Stack.
|
|
24
24
|
(--dotnet was removed in 3.0; it is still accepted, warns, and installs the same setup.)
|
|
25
|
-
npx crewforth adopt
|
|
25
|
+
npx crewforth adopt [--preset <name|file.json>]
|
|
26
26
|
Hand Crewforth over onto an existing project (adopt.sh).
|
|
27
|
+
--preset applies an organisation preset (default, strict, solo, or your own JSON file).
|
|
27
28
|
npx crewforth@latest update
|
|
28
29
|
Refresh a project that already has Crewforth. Alias of 'adopt': it reads .claude/kit.conf,
|
|
29
30
|
migrates a pre-3.0 .NET install (its pattern skill stays, as a project skill), and
|
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
|
|
62
|
-
| `sonnet` | feature, fix-known, refactor, test-write, audit, review;
|
|
63
|
-
| `opus` | **critical**: migration, security, architecture, fix-unknown, or a
|
|
62
|
+
| `haiku` | text, commit agent; test-run, mechanical work with `verify:` |
|
|
63
|
+
| `sonnet` | feature, fix-known, refactor, test-write, audit, review; other `verify: none`; critical-path prose |
|
|
64
|
+
| `opus` | **critical**: migration, security, architecture, fix-unknown, or a critical-path file (auth, payments, legal…), and its referees |
|
|
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
|