rhachet-roles-ehmpathy 1.9.0 β†’ 1.10.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 (18) hide show
  1. package/dist/logic/roles/coach/.briefs/claude.context-caching.md +76 -0
  2. package/dist/logic/roles/mechanic/.briefs/lessons/code.prod.typescript.types/bivariance_vs_contravariance.[lesson].md +95 -0
  3. package/dist/logic/roles/mechanic/.briefs/patterns/code.prod.errors.failfast/bad-practices/forbid.failhide.md +19 -0
  4. package/dist/logic/roles/mechanic/.briefs/patterns/code.prod.errors.failfast/best-practice/prefer.HelpfulError.wrap.md +54 -0
  5. package/dist/logic/roles/mechanic/.briefs/patterns/code.prod.narrative/bad-practices/forbid.else.md +54 -0
  6. package/dist/logic/roles/mechanic/.briefs/patterns/code.prod.narrative/best-practice/early-returns.named-checks.[demo].md +181 -0
  7. package/dist/logic/roles/mechanic/.briefs/patterns/code.prod.repo.structure/bad-practices/forbid.index.ts.md +3 -0
  8. package/dist/logic/roles/mechanic/.briefs/patterns/code.test.howto/best-practice/howto.diagnose.[lesson].md +14 -0
  9. package/dist/logic/roles/mechanic/.briefs/patterns/lang.terms/best-practice/require.order.noun_adj.md +39 -0
  10. package/dist/logic/roles/mechanic/.skills/declapract.upgrade.sh +50 -0
  11. package/dist/logic/roles/mechanic/.skills/init.bhuild.sh +260 -0
  12. package/dist/logic/roles/mechanic/.skills/init.claude.hooks.sh +113 -0
  13. package/dist/logic/roles/mechanic/.skills/init.claude.permissions.sh +109 -0
  14. package/dist/logic/roles/mechanic/.skills/init.claude.sh +35 -0
  15. package/dist/logic/roles/mechanic/.skills/link.claude.transcripts.sh +43 -0
  16. package/dist/logic/roles/mechanic/.skills/run.test.sh +251 -0
  17. package/dist/logic/roles/mechanic/.skills/test.integration.sh +50 -0
  18. package/package.json +2 -2
