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.
Files changed (110) hide show
  1. package/CHANGELOG.md +323 -0
  2. package/README.md +6 -3
  3. package/VERSION +1 -1
  4. package/adopt.sh +66 -6
  5. package/bin/cli.js +3 -2
  6. package/kit/AGENT_TEMPLATE.md +2 -1
  7. package/kit/CLAUDE.md +15 -14
  8. package/kit/agents/crew-commit-agent.md +11 -4
  9. package/kit/agents/crew-docs-agent.md +71 -0
  10. package/kit/agents/crew-planner.md +2 -0
  11. package/kit/agents/crew-refuter.md +77 -0
  12. package/kit/agents/crew-review-agent.md +2 -0
  13. package/kit/agents/crew-security-expert.md +3 -1
  14. package/kit/agents/crew-session-manager.md +11 -9
  15. package/kit/eval/doctor.sh +128 -6
  16. package/kit/eval/gate-report.sh +2 -0
  17. package/kit/eval/golden-routing.txt +9 -0
  18. package/kit/eval/lib/crew-map/crew-map.sh +26 -0
  19. package/kit/eval/lib/crew-map/detect.mjs +238 -0
  20. package/kit/eval/lib/crew-map/narrative.mjs +132 -0
  21. package/kit/eval/lib/crew-map/parse.mjs +305 -0
  22. package/kit/eval/lib/crew-map/project.mjs +164 -0
  23. package/kit/eval/lib/crew-map/rules/names.json +38 -0
  24. package/kit/eval/lib/crew-map/rules/packages.json +142 -0
  25. package/kit/eval/lib/crew-map/rules/python-stdlib.json +197 -0
  26. package/kit/eval/lib/crew-map/rules/tech.json +35 -0
  27. package/kit/eval/lib/crew-map/scan.mjs +266 -0
  28. package/kit/eval/lib/crew-map/stacks.mjs +547 -0
  29. package/kit/eval/lib/crew-map/surface.mjs +535 -0
  30. package/kit/eval/lib/findings/findings.mjs +410 -0
  31. package/kit/eval/lib/findings/findings.schema.json +122 -0
  32. package/kit/eval/lib/findings/findings.sh +29 -0
  33. package/kit/eval/lib/gate-log.sh +52 -0
  34. package/kit/eval/lib/json-string.awk +27 -0
  35. package/kit/eval/lib/preset.sh +109 -0
  36. package/kit/eval/lib/presets/default.json +7 -0
  37. package/kit/eval/lib/presets/solo.json +7 -0
  38. package/kit/eval/lib/presets/strict.json +11 -0
  39. package/kit/eval/lib/preview.sh +150 -0
  40. package/kit/eval/lib/review-bench/bench.mjs +273 -0
  41. package/kit/eval/lib/review-prepass/prepass.mjs +203 -0
  42. package/kit/eval/lib/review-prepass/prepass.sh +23 -0
  43. package/kit/eval/lib/settings-default.sh +36 -0
  44. package/kit/eval/lib/settings-json.awk +19 -4
  45. package/kit/eval/lib/star.sh +23 -7
  46. package/kit/eval/lib/statusline.settings.json +6 -0
  47. package/kit/eval/lib/statusline.sh +100 -0
  48. package/kit/eval/lib/verify-cmd.sh +17 -0
  49. package/kit/eval/lib/version.sh +41 -0
  50. package/kit/eval/review-bench.sh +26 -0
  51. package/kit/eval/smoke-test.sh +878 -53
  52. package/kit/hooks/agent-outcome.sh +44 -12
  53. package/kit/hooks/board-sync.sh +2 -23
  54. package/kit/hooks/guard-agent-model.sh +177 -24
  55. package/kit/hooks/guard-bash.sh +295 -204
  56. package/kit/hooks/guard-commit-scan.sh +10 -2
  57. package/kit/hooks/guard-question.sh +73 -0
  58. package/kit/hooks/guard-write.sh +24 -7
  59. package/kit/hooks/precompact-snapshot.sh +75 -0
  60. package/kit/hooks/prompt-approval.sh +389 -103
  61. package/kit/hooks/refuter-ledger.sh +80 -0
  62. package/kit/hooks/session-rehydrate.sh +25 -2
  63. package/kit/hooks/session-update-check.sh +9 -8
  64. package/kit/hooks/trace-blocklist.txt +9 -0
  65. package/kit/owned-blobs.tsv +4 -4
  66. package/kit/settings.json +51 -0
  67. package/kit/skills/crew-approve/SKILL.md +7 -0
  68. package/kit/skills/crew-code-review/SKILL.md +16 -0
  69. package/kit/skills/crew-doctor/SKILL.md +5 -1
  70. package/kit/skills/crew-handoff/SKILL.md +3 -2
  71. package/kit/skills/crew-map/SKILL.md +55 -0
  72. package/kit/skills/crew-review/SKILL.md +4 -1
  73. package/kit/skills/crew-ship/SKILL.md +3 -1
  74. package/kit/skills/crew-update/SKILL.md +1 -1
  75. package/kit/skills/incident-runbook/SKILL.md +2 -2
  76. package/kit/skills/security-scan/references/verify.md +6 -3
  77. package/kit/studio/README.md +25 -2
  78. package/kit/studio/server/index.js +187 -21
  79. package/kit/studio/server/lib/code-stamp.js +35 -0
  80. package/kit/studio/server/lib/crew-map.js +113 -0
  81. package/kit/studio/server/lib/graph.js +9 -1
  82. package/kit/studio/server/lib/kit-telemetry.js +30 -5
  83. package/kit/studio/server/lib/lan.js +87 -0
  84. package/kit/studio/server/lib/model-outcomes.js +130 -15
  85. package/kit/studio/server/lib/owned-stream.js +56 -0
  86. package/kit/studio/server/lib/pricing.js +3 -0
  87. package/kit/studio/server/lib/projects.js +11 -4
  88. package/kit/studio/server/lib/redact.js +60 -0
  89. package/kit/studio/server/lib/remote.js +185 -0
  90. package/kit/studio/server/lib/session.js +1 -1
  91. package/kit/studio/server/lib/terminal.js +51 -13
  92. package/kit/studio/server/lib/transcript.js +32 -0
  93. package/kit/studio/server/lib/usage.js +74 -14
  94. package/kit/studio/web/app.js +287 -17
  95. package/kit/studio/web/canvas.js +58 -122
  96. package/kit/studio/web/chat.js +114 -24
  97. package/kit/studio/web/graph-plan.js +13 -6
  98. package/kit/studio/web/index.html +10 -5
  99. package/kit/studio/web/liveness.js +14 -0
  100. package/kit/studio/web/map-plan.js +410 -0
  101. package/kit/studio/web/map.js +596 -0
  102. package/kit/studio/web/models-plan.js +61 -7
  103. package/kit/studio/web/models.js +19 -3
  104. package/kit/studio/web/qr.js +200 -0
  105. package/kit/studio/web/style.css +165 -0
  106. package/kit/studio/web/tokens.css +6 -0
  107. package/kit/studio/web/usage.js +12 -0
  108. package/kit/studio/web/viewport.js +160 -0
  109. package/package.json +6 -5
  110. package/start.sh +24 -1
