@indigoai-us/hq-cli 5.108.2 → 5.108.4

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.
@@ -0,0 +1,78 @@
1
+ // src/utils/qmd-workdir-missing-error.ts
2
+ //
3
+ // Classify a qmd spawn failure caused by a MISSING WORKING DIRECTORY — the
4
+ // directory the qmd child was told to run in (`cwd`, always the resolved hq
5
+ // root at the qmd call sites) does not exist — rather than an hq-cli code
6
+ // defect or a genuinely missing qmd. This is the caller's LOCAL filesystem (a
7
+ // deleted tree, a `--hq-root` pointing at a directory that is not there), not a
8
+ // bug HQ can fix in code, so the CLI surfaces an actionable remedy and SKIPS
9
+ // Sentry capture. Sibling of qmd-store-missing-error.ts (HQ-CLI-16, a missing
10
+ // STORE directory) and qmd-store-unopenable-error.ts (HQ-CLI-18): a failure
11
+ // that is NOT an hq-cli defect is printed with an actionable message and never
12
+ // filed as a crash.
13
+ //
14
+ // HQ-CLI-1A (Sentry indigo-d0/hq-cli 7705642434): `hq index status --hq-root
15
+ // /home/ec2-user/hq` spawned the bundled qmd as `<node interpreter> <qmd
16
+ // launcher>`, and spawnSync failed with `spawnSync /usr/bin/node ENOENT`. On
17
+ // Linux, spawnSync reports ENOENT with `path`/`syscall` set to the COMMAND both
18
+ // when the command is missing AND when chdir into `cwd` fails — two distinct
19
+ // causes with byte-identical text. finishRunQmd was handed only the qmd
20
+ // launcher path, so it blamed a THIRD path Node never faulted
21
+ // (`QmdBinaryMissingError: Unable to execute qmd at …/@tobilu/qmd/bin/qmd`) with
22
+ // a remedy (`Install @tobilu/qmd`) that cannot fix either real cause, and — with
23
+ // no boundary branch for it — the misattributed error was captured as a crash.
24
+ // finishRunQmd now disambiguates at the failure site: when the ENOENT is a
25
+ // missing working directory it raises the typed carrier this module classifies.
26
+ //
27
+ // Classification is STRUCTURAL — the typed carrier's own `name` plus its
28
+ // hq-populated `workdir` field, NEVER a text match on qmd's output or the
29
+ // caller's argv — so a search query or a document body can never trip it, and
30
+ // the class need not be imported here (avoiding a cycle with the module that
31
+ // defines it). Reading `name`/`workdir` off the error object also lets the
32
+ // top-level boundary, which reconstructs typed carriers structurally, branch on
33
+ // it the same way it does the sibling qmd errors.
34
+ /**
35
+ * True when `err` is a qmd working-directory-missing failure: it carries the
36
+ * QmdWorkdirMissingError name and an hq-populated `workdir`. Accepts either the
37
+ * thrown error or a bare `{ name, workdir }` probe object. A true result means
38
+ * the caller should print the classified remedy, exit non-zero, and SKIP Sentry
39
+ * capture.
40
+ */
41
+ export function isQmdWorkdirMissingError(err) {
42
+ if (err === null || typeof err !== "object")
43
+ return false;
44
+ const record = err;
45
+ return (record.name === "QmdWorkdirMissingError" &&
46
+ typeof record.workdir === "string" &&
47
+ record.workdir.length > 0);
48
+ }
49
+ /**
50
+ * The actionable remedy, naming the working directory that does not exist. The
51
+ * directory is an hq-DERIVED value — the resolved `cwd` (the hq root) the qmd
52
+ * child was handed — never caller argv/query or upstream free text, so the line
53
+ * stays input-free. Deliberately does NOT suggest reinstalling qmd (the reported
54
+ * misattribution's dead-end remedy) or `hq index sync` (reconciliation runs the
55
+ * same spawn and would hit the identical failure, a dead-end loop): the only fix
56
+ * is to make the working directory exist.
57
+ */
58
+ function remedyMessage(workdir) {
59
+ return (`hq's working directory (${workdir}) does not exist, so its local search index ` +
60
+ "could not run there. This is your machine's filesystem, not an hq bug: " +
61
+ "re-create that directory, or re-run with --hq-root pointing at a directory " +
62
+ "that exists.");
63
+ }
64
+ /**
65
+ * If `err` is a qmd working-directory-missing failure, return the actionable
66
+ * remedy; otherwise return `null`. Mirrors qmdStoreMissingMessage /
67
+ * qmdStoreUnopenableMessage so the top-level handler can branch on it the same
68
+ * way: a non-null result means print-and-skip-Sentry, null means "handle as
69
+ * usual". The working directory is read STRUCTURALLY from the error's own
70
+ * hq-populated `workdir` field, NEVER from qmd's output.
71
+ */
72
+ export function qmdWorkdirMissingMessage(err) {
73
+ if (!isQmdWorkdirMissingError(err))
74
+ return null;
75
+ const record = err;
76
+ return remedyMessage(record.workdir);
77
+ }
78
+ //# sourceMappingURL=qmd-workdir-missing-error.js.map
@@ -86,6 +86,11 @@ const KNOWN_ERROR_NAMES = new Set([
86
86
  "QmdStoreUnopenableError",
87
87
  "QmdQueryDocumentError",
88
88
  "QmdModelDownloadError",
89
+ // Shares the `Qmd` prefix the qmd branch keys on. The boundary now SUPPRESSES
90
+ // capture for this class, so it should never reach a capture route — allow-
91
+ // listed defensively so a future capture path cannot mint an unbounded group
92
+ // (HQ-CLI-1A).
93
+ "QmdWorkdirMissingError",
89
94
  ]);
90
95
  /** Fixed bucket for any error name outside the closed allowlist. */
91
96
  const FALLBACK_ERROR_NAME = "other";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@indigoai-us/hq-cli",
3
- "version": "5.108.2",
3
+ "version": "5.108.4",
4
4
  "description": "HQ by Indigo management CLI — modules and cloud sync",
5
5
  "main": "dist/index.js",
6
6
  "bin": {