rhachet-roles-ehmpathy 1.9.0 → 1.9.1

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.
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env bash
2
+ ######################################################################
3
+ # .what = upgrade declapract and apply latest best practices
4
+ #
5
+ # .why = declapract manages development best practices and tooling
6
+ # configuration across projects, ensuring consistency and
7
+ # enabling easy upgrades to latest standards.
8
+ #
9
+ # this skill upgrades declapract packages and reapplies
10
+ # practices, then validates the build still passes.
11
+ #
12
+ # guarantee:
13
+ # ✔ verifies declapract.use.yml exists before proceeding
14
+ # ✔ upgrades to latest declapract packages
15
+ # ✔ applies practices twice (ensures idempotency)
16
+ # ✔ reinstalls dependencies after application
17
+ # ✔ fail-fast on any error
18
+ ######################################################################
19
+
20
+ set -euo pipefail
21
+
22
+ PROJECT_ROOT="$PWD"
23
+ CONFIG_FILE="$PROJECT_ROOT/declapract.use.yml"
24
+
25
+ # Verify declapract config exists
26
+ if [[ ! -f "$CONFIG_FILE" ]]; then
27
+ echo "❌ no declapract.use.yml found in project root"
28
+ echo " $CONFIG_FILE"
29
+ echo "➡️ first configure declapract for this project"
30
+ exit 1
31
+ fi
32
+
33
+ echo "📦 upgrading declapract packages..."
34
+ npm install --save-dev declapract@latest declapract-typescript-ehmpathy@latest
35
+
36
+ echo ""
37
+ echo "✨ applying best practices..."
38
+ npx declapract apply && npx declapract apply
39
+
40
+ echo ""
41
+ echo "📦 reinstalling dependencies..."
42
+ npm install
43
+
44
+ echo ""
45
+ echo "✅ declapract upgrade complete!"
46
+ echo ""
47
+ echo "⚠️ next steps:"
48
+ echo " 1. verify build passes: npm run test:types && npm run build"
49
+ echo " 2. review changes for breaking updates"
50
+ echo " 3. test that all still behaves as expected"
@@ -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,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"
@@ -0,0 +1,245 @@
1
+ #!/usr/bin/env bash
2
+ ######################################################################
3
+ # # tldr
4
+ #
5
+ # .what: run tests with proper setup, logs, and context preservation
6
+ # .why: preserve test output for review without rerun, auto-configure AWS and testdb
7
+ # .how: ./run.test.sh unit
8
+ # ./run.test.sh integration "pattern"
9
+ # ./run.test.sh acceptance
10
+ #
11
+ ######################################################################
12
+ # # full
13
+ #
14
+ # .what
15
+ #
16
+ # run tests with proper setup, logs, and context preservation
17
+ #
18
+ # supports unit, integration, and acceptance tests with automatic:
19
+ # - output logs to .log/test/ for repeated review
20
+ # - scope filter and THOROUGH mode
21
+ # - AWS profile configuration (for repos with AWS resources)
22
+ # - test database provision (when start:testdb is available)
23
+ #
24
+ #
25
+ # .why
26
+ #
27
+ # tests require different setup depending on their type:
28
+ #
29
+ # unit tests:
30
+ # - isolated, no external dependencies
31
+ # - fast execution
32
+ # - use --changedSince by default for speed
33
+ #
34
+ # integration tests:
35
+ # - interact with databases and remote resources
36
+ # - require AWS credentials (if repo uses AWS)
37
+ # - require test databases (if repo uses a testdb)
38
+ # - test interactions between components
39
+ #
40
+ # acceptance tests:
41
+ # - end-to-end testing
42
+ # - require AWS credentials (if repo uses AWS)
43
+ # - require test database provisioning
44
+ # - verify complete user workflows
45
+ #
46
+ # all tests benefit from:
47
+ # - output logs via tee to .log/test/{type}/run.{timestamp}.out
48
+ # - preserved context for review without rerun
49
+ # - comparison of results across test runs
50
+ #
51
+ #
52
+ # .howto.use
53
+ #
54
+ # ## unit tests
55
+ #
56
+ # run all unit tests (uses --changedSince for speed):
57
+ # ./run.test.sh unit
58
+ #
59
+ # run unit tests that match a pattern (automatically THOROUGH):
60
+ # ./run.test.sh unit "syncPhone"
61
+ # ./run.test.sh unit "relate.*Path"
62
+ #
63
+ # run all unit tests thoroughly (no --changedSince):
64
+ # THOROUGH=true ./run.test.sh unit
65
+ #
66
+ # behavior:
67
+ # - no AWS_PROFILE configuration
68
+ # - no test database provision
69
+ # - uses --changedSince by default (unless scope provided or THOROUGH=true)
70
+ # - logs to .log/test/unit/run.{timestamp}.out
71
+ #
72
+ #
73
+ # ## integration tests
74
+ #
75
+ # run all integration tests:
76
+ # ./run.test.sh integration
77
+ #
78
+ # run integration tests that match a pattern:
79
+ # ./run.test.sh integration "database.*sync"
80
+ # ./run.test.sh integration "whodis"
81
+ #
82
+ # behavior:
83
+ # - sets AWS_PROFILE=$org.dev (if awsAccountId in declapract.use.yml)
84
+ # - runs start:testdb (if available in package.json)
85
+ # - uses --changedSince by default (unless scope provided or THOROUGH=true)
86
+ # - logs to .log/test/integration/run.{timestamp}.out
87
+ #
88
+ #
89
+ # ## acceptance tests
90
+ #
91
+ # run all acceptance tests locally:
92
+ # ./run.test.sh acceptance
93
+ #
94
+ # run acceptance tests that match a pattern:
95
+ # ./run.test.sh acceptance "user.*flow"
96
+ #
97
+ # behavior:
98
+ # - sets AWS_PROFILE=$org.dev (if awsAccountId in declapract.use.yml)
99
+ # - runs start:testdb (if available in package.json)
100
+ # - uses test:acceptance:locally (local execution only for now)
101
+ # - logs to .log/test/acceptance/run.{timestamp}.out
102
+ #
103
+ #
104
+ # ## review test output
105
+ #
106
+ # all test output is logged via tee to .log/test/{type}/run.{timestamp}.out
107
+ #
108
+ # review the latest test run:
109
+ # cat .log/test/unit/run.*.out | tail -n 1 | xargs cat
110
+ #
111
+ # compare test results across runs:
112
+ # ls -t .log/test/unit/
113
+ # diff .log/test/unit/run.2025-11-23T15-00-00Z.out \
114
+ # .log/test/unit/run.2025-11-23T15-10-00Z.out
115
+ #
116
+ # search for failures in logs:
117
+ # grep -r "FAIL" .log/test/unit/
118
+ #
119
+ #
120
+ # .guarantee
121
+ #
122
+ # ✔ configure AWS_PROFILE only if awsAccountId in declapract.use.yml
123
+ # ✔ provision test database only if start:testdb in package.json
124
+ # ✔ log output to .log/test/{type}/run.{timestamp}.out via tee
125
+ # ✔ preserve context for repeated review without rerun
126
+ # ✔ support jest pattern/scope filter
127
+ # ✔ automatically set THOROUGH=true when scope is provided
128
+ # ✔ fail-fast on test failures
129
+ # ✔ show relative paths for easy navigation
130
+ ######################################################################
131
+
132
+ set -euo pipefail
133
+
134
+ # Parse arguments
135
+ TEST_TYPE="${1:-}"
136
+ SCOPE="${2:-}"
137
+
138
+ # Default to THOROUGH mode when scope is provided (unless explicitly set)
139
+ if [[ -n "$SCOPE" ]] && [[ -z "${THOROUGH:-}" ]]; then
140
+ export THOROUGH=true
141
+ fi
142
+
143
+ # Validate test type
144
+ if [[ -z "$TEST_TYPE" ]]; then
145
+ echo "✗ test type required"
146
+ echo ""
147
+ echo "usage: $0 <type> [pattern]"
148
+ echo ""
149
+ echo "types:"
150
+ echo " unit - run unit tests"
151
+ echo " integration - run integration tests"
152
+ echo " acceptance - run acceptance tests"
153
+ echo ""
154
+ echo "examples:"
155
+ echo " $0 unit"
156
+ echo " $0 integration 'database.*sync'"
157
+ echo " THOROUGH=true $0 unit"
158
+ exit 1
159
+ fi
160
+
161
+ if [[ ! "$TEST_TYPE" =~ ^(unit|integration|acceptance)$ ]]; then
162
+ echo "✗ invalid test type: $TEST_TYPE"
163
+ echo " valid types: unit, integration, acceptance"
164
+ exit 1
165
+ fi
166
+
167
+ PROJECT_ROOT="$PWD"
168
+ LOG_DIR="$PROJECT_ROOT/.log/test/$TEST_TYPE"
169
+ TIMESTAMP=$(date -u +"%Y-%m-%dT%H-%M-%SZ")
170
+ LOG_FILE="$LOG_DIR/run.$TIMESTAMP.out"
171
+
172
+ # Ensure log directory exists
173
+ mkdir -p "$LOG_DIR"
174
+
175
+ echo "→ run $TEST_TYPE tests"
176
+ echo "→ log to: ${LOG_FILE#$PROJECT_ROOT/}"
177
+ echo ""
178
+
179
+ # Configure AWS profile and provision test database for integration/acceptance tests
180
+ if [[ "$TEST_TYPE" == "integration" ]] || [[ "$TEST_TYPE" == "acceptance" ]]; then
181
+ # Check if awsAccountId is specified in declapract.use.yml
182
+ if [[ -f "declapract.use.yml" ]] && grep -q "awsAccountId:" declapract.use.yml; then
183
+ # Extract organization from declapract.use.yml
184
+ ORGANIZATION=$(grep -E '^\s*organizationName:' declapract.use.yml | sed "s/.*organizationName:[[:space:]]*['\"]*//" | sed "s/['\"].*//")
185
+
186
+ if [[ -n "$ORGANIZATION" ]]; then
187
+ # Configure AWS profile for dev resources
188
+ export AWS_PROFILE="$ORGANIZATION.dev"
189
+ echo "→ AWS_PROFILE=$AWS_PROFILE"
190
+ fi
191
+ fi
192
+
193
+ # Start test database if available in package.json
194
+ if npm run | grep -q "start:testdb"; then
195
+ echo "→ start:testdb"
196
+ echo ""
197
+ npm run start:testdb 2>&1 | tee -a "$LOG_FILE"
198
+ fi
199
+ fi
200
+
201
+ # Build the test command
202
+ case "$TEST_TYPE" in
203
+ unit)
204
+ TEST_COMMAND="npm run test:unit"
205
+ ;;
206
+ integration)
207
+ TEST_COMMAND="npm run test:integration"
208
+ ;;
209
+ acceptance)
210
+ # only support local acceptance tests for now
211
+ TEST_COMMAND="npm run test:acceptance:locally"
212
+ ;;
213
+ esac
214
+
215
+ # Add scope filter if provided
216
+ if [[ -n "$SCOPE" ]]; then
217
+ echo "→ scope filter: $SCOPE"
218
+ echo ""
219
+ TEST_COMMAND="$TEST_COMMAND -- '$SCOPE'"
220
+ else
221
+ echo "→ scope: all tests"
222
+ echo ""
223
+ fi
224
+
225
+ # Run tests with output logged via tee
226
+ echo "> $TEST_COMMAND" | tee -a "$LOG_FILE"
227
+ echo "" | tee -a "$LOG_FILE"
228
+
229
+ eval "$TEST_COMMAND" 2>&1 | tee -a "$LOG_FILE"
230
+ TEST_EXIT_CODE=${PIPESTATUS[0]}
231
+
232
+ echo "" | tee -a "$LOG_FILE"
233
+
234
+ if [[ $TEST_EXIT_CODE -eq 0 ]]; then
235
+ echo "✓ $TEST_TYPE tests complete!" | tee -a "$LOG_FILE"
236
+ echo "→ log saved: ${LOG_FILE#$PROJECT_ROOT/}"
237
+ exit 0
238
+ else
239
+ echo "✗ $TEST_TYPE tests failed" | tee -a "$LOG_FILE"
240
+ echo "→ log saved: ${LOG_FILE#$PROJECT_ROOT/}"
241
+ echo ""
242
+ echo "→ review the log file for details:"
243
+ echo " cat ${LOG_FILE#$PROJECT_ROOT/}"
244
+ exit $TEST_EXIT_CODE
245
+ fi
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env bash
2
+ ######################################################################
3
+ # .what = run integration tests thoroughly with optional scope filter
4
+ #
5
+ # .why = integration tests verify interactions between components
6
+ # and external systems. running them thoroughly (without
7
+ # --changedSince) ensures all tests pass, not just changed ones.
8
+ #
9
+ # this is critical before releases, after major changes, or
10
+ # when verifying the entire test suite.
11
+ #
12
+ # usage for agents:
13
+ # - run all integration tests:
14
+ # ./test.integration.sh
15
+ #
16
+ # - run tests matching a specific scope/pattern:
17
+ # ./test.integration.sh <pattern>
18
+ # example: ./test.integration.sh "user.*auth"
19
+ # example: ./test.integration.sh "database"
20
+ #
21
+ # - the THOROUGH=true flag forces ALL tests to run, not just
22
+ # those changed since main branch
23
+ #
24
+ # guarantee:
25
+ # ✔ runs ALL integration tests (ignores --changedSince)
26
+ # ✔ supports optional jest pattern/scope filtering
27
+ # ✔ uses verbose output for debugging
28
+ # ✔ passes with no tests if scope matches nothing
29
+ # ✔ fail-fast on test failures
30
+ ######################################################################
31
+
32
+ set -euo pipefail
33
+
34
+ SCOPE="${1:-}"
35
+
36
+ echo "🧪 running integration tests thoroughly..."
37
+ echo ""
38
+
39
+ if [[ -n "$SCOPE" ]]; then
40
+ echo "📍 scope filter: $SCOPE"
41
+ echo ""
42
+ THOROUGH=true npm run test:integration -- "$SCOPE"
43
+ else
44
+ echo "📍 scope: all tests"
45
+ echo ""
46
+ THOROUGH=true npm run test:integration
47
+ fi
48
+
49
+ echo ""
50
+ echo "✅ integration tests complete!"
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "rhachet-roles-ehmpathy",
3
3
  "author": "ehmpathy",
