rhachet-roles-bhuild 0.1.3 → 0.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 (45) hide show
  1. package/dist/domain.operations/behavior/bind/flattenBranchName.cli.d.ts +2 -0
  2. package/dist/domain.operations/behavior/bind/flattenBranchName.cli.js +19 -0
  3. package/dist/domain.operations/behavior/bind/flattenBranchName.cli.js.map +1 -0
  4. package/dist/domain.operations/behavior/bind/flattenBranchName.d.ts +8 -0
  5. package/dist/domain.operations/behavior/bind/flattenBranchName.js +19 -0
  6. package/dist/domain.operations/behavior/bind/flattenBranchName.js.map +1 -0
  7. package/dist/domain.operations/behavior/bind/getBoundBehaviorByBranch.cli.d.ts +2 -0
  8. package/dist/domain.operations/behavior/bind/getBoundBehaviorByBranch.cli.js +18 -0
  9. package/dist/domain.operations/behavior/bind/getBoundBehaviorByBranch.cli.js.map +1 -0
  10. package/dist/domain.operations/behavior/bind/getBoundBehaviorByBranch.d.ts +11 -0
  11. package/dist/domain.operations/behavior/bind/getBoundBehaviorByBranch.js +51 -0
  12. package/dist/domain.operations/behavior/bind/getBoundBehaviorByBranch.js.map +1 -0
  13. package/dist/domain.operations/behavior/bind/getLatestBlueprintByBehavior.cli.d.ts +2 -0
  14. package/dist/domain.operations/behavior/bind/getLatestBlueprintByBehavior.cli.js +20 -0
  15. package/dist/domain.operations/behavior/bind/getLatestBlueprintByBehavior.cli.js.map +1 -0
  16. package/dist/domain.operations/behavior/bind/getLatestBlueprintByBehavior.d.ts +11 -0
  17. package/dist/domain.operations/behavior/bind/getLatestBlueprintByBehavior.js +51 -0
  18. package/dist/domain.operations/behavior/bind/getLatestBlueprintByBehavior.js.map +1 -0
  19. package/dist/domain.operations/behavior/bind/index.d.ts +3 -0
  20. package/dist/domain.operations/behavior/bind/index.js +10 -0
  21. package/dist/domain.operations/behavior/bind/index.js.map +1 -0
  22. package/dist/domain.roles/behaver/briefs/practices/behavior.blueprint/rule.require.criteria-satisfied.md +37 -0
  23. package/dist/domain.roles/behaver/briefs/practices/behavior.blueprint/rule.require.determinism-declared.md +44 -0
  24. package/dist/domain.roles/behaver/briefs/practices/behavior.blueprint/rule.require.test-coverage-specified.md +42 -0
  25. package/dist/domain.roles/behaver/briefs/practices/behavior.blueprint/rule.require.test-patterns-specified.md +43 -0
  26. package/dist/domain.roles/behaver/briefs/practices/behavior.criteria/rule.prefer.dependency-order.md +43 -0
  27. package/dist/domain.roles/behaver/briefs/practices/behavior.criteria/rule.prefer.depth-groups.md +44 -0
  28. package/dist/domain.roles/behaver/briefs/practices/behavior.criteria/rule.prefer.usecase-groups.md +41 -0
  29. package/dist/domain.roles/behaver/briefs/practices/behavior.criteria/rule.require.bdd-format.md +25 -0
  30. package/dist/domain.roles/behaver/briefs/practices/behavior.roadmap/rule.prefer.clear-deliverables.md +46 -0
  31. package/dist/domain.roles/behaver/briefs/practices/behavior.roadmap/rule.prefer.dependency-order.md +59 -0
  32. package/dist/domain.roles/behaver/briefs/practices/behavior.wish/rule.prefer.bounded-scope.md +29 -0
  33. package/dist/domain.roles/behaver/briefs/practices/behavior.wish/rule.prefer.clear-desires.md +31 -0
  34. package/dist/domain.roles/behaver/inits/claude.hooks/sessionstart.boot-behavior.sh +109 -0
  35. package/dist/domain.roles/behaver/inits/init.claude.hooks.findsert.sh +226 -0
  36. package/dist/domain.roles/behaver/inits/init.claude.hooks.sh +34 -0
  37. package/dist/domain.roles/behaver/skills/bind.behavior.sh +236 -0
  38. package/dist/domain.roles/behaver/skills/init.behavior.sh +51 -0
  39. package/dist/domain.roles/behaver/skills/review.behavior.sh +396 -0
  40. package/dist/domain.roles/behaver/skills/review.behavior.test.utils.d.ts +12 -0
  41. package/dist/domain.roles/behaver/skills/review.behavior.test.utils.js +63 -0
  42. package/dist/domain.roles/behaver/skills/review.behavior.test.utils.js.map +1 -0
  43. package/dist/domain.roles/behaver/skills/review.deliverable.sh +344 -0
  44. package/package.json +10 -8
  45. package/readme.md +34 -0