@@ -2,8 +2,8 @@
2
2
  name: crew-commit-agent
3
3
  color: cyan
4
4
  description: |
5
- Commit message specialist (thin trigger). Reads the staged diff and proposes a Conventional Commits message
6
- via the `commit-message` skill. Writes no source; commits only with user approval.
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:
@@ -94,14 +94,21 @@ write is refused because the file is on a critical path, do not reach it another
94
94
  proceed" is not approval (§4.4).
95
95
  The tool-level gate `guard-bash.sh` intercepts commit/push in **every** permission mode: in normal modes it raises an
96
96
  approval prompt only the user can answer — so present the message FIRST, then run the commit yourself and let the user
97
- approve it at the prompt. Never hand the user a command to paste into their own terminal. In `auto` and `dontAsk`
98
- the prompt reaches nobody: stage, then ask in this shape and with nothing after it — the message in ONE code block,
97
+ approve it at the prompt. Never hand the user a command to paste into their own terminal. In `auto`, when this agent
98
+ is called Crewforth hands the session the one-click approval question (below): ask it, with the message, instead of
99
+ asking for `/crew-approve`. In `dontAsk`, and in `auto` when Crewforth gives no question or says it is closed, the
100
+ prompt reaches nobody: ask in this shape and with nothing after it — the message in ONE code block,
99
101
  and under it one sentence in the user's language ("If you approve, send only this:") followed by the command
100
102
  on a line of its own: `/crew-approve`. With nothing after it, it approves what the gate just refused in this
101
103
  session (a commit, a push, or both when both were refused); spelled out it is `/crew-approve commit`,
102
104
  `/crew-approve push` or `/crew-approve commit+push`. The user approves by sending
103
105
  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
106
  recording hook is not wired), say so and offer Shift+Tab or their own terminal instead.
107
+ The approval question: call AskUserQuestion with exactly the input Crewforth prints (the fixed question and its four
108
+ answers, no answers of your own; never write the question yourself). The
109
+ user's click is recorded the same way; read the line Crewforth adds and run what it names. Where a
110
+ `PermissionRequest` hook may be wired the gate closes the question, and in `default` / `acceptEdits` its own
111
+ prompt too, because such a hook can answer either before the user does: then `/crew-approve` is the way.
105
112
  Then run `git commit -m '…'` alone in its call (single-quoted, or from a here-document with a quoted delimiter),
