devrites 2.2.0 → 2.4.0

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 (53) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +30 -17
  3. package/docs/architecture.md +30 -24
  4. package/docs/command-map.md +15 -6
  5. package/docs/flow.md +19 -5
  6. package/docs/orchestration.md +17 -7
  7. package/docs/skills.md +32 -8
  8. package/pack/.claude/agents/devrites-code-reviewer.md +6 -1
  9. package/pack/.claude/agents/devrites-devex-reviewer.md +94 -0
  10. package/pack/.claude/agents/devrites-forge-judge.md +92 -0
  11. package/pack/.claude/agents/devrites-frontend-reviewer.md +8 -0
  12. package/pack/.claude/agents/devrites-retrospector.md +91 -0
  13. package/pack/.claude/agents/devrites-slice-wright.md +18 -5
  14. package/pack/.claude/rules/README.md +5 -2
  15. package/pack/.claude/rules/agents.md +30 -2
  16. package/pack/.claude/rules/anti-patterns.md +11 -0
  17. package/pack/.claude/rules/code-review.md +16 -6
  18. package/pack/.claude/rules/core.md +13 -4
  19. package/pack/.claude/rules/developer-experience.md +119 -0
  20. package/pack/.claude/rules/principles.md +158 -0
  21. package/pack/.claude/rules/spec-grammar.md +106 -0
  22. package/pack/.claude/skills/devrites-browser-proof/SKILL.md +42 -3
  23. package/pack/.claude/skills/devrites-doubt/SKILL.md +1 -1
  24. package/pack/.claude/skills/devrites-lib/SKILL.md +9 -2
  25. package/pack/.claude/skills/devrites-lib/scripts/devrites.sh +8 -0
  26. package/pack/.claude/skills/devrites-lib/scripts/doubt-coverage.sh +39 -0
  27. package/pack/.claude/skills/devrites-lib/scripts/spec-validate.sh +130 -0
  28. package/pack/.claude/skills/rite-adopt/SKILL.md +13 -1
  29. package/pack/.claude/skills/rite-autocomplete/SKILL.md +3 -1
  30. package/pack/.claude/skills/rite-build/SKILL.md +51 -2
  31. package/pack/.claude/skills/rite-build/reference/anti-patterns.md +12 -0
  32. package/pack/.claude/skills/rite-build/reference/forge.md +171 -0
  33. package/pack/.claude/skills/rite-build/reference/one-slice-cycle.md +2 -0
  34. package/pack/.claude/skills/rite-build/reference/wright-dispatch.md +22 -2
  35. package/pack/.claude/skills/rite-define/SKILL.md +14 -1
  36. package/pack/.claude/skills/rite-frame/SKILL.md +7 -2
  37. package/pack/.claude/skills/rite-learn/SKILL.md +17 -4
  38. package/pack/.claude/skills/rite-polish/SKILL.md +3 -1
  39. package/pack/.claude/skills/rite-prove/SKILL.md +30 -1
  40. package/pack/.claude/skills/rite-quick/SKILL.md +9 -4
  41. package/pack/.claude/skills/rite-review/SKILL.md +5 -2
  42. package/pack/.claude/skills/rite-seal/SKILL.md +39 -4
  43. package/pack/.claude/skills/rite-seal/reference/anti-patterns.md +2 -0
  44. package/pack/.claude/skills/rite-ship/SKILL.md +21 -0
  45. package/pack/.claude/skills/rite-spec/SKILL.md +29 -5
  46. package/pack/.claude/skills/rite-spec/reference/spec-template.md +11 -1
  47. package/pack/.claude/skills/rite-status/SKILL.md +3 -1
  48. package/pack/.claude/skills/rite-vet/SKILL.md +46 -14
  49. package/package.json +1 -1
  50. package/scripts/check-cross-refs.py +4 -0
  51. package/scripts/run-behavioral-evals.sh +170 -0
  52. package/scripts/run-evals.sh +3 -0
  53. package/scripts/validate.sh +1 -1