@@ -0,0 +1,12 @@
1
+ export declare const SKILL_PATH: string;
2
+ export declare const FIXTURES_PATH: string;
3
+ /**
4
+ * .what = finds feedback file matching pattern with timestamp
5
+ * .why = feedback files have dynamic timestamps in filename
6
+ */
7
+ export declare const findFeedbackFile: (dir: string, pattern: string) => string | undefined;
8
+ /**
9
+ * .what = creates a temp copy of fixture with real git history
10
+ * .why = avoids git-within-git issues by isolating in /tmp
11
+ */
12
+ export declare const prepareFixtureWithGit: (fixturePath: string) => string;
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.prepareFixtureWithGit = exports.findFeedbackFile = exports.FIXTURES_PATH = exports.SKILL_PATH = void 0;
27
+ const child_process_1 = require("child_process");
28
+ const fs = __importStar(require("fs"));
29
+ const os = __importStar(require("os"));
30
+ const path = __importStar(require("path"));
31
+ exports.SKILL_PATH = path.join(__dirname, 'review.behavior.sh');
32
+ exports.FIXTURES_PATH = path.join(__dirname, '.test/assets/example.repo');
33
+ /**
34
+ * .what = finds feedback file matching pattern with timestamp
35
+ * .why = feedback files have dynamic timestamps in filename
36
+ */
37
+ const findFeedbackFile = (dir, pattern) => {
38
+ const files = fs.readdirSync(dir);
39
+ return files.find((f) => f.includes(pattern) && f.includes('[feedback]') && f.endsWith('.md'));
40
+ };
41
+ exports.findFeedbackFile = findFeedbackFile;
42
+ /**
43
+ * .what = creates a temp copy of fixture with real git history
44
+ * .why = avoids git-within-git issues by isolating in /tmp
45
+ */
46
+ const prepareFixtureWithGit = (fixturePath) => {
47
+ // create temp directory
48
+ const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'review-behavior-'));
49
+ // copy fixture contents (including hidden directories like .behavior/)
50
+ (0, child_process_1.execSync)(`cp -a ${fixturePath}/. ${tempDir}/`);
51
+ // init git repo
52
+ (0, child_process_1.execSync)('git init', { cwd: tempDir });
53
+ (0, child_process_1.execSync)('git config user.email "test@test.com"', { cwd: tempDir });
54
+ (0, child_process_1.execSync)('git config user.name "Test"', { cwd: tempDir });
55
+ // commit behavior declarations on main
56
+ (0, child_process_1.execSync)('git add .behavior/', { cwd: tempDir });
57
+ (0, child_process_1.execSync)('git commit -m "initial: add behavior declarations"', {
58
+ cwd: tempDir,
59
+ });
60
+ return tempDir;
61
+ };
62
+ exports.prepareFixtureWithGit = prepareFixtureWithGit;
63
+ //# sourceMappingURL=review.behavior.test.utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review.behavior.test.utils.js","sourceRoot":"","sources":["../../../../src/domain.roles/behaver/skills/review.behavior.test.utils.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,iDAAyC;AACzC,uCAAyB;AACzB,uCAAyB;AACzB,2CAA6B;AAEhB,QAAA,UAAU,GAAW,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,oBAAoB,CAAC,CAAC;AAChE,QAAA,aAAa,GAAW,IAAI,CAAC,IAAI,CAC5C,SAAS,EACT,2BAA2B,CAC5B,CAAC;AAEF;;;GAGG;AACI,MAAM,gBAAgB,GAAG,CAC9B,GAAW,EACX,OAAe,EACK,EAAE;IACtB,MAAM,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAClC,OAAO,KAAK,CAAC,IAAI,CACf,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAC5E,CAAC;AACJ,CAAC,CAAC;AARW,QAAA,gBAAgB,oBAQ3B;AAEF;;;GAGG;AACI,MAAM,qBAAqB,GAAG,CAAC,WAAmB,EAAU,EAAE;IACnE,wBAAwB;IACxB,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,kBAAkB,CAAC,CAAC,CAAC;IAE3E,uEAAuE;IACvE,IAAA,wBAAQ,EAAC,SAAS,WAAW,MAAM,OAAO,GAAG,CAAC,CAAC;IAE/C,gBAAgB;IAChB,IAAA,wBAAQ,EAAC,UAAU,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;IACvC,IAAA,wBAAQ,EAAC,uCAAuC,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;IACpE,IAAA,wBAAQ,EAAC,6BAA6B,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;IAE1D,uCAAuC;IACvC,IAAA,wBAAQ,EAAC,oBAAoB,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;IACjD,IAAA,wBAAQ,EAAC,oDAAoD,EAAE;QAC7D,GAAG,EAAE,OAAO;KACb,CAAC,CAAC;IAEH,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC;AAnBW,QAAA,qBAAqB,yBAmBhC"}
@@ -0,0 +1,344 @@
1
+ #!/usr/bin/env bash
2
+ ######################################################################
3
+ # .what = review deliverable against behavior declarations
4
+ #
5
+ # .why = enables automated and interactive review of implementation
6
+ # against wish, vision, criteria, blueprint, or roadmap
7
+ # declarations, producing structured feedback via claude code
8
+ #
9
+ # .how = 1. resolve behavior directory from --for.behavior
10
+ # 2. resolve declaration file(s) from --against
11
+ # 3. build prompt with declaration path(s)
12
+ # 4. invoke claude code (interactive or non-interactive)
13
+ # 5. feedback emits to 7.1.review.behavior.per_{targets}.[feedback].[given].by_robot.v{timestamp}.md
14
+ #
15
+ # usage:
16
+ # review.deliverable.sh --for.behavior <name> --against <target> [--interactive]
17
+ #
18
+ # examples:
19
+ # review.deliverable.sh --for.behavior get-weather-emoji --against blueprint
20
+ # review.deliverable.sh --for.behavior get-weather-emoji --against wish,vision,criteria
21
+ # review.deliverable.sh --for.behavior get-weather-emoji --against blueprint --interactive
22
+ #
23
+ # guarantee:
24
+ # - fail-fast if behavior not found or ambiguous
25
+ # - fail-fast if declaration file(s) missing
26
+ # - latest major version selected for versioned files (v3.i2 > v2.i3)
27
+ # - idempotent: safe to rerun
28
+ ######################################################################
29
+
30
+ set -euo pipefail
31
+
32
+ trap 'echo "review.deliverable.sh failed at line $LINENO"' ERR
33
+
34
+ # ────────────────────────────────────────────────────────────────────
35
+ # script location resolution
36
+ # ────────────────────────────────────────────────────────────────────
37
+
38
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
39
+
40
+ # resolve claude binary (prefer global, fallback to local node_modules)
41
+ CLAUDE_BIN=""
42
+ if command -v claude >/dev/null 2>&1; then
43
+ CLAUDE_BIN="claude"
44
+ else
45
+ NPM_BIN_DIR="$(cd "$SCRIPT_DIR" && npm bin 2>/dev/null || echo "")"
46
+ if [[ -n "$NPM_BIN_DIR" && -x "$NPM_BIN_DIR/claude" ]]; then
47
+ CLAUDE_BIN="$NPM_BIN_DIR/claude"
48
+ else
49
+ echo "error: claude binary not found (install @anthropic-ai/claude-code or ensure claude is in PATH)"
50
+ exit 1
51
+ fi
52
+ fi
53
+
54
+ # ────────────────────────────────────────────────────────────────────
55
+ # argument parsing
56
+ # ────────────────────────────────────────────────────────────────────
57
+
58
+ BEHAVIOR_NAME=""
59
+ AGAINST=""
60
+ INTERACTIVE=false
61
+ TARGET_DIR="$PWD"
62
+
63
+ while [[ $# -gt 0 ]]; do
64
+ case $1 in
65
+ --for.behavior)
66
+ BEHAVIOR_NAME="$2"
67
+ shift 2
68
+ ;;
69
+ --against)
70
+ AGAINST="$2"
71
+ shift 2
72
+ ;;
73
+ --interactive)
74
+ INTERACTIVE=true
75
+ shift
76
+ ;;
77
+ --dir)
78
+ TARGET_DIR="$2"
79
+ shift 2
80
+ ;;
81
+ --skill|--repo|--role|-s)
82
+ # ignore rhachet passthrough args
83
+ shift 2
84
+ ;;
85
+ *)
86
+ echo "error: unknown argument '$1'"
87
+ echo "usage: review.deliverable.sh --for.behavior <name> --against <target> [--interactive]"
88
+ exit 1
89
+ ;;
90
+ esac
91
+ done
92
+
93
+ # validate required arguments
94
+ if [[ -z "$BEHAVIOR_NAME" ]]; then
95
+ echo "error: --for.behavior is required"
96
+ exit 1
97
+ fi
98
+ if [[ -z "$AGAINST" ]]; then
99
+ echo "error: --against is required (wish|vision|criteria|blueprint|roadmap or comma-separated)"
100
+ exit 1
101
+ fi
102
+
103
+ # ────────────────────────────────────────────────────────────────────
104
+ # behavior directory resolution
105
+ # ────────────────────────────────────────────────────────────────────
106
+
107
+ BEHAVIOR_ROOT="$TARGET_DIR/.behavior"
108
+ if [[ ! -d "$BEHAVIOR_ROOT" ]]; then
109
+ echo "error: .behavior/ directory not found in $TARGET_DIR"
110
+ exit 1
111
+ fi
112
+
113
+ # find matching behavior directories
114
+ MATCHES=()
115
+ while IFS= read -r -d '' dir; do
116
+ MATCHES+=("$dir")
117
+ done < <(find "$BEHAVIOR_ROOT" -maxdepth 1 -type d -name "*${BEHAVIOR_NAME}*" -print0 2>/dev/null)
118
+
119
+ if [[ ${#MATCHES[@]} -eq 0 ]]; then
120
+ echo "error: no behavior found matching '$BEHAVIOR_NAME'"
121
+ echo "available behaviors:"
122
+ ls -1 "$BEHAVIOR_ROOT" 2>/dev/null | sed 's/^/ /'
123
+ exit 1
124
+ fi
125
+
126
+ if [[ ${#MATCHES[@]} -gt 1 ]]; then
127
+ echo "error: multiple behaviors match '$BEHAVIOR_NAME'"
128
+ echo "matches:"
129
+ printf ' %s\n' "${MATCHES[@]}"
130
+ echo "please provide a more specific name"
131
+ exit 1
132
+ fi
133
+
134
+ BEHAVIOR_DIR="${MATCHES[0]}"
135
+ BEHAVIOR_DIR_REL=$(realpath --relative-to="$PWD" "$BEHAVIOR_DIR")
136
+
137
+ # ────────────────────────────────────────────────────────────────────
138
+ # declaration file resolution
139
+ # ────────────────────────────────────────────────────────────────────
140
+
141
+ # map target to filename pattern
142
+ get_target_file() {
143
+ local target="$1"
144
+ local behavior_dir="$2"
145
+ local found
146
+
147
+ case "$target" in
148
+ wish|vision|criteria)
149
+ # find file ending in .<target>.md (e.g., *.wish.md, *.vision.md, *.criteria.md)
150
+ found=$(find "$behavior_dir" -maxdepth 1 -name "*.${target}.md" -print0 2>/dev/null \
151
+ | head -z -n1 \
152
+ | tr -d '\0')
153
+ echo "${found:-$behavior_dir/*.${target}.md}"
154
+ ;;
155
+ blueprint|roadmap)
156
+ # find latest major version: *.<target>.vN.iM.md
157
+ found=$(find "$behavior_dir" -maxdepth 1 -name "*.${target}.v*.i*.md" -print0 2>/dev/null \
158
+ | sort -zV -t'v' -k2 \
159
+ | tail -z -n1 \
160
+ | tr -d '\0')
161
+ echo "${found:-$behavior_dir/*.${target}.v*.i*.md}"
162
+ ;;
163
+ *)
164
+ echo ""
165
+ ;;
166
+ esac
167
+ }
168
+
169
+ # resolve all targets
170
+ IFS=',' read -ra TARGETS <<< "$AGAINST"
171
+ DECLARATION_FILES=()
172
+ TARGETS_SLUG=""
173
+
174
+ for target in "${TARGETS[@]}"; do
175
+ target=$(echo "$target" | tr -d ' ') # trim whitespace
176
+ file=$(get_target_file "$target" "$BEHAVIOR_DIR")
177
+
178
+ if [[ -z "$file" ]]; then
179
+ echo "error: unknown target '$target'"
180
+ echo "valid targets: wish, vision, criteria, blueprint, roadmap"
181
+ exit 1
182
+ fi
183
+
184
+ if [[ ! -f "$file" ]]; then
185
+ echo "error: declaration file not found for target '$target'"
186
+ echo "expected: $file"
187
+ exit 1
188
+ fi
189
+
190
+ DECLARATION_FILES+=("$file")
191
+
192
+ # build slug for output filename
193
+ if [[ -n "$TARGETS_SLUG" ]]; then
194
+ TARGETS_SLUG="${TARGETS_SLUG}_${target}"
195
+ else
196
+ TARGETS_SLUG="$target"
197
+ fi
198
+ done
199
+
200
+ # ────────────────────────────────────────────────────────────────────
201
+ # prompt construction
202
+ # ────────────────────────────────────────────────────────────────────
203
+
204
+ # build declaration paths for prompt (relative to TARGET_DIR where claude runs)
205
+ DECLARATION_PATHS=""
206
+ for file in "${DECLARATION_FILES[@]}"; do
207
+ rel_path=$(realpath --relative-to="$TARGET_DIR" "$file")
208
+ DECLARATION_PATHS="${DECLARATION_PATHS}- ${rel_path}\n"
209
+ done
210
+
211
+ # timestamp for output file and logs
212
+ TIMESTAMP=$(date +%Y%m%d_%H%M%S)
213
+
214
+ # output file path (relative to TARGET_DIR where claude runs)
215
+ OUTPUT_FILE="$BEHAVIOR_DIR/7.1.review.behavior.per_${TARGETS_SLUG}.[feedback].[given].by_robot.v${TIMESTAMP}.md"
216
+ OUTPUT_FILE_REL=$(realpath --relative-to="$TARGET_DIR" "$OUTPUT_FILE")
217
+
218
+ # feedback template path (relative to TARGET_DIR where claude runs)
219
+ TEMPLATE_FILE="$BEHAVIOR_DIR/.ref.[feedback].v1.[given].by_human.md"
220
+ TEMPLATE_FILE_REL=$(realpath --relative-to="$TARGET_DIR" "$TEMPLATE_FILE")
221
+
222
+ # build prompt (asks claude to output review to stdout, script writes to file)
223
+ PROMPT=$(cat <<EOF
224
+ # review.deliverable
225
+
226
+ you are reviewing the implementation deliverable against the following behavior declaration(s):
227
+
228
+ $(echo -e "$DECLARATION_PATHS")
229
+
230
+ ## instructions
231
+
232
+ 1. read each declaration file listed above
233
+ 2. examine the implementation (git diff from main, staged changes, unstaged changes)
234
+ 3. compare implementation against the declared behaviors
235
+ 4. identify BLOCKERs (must fix before merge) and NITPICKs (suggestions, non-blocking)
236
+
237
+ ## output format
238
+
239
+ output your review feedback directly to stdout (do NOT use any tools to write files).
240
+
241
+ follow the template structure in:
242
+ - $TEMPLATE_FILE_REL
243
+
244
+ start your output with:
245
+ # generated by: review.deliverable --for.behavior $BEHAVIOR_NAME --against $AGAINST
246
+
247
+ then list your findings as:
248
+ - # blocker.N = description
249
+ - # nitpick.N = description
250
+
251
+ with clear explanations for each finding.
252
+
253
+ ## begin review
254
+
255
+ read the declaration files now and review the implementation. output review to stdout only.
256
+ EOF
257
+ )
258
+
259
+ # ────────────────────────────────────────────────────────────────────
260
+ # logging setup
261
+ # ────────────────────────────────────────────────────────────────────
262
+
263
+ LOG_DIR="$TARGET_DIR/.log/bhuild/review.deliverable/$TIMESTAMP"
264
+ mkdir -p "$LOG_DIR"
265
+ LOG_DIR_REL=$(realpath --relative-to="$PWD" "$LOG_DIR")
266
+
267
+ # emit input args
268
+ cat > "$LOG_DIR/input.args.json" <<ARGS_EOF
269
+ {
270
+ "behavior_name": "$BEHAVIOR_NAME",
271
+ "against": "$AGAINST",
272
+ "interactive": $INTERACTIVE,
273
+ "target_dir": "$TARGET_DIR",
274
+ "behavior_dir": "$BEHAVIOR_DIR",
275
+ "output_file": "$OUTPUT_FILE"
276
+ }
277
+ ARGS_EOF
278
+
279
+ # emit input prompt
280
+ echo "$PROMPT" > "$LOG_DIR/input.prompt.md"
281
+
282
+ # ────────────────────────────────────────────────────────────────────
283
+ # claude code invocation
284
+ # ────────────────────────────────────────────────────────────────────
285
+
286
+ if [[ "$INTERACTIVE" == "true" ]]; then
287
+ echo ""
288
+ echo "🔭 review.deliverable (interactive)"
289
+ echo "├── behavior: $BEHAVIOR_DIR_REL"
290
+ echo "├── against: $AGAINST"
291
+ echo "├── prompt: $LOG_DIR_REL/input.prompt.md"
292
+ echo "└── output: $OUTPUT_FILE_REL"
293
+ echo ""
294
+
295
+ # interactive mode: open claude code shell in target dir
296
+ (cd "$TARGET_DIR" && "$CLAUDE_BIN" --print "$PROMPT")
297
+ else
298
+ # show tree-structured status
299
+ echo ""
300
+ echo "🔭 review.deliverable"
301
+ echo "├── behavior: $BEHAVIOR_DIR_REL"
302
+ echo "├── against: $AGAINST"
303
+ echo "├── prompt: $LOG_DIR_REL/input.prompt.md"
304
+ echo "└── output: $OUTPUT_FILE_REL"
305
+ echo ""
306
+
307
+ # show spinner while claude runs
308
+ echo -n "⏳ reviewing "
309
+ (cd "$TARGET_DIR" && echo "$PROMPT" | "$CLAUDE_BIN" --print 2>&1) > "$LOG_DIR/output.response.md" &
310
+ CLAUDE_PID=$!
311
+
312
+ # spinner animation
313
+ SPINNER="⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏"
314
+ ELAPSED=0
315
+ while kill -0 $CLAUDE_PID 2>/dev/null; do
316
+ for (( i=0; i<${#SPINNER}; i++ )); do
317
+ if ! kill -0 $CLAUDE_PID 2>/dev/null; then break; fi
318
+ echo -ne "\r⏳ reviewing ${SPINNER:$i:1} ${ELAPSED}s"
319
+ sleep 0.1
320
+ done
321
+ ELAPSED=$((ELAPSED + 1))
322
+ done
323
+
324
+ wait $CLAUDE_PID
325
+ CLAUDE_EXIT=$?
326
+
327
+ # read output
328
+ CLAUDE_OUTPUT=$(cat "$LOG_DIR/output.response.md")
329
+ echo "{\"exit_code\": $CLAUDE_EXIT, \"elapsed_seconds\": $ELAPSED}" > "$LOG_DIR/output.response.json"
330
+
331
+ echo ""
332
+ if [[ $CLAUDE_EXIT -eq 0 ]]; then
333
+ # write claude's output to the feedback file
334
+ echo "$CLAUDE_OUTPUT" > "$OUTPUT_FILE"
335
+ echo ""
336
+ echo "✨ review complete (${ELAPSED}s)"
337
+ echo "└── $OUTPUT_FILE_REL"
338
+ else
339
+ echo ""
340
+ echo "⛈️ review failed (exit code: $CLAUDE_EXIT)"
341
+ echo "└── see: $LOG_DIR_REL/output.response.md"
342
+ exit $CLAUDE_EXIT
343
+ fi
344
+ fi
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "rhachet-roles-bhuild",
3
3
  "author": "ehmpathy",
4
4
  "description": "reliable thought concept navigation roles, briefs, and skills, via rhachet",
5
- "version": "0.1.3",
5
+ "version": "0.4.0",
6
6
  "repository": "ehmpathy/rhachet-roles-bhuild",
7
7
  "homepage": "https://github.com/ehmpathy/rhachet-roles-bhuild",
8
8
  "keywords": [
@@ -27,18 +27,17 @@
27
27
  "fix": "npm run fix:format && npm run fix:lint",
28
28
  "build:clean": "chmod -R u+w dist 2>/dev/null; rm -rf dist/",
29
29
  "build:compile": "tsc -p ./tsconfig.build.json && tsc-alias -p ./tsconfig.build.json",
30
- "build:complete": "rsync -a --prune-empty-dirs --include='*/' --exclude='**/.route/**' --exclude='**/.scratch/**' --exclude='**/.behavior/**' --exclude='**/*.test.sh' --include='**/*.template.md' --include='**/briefs/**/*.md' --include='**/briefs/*.md' --include='**/skills/**/*.sh' --include='**/skills/*.sh' --include='**/skills/**/*.jsonc' --include='**/skills/*.jsonc' --exclude='*' src/ dist/",
30
+ "build:complete": "rsync -a --prune-empty-dirs --include='*/' --exclude='**/.route/**' --exclude='**/.scratch/**' --exclude='**/.behavior/**' --exclude='**/*.test.sh' --include='**/*.template.md' --include='**/briefs/**/*.md' --include='**/briefs/*.md' --include='**/skills/**/*.sh' --include='**/skills/*.sh' --include='**/skills/**/*.jsonc' --include='**/skills/*.jsonc' --include='**/inits/**/*.sh' --include='**/inits/*.sh' --exclude='*' src/ dist/",
31
31
  "build": "npm run build:clean && npm run build:compile && npm run build:complete --if-present",
32
32
  "test:commits": "LAST_TAG=$(git describe --tags --abbrev=0 @^ 2> /dev/null || git rev-list --max-parents=0 HEAD) && npx commitlint --from $LAST_TAG --to HEAD --verbose",
33
33
  "test:types": "tsc -p ./tsconfig.json --noEmit",
34
34
  "test:format": "npm run test:format:biome",
35
35
  "test:lint:deps": "npx depcheck -c ./.depcheckrc.yml",
36
- "test:integration:hold": "jest -c ./jest.integration.config.ts --forceExit --verbose --passWithNoTests $([ -z $THOROUGH ] && echo '--changedSince=main')",
37
36
  "test:lint:biome": "biome check --diagnostic-level=error",
38
37
  "test:lint:biome:all": "biome check",
39
38
  "test:lint": "npm run test:lint:biome && npm run test:lint:deps",
40
39
  "test:unit": "jest -c ./jest.unit.config.ts --forceExit --verbose --passWithNoTests $([ -z $THOROUGH ] && echo '--changedSince=main') $([ -n $RESNAP ] && echo '--updateSnapshot')",
41
- "test:integration": "echo 'todo: release'",
40
+ "test:integration": "jest -c ./jest.integration.config.ts --forceExit --verbose --passWithNoTests $([ -z $THOROUGH ] && echo '--changedSince=main') $([ -n $RESNAP ] && echo '--updateSnapshot')",
42
41
  "test:acceptance:locally": "npm run build && LOCALLY=true jest -c ./jest.acceptance.config.ts --forceExit --verbose --runInBand --passWithNoTests $([ -n $RESNAP ] && echo '--updateSnapshot')",
43
42
  "test": "npm run test:commits && npm run test:types && npm run test:format && npm run test:lint && npm run test:unit && npm run test:integration && npm run test:acceptance:locally",
44
43
  "test:acceptance": "npm run build && jest -c ./jest.acceptance.config.ts --forceExit --verbose --runInBand --passWithNoTests $([ -n $RESNAP ] && echo '--updateSnapshot')",
@@ -49,14 +48,17 @@
49
48
  "prepare:husky": "husky install && chmod ug+x .husky/*",
50
49
  "prepare": "if [ -e .git ] && [ -z $CI ]; then npm run prepare:husky && npm run prepare:rhachet; fi",
51
50
  "test:format:biome": "biome format",
52
- "prepare:rhachet": "rhachet init && rhachet roles link --role mechanic && .agent/repo=ehmpathy/role=mechanic/skills/.skills/init.claude.sh"
51
+ "prepare:rhachet": "rhachet init && rhachet roles link --role mechanic && rhachet roles init --role mechanic"
53
52
  },
54
53
  "dependencies": {
55
54
  "domain-objects": "0.31.7",
56
55
  "helpful-errors": "1.5.3",
57
- "rhachet": "1.15.2"
56
+ "rhachet": "1.15.2",
57
+ "rhachet-roles-bhrain": "0.3.0",
58
+ "test-fns": "1.7.2"
58
59
  },
59
60
  "devDependencies": {
61
+ "@anthropic-ai/claude-code": "2.0.76",
60
62
  "@biomejs/biome": "2.3.8",
61
63
  "@commitlint/cli": "19.5.0",
62
64
  "@commitlint/config-conventional": "19.5.0",
@@ -76,8 +78,8 @@
76
78
  "husky": "8.0.3",
77
79
  "jest": "30.2.0",
78
80
  "rhachet": "1.13.11",
79
- "rhachet-roles-bhuild": "0.1.1",
80
- "rhachet-roles-ehmpathy": "1.15.12",
81
+ "rhachet-roles-bhuild": "0.1.3",
82
+ "rhachet-roles-ehmpathy": "1.15.18",
81
83
  "tsc-alias": "1.8.10",
82
84
  "tsx": "4.20.6",
83
85
  "typescript": "5.4.5",
package/readme.md CHANGED
@@ -39,3 +39,37 @@ Used to declare clear and testable behaviors that can be reliably built and veri
39
39
 
40
40
  Used to maximize prioritized throughput within a resource bandwidth.
41
41
  ```
42
+
43
+ ## skills
44
+
45
+ ### behaver: review.deliverable
46
+
47
+ reviews an implementation deliverable against behavior declarations (wish, vision, criteria, blueprint, roadmap).
48
+
49
+ ```sh
50
+ # review against a single declaration
51
+ npx rhachet run --repo bhuild --skill review.deliverable \
52
+ --for.behavior get-weather-emoji \
53
+ --against blueprint
54
+
55
+ # review against multiple declarations
56
+ npx rhachet run --repo bhuild --skill review.deliverable \
57
+ --for.behavior get-weather-emoji \
58
+ --against wish,vision,criteria
59
+
60
+ # interactive mode (opens claude code session)
61
+ npx rhachet run --repo bhuild --skill review.deliverable \
62
+ --for.behavior get-weather-emoji \
63
+ --against blueprint \
64
+ --interactive
65
+
66
+ # specify a different directory
67
+ npx rhachet run --repo bhuild --skill review.deliverable \
68
+ --for.behavior get-weather-emoji \
69
+ --against blueprint \
70
+ --dir /path/to/project
71
+ ```
72
+
73
+ output:
74
+ - creates `.behavior/<behavior>/7.1.review.behavior.per_<targets>.[feedback].v1.[given].by_robot.v1.md`
75
+ - logs to `.log/bhuild/review.deliverable/<timestamp>/`