@@ -0,0 +1,260 @@
1
+ #!/usr/bin/env bash
2
+ ######################################################################
3
+ # .what = initialize a .behavior directory for bhuild thoughtroute
4
+ #
5
+ # .why = standardize the behavior-driven development thoughtroute
6
+ # by scaffolding a structured directory with:
7
+ # - wish definition
8
+ # - vision statement
9
+ # - acceptance criteria
10
+ # - research prompts
11
+ # - distillation prompts
12
+ # - blueprint prompts
13
+ # - roadmap prompts
14
+ # - execution prompts
15
+ # - feedback template
16
+ #
17
+ # .how = creates .behavior/v${isodate}.${behaviorname}/ with
18
+ # all necessary scaffold files for the bhuild thoughtroute
19
+ #
20
+ # usage:
21
+ # init.bhuild.sh --name <behaviorname> [--dir <directory>]
22
+ #
23
+ # guarantee:
24
+ # - creates .behavior/ if missing
25
+ # - creates versioned behavior directory
26
+ # - findserts all thoughtroute files (creates if missing, skips if exists)
27
+ # - idempotent: safe to rerun
28
+ # - fail-fast on errors
29
+ ######################################################################
30
+
31
+ set -euo pipefail
32
+
33
+ # parse arguments
34
+ BEHAVIOR_NAME=""
35
+ TARGET_DIR="$PWD"
36
+ while [[ $# -gt 0 ]]; do
37
+ case $1 in
38
+ --name)
39
+ BEHAVIOR_NAME="$2"
40
+ shift 2
41
+ ;;
42
+ --dir)
43
+ TARGET_DIR="$2"
44
+ shift 2
45
+ ;;
46
+ *)
47
+ echo "error: unknown argument '$1'"
48
+ echo "usage: init.bhuild.sh --name <behaviorname> [--dir <directory>]"
49
+ exit 1
50
+ ;;
51
+ esac
52
+ done
53
+
54
+ # validate required arguments
55
+ if [[ -z "$BEHAVIOR_NAME" ]]; then
56
+ echo "error: --name is required"
57
+ echo "usage: init.bhuild.sh --name <behaviorname> [--dir <directory>]"
58
+ exit 1
59
+ fi
60
+
61
+ # generate isodate in format YYYY_MM_DD
62
+ ISO_DATE=$(date +%Y_%m_%d)
63
+
64
+ # trim trailing .behavior from TARGET_DIR if present
65
+ TARGET_DIR="${TARGET_DIR%/.behavior}"
66
+ TARGET_DIR="${TARGET_DIR%.behavior}"
67
+
68
+ # construct behavior directory path (absolute)
69
+ BEHAVIOR_DIR="$TARGET_DIR/.behavior/v${ISO_DATE}.${BEHAVIOR_NAME}"
70
+
71
+ # compute relative path from caller's $PWD for file contents
72
+ BEHAVIOR_DIR_REL="$(realpath --relative-to="$PWD" "$TARGET_DIR")/.behavior/v${ISO_DATE}.${BEHAVIOR_NAME}"
73
+ # normalize: remove leading ./ if present
74
+ BEHAVIOR_DIR_REL="${BEHAVIOR_DIR_REL#./}"
75
+
76
+ # create behavior directory (idempotent)
77
+ mkdir -p "$BEHAVIOR_DIR"
78
+
79
+ # helper: findsert file (create if missing, skip if exists)
80
+ findsert() {
81
+ local filepath="$1"
82
+ if [[ -f "$filepath" ]]; then
83
+ echo " [KEEP] $(basename "$filepath")"
84
+ return 0
85
+ fi
86
+ cat > "$filepath"
87
+ echo " [CREATE] $(basename "$filepath")"
88
+ }
89
+
90
+ # findsert 0.wish.md
91
+ findsert "$BEHAVIOR_DIR/0.wish.md" << 'EOF'
92
+ wish =
93
+
94
+ EOF
95
+
96
+ # findsert 1.vision.md
97
+ findsert "$BEHAVIOR_DIR/1.vision.md" << 'EOF'
98
+
99
+ EOF
100
+
101
+ # findsert 2.criteria.md
102
+ findsert "$BEHAVIOR_DIR/2.criteria.md" << 'EOF'
103
+ # usecase.1 = ...
104
+ given()
105
+ when()
106
+ then()
107
+ sothat()
108
+ then()
109
+ then()
110
+ sothat()
111
+ when()
112
+ then()
113
+
114
+ given()
115
+ ...
116
+
117
+ # usecase.2 = ...
118
+ ...
119
+ EOF
120
+
121
+ # findsert 3.1.research.domain._.v1.src
122
+ findsert "$BEHAVIOR_DIR/3.1.research.domain._.v1.src" << EOF
123
+ research the domain available in order to fulfill the wish declared
124
+ in $BEHAVIOR_DIR_REL/0.wish.md
125
+
126
+ specifically
127
+ - what are the domain objects that are involved with this wish
128
+ - entities
129
+ - events
130
+ - literals
131
+ - what are the domain operations
132
+ - getOne
133
+ - getAll
134
+ - setCreate
135
+ - setUpdate
136
+ - setDelete
137
+ - ...
138
+
139
+ ---
140
+
141
+ use web search to discover and research
142
+ - cite every claim
143
+ - number each citation
144
+ - clone exact quotes from each citation
145
+
146
+ focus on these sdk's for reference, if provided
147
+ -
148
+
149
+ ---
150
+
151
+ emit into $BEHAVIOR_DIR_REL/3.1.research.domain._.v1.i1.md
152
+ EOF
153
+
154
+ # findsert 3.2.distill.domain._.v1.src
155
+ findsert "$BEHAVIOR_DIR/3.2.distill.domain._.v1.src" << EOF
156
+ distill the declastruct domain.objects and domain.operations that would
157
+ - enable fulfillment of this wish $BEHAVIOR_DIR_REL/0.wish.md
158
+ - given the research declared here $BEHAVIOR_DIR_REL/3.1.research.domain._.v1.i1.md
159
+
160
+ procedure
161
+ 1. declare the usecases and envision the contract that would be used to fulfill the usecases
162
+ 2. declare the domain.objects, domain.operations, and access.daos that would fulfill this, via the declastruct pattern in this repo
163
+
164
+ emit into
165
+ - $BEHAVIOR_DIR_REL/3.2.distill.domain._.v1.i1.md
166
+ EOF
167
+
168
+ # findsert 3.3.blueprint.v1.src
169
+ findsert "$BEHAVIOR_DIR/3.3.blueprint.v1.src" << EOF
170
+ propose a blueprint for how we can implement the wish described
171
+ - in $BEHAVIOR_DIR_REL/0.wish.md
172
+
173
+ with the domain distillation declared
174
+ - in $BEHAVIOR_DIR_REL/3.2.distill.domain._.v1.i1.md
175
+
176
+ follow the patterns already present in this repo
177
+
178
+ ---
179
+
180
+ reference the below for full context
181
+ - $BEHAVIOR_DIR_REL/0.wish.md
182
+ - $BEHAVIOR_DIR_REL/3.1.research.domain._.v1.i1.md
183
+ - $BEHAVIOR_DIR_REL/3.2.distill.domain._.v1.i1.md
184
+
185
+
186
+ ---
187
+
188
+ emit to $BEHAVIOR_DIR_REL/3.3.blueprint.v1.i1.md
189
+ EOF
190
+
191
+ # findsert 4.1.roadmap.v1.src
192
+ findsert "$BEHAVIOR_DIR/4.1.roadmap.v1.src" << EOF
193
+ declare a roadmap,
194
+
195
+ - checklist style
196
+ - with ordered dependencies
197
+ - with behavioral acceptance criteria
198
+ - with behavioral acceptance verification at each step
199
+
200
+ for how to execute the blueprint specified in $BEHAVIOR_DIR_REL/3.3.blueprint.v1.i1.md
201
+
202
+ ---
203
+
204
+ emit into $BEHAVIOR_DIR_REL/4.1.roadmap.v1.i1.md
205
+ EOF
206
+
207
+ # findsert 5.1.execution.phase0_to_phaseN.v1.src
208
+ findsert "$BEHAVIOR_DIR/5.1.execution.phase0_to_phaseN.v1.src" << EOF
209
+ bootup your mechanic's role via \`npx rhachet roles boot --repo ehmpathy --role mechanic\`
210
+
211
+ then, execute
212
+ - phase0 to phaseN
213
+ of roadmap
214
+ - $BEHAVIOR_DIR_REL/4.1.roadmap.v1.i1.md
215
+
216
+ ref:
217
+ - $BEHAVIOR_DIR_REL/3.3.blueprint.v1.i1.md
218
+
219
+ ---
220
+
221
+ track your progress
222
+
223
+ emit todos and check them off into
224
+ - $BEHAVIOR_DIR_REL/5.1.execution.phase0_to_phaseN.v1.i1.md
225
+ EOF
226
+
227
+ # findsert .ref.[feedback].v1.[given].by_human.md
228
+ findsert "$BEHAVIOR_DIR/.ref.[feedback].v1.[given].by_human.md" << EOF
229
+ emit your response to the feedback into
230
+ - $BEHAVIOR_DIR_REL/.ref.[feedback].v1.[taken].by_robot.md
231
+
232
+ 1. emit your response checklist
233
+ 2. exec your response plan
234
+ 3. emit your response checkoffs into the checklist
235
+
236
+ ---
237
+
238
+ first, bootup your mechanics briefs again
239
+
240
+ npx rhachet roles boot --repo ehmpathy --role mechanic
241
+
242
+ ---
243
+ ---
244
+ ---
245
+
246
+
247
+ # blocker.1
248
+
249
+ ---
250
+
251
+ # nitpick.2
252
+
253
+ ---
254
+
255
+ # blocker.3
256
+ EOF
257
+
258
+ echo ""
259
+ echo "behavior thoughtroute initialized!"
260
+ echo " $BEHAVIOR_DIR"
@@ -0,0 +1,113 @@
1
+ #!/usr/bin/env bash
2
+ ######################################################################
3
+ # .what = bind mechanic SessionStart hook to Claude settings
4
+ #
5
+ # .why = the mechanic role needs to boot on every Claude session
6
+ # to ensure project context and briefs are loaded.
7
+ #
8
+ # this script "findserts" (find-or-insert) the SessionStart
9
+ # hook into .claude/settings.local.json, ensuring:
10
+ # β€’ the hook is present after running this skill
11
+ # β€’ no duplication if already present
12
+ # β€’ idempotent: safe to rerun
13
+ #
14
+ # .how = uses jq to merge the SessionStart hook configuration
15
+ # into the existing hooks structure, creating it if absent.
16
+ #
17
+ # guarantee:
18
+ # βœ” creates .claude/settings.local.json if missing
19
+ # βœ” preserves existing settings (permissions, other hooks)
20
+ # βœ” idempotent: no-op if hook already present
21
+ # βœ” fail-fast on errors
22
+ ######################################################################
23
+
24
+ set -euo pipefail
25
+
26
+ PROJECT_ROOT="$PWD"
27
+ SETTINGS_FILE="$PROJECT_ROOT/.claude/settings.local.json"
28
+
29
+ # Define the hook configuration to findsert
30
+ HOOK_CONFIG=$(cat <<'EOF'
31
+ {
32
+ "hooks": {
33
+ "SessionStart": [
34
+ {
35
+ "matcher": "*",
36
+ "hooks": [
37
+ {
38
+ "type": "command",
39
+ "command": "npx rhachet roles boot --repo ehmpathy --role mechanic",
40
+ "timeout": 60
41
+ }
42
+ ]
43
+ }
44
+ ]
45
+ }
46
+ }
47
+ EOF
48
+ )
49
+
50
+ # Ensure .claude directory exists
51
+ mkdir -p "$(dirname "$SETTINGS_FILE")"
52
+
53
+ # Initialize settings file if it doesn't exist
54
+ if [[ ! -f "$SETTINGS_FILE" ]]; then
55
+ echo "{}" > "$SETTINGS_FILE"
56
+ fi
57
+
58
+ # Findsert: merge the hook configuration if not already present
59
+ # Strategy: deep merge with existing hooks, creating structure if needed
60
+ jq --argjson hook "$HOOK_CONFIG" '
61
+ # Define the target command for comparison
62
+ def targetCmd: "npx rhachet roles boot --repo ehmpathy --role mechanic";
63
+
64
+ # Check if hook already exists
65
+ def hookExists:
66
+ (.hooks.SessionStart // [])
67
+ | map(select(.matcher == "*") | .hooks // [])
68
+ | flatten
69
+ | map(.command)
70
+ | index(targetCmd) != null;
71
+
72
+ # If hook already exists, return unchanged
73
+ if hookExists then
74
+ .
75
+ else
76
+ # Ensure .hooks exists
77
+ .hooks //= {} |
78
+
79
+ # Ensure .hooks.SessionStart exists
80
+ .hooks.SessionStart //= [] |
81
+
82
+ # Check if our matcher already exists
83
+ if (.hooks.SessionStart | map(.matcher) | index("*")) then
84
+ # Matcher exists, add our hook to its hooks array
85
+ .hooks.SessionStart |= map(
86
+ if .matcher == "*" then
87
+ .hooks += $hook.hooks.SessionStart[0].hooks
88
+ else
89
+ .
90
+ end
91
+ )
92
+ else
93
+ # Matcher does not exist, add the entire entry
94
+ .hooks.SessionStart += $hook.hooks.SessionStart
95
+ end
96
+ end
97
+ ' "$SETTINGS_FILE" > "$SETTINGS_FILE.tmp"
98
+
99
+ # Check if any changes were made
100
+ if diff -q "$SETTINGS_FILE" "$SETTINGS_FILE.tmp" >/dev/null 2>&1; then
101
+ rm "$SETTINGS_FILE.tmp"
102
+ echo "πŸ‘Œ mechanic SessionStart hook already bound"
103
+ echo " $SETTINGS_FILE"
104
+ exit 0
105
+ fi
106
+
107
+ # Atomic replace
108
+ mv "$SETTINGS_FILE.tmp" "$SETTINGS_FILE"
109
+
110
+ echo "πŸ”— mechanic SessionStart hook bound successfully!"
111
+ echo " $SETTINGS_FILE"
112
+ echo ""
113
+ echo "✨ next time you start a Claude session, the mechanic will boot automatically"
@@ -0,0 +1,109 @@
1
+ #!/usr/bin/env bash
2
+ ######################################################################
3
+ # .what = bind mechanic permissions to Claude settings
4
+ #
5
+ # .why = the mechanic role needs conservative permissions to operate
6
+ # safely while still being productive.
7
+ #
8
+ # this script manages permissions in .claude/settings.local.json:
9
+ # β€’ replaces existing allows entirely (conservative)
10
+ # β€’ extends denies by appending new entries (conservative)
11
+ # β€’ extends asks by appending new entries (conservative)
12
+ # β€’ idempotent: safe to rerun
13
+ #
14
+ # .how = uses jq to merge the permissions configuration
15
+ # into the existing settings structure, creating it if absent.
16
+ #
17
+ # guarantee:
18
+ # βœ” creates .claude/settings.local.json if missing
19
+ # βœ” preserves existing settings (hooks, other configs)
20
+ # βœ” replaces allow list entirely
21
+ # βœ” appends to deny list (no duplicates)
22
+ # βœ” appends to ask list (no duplicates)
23
+ # βœ” idempotent: safe to rerun
24
+ # βœ” fail-fast on errors
25
+ ######################################################################
26
+
27
+ set -euo pipefail
28
+
29
+ PROJECT_ROOT="$PWD"
30
+ SETTINGS_FILE="$PROJECT_ROOT/.claude/settings.local.json"
31
+
32
+ # define the permissions configuration to apply
33
+ PERMISSIONS_CONFIG=$(cat <<'EOF'
34
+ {
35
+ "permissions": {
36
+ "deny": [
37
+ "Bash(git commit:*)"
38
+ ],
39
+ "ask": [
40
+ "Bash(chmod:*)",
41
+ "Bash(pnpm install:*)",
42
+ "Bash(pnpm add:*)"
43
+ ],
44
+ "allow": [
45
+ "WebSearch",
46
+ "WebFetch(domain:github.com)",
47
+ "WebFetch(domain:www.npmjs.com)",
48
+ "WebFetch(domain:hub.docker.com)",
49
+ "WebFetch(domain:raw.githubusercontent.com)",
50
+ "Bash(THOROUGH=true npm run test:*)",
51
+ "Bash(AWS_PROFILE=ahbode.dev npm run test:integration:*)",
52
+ "Bash(npm run fix:*)",
53
+ "Bash(AWS_PROFILE=ahbode.dev npx jest:*)",
54
+ "Bash(AWS_PROFILE=ahbode.dev npm run deploy:dev:*)",
55
+ "Bash(AWS_PROFILE=ahbode.dev STAGE=dev npm run test:acceptance:*)",
56
+ "Bash(npm run start:testdb:*)",
57
+ "Bash(cat:*)",
58
+ "Bash(unzip:*)",
59
+ "Bash(npm view:*)"
60
+ ]
61
+ }
62
+ }
63
+ EOF
64
+ )
65
+
66
+ # ensure .claude directory exists
67
+ mkdir -p "$(dirname "$SETTINGS_FILE")"
68
+
69
+ # initialize settings file if it doesn't exist
70
+ if [[ ! -f "$SETTINGS_FILE" ]]; then
71
+ echo "{}" > "$SETTINGS_FILE"
72
+ fi
73
+
74
+ # apply permissions:
75
+ # - replace allow entirely
76
+ # - append to deny (unique)
77
+ # - append to ask (unique)
78
+ jq --argjson perms "$PERMISSIONS_CONFIG" '
79
+ # ensure .permissions exists
80
+ .permissions //= {} |
81
+
82
+ # replace allow entirely with our config
83
+ .permissions.allow = $perms.permissions.allow |
84
+
85
+ # append to deny (unique entries only)
86
+ .permissions.deny = ((.permissions.deny // []) + $perms.permissions.deny | unique) |
87
+
88
+ # append to ask (unique entries only)
89
+ .permissions.ask = ((.permissions.ask // []) + $perms.permissions.ask | unique)
90
+ ' "$SETTINGS_FILE" > "$SETTINGS_FILE.tmp"
91
+
92
+ # check if any changes were made
93
+ if diff -q "$SETTINGS_FILE" "$SETTINGS_FILE.tmp" >/dev/null 2>&1; then
94
+ rm "$SETTINGS_FILE.tmp"
95
+ echo "πŸ‘Œ mechanic permissions already configured"
96
+ echo " $SETTINGS_FILE"
97
+ exit 0
98
+ fi
99
+
100
+ # atomic replace
101
+ mv "$SETTINGS_FILE.tmp" "$SETTINGS_FILE"
102
+
103
+ echo "πŸ” mechanic permissions configured successfully!"
104
+ echo " $SETTINGS_FILE"
105
+ echo ""
106
+ echo "✨ permissions applied:"
107
+ echo " β€’ allow: replaced entirely"
108
+ echo " β€’ deny: extended (no duplicates)"
109
+ echo " β€’ ask: extended (no duplicates)"
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env bash
2
+ ######################################################################
3
+ # .what = initialize Claude settings for mechanic role
4
+ #
5
+ # .why = mechanic needs both hooks and permissions configured to
6
+ # operate effectively. this script dispatches to both:
7
+ # β€’ init.claude.hooks.sh - binds SessionStart hook
8
+ # β€’ init.claude.permissions.sh - configures permissions
9
+ #
10
+ # single entry point for full Claude configuration.
11
+ #
12
+ # .how = runs both init scripts in sequence from the same directory.
13
+ #
14
+ # guarantee:
15
+ # βœ” runs both hooks and permissions initialization
16
+ # βœ” fail-fast on any error
17
+ # βœ” idempotent: safe to rerun
18
+ ######################################################################
19
+
20
+ set -euo pipefail
21
+
22
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
23
+
24
+ echo "πŸ”§ init claude config for mechanic role..."
25
+ echo ""
26
+
27
+ # initialize hooks
28
+ "$SCRIPT_DIR/init.claude.hooks.sh"
29
+ echo ""
30
+
31
+ # initialize permissions
32
+ "$SCRIPT_DIR/init.claude.permissions.sh"
33
+ echo ""
34
+
35
+ echo "πŸ‘Œ claude config ready"
@@ -0,0 +1,43 @@
1
+ #!/usr/bin/env bash
2
+ ######################################################################
3
+ # .what = link Claude transcripts into project-local structure
4
+ #
5
+ # .why = Claude stores transcripts in ~/.claude/projects/<encoded-path>
6
+ # which makes them hard to browse, version-control, and sync.
7
+ #
8
+ # this script creates a symlink so transcripts appear under:
9
+ # <project>/.rhachet/claude/transcripts
10
+ #
11
+ # without altering, moving, or creating files in Claude storage.
12
+ #
13
+ # guarantee:
14
+ # βœ” zero mutation to Claude's storage
15
+ # βœ” fail-fast if transcripts don't exist yet
16
+ # βœ” safe to rerun (idempotent)
17
+ ######################################################################
18
+
19
+ set -euo pipefail
20
+
21
+ PROJECT_ROOT="$PWD"
22
+ DEST="$PROJECT_ROOT/.rhachet/claude/transcripts"
23
+
24
+ # Resolve where Claude stores transcripts for this project’s cwd
25
+ ENCODED_PATH="$(echo "$PROJECT_ROOT" | sed 's#/#-#g')"
26
+ CLAUDE_STORAGE="$HOME/.claude/projects/$ENCODED_PATH"
27
+
28
+ # Fail if Claude hasn't created the storage dir yet
29
+ if [[ ! -d "$CLAUDE_STORAGE" ]]; then
30
+ echo "❌ no Claude transcripts found for this project:"
31
+ echo " $CLAUDE_STORAGE"
32
+ echo "➑️ first run 'claude' once in this directory to create them"
33
+ exit 1
34
+ fi
35
+
36
+ # Ensure our local parent folder exists (not Claude’s)
37
+ mkdir -p "$(dirname "$DEST")"
38
+
39
+ # Create symlink pointing into Claude-managed storage
40
+ ln -sfn "$CLAUDE_STORAGE" "$DEST"
41
+
42
+ echo "πŸ”— linked:"
43
+ echo " $DEST β†’ $CLAUDE_STORAGE"