@rulemetric/hooks 0.7.27 → 0.7.28
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/package.json +1 -1
- package/scripts/_ensure-session.sh +30 -0
package/package.json
CHANGED
|
@@ -117,16 +117,46 @@ _rulemetric_ensure_session() {
|
|
|
117
117
|
is_headless="true"
|
|
118
118
|
fi
|
|
119
119
|
|
|
120
|
+
# Harness version, read from the transcript the hook was handed.
|
|
121
|
+
#
|
|
122
|
+
# `claudeCodeVersion` used to arrive ONLY on the SessionEnd transcript
|
|
123
|
+
# reimport, so any session that never ended cleanly — still running, crashed,
|
|
124
|
+
# or killed by a "Hook cancelled" — never got one. Measured 2026-07-27:
|
|
125
|
+
# harness_version was null on 96 of 326 claude_code sessions over 14 days
|
|
126
|
+
# (~30%), including long-lived live sessions, which is what blocks
|
|
127
|
+
# version-scoped segment comparisons (§6c.f attribution depth).
|
|
128
|
+
#
|
|
129
|
+
# Claude Code stamps `version` on every transcript entry from the first user
|
|
130
|
+
# message onward, so scanning the head of the file finds it. The first line is
|
|
131
|
+
# an `operation` record with no version, hence the scan rather than a
|
|
132
|
+
# first-line read. Reposts merge metadata server-side (jsonb ||), so if the
|
|
133
|
+
# transcript had no entries yet at SessionStart, a later hook call fills it in.
|
|
134
|
+
# Extracted with grep, NOT jq, on purpose: the bundled `jq` shim supports only
|
|
135
|
+
# the narrow filter subset already used here and returns EMPTY for anything
|
|
136
|
+
# else (verified — `select(.version != null) | .version` and even `.version`
|
|
137
|
+
# yield nothing). On a host without real jq that would silently capture no
|
|
138
|
+
# version at all, which is the exact failure being fixed. The semver-shaped
|
|
139
|
+
# pattern keeps prose in message content from matching.
|
|
140
|
+
local harness_version=""
|
|
141
|
+
if [ -n "${HOOK_TRANSCRIPT_PATH:-}" ] && [ -f "$HOOK_TRANSCRIPT_PATH" ]; then
|
|
142
|
+
harness_version=$(head -n 50 "$HOOK_TRANSCRIPT_PATH" 2>/dev/null \
|
|
143
|
+
| grep -oE '"version"[[:space:]]*:[[:space:]]*"[0-9]+\.[0-9]+[0-9A-Za-z.-]*"' \
|
|
144
|
+
| head -n 1 \
|
|
145
|
+
| sed -E 's/.*"([0-9][^"]*)"$/\1/') || harness_version=""
|
|
146
|
+
fi
|
|
147
|
+
|
|
120
148
|
local metadata
|
|
121
149
|
metadata=$(jq -n \
|
|
122
150
|
--arg gitRemote "$git_remote" \
|
|
123
151
|
--arg gitRootCommit "$git_root_commit" \
|
|
124
152
|
--arg launchProjectPath "$launch_project_path" \
|
|
153
|
+
--arg claudeCodeVersion "$harness_version" \
|
|
125
154
|
--argjson isWorktree "$is_worktree" \
|
|
126
155
|
--argjson isHeadless "$is_headless" \
|
|
127
156
|
'{} + (if $gitRemote != "" then {gitRemote: $gitRemote} else {} end)
|
|
128
157
|
+ (if $gitRootCommit != "" then {gitRootCommit: $gitRootCommit} else {} end)
|
|
129
158
|
+ (if $launchProjectPath != "" then {launchProjectPath: $launchProjectPath} else {} end)
|
|
159
|
+
+ (if $claudeCodeVersion != "" then {claudeCodeVersion: $claudeCodeVersion} else {} end)
|
|
130
160
|
+ {isWorktree: $isWorktree, headless: $isHeadless}')
|
|
131
161
|
|
|
132
162
|
# Optional org attribution (Phase 8.1). RULEMETRIC_ORG_ID is exported by
|