@rulemetric/hooks 0.7.5 → 0.7.7
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/session-start.sh +83 -2
package/package.json
CHANGED
package/scripts/session-start.sh
CHANGED
|
@@ -168,12 +168,19 @@ _rulemetric_suggest_instructions() {
|
|
|
168
168
|
else
|
|
169
169
|
event_type="surfaced"
|
|
170
170
|
fi
|
|
171
|
+
# Include the harness session id (HOOK_SESSION_ID — the external Claude Code /
|
|
172
|
+
# Cursor / … session id, UUID-validated by _normalize.sh). The DB session row
|
|
173
|
+
# usually doesn't exist yet at session-start (the proxy creates it from the
|
|
174
|
+
# first wire traffic), so the API can't resolve it here — instead it stores
|
|
175
|
+
# this external id and reconciles it to a treatment_exposures row at session
|
|
176
|
+
# close (reimport matches sessions.external_session_id). Without this, every
|
|
177
|
+
# surfaced event has session_id=NULL and suggestions can never be measured.
|
|
171
178
|
curl -s --noproxy '*' --max-time 3 -X POST \
|
|
172
179
|
"${api_url}/api/instruction-suggestions/${sid}/events" \
|
|
173
180
|
-H "Authorization: Bearer ${auth_token}" \
|
|
174
181
|
-H "Content-Type: application/json" \
|
|
175
|
-
-d "$(jq -n --arg eventType "$event_type" --arg tool "$tool" --arg projectPath "$project_path" \
|
|
176
|
-
'{eventType: $eventType, tool: $tool, projectPath: $projectPath}')" \
|
|
182
|
+
-d "$(jq -n --arg eventType "$event_type" --arg tool "$tool" --arg projectPath "$project_path" --arg sessionId "$HOOK_SESSION_ID" \
|
|
183
|
+
'{eventType: $eventType, tool: $tool, projectPath: $projectPath, sessionId: $sessionId}')" \
|
|
177
184
|
>/dev/null 2>&1 &
|
|
178
185
|
disown 2>/dev/null || true
|
|
179
186
|
i=$((i + 1))
|
|
@@ -181,3 +188,77 @@ _rulemetric_suggest_instructions() {
|
|
|
181
188
|
}
|
|
182
189
|
|
|
183
190
|
_rulemetric_suggest_instructions || true
|
|
191
|
+
|
|
192
|
+
# ── Memory injection (non-blocking) ──
|
|
193
|
+
# Surface this project's durable memories (facts / decisions / corrections /
|
|
194
|
+
# conventions distilled from prior sessions) to the model as session context, then
|
|
195
|
+
# stamp a treatment exposure per injected memory so their MEASURED effect flows
|
|
196
|
+
# through the effectiveness engine (GET /api/insights/memory-impact). The DB session
|
|
197
|
+
# doesn't exist yet at session-start (the proxy creates it from the first wire
|
|
198
|
+
# traffic), so the exposure is BUFFERED by this harness session id and reconciled at
|
|
199
|
+
# session close (reimport). All failures are silent — this block MUST NOT prevent
|
|
200
|
+
# session start. Same 4s read / 3s write timeouts as the suggestion block above.
|
|
201
|
+
# Mirrors _rulemetric_suggest_instructions() deliberately.
|
|
202
|
+
_rulemetric_inject_memories() {
|
|
203
|
+
local api_url="${RULEMETRIC_API_URL:-}"
|
|
204
|
+
local auth_token="${RULEMETRIC_API_KEY:-${RULEMETRIC_ACCESS_TOKEN:-}}"
|
|
205
|
+
local project_path
|
|
206
|
+
project_path="$(realpath -m "$(pwd)" 2>/dev/null || pwd)"
|
|
207
|
+
|
|
208
|
+
[ -n "$api_url" ] && [ -n "$auth_token" ] || return 0
|
|
209
|
+
command -v jq >/dev/null 2>&1 || return 0
|
|
210
|
+
|
|
211
|
+
local encoded_path
|
|
212
|
+
encoded_path="$(python3 -c \
|
|
213
|
+
"import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))" \
|
|
214
|
+
"$project_path" 2>/dev/null)" || encoded_path="$project_path"
|
|
215
|
+
|
|
216
|
+
local response
|
|
217
|
+
# Cap at 10 so a large memory set can't blow the context budget. Trust-gated
|
|
218
|
+
# priority ordering (inject the proven-helpful ones first) is the distiller's
|
|
219
|
+
# job — a later slice; today this is newest-active-first.
|
|
220
|
+
response="$(curl -s --noproxy '*' --max-time 4 \
|
|
221
|
+
"${api_url}/api/memories?projectPath=${encoded_path}&status=active&limit=10" \
|
|
222
|
+
-H "Authorization: Bearer ${auth_token}" 2>/dev/null)" || return 0
|
|
223
|
+
|
|
224
|
+
local count
|
|
225
|
+
count="$(printf '%s' "$response" | jq -r '.memories | length' 2>/dev/null)" || return 0
|
|
226
|
+
[ "$count" != "0" ] && [ "$count" != "null" ] && [ -n "$count" ] || return 0
|
|
227
|
+
|
|
228
|
+
printf '\n---\n'
|
|
229
|
+
printf '[rulemetric] %s durable project memory(ies) from prior sessions included as context.\n' "$count"
|
|
230
|
+
|
|
231
|
+
local i=0
|
|
232
|
+
while [ "$i" -lt "$count" ]; do
|
|
233
|
+
local kind title body
|
|
234
|
+
kind="$(printf '%s' "$response" | jq -r ".memories[$i].kind" 2>/dev/null)" || break
|
|
235
|
+
title="$(printf '%s' "$response" | jq -r ".memories[$i].title" 2>/dev/null)" || break
|
|
236
|
+
body="$(printf '%s' "$response" | jq -r ".memories[$i].body" 2>/dev/null)" || break
|
|
237
|
+
printf '\n### [%s] %s\n%s\n' "$kind" "$title" "$body"
|
|
238
|
+
i=$((i + 1))
|
|
239
|
+
done
|
|
240
|
+
|
|
241
|
+
printf '\n---\n'
|
|
242
|
+
|
|
243
|
+
# Stamp an exposure per injected memory (fire-and-forget). Keyed by the harness
|
|
244
|
+
# session id (HOOK_SESSION_ID); the DB session is created later by the proxy, so
|
|
245
|
+
# the API buffers the exposure (pending_treatment_exposures) and reconciles it to
|
|
246
|
+
# a treatment_exposures row at session close. Idempotent server-side, so duplicate
|
|
247
|
+
# hook fires are safe.
|
|
248
|
+
i=0
|
|
249
|
+
while [ "$i" -lt "$count" ]; do
|
|
250
|
+
local mid
|
|
251
|
+
mid="$(printf '%s' "$response" | jq -r ".memories[$i].id" 2>/dev/null)" || break
|
|
252
|
+
curl -s --noproxy '*' --max-time 3 -X POST \
|
|
253
|
+
"${api_url}/api/memories/${mid}/exposures" \
|
|
254
|
+
-H "Authorization: Bearer ${auth_token}" \
|
|
255
|
+
-H "Content-Type: application/json" \
|
|
256
|
+
-d "$(jq -n --arg externalSessionId "$HOOK_SESSION_ID" --arg projectPath "$project_path" \
|
|
257
|
+
'{externalSessionId: $externalSessionId, projectPath: $projectPath}')" \
|
|
258
|
+
>/dev/null 2>&1 &
|
|
259
|
+
disown 2>/dev/null || true
|
|
260
|
+
i=$((i + 1))
|
|
261
|
+
done
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
_rulemetric_inject_memories || true
|