4
4
  "description": "empathetic software construction roles and skills, via rhachet",
5
- "version": "1.9.0",
5
+ "version": "1.9.1",
6
6
  "repository": "ehmpathy/rhachet-roles-ehmpathy",
7
7
  "homepage": "https://github.com/ehmpathy/rhachet-roles-ehmpathy",
8
8
  "keywords": [
@@ -26,7 +26,7 @@
26
26
  "fix:lint": "eslint -c ./.eslintrc.js src/**/*.ts --fix",
27
27
  "build:clean": "rm dist/ -rf",
28
28
  "build:compile": "tsc -p ./tsconfig.build.json",
29
- "build:complete": "rsync -a --prune-empty-dirs --include='*/' --exclude='**/.route/**' --exclude='**/.scratch/**' --include='**/*.template.md' --include='**/.briefs/**/*.md' --include='**/.briefs/*.md' --exclude='*' src/ dist/",
29
+ "build:complete": "rsync -a --prune-empty-dirs --include='*/' --exclude='**/.route/**' --exclude='**/.scratch/**' --include='**/*.template.md' --include='**/.briefs/**/*.md' --include='**/.briefs/*.md' --include='**/.skills/**/*.sh' --include='**/.skills/*.sh' --exclude='*' src/ dist/",
30
30
  "build": "npm run build:clean && npm run build:compile && npm run build:complete",
31
31
  "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",
32
32
  "test:types": "tsc -p ./tsconfig.build.json --noEmit",