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.
- package/dist/domain.operations/behavior/bind/flattenBranchName.cli.d.ts +2 -0
- package/dist/domain.operations/behavior/bind/flattenBranchName.cli.js +19 -0
- package/dist/domain.operations/behavior/bind/flattenBranchName.cli.js.map +1 -0
- package/dist/domain.operations/behavior/bind/flattenBranchName.d.ts +8 -0
- package/dist/domain.operations/behavior/bind/flattenBranchName.js +19 -0
- package/dist/domain.operations/behavior/bind/flattenBranchName.js.map +1 -0
- package/dist/domain.operations/behavior/bind/getBoundBehaviorByBranch.cli.d.ts +2 -0
- package/dist/domain.operations/behavior/bind/getBoundBehaviorByBranch.cli.js +18 -0
- package/dist/domain.operations/behavior/bind/getBoundBehaviorByBranch.cli.js.map +1 -0
- package/dist/domain.operations/behavior/bind/getBoundBehaviorByBranch.d.ts +11 -0
- package/dist/domain.operations/behavior/bind/getBoundBehaviorByBranch.js +51 -0
- package/dist/domain.operations/behavior/bind/getBoundBehaviorByBranch.js.map +1 -0
- package/dist/domain.operations/behavior/bind/getLatestBlueprintByBehavior.cli.d.ts +2 -0
- package/dist/domain.operations/behavior/bind/getLatestBlueprintByBehavior.cli.js +20 -0
- package/dist/domain.operations/behavior/bind/getLatestBlueprintByBehavior.cli.js.map +1 -0
- package/dist/domain.operations/behavior/bind/getLatestBlueprintByBehavior.d.ts +11 -0
- package/dist/domain.operations/behavior/bind/getLatestBlueprintByBehavior.js +51 -0
- package/dist/domain.operations/behavior/bind/getLatestBlueprintByBehavior.js.map +1 -0
- package/dist/domain.operations/behavior/bind/index.d.ts +3 -0
- package/dist/domain.operations/behavior/bind/index.js +10 -0
- package/dist/domain.operations/behavior/bind/index.js.map +1 -0
- package/dist/domain.roles/behaver/briefs/practices/behavior.blueprint/rule.require.criteria-satisfied.md +37 -0
- package/dist/domain.roles/behaver/briefs/practices/behavior.blueprint/rule.require.determinism-declared.md +44 -0
- package/dist/domain.roles/behaver/briefs/practices/behavior.blueprint/rule.require.test-coverage-specified.md +42 -0
- package/dist/domain.roles/behaver/briefs/practices/behavior.blueprint/rule.require.test-patterns-specified.md +43 -0
- package/dist/domain.roles/behaver/briefs/practices/behavior.criteria/rule.prefer.dependency-order.md +43 -0
- package/dist/domain.roles/behaver/briefs/practices/behavior.criteria/rule.prefer.depth-groups.md +44 -0
- package/dist/domain.roles/behaver/briefs/practices/behavior.criteria/rule.prefer.usecase-groups.md +41 -0
- package/dist/domain.roles/behaver/briefs/practices/behavior.criteria/rule.require.bdd-format.md +25 -0
- package/dist/domain.roles/behaver/briefs/practices/behavior.roadmap/rule.prefer.clear-deliverables.md +46 -0
- package/dist/domain.roles/behaver/briefs/practices/behavior.roadmap/rule.prefer.dependency-order.md +59 -0
- package/dist/domain.roles/behaver/briefs/practices/behavior.wish/rule.prefer.bounded-scope.md +29 -0
- package/dist/domain.roles/behaver/briefs/practices/behavior.wish/rule.prefer.clear-desires.md +31 -0
- package/dist/domain.roles/behaver/inits/claude.hooks/sessionstart.boot-behavior.sh +109 -0
- package/dist/domain.roles/behaver/inits/init.claude.hooks.findsert.sh +226 -0
- package/dist/domain.roles/behaver/inits/init.claude.hooks.sh +34 -0
- package/dist/domain.roles/behaver/skills/bind.behavior.sh +236 -0
- package/dist/domain.roles/behaver/skills/init.behavior.sh +51 -0
- package/dist/domain.roles/behaver/skills/review.behavior.sh +396 -0
- package/dist/domain.roles/behaver/skills/review.behavior.test.utils.d.ts +12 -0
- package/dist/domain.roles/behaver/skills/review.behavior.test.utils.js +63 -0
- package/dist/domain.roles/behaver/skills/review.behavior.test.utils.js.map +1 -0
- package/dist/domain.roles/behaver/skills/review.deliverable.sh +344 -0
- package/package.json +10 -8
- 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.
|
|
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 '
|
|
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 &&
|
|
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.
|
|
80
|
-
"rhachet-roles-ehmpathy": "1.15.
|
|
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>/`
|