106
113
  and a push as `git push <remote> <branch>`. Never write that message yourself. Under `plan` and
107
114
  `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.
@@ -30,6 +30,8 @@ Read-only; the trigger for the `crew-code-review` skill.
30
30
  Before a work package closes (pre-commit), on the changed diff.
31
31
 
32
32
  ## How (applies the `crew-code-review` skill)
33
+ - First the deterministic pre-pass (`eval/lib/review-prepass/prepass.sh`), carried over as it is; your own findings
34
+ go to `.crewforth/review.json` in the same findings shape, blockers through crew-refuter (skill §0).
33
35
  - Simplicity: flag when 200 lines could be 50.
34
36
  - Surgical: catch out-of-scope touches.
35
37
  - Readability: naming, dead code, comment traps (S125 — commented-out code-like prose).
@@ -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.
@@ -2,8 +2,8 @@
2
2
  name: crew-session-manager
3
3
  color: blue
4
4
  description: |
5
- Session/context health auditor for a PHASE BOUNDARY: audits fill, recommends the handover. The per-turn
6
- status line is the main thread's own, from the hook. Evaluates only; writes no code.
5
+ Use at a phase boundary or when the fill reads medium or more: audits fill, drafts the handover. The
6
+ per-turn status line stays the main thread's. Writes no code.
7
7
  tools: Read, Grep, Glob, Bash, PowerShell
8
8
  # No `model` field: the caller names it per call. Not `haiku`: the handover is a synthesis over an entire
9
9
  # session and decides what the NEXT session knows, and a thin one fails silently.
@@ -18,7 +18,8 @@ metadata:
18
18
  Trigger phrases: "session status", "session health", "context status", "is a handover needed", "is it time to clear", "handover", "hand over", "switch topic", "getting long", "running out of context"
19
19
 
20
20
  Purpose: so the user never has to track context/token management by hand.
21
- Since proactive background alerts aren't possible, the trigger is **every task completion**.
21
+ It is called at a **phase boundary** or when the measured fill reads medium or more; the per-turn 🔋 line itself
22
+ is the main thread's, from the hook, and needs no agent.
22
23
 
23
24
  ## Expertise stance (context/operations manager)
24
25
  - **Measure, do NOT guess**: the assistant can't run `/context`; actual fill is read from the transcript via `context-usage.sh` (below).
@@ -27,13 +28,14 @@ Since proactive background alerts aren't possible, the trigger is **every task c
27
28
  - **Token discipline:** on the delegate / summary / file-offload decision, apply the `token-budget` skill.
28
29
 
29
30
  ## When
30
- - At the close of every task/subtask (at the very end of the DoD chain).
31
- - When the user says "session status?".
31
+ - At a phase boundary: after crew-commit-agent, at the end of the chain, and as the first step of `/crew-handoff`.
32
+ - When the 🔋 line reads medium or more, or the user says "session status?".
32
33
 
33
34
  ## What it does
34
- Appends a single line to the very END of the response:
35
+ Reports the measured fill and the recommendation in the same form as the per-turn line, and, when the
36
+ recommendation is a handover, a draft of it (`handoff` skill) for `/crew-handoff` to write:
35
37
 
36
- `🔋 Session: [low/medium/high fill] · Recommendation: [continue / handoff+clear / new session]`
38
+ `🔋 Session %NN → [low/medium/high] fill · Recommendation: [continue / handoff+clear / new session]`
37
39
 
38
40
  **Actual fill is MEASURED, guessing is FORBIDDEN.** The `UserPromptSubmit` hook runs `context-usage.sh` each turn,
39
41
  automatically injecting the real `🔋 Session: %.. (token) → level` line into the context — use that value. If you want an
@@ -63,13 +65,13 @@ paused should be released with its handover note.
63
65
  - Reports the decision; doesn't run `/clear` on the user's behalf.
64
66
 
65
67
  ## Output & context (token)
66
- To the main thread: a single health line + recommendation. Do no long analysis; read the `context-usage.sh` output, add no commentary.
68
+ To the main thread: the health line + recommendation, and the handover draft when it recommends one. Do no long analysis; read the `context-usage.sh` output, add no commentary.
67
69
 
68
70
  ## Errors/escalation
69
71
  When you notice a topic change / threshold breach, **recommend but don't interrupt**; don't force a clear mid-task.
70
72
 
71
73
  ## Example delegation
72
- - ✅ Session-health line at task completion
74
+ - ✅ A phase boundary, or the 🔋 line at medium or more
73
75
  - ❌ Content/code generation (out of scope)
74
76
 
75
77
  ## Confidence
@@ -7,7 +7,9 @@
7
7
  set -uo pipefail
8
8
  # The 2.x names of the variables a user can set still work (one helper: eval/lib/crew-env.sh).
9
9
  _crew_d="${BASH_SOURCE%/*}"; [ "$_crew_d" = "${BASH_SOURCE}" ] && _crew_d=.
10
- [ -f "$_crew_d/lib/crew-env.sh" ] && . "$_crew_d/lib/crew-env.sh"; unset _crew_d
10
+ [ -f "$_crew_d/lib/crew-env.sh" ] && . "$_crew_d/lib/crew-env.sh"
11
+ [ -f "$_crew_d/lib/version.sh" ] && . "$_crew_d/lib/version.sh" # an rc orders before its final
12
+ _DOC_LIB="$(cd "$_crew_d/lib" 2>/dev/null && pwd)"; unset _crew_d # absolute: the doctor cd's into ROOT below
11
13
  ROOT="${1:-.}"
12
14
  cd "$ROOT" 2>/dev/null || { echo "doctor: cannot enter '$ROOT'"; exit 2; }
13
15
 
@@ -98,6 +100,22 @@ _mt() {
98
100
  'settings.json is invalid JSON') s='settings.json geçersiz JSON' ;;
99
101
  "Claude Code %s is older than 2.1.293 — the model alias haiku may not resolve to Haiku 5.5 there, so an agent called with model haiku can run on an older model (update Claude Code)") s="Claude Code %s, 2.1.293'ten eski — orada haiku model takma adı Haiku 5.5'e çözülmeyebilir; model haiku ile çağrılan bir ajan eski bir modelde koşabilir (Claude Code'u güncelleyin)" ;;
100
102
  'approval by your own message is wired (auto / dontAsk: /crew-approve commit)') s='kendi mesajınızla onay bağlı (auto / dontAsk: /crew-approve commit)' ;;
103
+ 'the published Crewforth version is not measured: no update check has run here yet (.claude/.state/update-check)') s='yayınlanmış Crewforth sürümü ölçülmedi: burada henüz hiç güncelleme denetimi koşmadı (.claude/.state/update-check)' ;;
104
+ 'two editions at once: not measured (the plugin list could not be read)') s='iki edisyon birden: ölçülmedi (plugin listesi okunamadı)' ;;
105
+ 'two editions at once: not measured (no claude CLI here to list the plugins)') s='iki edisyon birden: ölçülmedi (pluginleri listeleyecek claude CLI burada yok)' ;;
106
+ 'the %s plugin is enabled and this project has Crewforth installed in .claude/ — every hook runs twice; turn one off (claude plugin disable %s, or remove the install)') s="%s plugin'i etkin ve bu projede Crewforth .claude/ altında da kurulu — her hook iki kez koşuyor; birini kapatın (claude plugin disable %s ya da kurulumu kaldırın)" ;;
107
+ 'one edition: the Crewforth plugin is not enabled beside this install') s="tek edisyon: Crewforth plugin'i bu kurulumun yanında etkin değil" ;;
108
+ 'advisor: off (CLAUDE_CODE_DISABLE_ADVISOR_TOOL=1)') s='advisor: kapalı (CLAUDE_CODE_DISABLE_ADVISOR_TOOL=1)' ;;
109
+ "status line: Crewforth's (from %s)") s="durum satırı: Crewforth'unki (%s içinden)" ;;
110
+ "status line: your own (from %s); Crewforth's is not used") s="durum satırı: seninki (%s içinden); Crewforth'unki kullanılmıyor" ;;
111
+ "organisation preset: %s") s="kurum preset'i: %s" ;;
112
+ "verify commands never run, %s time(s), because nothing allows them; to let the hook run one, add its line to .claude/crew-model-rules: %s") s="doğrulama komutları %s kez hiç koşmadı, çünkü hiçbir şey izin vermiyor; hook'un koşturması için satırını .claude/crew-model-rules dosyasına ekle: %s" ;;
113
+ "status line: none; Crewforth's: bash .claude/eval/lib/statusline.sh --install (Bash tool, not PowerShell)") s="durum satırı: yok; Crewforth'unki: bash .claude/eval/lib/statusline.sh --install (Bash tool, not PowerShell)" ;;
114
+ "advisor: off (no advisorModel set; Crewforth never turns it on)") s='advisor: kapalı (advisorModel ayarlı değil; Crewforth onu hiç açmaz)' ;;
115
+ 'advisorModel is %s in %s, but CLAUDE_CODE_DISABLE_ADVISOR_TOOL=1 turns the advisor off') s="advisorModel %s (%s içinde), ama CLAUDE_CODE_DISABLE_ADVISOR_TOOL=1 advisor'ı kapatıyor" ;;
116
+ 'advisorModel is %s in %s, but %s is set and the advisor needs the Anthropic API — it is not used') s="advisorModel %s (%s içinde), ama %s ayarlı ve advisor Anthropic API ister — kullanılmıyor" ;;
117
+ "advisor: on, %s (from %s); not a gate, and its tokens are in /usage and in Studio's session cost") s="advisor: açık, %s (%s içinden); bir kapı değil, token'ları /usage'da ve Studio'nun oturum maliyetinde" ;;
118
+ 'the advisor (%s) is below the critical tier (opus): Claude Code does not attach an advisor below the model it would advise, so critical work runs without one') s="advisor (%s) kritik seviyenin (opus) altında: Claude Code danışacağı modelin altındaki bir advisor'ı eklemiyor, yani kritik iş advisor'sız koşuyor" ;;
101
119
  "settings.json wires prompt-approval.sh but the script is missing — in auto and dontAsk '/crew-approve commit' records nothing; switch mode with Shift+Tab or commit in your own terminal (update Crewforth)") s="settings.json prompt-approval.sh'i bağlıyor ama betik yok — auto ve dontAsk modunda '/crew-approve commit' hiçbir şey kaydetmez; Shift+Tab ile mod değiştirin ya da kendi terminalinizden commit edin (Crewforth'u güncelleyin)" ;;
102
120
  "prompt-approval.sh is not wired on UserPromptSubmit — in auto and dontAsk '/crew-approve commit' records nothing; switch mode with Shift+Tab or commit in your own terminal (update Crewforth)") s="prompt-approval.sh UserPromptSubmit'e bağlı değil — auto ve dontAsk modunda '/crew-approve commit' hiçbir şey kaydetmez; Shift+Tab ile mod değiştirin ya da kendi terminalinizden commit edin (Crewforth'u güncelleyin)" ;;
103
121
  "worktree %s carries Crewforth %s, this one %s — a session there runs that version's gates and approval path (update Crewforth there)") s="%s worktree'sinde Crewforth %s var, burada %s — orada açılan oturum o sürümün kapılarını ve onay yolunu koşar (Crewforth'u orada güncelleyin)" ;;
@@ -204,10 +222,11 @@ if [ -f .claude/VERSION ] && [ -f .claude/.state/update-check ]; then
204
222
  read -r DLATEST _ < .claude/.state/update-check 2>/dev/null || DLATEST=""
205
223
  DLATEST="$(printf '%s' "${DLATEST:-}" | tr -cd '0-9A-Za-z.-')"
206
224
  DCUR="$(head -1 .claude/VERSION 2>/dev/null | tr -cd '0-9A-Za-z.-')"
207
- if [ -n "$DLATEST" ] && awk -v a="$DLATEST" -v b="$DCUR" 'BEGIN{split(a,x,".");split(b,y,".");
208
- for(i=1;i<=3;i++){if(x[i]+0>y[i]+0)exit 0; if(x[i]+0<y[i]+0)exit 1} exit 1}'; then
225
+ if [ -n "$DLATEST" ] && awk -v a="$DLATEST" -v b="$DCUR" "${CREW_VCMP_AWK:-}"' BEGIN { exit !(vcmp(a, b) > 0) }' 2>/dev/null; then
209
226
  warn "Crewforth v%s installed, v%s published — update with /crew-update" "$DCUR" "$DLATEST"
210
227
  fi
228
+ elif [ -f .claude/VERSION ]; then
229
+ skip "the published Crewforth version is not measured: no update check has run here yet (.claude/.state/update-check)"
211
230
  fi
212
231
 
213
232
  # 1c) Install trace. An update leaves VERSION, the install manifest and the components on disk agreeing; when they do
@@ -643,9 +662,9 @@ for _v in $(compgen -e); do
643
662
  esac
644
663
  done
645
664
  if [ "$FAIL" -eq 0 ]; then _mt "DOCTOR: healthy ✅%s" "$PANEL_NOTE"; echo "$_M"
646
- # Healthy verdict: the star line, once per kit version — the marker is shared with the installers, so the
647
- # doctor run that /crew-update makes right after an update stays quiet. Text/URL/silence: lib/star.sh.
648
- [ -f "$(dirname "$0")/lib/star.sh" ] && bash "$(dirname "$0")/lib/star.sh" --once .
665
+ # Healthy verdict: the star line, once per kit version under doctor's own marker (the installers keep theirs).
666
+ # /crew-update runs this with CREW_NO_STAR=1, so an update shows it once, not twice. Text/URL/silence: lib/star.sh.
667
+ [ -f "$(dirname "$0")/lib/star.sh" ] && bash "$(dirname "$0")/lib/star.sh" --once . doctor
649
668
  else _mt "DOCTOR: %s issue(s) ❌ — apply the fixes above%s" "$FAIL" "$PANEL_NOTE"; echo "$_M"; fi
650
669
 
651
670
  # 9) The auto-mode classifier. Since 2026-08-14 auto mode is the default permission mode on Pro/Max/Team, so a
@@ -684,6 +703,109 @@ EOF_CCV
684
703
  fi ;;
685
704
  esac
686
705
  fi
706
+ # 9c) Two editions at once, and the advisor. Advisory, never a failure.
707
+ # PLUGIN AND INSTALL BOTH ON: the plugin edition and this .claude/ install each wire every hook, so with both
708
+ # enabled each gate runs twice on every call (and a gate's own refusal is printed twice). Asked of the CLI —
709
+ # `claude plugin list --json`, whose `enabled` is "enabled in your merged settings" — because the settings files
710
+ # alone cannot say what a managed or a --plugin-dir layer added. No CLI: not measured, and said so.
711
+ # THE ADVISOR (advisorModel; documented: fable, opus, sonnet or a full model id, unset = off; Anthropic API only;
712
+ # CLAUDE_CODE_DISABLE_ADVISOR_TOOL=1 turns it off). Crewforth never sets it. What is reported is whether it is on
713
+ # and on what, read from the same three settings files as the skill-listing budget above (a managed layer is not
714
+ # read), and a note when it sits below the critical tier: Claude Code does not attach an advisor that ranks below
715
+ # the model it would advise (code.claude.com/docs/en/advisor), so an agent on opus gets none.
716
+ # Its usage is not reported here. It is in /usage, and in the transcript (usage.iterations, `advisor_message`,
717
+ # measured on a real advisor session), which is where Studio's session cost reads it.
718
+ if [ -f .claude/hooks/guard-bash.sh ]; then
719
+ if command -v claude >/dev/null 2>&1 && _pl="$(claude plugin list --json 2>/dev/null)" && [ -n "$_pl" ]; then
720
+ _pon=""; _pn="$(printf '{"p":%s}' "$_pl" | awk -v op=len -v path=p -f "${SJ:-.claude/eval/lib/settings-json.awk}" - 2>/dev/null)" || _pn=""
721
+ case "$_pn" in ''|*[!0-9]*) skip "two editions at once: not measured (the plugin list could not be read)" ;;
722
+ *) _pi=0
723
+ while [ "$_pi" -lt "$_pn" ]; do
724
+ _pid="$(printf '{"p":%s}' "$_pl" | awk -v op=get -v path="p.$_pi.id" -f "${SJ:-.claude/eval/lib/settings-json.awk}" - 2>/dev/null)"
725
+ # crewforth@… is 3.x; claude-starter-kit@… is the 2.x plugin, which wires the same hooks and is often still
726
+ # enabled at user scope after a 3.x install (measured in a real project).
727
+ case "$_pid" in '"crewforth@'*|'"claude-starter-kit@'*)
728
+ _pen="$(printf '{"p":%s}' "$_pl" | awk -v op=get -v path="p.$_pi.enabled" -f "${SJ:-.claude/eval/lib/settings-json.awk}" - 2>/dev/null)"
729
+ [ "$_pen" = true ] && _pon="${_pid//\"/}" ;;
730
+ esac
731
+ _pi=$((_pi+1))
732
+ done
733
+ if [ -n "$_pon" ]; then
734
+ warn "the %s plugin is enabled and this project has Crewforth installed in .claude/ — every hook runs twice; turn one off (claude plugin disable %s, or remove the install)" "$_pon" "$_pon"
735
+ else ok "one edition: the Crewforth plugin is not enabled beside this install"; fi ;;
736
+ esac
737
+ else
738
+ skip "two editions at once: not measured (no claude CLI here to list the plugins)"
739
+ fi
740
+ fi
741
+ _adv=""; _advf=""
742
+ for sf in .claude/settings.local.json .claude/settings.json "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/settings.json"; do
743
+ [ -f "$sf" ] || continue
744
+ v="$(awk -v op=get -v path=advisorModel -f "${SJ:-.claude/eval/lib/settings-json.awk}" "$sf" 2>/dev/null)" || v=""
745
+ v="${v#\"}"; v="${v%\"}"
746
+ [ -n "$v" ] && { _adv="$v"; _advf="$sf"; break; }
747
+ done
748
+ _advprov=""; for _ev in CLAUDE_CODE_USE_BEDROCK CLAUDE_CODE_USE_VERTEX; do
749
+ eval "_evv=\"\${$_ev:-}\""; case "$_evv" in ''|0|false) ;; *) _advprov="$_ev"; break ;; esac
750
+ done
751
+ if [ -z "$_adv" ]; then
752
+ if [ "${CLAUDE_CODE_DISABLE_ADVISOR_TOOL:-}" = 1 ]; then ok "advisor: off (CLAUDE_CODE_DISABLE_ADVISOR_TOOL=1)"
753
+ else ok "advisor: off (no advisorModel set; Crewforth never turns it on)"; fi
754
+ elif [ "${CLAUDE_CODE_DISABLE_ADVISOR_TOOL:-}" = 1 ]; then
755
+ warn "advisorModel is %s in %s, but CLAUDE_CODE_DISABLE_ADVISOR_TOOL=1 turns the advisor off" "$_adv" "$_advf"
756
+ elif [ -n "$_advprov" ]; then
757
+ warn "advisorModel is %s in %s, but %s is set and the advisor needs the Anthropic API — it is not used" "$_adv" "$_advf" "$_advprov"
758
+ else
759
+ ok "advisor: on, %s (from %s); not a gate, and its tokens are in /usage and in Studio's session cost" "$_adv" "$_advf"
760
+ case "$_adv" in *haiku*|*sonnet*)
761
+ warn "the advisor (%s) is below the critical tier (opus): Claude Code does not attach an advisor below the model it would advise, so critical work runs without one" "$_adv" ;;
762
+ esac
763
+ fi
764
+ # 9d) The status line. Advisory, never a failure. The installers set Crewforth's only where none is set; a line of
765
+ # the user's own is never replaced (the project's setting would win over it). A managed layer is not read.
766
+ _slj="${SJ:-.claude/eval/lib/settings-json.awk}"; _sl=""; _slf=""
767
+ for _f in .claude/settings.json .claude/settings.local.json "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/settings.json"; do
768
+ [ -f "$_f" ] && [ -f "$_slj" ] || continue
769
+ _v="$(awk -v op=get -v path=statusLine.command -f "$_slj" "$_f" 2>/dev/null)" || _v=""
770
+ [ -n "$_v" ] && { _sl="$_v"; _slf="$_f"; break; }
771
+ done
772
+ case "$_sl" in
773
+ *eval/lib/statusline.sh*) ok "status line: Crewforth's (from %s)" "${_slf/#$HOME/~}" ;;
774
+ ?*) ok "status line: your own (from %s); Crewforth's is not used" "${_slf/#$HOME/~}" ;;
775
+ *) [ -f .claude/eval/lib/statusline.sh ] && ok "status line: none; Crewforth's: bash .claude/eval/lib/statusline.sh --install (Bash tool, not PowerShell)" ;;
776
+ esac
777
+
778
+ # 9e) What model routing costs. Advisory. A verify command the hook was never allowed to run cannot vouch for
779
+ # cheaper work: the ones refused for that reason are listed with the line that allows them (measured on one
780
+ # project: 23 of 71 refusals).
781
+ [ -f .claude/eval/lib/verify-cmd.sh ] && . .claude/eval/lib/verify-cmd.sh # the rule names the command a cd prefix leads to
782
+ _vbn=0; _vbl=""
783
+ for _f in .claude/state/crew-model/results/*; do
784
+ [ -f "$_f" ] || continue
785
+ _vb=0; _vw=""; _vc=""
786
+ while IFS= read -r _l || [ -n "$_l" ]; do
787
+ case "$_l" in verify=blocked) _vb=1 ;; whynot=*) _vw="${_l#whynot=}" ;; cmd=*) _vc="${_l#cmd=}" ;; esac
788
+ done < "$_f"
789
+ [ "$_vb" = 1 ] || continue
790
+ # Both ways of saying "nothing allows it": in auto/bypassPermissions (not on the runner list) and in the other
791
+ # modes (Claude Code itself would not run it unallowed). Measured on Windows: the second was not listed at all.
792
+ case "$_vw" in *"not a test or build command on this hook's list"*|*"does not run a command the user has not allowed"*) ;; *) continue ;; esac
793
+ # A rule names the command alone: `cd sub && ./check.sh` is allowed by `verify ./check.sh` (measured on Windows:
794
+ # the line with the cd in it did not allow it).
795
+ declare -F crew_verify_split >/dev/null && { crew_verify_split "$_vc" .; _vc="$_AMVC"; }
796
+ _vc="${_vc:0:80}"; [ -n "$_vc" ] || continue
797
+ _vbn=$((_vbn+1))
798
+ case "$_vc" in *'('*|*' + '*) continue ;; esac # a sentence, not a command: counted, not offered as a rule
799
+ case "$_vbl" in *"| verify $_vc |"*) ;; *) _vbl="$_vbl| verify $_vc |" ;; esac
800
+ done
801
+ if [ "$_vbn" -gt 0 ]; then
802
+ _vsep=' || '; _vdot=' · '; _vbs="${_vbl//"$_vsep"/$_vdot}"; _vbs="${_vbs#| }"; _vbs="${_vbs% |}"; _vbs="${_vbs:0:300}"
803
+ warn "verify commands never run, %s time(s), because nothing allows them; to let the hook run one, add its line to .claude/crew-model-rules: %s" "$_vbn" "$_vbs"
804
+ fi
805
+ # The organisation preset in force: the block preset.sh wrote at the top of crew-model-rules, asked of preset.sh itself.
806
+ _pre=""; [ -n "$_DOC_LIB" ] && [ -f "$_DOC_LIB/preset.sh" ] && _pre="$(bash "$_DOC_LIB/preset.sh" --show 2>/dev/null)"
807
+ ok "organisation preset: %s" "${_pre:-none}"
808
+
687
809
  # 10) Gate activity. The suite proves the gates CAN fire; this reports whether anything actually tripped them.
688
810
  # Recording is on by default (rule names only, never the command), so "no log" here means no gate has
689
811
  # fired yet — a measured zero, not a gap. Never a failure either way.
@@ -29,6 +29,8 @@ HOOKS="./.claude/hooks"; [ -d "$HOOKS" ] || HOOKS="./hooks"
29
29
  [ -f "$HOOKS/guard-bash.sh" ] || { echo "gate-report: guard-bash.sh not found (run from the project root)" >&2; exit 4; }
30
30
 
31
31
  # Default log location, so `--log` is not required once logging is on.
32
+ # The same rule the gates write by (eval/lib/gate-log.sh): .claude/gate-log.tsv, or the repository's .git.
33
+ if [ -z "$LOG" ] && [ -f ./.claude/eval/lib/gate-log.sh ]; then . ./.claude/eval/lib/gate-log.sh; crew_gate_log_read; LOG="$_CREW_GL"; fi
32
34
  [ -z "$LOG" ] && [ -f "./.claude/gate-log.tsv" ] && LOG="./.claude/gate-log.tsv"
33
35
 
34
36
  TMP="${TMPDIR:-/tmp}/crew-gate-$$"; mkdir -p "$TMP"; trap 'rm -rf "$TMP"' EXIT
@@ -225,3 +225,12 @@ we picked the wrong language for this service, write an adr|!i18n-integrity
225
225
  write the README in english for the public repo|!i18n-integrity
226
226
  the connection strings are missing from appsettings|!i18n-integrity
227
227
  add language support for kotlin to the parser|!i18n-integrity
228
+ try to refute this finding: the token check at src/auth.js:42 can be bypassed|crew-refuter
229
+ disprove this claim before it goes in the report|crew-refuter
230
+ run a security audit of the login flow|!crew-refuter
231
+ review my diff before I commit|!crew-refuter
232
+ update the privacy policy text for the new data retention period|crew-docs-agent
233
+ write the release notes and the changelog entry for this version|crew-docs-agent
234
+ rewrite the app store description for the new release|crew-docs-agent
235
+ add an endpoint that returns the privacy settings|!crew-docs-agent
236
+ fix the failing unit test in the payment module|!crew-docs-agent
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env bash
2
+ # crew-map.sh — the shell entry to scan.mjs. It does one thing: find a Node that RUNS and hand over.
3
+ #
4
+ # bash crew-map.sh [--root DIR] [--stdout | --check] the arguments and exit codes of scan.mjs (0, 1, 2)
5
+ # rc 3 = no usable Node here, so nothing was scanned. Not a pass: a caller must not read 3 as a fresh map.
6
+ #
7
+ # The same resolution as findings.sh beside it: ask node for its version (the Windows Store's stub resolves and
8
+ # then exits 49), and when PATH has none, ask the panel's resolver. This file never installs anything.
9
+ set -u
10
+ # Cut at either separator: on Windows a caller may name this file with backslashes.
11
+ d="${BASH_SOURCE%[/\\]*}"; [ "$d" = "${BASH_SOURCE}" ] && d=.
12
+ FLOOR=18
13
+
14
+ usable(){ local v; v="$("$1" -p 'process.versions.node.split(".")[0]' 2>/dev/null)" || return 1
15
+ case "$v" in ''|*[!0-9]*) return 1 ;; esac; [ "$v" -ge "$FLOOR" ]; }
16
+
17
+ NODE=""
18
+ if usable node; then NODE=node
19
+ elif [ -f "$d/../../../studio/ensure-node.sh" ]; then
20
+ n="$(bash "$d/../../../studio/ensure-node.sh" 2>/dev/null)" && [ -n "$n" ] && usable "$n" && NODE="$n"
21
+ fi
22
+ if [ -z "$NODE" ]; then
23
+ echo "crew-map: no Node $FLOOR+ that runs was found, so nothing was scanned (this is not a pass)" >&2
24
+ exit 3
25
+ fi
26
+ exec "$NODE" "$d/scan.mjs" "$@"