@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 +12 -0
- package/dist/lib/checkpoint-ontology/plan.js +1 -1
- package/dist/lib/flag-registry.js +14 -6
- package/dist/sentry.js +31 -3
- package/package.json +1 -1
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
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
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
|
-
|
|
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.
|