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
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
name: crew-commit-agent
|
|
3
3
|
color: cyan
|
|
4
4
|
description: |
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
Use immediately after the DoD is clean, before any git commit: proposes the Conventional Commits message
|
|
6
|
+
from the staged diff (`commit-message`). Commits only with user approval.
|
|
7
7
|
tools: Read, Grep, Glob, Bash, PowerShell
|
|
8
8
|
model: haiku
|
|
9
9
|
metadata:
|
|
@@ -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
|
|
98
|
-
|
|
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
|
-
|
|
6
|
-
status line
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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:
|
|
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
|
-
- ✅
|
|
74
|
+
- ✅ A phase boundary, or the 🔋 line at medium or more
|
|
73
75
|
- ❌ Content/code generation (out of scope)
|
|
74
76
|
|
|
75
77
|
## Confidence
|
package/kit/eval/doctor.sh
CHANGED
|
@@ -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"
|
|
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{
|
|
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
|
|
647
|
-
#
|
|
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.
|
package/kit/eval/gate-report.sh
CHANGED
|
@@ -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" "$@"
|