happyskills 0.53.0 → 0.54.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/CHANGELOG.md +6 -0
- package/package.json +1 -1
- package/src/commands/postlex.js +7 -1
- package/src/commands/search.js +8 -0
- package/src/utils/intent.js +22 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.54.0] - 2026-05-26
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **`intent_id` is now attached to every `/telemetry/discovery` beacon payload** (spec 260521-03 addendum § 4 — CLI half of Phase A). The CLI sources the value from the active intent envelope via a new `get_intent_id()` helper in `cli/src/utils/intent.js`, which decodes the envelope's base64url payload portion and extracts `intent_id`. Sent on all four beacon types fired from `search` and `postlex`: `rerank_started`, `rerank_completed`, `clarify_triggered`, `clarify_completed`. When no envelope is active the payload includes `intent_id: null`. Before this change, every `search.rerank` and `search.clarify` row in `analytics.events` landed with `intent_id = NULL`, defeating the addendum's goal of correlating beacons with the discovery chain.
|
|
15
|
+
|
|
10
16
|
## [0.53.0] - 2026-05-25
|
|
11
17
|
|
|
12
18
|
### Added
|
package/package.json
CHANGED
package/src/commands/postlex.js
CHANGED
|
@@ -15,6 +15,7 @@ const { exit_with_error, UsageError, CliError } = require('../utils/errors')
|
|
|
15
15
|
const { EXIT_CODES } = require('../constants')
|
|
16
16
|
const { slug_token_set, compute_lex_tier } = require('../utils/slug_tokens')
|
|
17
17
|
const { fire_discovery_telemetry } = require('../api/telemetry')
|
|
18
|
+
const { get_intent_id } = require('../utils/intent')
|
|
18
19
|
|
|
19
20
|
const HELP_TEXT = `Usage: happyskills postlex --query <q> --ranking <file|-> [options]
|
|
20
21
|
|
|
@@ -425,9 +426,13 @@ const run = (args) => catch_errors('Postlex failed', async () => {
|
|
|
425
426
|
const next_step = determine_next_step(final_ordering, query, clarification_turns_used)
|
|
426
427
|
|
|
427
428
|
// Fire telemetry — rerank_completed first (the rerank step succeeded);
|
|
428
|
-
// clarify_triggered separately if applicable.
|
|
429
|
+
// clarify_triggered separately if applicable. `intent_id` is sourced from
|
|
430
|
+
// the active intent envelope so these beacons correlate with the same
|
|
431
|
+
// discovery chain (spec 260521-03 addendum § 4).
|
|
432
|
+
const intent_id = get_intent_id()
|
|
429
433
|
fire_discovery_telemetry({
|
|
430
434
|
event: 'rerank_completed',
|
|
435
|
+
intent_id,
|
|
431
436
|
query,
|
|
432
437
|
promoted,
|
|
433
438
|
promoted_from_rank,
|
|
@@ -436,6 +441,7 @@ const run = (args) => catch_errors('Postlex failed', async () => {
|
|
|
436
441
|
if (next_step.action === 'clarify') {
|
|
437
442
|
fire_discovery_telemetry({
|
|
438
443
|
event: 'clarify_triggered',
|
|
444
|
+
intent_id,
|
|
439
445
|
query,
|
|
440
446
|
reason: 'post_rerank_weak',
|
|
441
447
|
turn_number: clarification_turns_used + 1,
|
package/src/commands/search.js
CHANGED
|
@@ -6,6 +6,7 @@ const { exit_with_error, UsageError, AuthError } = require('../utils/errors')
|
|
|
6
6
|
const { EXIT_CODES, VALID_SKILL_TYPES } = require('../constants')
|
|
7
7
|
const { load_token } = require('../auth/token_store')
|
|
8
8
|
const { fire_discovery_telemetry } = require('../api/telemetry')
|
|
9
|
+
const { get_intent_id } = require('../utils/intent')
|
|
9
10
|
|
|
10
11
|
const HELP_TEXT = `Usage: happyskills search [query] [options]
|
|
11
12
|
|
|
@@ -221,9 +222,14 @@ const run_smart_search = (args, query, options) => catch_errors('Smart search fa
|
|
|
221
222
|
const next_step = build_search_next_step(response, query, { with_rerank, clarification_turns_used })
|
|
222
223
|
|
|
223
224
|
// Telemetry beacons (fire-and-forget). Spec § 5.1 + § 5.3.
|
|
225
|
+
// `intent_id` is sourced from the active intent envelope (spec 260521-03
|
|
226
|
+
// addendum § 4) so search.rerank / search.clarify rows correlate with
|
|
227
|
+
// the same discovery chain as the search.query that minted the envelope.
|
|
228
|
+
const intent_id = get_intent_id()
|
|
224
229
|
if (with_rerank && next_step?.action === 'rank_digests_inline') {
|
|
225
230
|
fire_discovery_telemetry({
|
|
226
231
|
event: 'rerank_started',
|
|
232
|
+
intent_id,
|
|
227
233
|
query,
|
|
228
234
|
rerank_prompt_version: response?.rerank_prompt_version || null,
|
|
229
235
|
})
|
|
@@ -231,6 +237,7 @@ const run_smart_search = (args, query, options) => catch_errors('Smart search fa
|
|
|
231
237
|
if (with_rerank && next_step?.action === 'clarify') {
|
|
232
238
|
fire_discovery_telemetry({
|
|
233
239
|
event: 'clarify_triggered',
|
|
240
|
+
intent_id,
|
|
234
241
|
query,
|
|
235
242
|
reason: 'match_notice',
|
|
236
243
|
turn_number: clarification_turns_used + 1,
|
|
@@ -241,6 +248,7 @@ const run_smart_search = (args, query, options) => catch_errors('Smart search fa
|
|
|
241
248
|
// with a refined query.
|
|
242
249
|
fire_discovery_telemetry({
|
|
243
250
|
event: 'clarify_completed',
|
|
251
|
+
intent_id,
|
|
244
252
|
query,
|
|
245
253
|
turn_number: clarification_turns_used,
|
|
246
254
|
})
|
package/src/utils/intent.js
CHANGED
|
@@ -39,4 +39,25 @@ const clear_envelope = () => {
|
|
|
39
39
|
delete process.env[ENV_VAR]
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
// Spec 260521-03 addendum § 4 — Extract the intent_id UUID from the active
|
|
43
|
+
// envelope so the CLI can attach it to /telemetry/discovery beacon payloads.
|
|
44
|
+
// The envelope is `<base64url-payload>.<base64url-hmac>`; the CLI doesn't
|
|
45
|
+
// have the HMAC secret and doesn't need to verify — it just reads the
|
|
46
|
+
// payload portion. Returns null when no envelope is active or the payload
|
|
47
|
+
// can't be decoded.
|
|
48
|
+
const get_intent_id = () => {
|
|
49
|
+
const env = get_envelope()
|
|
50
|
+
if (!env) return null
|
|
51
|
+
try {
|
|
52
|
+
const dot = env.indexOf('.')
|
|
53
|
+
if (dot <= 0) return null
|
|
54
|
+
const body = env.slice(0, dot)
|
|
55
|
+
const json = Buffer.from(body, 'base64url').toString('utf-8')
|
|
56
|
+
const payload = JSON.parse(json)
|
|
57
|
+
return payload.intent_id || null
|
|
58
|
+
} catch {
|
|
59
|
+
return null
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
module.exports = { init_from_env, init_from_flag, get_envelope, set_envelope, clear_envelope, get_intent_id, ENV_VAR }
|