@@ -0,0 +1,170 @@
1
+ #!/usr/bin/env bash
2
+ # scripts/run-behavioral-evals.sh — validate the SHAPE of DevRites behavioral evals.
3
+ #
4
+ # Trigger evals (run-evals.sh) test whether the right skill *fires*. Behavioral
5
+ # evals test whether a gating skill's discipline *holds under pressure* — does it
6
+ # resist the rationalizations it documents in `rules/anti-patterns.md` (and its own
7
+ # `reference/anti-patterns.md`), or does the agent talk itself past the gate. Each
8
+ # scenario pairs a pressure prompt with the resistance a holding response shows and
9
+ # the capitulation markers a failed one shows.
10
+ #
11
+ # This script is the DETERMINISTIC, zero-token CI gate — the analog of run-evals.sh's
12
+ # schema path and spec-validate.sh: it checks that every behavioral eval is well-formed
13
+ # so a malformed one can't reach the live grader. It does NOT invoke a model. Executing
14
+ # the scenarios against a live Claude (does the skill actually resist?) is the labeled /
15
+ # nightly rung documented in evals/behavioral/README.md.
16
+ #
17
+ # Usage:
18
+ # scripts/run-behavioral-evals.sh # validate every evals/behavioral/*.json
19
+ # scripts/run-behavioral-evals.sh evals/behavioral/rite-prove.json # validate one file
20
+ #
21
+ # Exit: 0 all valid (or no behavioral evals present — opt-in, never a failure) ·
22
+ # 1 shape violation(s) · 2 missing parser
23
+
24
+ set -euo pipefail
25
+
26
+ ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
27
+ # Overridable so the test harness can exercise the opt-in no-op path against a
28
+ # scratch directory; defaults to the real behavioral-eval set.
29
+ BEHAVIORAL_DIR="${DEVRITES_BEHAVIORAL_DIR:-$ROOT/evals/behavioral}"
30
+
31
+ if [[ $# -gt 0 ]]; then
32
+ FILES=("$@")
33
+ else
34
+ if [[ ! -d "$BEHAVIORAL_DIR" ]]; then
35
+ echo "No evals/behavioral/ directory — behavioral evals are opt-in; nothing to validate."
36
+ exit 0
37
+ fi
38
+ FILES=()
39
+ while IFS= read -r f; do
40
+ [[ "$f" == */README.md ]] && continue
41
+ FILES+=("$f")
42
+ done < <(find "$BEHAVIORAL_DIR" -type f -name '*.json' | sort)
43
+ fi
44
+
45
+ if [[ ${#FILES[@]} -eq 0 ]]; then
46
+ echo "No behavioral eval files — behavioral evals are opt-in; nothing to validate."
47
+ exit 0
48
+ fi
49
+
50
+ if command -v python3 >/dev/null 2>&1; then
51
+ PARSER="python3"
52
+ elif command -v jq >/dev/null 2>&1; then
53
+ PARSER="jq"
54
+ else
55
+ echo "Need python3 or jq to validate JSON." >&2
56
+ exit 2
57
+ fi
58
+
59
+ FAILED=0
60
+ TOTAL=0
61
+ SCENARIOS=0
62
+
63
+ for file in "${FILES[@]}"; do
64
+ TOTAL=$((TOTAL + 1))
65
+ printf '== %s ==\n' "$file"
66
+
67
+ if [[ "$PARSER" == "python3" ]]; then
68
+ if OUT=$(python3 - "$file" <<'PY'
69
+ import json, sys, pathlib
70
+ path = pathlib.Path(sys.argv[1])
71
+ try:
72
+ data = json.loads(path.read_text())
73
+ except Exception as e:
74
+ print(f" FAIL: INVALID JSON: {e}")
75
+ sys.exit(1)
76
+
77
+ errors = []
78
+ for key in ("skill", "description", "scenarios"):
79
+ if key not in data:
80
+ errors.append(f"missing top-level key: {key}")
81
+
82
+ scenarios = data.get("scenarios", [])
83
+ if not isinstance(scenarios, list):
84
+ errors.append("scenarios is not a list")
85
+ scenarios = []
86
+ elif len(scenarios) == 0:
87
+ errors.append("scenarios is empty — a behavioral eval needs at least one")
88
+
89
+ seen_ids = {}
90
+ for i, s in enumerate(scenarios):
91
+ if not isinstance(s, dict):
92
+ errors.append(f"scenario[{i}] not an object")
93
+ continue
94
+ sid = s.get("id")
95
+ if not sid or not isinstance(sid, str):
96
+ errors.append(f"scenario[{i}] missing non-empty string id")
97
+ elif sid in seen_ids:
98
+ errors.append(f"scenario[{i}] duplicate id {sid!r} (also scenario[{seen_ids[sid]}])")
99
+ else:
100
+ seen_ids[sid] = i
101
+ where = sid or f"[{i}]"
102
+ # Non-empty string fields.
103
+ for k in ("rationalization", "pressure", "source"):
104
+ v = s.get(k)
105
+ if not isinstance(v, str) or not v.strip():
106
+ errors.append(f"scenario {where} missing non-empty {k}")
107
+ # Non-empty list-of-string fields.
108
+ for k in ("expected_resistance", "capitulation_markers"):
109
+ v = s.get(k)
110
+ if not isinstance(v, list) or len(v) == 0:
111
+ errors.append(f"scenario {where} missing non-empty {k} list")
112
+ elif not all(isinstance(x, str) and x.strip() for x in v):
113
+ errors.append(f"scenario {where} {k} has an empty / non-string entry")
114
+
115
+ if errors:
116
+ for e in errors:
117
+ print(f" FAIL: {e}")
118
+ sys.exit(1)
119
+
120
+ print(f" skill: {data['skill']}")
121
+ print(f" scenarios: {len(scenarios)}")
122
+ print(f"__COUNT__ {len(scenarios)}")
123
+ PY
124
+ ); then rc=0; else rc=$?; fi
125
+ else
126
+ if OUT=$(jq -r '
127
+ if (.skill and .description and (.scenarios|type=="array") and (.scenarios|length > 0)) then
128
+ ( [ .scenarios[]
129
+ | select(
130
+ ((.id|type=="string") and (.id|length>0))
131
+ and ((.rationalization|type=="string") and (.rationalization|length>0))
132
+ and ((.pressure|type=="string") and (.pressure|length>0))
133
+ and ((.source|type=="string") and (.source|length>0))
134
+ and ((.expected_resistance|type=="array") and (.expected_resistance|length>0))
135
+ and ((.capitulation_markers|type=="array") and (.capitulation_markers|length>0))
136
+ ) ] | length
137
+ ) as $ok
138
+ | if $ok == (.scenarios|length)
139
+ then " skill: \(.skill)\n scenarios: \(.scenarios|length)\n__COUNT__ \(.scenarios|length)"
140
+ else " FAIL: \((.scenarios|length) - $ok) scenario(s) missing required fields"
141
+ end
142
+ else
143
+ " FAIL: missing required keys or empty scenarios"
144
+ end
145
+ ' "$file"); then rc=0; else rc=$?; fi
146
+ fi
147
+
148
+ COUNT=$(printf '%s\n' "$OUT" | sed -n 's/^__COUNT__ //p')
149
+ OUT=$(printf '%s\n' "$OUT" | grep -v '^__COUNT__' || true)
150
+ printf '%s\n' "$OUT"
151
+
152
+ if [[ ${rc:-0} -ne 0 ]] || [[ "$OUT" == *"FAIL"* ]]; then
153
+ FAILED=$((FAILED + 1))
154
+ else
155
+ SCENARIOS=$((SCENARIOS + ${COUNT:-0}))
156
+ fi
157
+ done
158
+
159
+ echo
160
+ printf 'Validated %d behavioral eval file(s); %d scenario(s); %d failed.\n' "$TOTAL" "$SCENARIOS" "$FAILED"
161
+
162
+ if [[ $FAILED -gt 0 ]]; then
163
+ exit 1
164
+ fi
165
+
166
+ echo
167
+ echo "Note: this is shape validation only — it does not execute the scenarios."
168
+ echo "To grade whether the skills actually resist under pressure (live model):"
169
+ echo " see evals/behavioral/README.md — the labeled / nightly rung."
170
+ exit 0
@@ -26,6 +26,9 @@ else
26
26
  FILES=()
27
27
  while IFS= read -r f; do
28
28
  [[ "$f" == */README.md ]] && continue
29
+ # Behavioral evals have their own schema + validator (run-behavioral-evals.sh);
30
+ # they are not 20-query trigger evals, so keep them out of this scan.
31
+ [[ "$f" == */behavioral/* ]] && continue
29
32
  FILES+=("$f")
30
33
  done < <(find "$EVALS_DIR" -type f -name '*.json' | sort)
31
34
  fi
@@ -14,7 +14,7 @@ good() { printf 'ok: %s\n' "$*"; }
14
14
 
15
15
  PUBLIC="rite rite-spec rite-adopt rite-temper rite-define rite-vet rite-plan rite-build rite-prove rite-polish rite-review rite-seal rite-ship rite-status rite-doctor rite-resolve rite-pressure-test rite-zoom-out rite-prototype rite-handoff rite-autocomplete"
16
16
  INTERNAL="devrites-interview devrites-source-driven devrites-doubt devrites-ux-shape devrites-frontend-craft devrites-browser-proof devrites-debug-recovery devrites-api-interface devrites-audit"
17
- AGENT_FILES="devrites-spec-reviewer devrites-code-reviewer devrites-test-analyst devrites-frontend-reviewer devrites-security-auditor devrites-performance-reviewer devrites-doubt-reviewer devrites-simplifier-reviewer devrites-strategy-reviewer devrites-plan-reviewer devrites-slice-wright"
17
+ AGENT_FILES="devrites-spec-reviewer devrites-code-reviewer devrites-test-analyst devrites-frontend-reviewer devrites-security-auditor devrites-performance-reviewer devrites-devex-reviewer devrites-doubt-reviewer devrites-simplifier-reviewer devrites-strategy-reviewer devrites-plan-reviewer devrites-retrospector devrites-slice-wright"
18
18
 
19
19
  # ---- 1. bash -n on every shell script ------------------------------------
20
20
  section "bash syntax (bash -n)"