@indigoai-us/hq-cli 5.201.1 → 5.201.3

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 CHANGED
@@ -2,6 +2,18 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [5.201.3] — 2026-09-25
6
+
7
+ ### Fixed
8
+
9
+ - A flag-registry worker whose startup fails because the working directory was deleted or its package files were being replaced no longer creates a Sentry issue. Other flag-registry worker errors remain visible with a worker tag.
10
+
11
+ ## [5.201.2] — 2026-09-25
12
+
13
+ ### Changed
14
+
15
+ - The checkpoint ontology plan tells the model to name a person by the full name the input or the company's entities give, not a first name alone.
16
+
5
17
  ## [5.201.1] — 2026-09-25
6
18
 
7
19
  ### Fixed
@@ -29,7 +29,7 @@ const CANDIDATE_INSTRUCTIONS = [
29
29
  `Write ${CANDIDATES_FILE} in the run directory as {"schema":"${CANDIDATES_SCHEMA}","candidates":[...]} and nothing else.`,
30
30
  "Each candidate: {input, type, name, aliases, confidence, evidence}. input is one of this plan's input ids; type is person, project, company or concept; name is the entity's full proper name; aliases are other names the input uses for it (at most 5); confidence is 0 to 1; evidence is a short quote from the input.",
31
31
  "Read only the files and line ranges this plan lists. For a signal, read its body and name the entities in missing_refs if the signal supports them.",
32
- "Name the specific people, projects, products, companies and named concepts that the input says something about. That includes the company that owns this knowledge and its own products when the input describes them. Name a third-party tool, vendor or service only when a section of the input is about it; skip ones that appear in a list, a stack summary or a passing mention. Skip generic words, file names and headings.",
32
+ "Name the specific people, projects, products, companies and named concepts that the input says something about. That includes the company that owns this knowledge and its own products when the input describes them. Name a third-party tool, vendor or service only when a section of the input is about it; skip ones that appear in a list, a stack summary or a passing mention. Skip generic words, file names and headings. Name a person by the full name the input or the company's entities give, not a first name alone.",
33
33
  "For the session input (its text is session_text in this plan), name only entities that already exist in the company and that the session did work on. Session candidates are recorded as links, never created.",
34
34
  "Do not create, edit, move or delete anything under ontology/, signals/ or sources/ yourself.",
35
35
  ];
@@ -6,6 +6,7 @@
6
6
  * keep a short-lived, offline CLI alive until the client's network deadline.
7
7
  */
8
8
  import { Worker } from "node:worker_threads";
9
+ import * as Sentry from "@sentry/node";
9
10
  import { isFlagSnapshot, readLocalOverride, resolveFlag, } from "@indigoai-us/hq-flags-client";
10
11
  import { readMachineCompanyBinding } from "./work-context/company.js";
11
12
  import { readSessionState } from "./work-context/state.js";
