crewscore 0.2.0__tar.gz → 0.2.2__tar.gz

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 (62) hide show
  1. crewscore-0.2.2/.github/ISSUE_TEMPLATE/bug_report.md +22 -0
  2. crewscore-0.2.2/.github/ISSUE_TEMPLATE/feature_request.md +14 -0
  3. crewscore-0.2.2/.github/ISSUE_TEMPLATE/scoring_feedback.md +24 -0
  4. {crewscore-0.2.0 → crewscore-0.2.2}/.github/workflows/crewscore-selftest.yml +46 -46
  5. {crewscore-0.2.0 → crewscore-0.2.2}/.github/workflows/example-ci.yml +65 -46
  6. crewscore-0.2.2/.github/workflows/pytest.yml +29 -0
  7. {crewscore-0.2.0 → crewscore-0.2.2}/.gitignore +13 -13
  8. {crewscore-0.2.0 → crewscore-0.2.2}/AGENTS.md +90 -72
  9. crewscore-0.2.2/CONTRIBUTING.md +49 -0
  10. {crewscore-0.2.0 → crewscore-0.2.2}/PKG-INFO +105 -30
  11. {crewscore-0.2.0 → crewscore-0.2.2}/README.md +359 -284
  12. crewscore-0.2.2/action.yml +98 -0
  13. {crewscore-0.2.0 → crewscore-0.2.2}/crewscore/__init__.py +3 -3
  14. {crewscore-0.2.0 → crewscore-0.2.2}/crewscore/cli.py +618 -403
  15. {crewscore-0.2.0 → crewscore-0.2.2}/crewscore/report.py +214 -171
  16. crewscore-0.2.2/crewscore/rules_catalog.py +127 -0
  17. crewscore-0.2.2/crewscore/scan.py +151 -0
  18. {crewscore-0.2.0 → crewscore-0.2.2}/crewscore/scorers/structural_analysis.py +472 -359
  19. crewscore-0.2.2/crewscore/scoring.py +116 -0
  20. {crewscore-0.2.0 → crewscore-0.2.2}/crewscore/vendor_scorecard.py +409 -412
  21. crewscore-0.2.2/crewscore/web_export.py +326 -0
  22. crewscore-0.2.2/docs/demo.svg +54 -0
  23. {crewscore-0.2.0 → crewscore-0.2.2}/docs/launch/README.md +57 -57
  24. {crewscore-0.2.0 → crewscore-0.2.2}/docs/launch/devto.md +107 -107
  25. {crewscore-0.2.0 → crewscore-0.2.2}/docs/launch/linkedin.md +49 -49
  26. {crewscore-0.2.0 → crewscore-0.2.2}/docs/launch/reddit.md +105 -105
  27. {crewscore-0.2.0 → crewscore-0.2.2}/docs/launch/show-hn.md +64 -64
  28. {crewscore-0.2.0 → crewscore-0.2.2}/docs/launch/x-post.md +64 -64
  29. crewscore-0.2.2/docs/next-steps-eval.md +72 -0
  30. {crewscore-0.2.0 → crewscore-0.2.2}/docs/publish-checklist.md +146 -132
  31. crewscore-0.2.2/docs/research/2026-07-28-useful-product-and-virality-research.md +318 -0
  32. {crewscore-0.2.0 → crewscore-0.2.2}/docs/superpowers/plans/2026-07-28-crewscore-viral-launch.md +457 -457
  33. crewscore-0.2.2/docs/superpowers/plans/2026-07-28-useful-product-slice.md +63 -0
  34. crewscore-0.2.2/docs/superpowers/plans/2026-07-28-workstream-a-scoring-report.md +84 -0
  35. crewscore-0.2.2/docs/superpowers/plans/2026-07-28-workstream-b-scan-report.md +184 -0
  36. crewscore-0.2.2/docs/superpowers/plans/2026-07-28-workstream-cd-product-action-report.md +113 -0
  37. {crewscore-0.2.0 → crewscore-0.2.2}/docs/viral-product-spec-2026-07-28.md +354 -354
  38. {crewscore-0.2.0 → crewscore-0.2.2}/examples/sample-prompt.md +1 -1
  39. crewscore-0.2.2/favicon.ico +0 -0
  40. crewscore-0.2.2/favicon.svg +5 -0
  41. crewscore-0.2.2/index.html +556 -0
  42. {crewscore-0.2.0 → crewscore-0.2.2}/pyproject.toml +62 -62
  43. crewscore-0.2.2/score-engine.js +706 -0
  44. crewscore-0.2.2/scripts/export_web_engine.py +23 -0
  45. crewscore-0.2.2/tests/test_action_manifest.py +55 -0
  46. {crewscore-0.2.0 → crewscore-0.2.2}/tests/test_cli.py +148 -98
  47. {crewscore-0.2.0 → crewscore-0.2.2}/tests/test_explain.py +145 -108
  48. {crewscore-0.2.0 → crewscore-0.2.2}/tests/test_report.py +130 -114
  49. crewscore-0.2.2/tests/test_rules_catalog.py +105 -0
  50. crewscore-0.2.2/tests/test_scan.py +263 -0
  51. {crewscore-0.2.0 → crewscore-0.2.2}/tests/test_structural_analysis.py +130 -86
  52. {crewscore-0.2.0 → crewscore-0.2.2}/tests/test_vendor.py +170 -152
  53. crewscore-0.2.2/tests/test_web_engine.py +149 -0
  54. crewscore-0.2.0/action.yml +0 -62
  55. crewscore-0.2.0/crewscore/scoring.py +0 -75
  56. crewscore-0.2.0/index.html +0 -274
  57. crewscore-0.2.0/tests/test_action_manifest.py +0 -10
  58. {crewscore-0.2.0 → crewscore-0.2.2}/CNAME +0 -0
  59. {crewscore-0.2.0 → crewscore-0.2.2}/LICENSE +0 -0
  60. {crewscore-0.2.0 → crewscore-0.2.2}/crewscore/scorers/__init__.py +0 -0
  61. {crewscore-0.2.0 → crewscore-0.2.2}/crewscore/scorers/fix_patterns.py +0 -0
  62. {crewscore-0.2.0 → crewscore-0.2.2}/docs/pmf-research-2026-07-28.md +0 -0