@@ -116,12 +117,19 @@ export function kickFlagRegistryReadiness(dependencies = {}) {
116
117
  const companyIdentifiers = [companyUid, company.companySlug].filter((value) => Boolean(value));
117
118
  processReader = processSnapshotReader(companyIdentifiers);
118
119
  try {
119
- const worker = (dependencies.createWorker ?? ((filename, options) => new Worker(filename, options)))(new URL("./flag-registry-worker.js", import.meta.url), {
120
- workerData: {
121
- endpoint,
122
- ...(companyUid ? { companyUid } : {}),
123
- ...(company.companySlug ? { companyIdentifiers: [company.companySlug] } : {}),
124
- },
120
+ // The SDK's child-process integration captures every Worker error unless
121
+ // its process-wide captureWorkerErrors option is disabled. Scope only this
122
+ // worker so the reporting boundary can classify its startup errors without
123
+ // changing capture for unrelated workers.
124
+ const worker = Sentry.withScope((scope) => {
125
+ scope.setTag("worker", "flag-registry");
126
+ return (dependencies.createWorker ?? ((filename, options) => new Worker(filename, options)))(new URL("./flag-registry-worker.js", import.meta.url), {
127
+ workerData: {
128
+ endpoint,
129
+ ...(companyUid ? { companyUid } : {}),
130
+ ...(company.companySlug ? { companyIdentifiers: [company.companySlug] } : {}),
131
+ },
132
+ });
125
133
  });
126
134
  worker.on("message", (value) => {
127
135
  if (isFlagSnapshot(value))
package/dist/sentry.js CHANGED
@@ -20,7 +20,14 @@ import { installTreeTornSentryTagsFor, sentryFingerprintFor, sentryMcpCollisionC
20
20
  * Consistent with the swallow-EPIPE posture established in #138.
21
21
  */
22
22
  export function epipeAwareBeforeSend(event, hint) {
23
- if (isEpipe(hint?.originalException))
23
+ const flagRegistryWorkerEvent = isFlagRegistryWorkerEvent(event);
24
+ if (flagRegistryWorkerEvent) {
25
+ if (isExpectedFlagRegistryWorkerStartupFailure(hint?.originalException))
26
+ return null;
27
+ event.level = "warning";
28
+ event.tags = { ...event.tags, worker: "flag-registry" };
29
+ }
30
+ if (!flagRegistryWorkerEvent && isEpipe(hint?.originalException))
24
31
  return null;
25
32
  // Path-independent belt for environmental filesystem failures (ENOSPC /
26
33
  // EDQUOT / EROFS — a full disk, exhausted quota, or read-only mount, e.g.
@@ -31,7 +38,7 @@ export function epipeAwareBeforeSend(event, hint) {
31
38
  // either. handleTopLevelError already prints an actionable message for the
32
39
  // boundary route; dropping the event here suppresses the fatal regardless of
33
40
  // route, while the CLI still exits non-zero. HQ-CLI-R (Sentry 7671416365).
34
- if (environmentalFsErrorMessage(hint?.originalException))
41
+ if (!flagRegistryWorkerEvent && environmentalFsErrorMessage(hint?.originalException))
35
42
  return null;
36
43
  // Path-independent belt for an IN-PROCESS incomplete-install module-load
37
44
  // failure — hq-cli's own globally installed tree is not intact at load time
@@ -50,7 +57,7 @@ export function epipeAwareBeforeSend(event, hint) {
50
57
  // node_modules, so an hq-cli packaging fault (a dist/ miss, or a bare miss the
51
58
  // requirer does NOT declare — a possible undeclared/peer dependency) and the
52
59
  // path-less unattributable shape are NOT dropped here and stay captured.
53
- if (incompleteInstallMessage(hint?.originalException))
60
+ if (!flagRegistryWorkerEvent && incompleteInstallMessage(hint?.originalException))
54
61
  return null;
55
62
  // An incomplete-install shape that is NOT suppressed (a bare miss the requirer
56
63
  // does not declare, or a path-less loader/resolver ENOENT) should still arrive
@@ -95,6 +102,27 @@ export function epipeAwareBeforeSend(event, hint) {
95
102
  }
96
103
  return beforeSend(event, hint);
97
104
  }
105
+ function isFlagRegistryWorkerEvent(event) {
106
+ return event.tags?.worker === "flag-registry" && Boolean(event.exception?.values?.some((value) => value.mechanism?.type === "auto.child_process.worker_thread"));
107
+ }
108
+ function isExpectedFlagRegistryWorkerStartupFailure(error) {
109
+ if (typeof error !== "object" || error === null)
110
+ return false;
111
+ const details = error;
112
+ if (details.code === "ENOENT" && details.syscall === "uv_cwd") {
113
+ const stack = typeof details.stack === "string" ? details.stack : "";
114
+ return stack.includes("node:internal/main/worker_thread") && /\bat process\.cwd \(/.test(stack);
115
+ }
116
+ if (details.code !== "MODULE_NOT_FOUND" && details.code !== "ERR_MODULE_NOT_FOUND") {
117
+ return false;
118
+ }
119
+ const message = typeof details.message === "string" ? details.message : "";
120
+ const missingModule = /Cannot find module\s+['"]([^'"]+)['"]/.exec(message)?.[1];
121
+ if (!missingModule)
122
+ return false;
123
+ return missingModule.replaceAll("\\", "/").endsWith("/flag-registry-worker.js") ||
124
+ missingModule === "flag-registry-worker.js";
125
+ }
98
126
  /**
99
127
  * Tests substitute only the transport so the real SDK lifecycle can be
100
128
  * exercised without an ingest request. Production callers pass nothing.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@indigoai-us/hq-cli",
3
- "version": "5.201.1",
3
+ "version": "5.201.3",
4
4
  "description": "HQ by Indigo management CLI — modules and cloud sync",
5
5
  "main": "dist/index.js",
6
6
  "bin": {