@@ -0,0 +1,22 @@
1
+ ---
2
+ name: Bug report
3
+ about: Something broken in CLI, Action, or web scorecard
4
+ title: "[bug] "
5
+ labels: bug
6
+ ---
7
+
8
+ ## What happened
9
+
10
+ ## Expected
11
+
12
+ ## Repro
13
+
14
+ ```bash
15
+ crewscore test --prompt "..."
16
+ ```
17
+
18
+ ## Environment
19
+
20
+ - OS:
21
+ - `crewscore --version`:
22
+ - Install method: pip / source
@@ -0,0 +1,14 @@
1
+ ---
2
+ name: Feature request
3
+ about: New dimension, fix template, or CI surface
4
+ title: "[feat] "
5
+ labels: enhancement
6
+ ---
7
+
8
+ ## Problem
9
+
10
+ ## Proposed solution
11
+
12
+ ## Why not a runtime / adversarial tool instead?
13
+
14
+ CrewScore stays offline structural by default. Say if this must stay structural.
@@ -0,0 +1,24 @@
1
+ ---
2
+ name: Scoring false positive/negative
3
+ about: Pattern matched wrong or missed a real guardrail
4
+ title: "[scoring] "
5
+ labels: scoring
6
+ ---
7
+
8
+ ## Dimension
9
+
10
+ injection / hallucination / citation / cost / human_gate / safe_stop / audit / compliance
11
+
12
+ ## Prompt excerpt (redact secrets)
13
+
14
+ ```
15
+ ```
16
+
17
+ ## What CrewScore did
18
+
19
+ - Score:
20
+ - Matched / missing (from `--explain` if possible):
21
+
22
+ ## What you expected
23
+
24
+ ## Suggested pattern (optional)
@@ -1,46 +1,46 @@
1
- # Self-test for the composite CrewScore action in this repo.
2
- # Installs from github.action_path so it works before PyPI publish.
3
- name: CrewScore Self-Test
4
-
5
- on:
6
- push:
7
- pull_request:
8
-
9
- jobs:
10
- selftest:
11
- runs-on: ubuntu-latest
12
- steps:
13
- - name: Checkout
14
- uses: actions/checkout@v4
15
-
16
- - name: Score sample prompt (smoke, threshold 0)
17
- id: score
18
- uses: ./
19
- with:
20
- prompt-file: examples/sample-prompt.md
21
- threshold: "0"
22
-
23
- - name: Assert score and tier outputs parse
24
- run: |
25
- echo "score=${{ steps.score.outputs.score }}"
26
- echo "tier=${{ steps.score.outputs.tier }}"
27
- python -c "
28
- import sys
29
- score = int(sys.argv[1])
30
- tier = sys.argv[2]
31
- assert 0 <= score <= 100, score
32
- assert tier, 'tier output empty'
33
- print(f'OK score={score} tier={tier!r}')
34
- " "${{ steps.score.outputs.score }}" "${{ steps.score.outputs.tier }}"
35
-
36
- - name: Threshold gate fails when score is below threshold
37
- run: |
38
- set +e
39
- crewscore test --prompt-file examples/sample-prompt.md --json --threshold 50
40
- EXIT=$?
41
- set -e
42
- if [ "$EXIT" -ne 2 ]; then
43
- echo "Expected exit code 2 for bare sample prompt under threshold 50, got $EXIT"
44
- exit 1
45
- fi
46
- echo "Threshold failure behaved as expected (exit 2)"
1
+ # Self-test for the composite CrewScore action in this repo.
2
+ # Installs from github.action_path so it works before PyPI publish.
3
+ name: CrewScore Self-Test
4
+
5
+ on:
6
+ push:
7
+ pull_request:
8
+
9
+ jobs:
10
+ selftest:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - name: Checkout
14
+ uses: actions/checkout@v4
15
+
16
+ - name: Score sample prompt (smoke, threshold 0)
17
+ id: score
18
+ uses: ./
19
+ with:
20
+ prompt-file: examples/sample-prompt.md
21
+ threshold: "0"
22
+
23
+ - name: Assert score and tier outputs parse
24
+ run: |
25
+ echo "score=${{ steps.score.outputs.score }}"
26
+ echo "tier=${{ steps.score.outputs.tier }}"
27
+ python -c "
28
+ import sys
29
+ score = int(sys.argv[1])
30
+ tier = sys.argv[2]
31
+ assert 0 <= score <= 100, score
32
+ assert tier, 'tier output empty'
33
+ print(f'OK score={score} tier={tier!r}')
34
+ " "${{ steps.score.outputs.score }}" "${{ steps.score.outputs.tier }}"
35
+
36
+ - name: Threshold gate fails when score is below threshold
37
+ run: |
38
+ set +e
39
+ crewscore test --prompt-file examples/sample-prompt.md --json --threshold 50
40
+ EXIT=$?
41
+ set -e
42
+ if [ "$EXIT" -ne 2 ]; then
43
+ echo "Expected exit code 2 for bare sample prompt under threshold 50, got $EXIT"
44
+ exit 1
45
+ fi
46
+ echo "Threshold failure behaved as expected (exit 2)"
@@ -1,46 +1,65 @@
1
- # Documented copy-paste example for consumers.
2
- #
3
- # In your own repo, prefer the published tag:
4
- # uses: shmindmaster/crewscore@v1
5
- #
6
- # When developing this monorepo (or a fork), local path works:
7
- # uses: ./
8
- #
9
- # Point prompt-file at your agent system prompt. The sample path below is only
10
- # for illustration; examples/sample-prompt.md intentionally scores low.
11
- #
12
- # workflow_dispatch only so this example does not fail default CI on the bare
13
- # sample prompt. Use crewscore-selftest.yml for green self-tests.
14
- name: CrewScore CI Example
15
-
16
- on:
17
- workflow_dispatch:
18
-
19
- jobs:
20
- score:
21
- runs-on: ubuntu-latest
22
- steps:
23
- - name: Checkout
24
- uses: actions/checkout@v4
25
-
26
- # Published action (recommended for consumer repos):
27
- # - name: CrewScore
28
- # uses: shmindmaster/crewscore@v1
29
- # with:
30
- # prompt-file: agents/system-prompt.md
31
- # threshold: "50"
32
- # # explain: "true"
33
-
34
- # Local composite action (this repo / monorepo self-check):
35
- - name: CrewScore
36
- id: crewscore
37
- uses: ./
38
- with:
39
- prompt-file: examples/sample-prompt.md
40
- threshold: "50"
41
-
42
- - name: Use score outputs
43
- if: always()
44
- run: |
45
- echo "score=${{ steps.crewscore.outputs.score }}"
46
- echo "tier=${{ steps.crewscore.outputs.tier }}"
1
+ # Documented copy-paste example for consumers.
2
+ #
3
+ # In your own repo, prefer the published tag:
4
+ # uses: shmindmaster/crewscore@v1
5
+ #
6
+ # When developing this monorepo (or a fork), local path works:
7
+ # uses: ./
8
+ #
9
+ # Point prompt-file at your agent system prompt. The sample path below is only
10
+ # for illustration; examples/sample-prompt.md intentionally scores low.
11
+ #
12
+ # Prefer scan-path when the repo has multiple agent artifacts (AGENTS.md,
13
+ # system-prompt.md, prompts/*, etc.). The Action reports the worst (min) overall.
14
+ #
15
+ # workflow_dispatch only so this example does not fail default CI on the bare
16
+ # sample prompt. Use crewscore-selftest.yml for green self-tests.
17
+ name: CrewScore CI Example
18
+
19
+ on:
20
+ workflow_dispatch:
21
+
22
+ jobs:
23
+ score:
24
+ runs-on: ubuntu-latest
25
+ steps:
26
+ - name: Checkout
27
+ uses: actions/checkout@v4
28
+
29
+ # Published action (recommended for consumer repos):
30
+ # - name: CrewScore
31
+ # uses: shmindmaster/crewscore@v1
32
+ # with:
33
+ # prompt-file: agents/system-prompt.md
34
+ # threshold: "50"
35
+ # # explain: "true"
36
+
37
+ # Repo-wide structural scan (preferred when you have multiple agent files):
38
+ # - name: CrewScore scan
39
+ # id: crewscore
40
+ # uses: shmindmaster/crewscore@v1
41
+ # with:
42
+ # scan-path: "."
43
+ # threshold: "50"
44
+
45
+ # Local composite action (this repo / monorepo self-check) — single file:
46
+ - name: CrewScore
47
+ id: crewscore
48
+ uses: ./
49
+ with:
50
+ prompt-file: examples/sample-prompt.md
51
+ threshold: "50"
52
+
53
+ # Local scan example (uncomment when `crewscore scan` is available):
54
+ # - name: CrewScore scan
55
+ # id: crewscore-scan
56
+ # uses: ./
57
+ # with:
58
+ # scan-path: "."
59
+ # threshold: "50"
60
+
61
+ - name: Use score outputs
62
+ if: always()
63
+ run: |
64
+ echo "score=${{ steps.crewscore.outputs.score }}"
65
+ echo "tier=${{ steps.crewscore.outputs.tier }}"
@@ -0,0 +1,29 @@
1
+ name: pytest
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ubuntu-latest
11
+ strategy:
12
+ matrix:
13
+ python-version: ["3.11", "3.12", "3.13"]
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ - uses: actions/setup-python@v5
17
+ with:
18
+ python-version: ${{ matrix.python-version }}
19
+ - name: Install
20
+ run: pip install -e ".[dev]"
21
+ - name: Export web engine (freshness check via tests)
22
+ run: python scripts/export_web_engine.py
23
+ - name: Test
24
+ run: pytest -q
25
+ - name: Node parity (optional extra)
26
+ run: |
27
+ if command -v node >/dev/null; then
28
+ node -e "console.log('node', process.version)"
29
+ fi
@@ -1,14 +1,14 @@
1
- __pycache__/
2
- *.pyc
3
- *.egg-info/
4
- dist/
5
- build/
6
- .venv/
7
- .env
8
- *.sqlite3
9
- agent-guard-report-*.html
10
- .DS_Store
11
-
12
- .superpowers/
13
- .worktrees/
1
+ __pycache__/
2
+ *.pyc
3
+ *.egg-info/
4
+ dist/
5
+ build/
6
+ .venv/
7
+ .env
8
+ *.sqlite3
9
+ agent-guard-report-*.html
10
+ .DS_Store
11
+
12
+ .superpowers/
13
+ .worktrees/
14
14
 
@@ -1,72 +1,90 @@
1
- # CrewScore — agent instructions
2
-
3
- ## What this is
4
-
5
- Offline CLI that **structurally** scores AI agent system prompts for production-readiness signals (injection defense, hallucination policy, citations, cost limits, human gates, safe-stop, audit, compliance), applies fix patterns, and runs a non-technical AI vendor checklist.
6
-
7
- Public brand: **CrewScore** · Domain: **https://crewscore.ai** · PyPI: **`crewscore`** · Repo: **shmindmaster/crewscore**
8
-
9
- It does **not** (yet) run live adversarial LLM attacks or parse LangGraph/CrewAI runtimes.
10
-
11
- ## Stack
12
-
13
- - Python 3.11+
14
- - click + rich
15
- - hatchling packaging
16
- - pytest
17
-
18
- ## Commands
19
-
20
- ```bash
21
- # install (editable)
22
- pip install -e ".[dev]"
23
-
24
- # score a prompt
25
- crewscore test --prompt "You are a helpful assistant..."
26
- crewscore test --prompt-file ./system-prompt.md
27
- crewscore test --prompt-file ./system-prompt.md --json
28
- crewscore test --prompt-file ./system-prompt.md --json --threshold 50
29
-
30
- # apply guardrail patterns
31
- crewscore fix --prompt-file ./system-prompt.md
32
- crewscore fix --prompt-file ./system-prompt.md --apply
33
- crewscore fix --prompt-file ./system-prompt.md --output ./guarded.md --json
34
-
35
- # vendor checklist
36
- crewscore assess-vendor --name "Acme AI" --answers "y,y,n,dk,y,y,n,y,n,y" --json
37
-
38
- # tests
39
- pytest
40
- ```
41
-
42
- Legacy CLI entry point `agent-guard` still maps to the same `crewscore.cli:main` after install.
43
-
44
- ## Layout
45
-
46
- ```
47
- crewscore/
48
- cli.py # click entry (test, fix)
49
- scoring.py # shared result model / tiers
50
- vendor_scorecard.py # assess-vendor command
51
- scorers/
52
- structural_analysis.py
53
- fix_patterns.py
54
- tests/
55
- index.html # static browser demo (client-side structural scan)
56
- ```
57
-
58
- ## Product constraints
59
-
60
- - Prefer honest capability claims over roadmap theater.
61
- - Structural scores are pattern matches on prompt text, not proof of runtime behavior.
62
- - Keep the package dependency-light (no LLM SDKs required for the core path).
63
- - Fame follows usefulness: explainable findings, fix, CI gate before launch theater.
64
- - Breaking CLI flags are acceptable if all docs and tests update in the same change.
65
- - Never document `pip install agent-guard` as *this* product (that PyPI name is taken by another package).
66
-
67
- ## Do not
68
-
69
- - Reintroduce fake `--langgraph` / `--crewai` loaders or adversarial mode stubs without real implementations.
70
- - Link to non-existent report hosts or wrong GitHub/PyPI names.
71
- - Add empty `examples/` / `evaluator/` / `patterns/` directories without content.
72
- - Overclaim “production safety certification” or “7 regulated systems” beyond structural scanning.
1
+ # CrewScore — agent instructions
2
+
3
+ ## What this is
4
+
5
+ Offline CLI that **structurally** scores AI agent system prompts for production-readiness signals (injection defense, hallucination policy, citations, cost limits, human gates, safe-stop, audit, compliance), applies fix patterns, and optionally runs a non-technical AI vendor checklist (self-attest only).
6
+
7
+ Public brand: **CrewScore** · Domain: **https://crewscore.ai** · PyPI: **`crewscore`** · Repo: **shmindmaster/crewscore**
8
+
9
+ It does **not** (yet) run live adversarial LLM attacks or parse LangGraph/CrewAI runtimes. For live testing, hand off to Promptfoo / garak — see `docs/next-steps-eval.md`.
10
+
11
+ ## Stack
12
+
13
+ - Python 3.11+
14
+ - click + rich
15
+ - hatchling packaging
16
+ - pytest
17
+
18
+ ## Commands
19
+
20
+ ```bash
21
+ # install (editable)
22
+ pip install -e ".[dev]"
23
+
24
+ # repo scan (preferred for CI / monorepos)
25
+ crewscore scan .
26
+ crewscore scan . --json --threshold 50
27
+
28
+ # score a single prompt
29
+ crewscore test --prompt "You are a helpful assistant..."
30
+ crewscore test --prompt-file ./system-prompt.md --explain
31
+ crewscore test --prompt-file ./system-prompt.md --json --explain
32
+ crewscore test --prompt-file ./system-prompt.md --json --threshold 50
33
+ crewscore test --prompt-file ./system-prompt.md --report out.html --badge badge.svg
34
+
35
+ # apply guardrail patterns
36
+ crewscore fix --prompt-file ./system-prompt.md
37
+ crewscore fix --prompt-file ./system-prompt.md --apply
38
+ crewscore fix --prompt-file ./system-prompt.md --output ./guarded.md --json
39
+
40
+ # vendor checklist (secondary / self-attest)
41
+ crewscore assess-vendor --name "Acme AI" --answers "y,y,n,dk,y,y,n,y,n,y" --json
42
+
43
+ # after pattern changes: keep web in lockstep
44
+ python scripts/export_web_engine.py
45
+
46
+ # tests
47
+ pytest
48
+ ```
49
+
50
+ Legacy CLI entry point `agent-guard` still maps to the same `crewscore.cli:main` after install.
51
+
52
+ ## Layout
53
+
54
+ ```
55
+ crewscore/
56
+ cli.py # click entry (test, fix, scan)
57
+ scoring.py # shared result model / tiers
58
+ vendor_scorecard.py # assess-vendor command
59
+ web_export.py # builds score-engine.js payload
60
+ report.py # HTML report + SVG badge
61
+ scorers/
62
+ structural_analysis.py
63
+ fix_patterns.py
64
+ scripts/export_web_engine.py
65
+ score-engine.js # generated commit after pattern changes
66
+ index.html # builder-first site (uses score-engine.js)
67
+ action.yml # composite GH Action (prompt-file or scan-path)
68
+ docs/launch/ # launch copy kit
69
+ docs/next-steps-eval.md # Promptfoo / garak handoff
70
+ tests/
71
+ ```
72
+
73
+ ## Product constraints
74
+
75
+ - Prefer honest capability claims over roadmap theater.
76
+ - Structural scores are pattern matches on prompt text, not proof of runtime behavior.
77
+ - **Honesty scoring:** do not claim certification, audit, or red-team results; templates can inflate scores; under-score rather than over-claim.
78
+ - Prefer `crewscore scan .` / Action `scan-path` for repo-native hygiene; demote vendor checklist in UX and docs.
79
+ - Keep the package dependency-light (no LLM SDKs required for the core path).
80
+ - Fame follows usefulness: explainable findings, fix, CI gate before launch theater.
81
+ - Breaking CLI flags are acceptable if all docs and tests update in the same change.
82
+ - Never document `pip install agent-guard` as *this* product (that PyPI name is taken by another package).
83
+
84
+ ## Do not
85
+
86
+ - Reintroduce fake `--langgraph` / `--crewai` loaders or adversarial mode stubs without real implementations.
87
+ - Link to non-existent report hosts or wrong GitHub/PyPI names.
88
+ - Add empty `examples/` / `evaluator/` / `patterns/` directories without content.
89
+ - Overclaim “production safety certification” or “7 regulated systems” beyond structural scanning.
90
+ - Elevate the vendor self-attest checklist to equal primary product surface.
@@ -0,0 +1,49 @@
1
+ # Contributing to CrewScore
2
+
3
+ Thanks for helping improve an offline structural scorecard for AI agent prompts.
4
+
5
+ ## Dev setup
6
+
7
+ ```bash
8
+ git clone https://github.com/shmindmaster/crewscore.git
9
+ cd crewscore
10
+ pip install -e ".[dev]"
11
+ pytest -q
12
+ ```
13
+
14
+ ## How scoring works
15
+
16
+ - Patterns live in `crewscore/scorers/structural_analysis.py` (`SCORER_MAP`).
17
+ - Scores are match counts mapped to 0–100 (see `_score_from_match_count`).
18
+ - Explain labels: `DIMENSION_SIGNAL_LABELS` (pattern → human label pairs).
19
+ - CLI: `crewscore test`, `fix`, `assess-vendor`.
20
+ - **Web uses the same engine:** after changing patterns, regenerate:
21
+
22
+ ```bash
23
+ python scripts/export_web_engine.py
24
+ pytest tests/test_web_engine.py -q
25
+ ```
26
+
27
+ Commit the updated `score-engine.js` with your pattern change.
28
+
29
+ ## Adding a pattern
30
+
31
+ 1. Add a regex to the right list in `structural_analysis.py`.
32
+ 2. Optionally add a `(pattern, human_label)` to `DIMENSION_SIGNAL_LABELS`.
33
+ 3. Add/adjust a unit test in `tests/test_structural_analysis.py` or `tests/test_explain.py`.
34
+ 4. Run `python scripts/export_web_engine.py` and `pytest -q`.
35
+
36
+ ## Adding a fix template
37
+
38
+ Edit `crewscore/scorers/fix_patterns.py` `FIX_TEMPLATES` for the dimension key.
39
+
40
+ ## PR rules
41
+
42
+ - Prefer TDD for behavior changes.
43
+ - Keep claims honest: structural ≠ runtime red-team.
44
+ - Never document `pip install agent-guard` as this product.
45
+ - Do not add LLM API dependencies for the core path.
46
+
47
+ ## Code of conduct
48
+
49
+ Be respectful. File false-positive / false-negative scoring issues with the prompt text and expected dimension.