@indigoai-us/hq-cli 5.345.101 → 5.345.102

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,12 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [5.345.102] — 2026-10-12
6
+ - Session-start health no longer files a leftover company journal as an
7
+ unrepaired doctor finding, and company manifest rows keep a real check id
8
+ instead of showing up as unlabeled `unknown`. `hq doctor --fix` still
9
+ refreshes that company journal when hook files have uncommitted changes.
10
+
5
11
  ## [5.345.101] — 2026-10-12
6
12
  - Doctor JSON no longer counts an ordinary HQ Core upgrade warning in its
7
13
  summary after omitting it from results. Session-start health that only saw
@@ -33,7 +33,7 @@ import { PARITY_FAMILY_ID, PARITY_FAMILY_TITLE, runParityReplay, } from "../lib/
33
33
  import { applyFixes } from "../lib/doctor/fix/apply.js";
34
34
  import { renderDoctorFixJson } from "../lib/doctor/fix/json-output.js";
35
35
  import { clientHealthCheckStatusEnabled as isActiveCompanyClientHealthCheckStatusEnabled, clientHealthCheckStatusEnabledForCompany, clientHealthReasonCodesEnabled as isActiveCompanyClientHealthReasonCodesEnabled, clientHealthReasonCodesEnabledForCompany, } from "../lib/doctor/client-health-reason-codes-flag.js";
36
- import { isCompanyJournalSlug } from "../lib/doctor/checks/sync-health.js";
36
+ import { clientHealthCompanyScopeFromCheckId } from "../lib/doctor/checks/sync-health.js";
37
37
  import { readCompaniesManifestMap } from "../lib/work-context/repo-remote.js";
38
38
  import * as readline from "node:readline";
39
39
  import { runSideEffectTests } from "../lib/doctor/deep/sandbox.js";
@@ -207,15 +207,7 @@ async function resolveClientHealthReasonCodesCheckIds(families, resolveForCompan
207
207
  (result.status !== "FAIL" && result.status !== "WARN")) {
208
208
  continue;
209
209
  }
210
- const scoped = /^sync\.(?:journal|manifest)\.(.+)$/.exec(result.checkId);
211
- const companyUidScope = scoped
212
- ? /^company:(cmp_[A-Za-z0-9]{3,128})$/.exec(scoped[1])
213
- : null;
214
- const companySlug = companyUidScope
215
- ? `company:${companyUidScope[1]}`
216
- : scoped && isCompanyJournalSlug(scoped[1])
217
- ? scoped[1]
218
- : null;
210
+ const companySlug = clientHealthCompanyScopeFromCheckId(result.checkId);
219
211
  const checkIds = checksByCompany.get(companySlug) ?? [];
220
212
  checkIds.push(result.checkId);
221
213
  checksByCompany.set(companySlug, checkIds);
@@ -242,8 +234,7 @@ async function resolveClientHealthCheckStatusCheckIds(families, resolveForCompan
242
234
  for (const result of run.results) {
243
235
  if (result.status !== "FAIL" && result.status !== "WARN")
244
236
  continue;
245
- const scoped = /^sync\.(?:journal|manifest)\.(.+)$/.exec(result.checkId);
246
- const companySlug = scoped && isCompanyJournalSlug(scoped[1]) ? scoped[1] : null;
237
+ const companySlug = clientHealthCompanyScopeFromCheckId(result.checkId);
247
238
  const checkIds = checksByCompany.get(companySlug) ?? [];
248
239
  checkIds.push(result.checkId);
249
240
  checksByCompany.set(companySlug, checkIds);
@@ -107,6 +107,23 @@ export interface SyncHealthDeps {
107
107
  * outside `companies/`.
108
108
  */
109
109
  export declare function isSafeCompanySlug(slug: string): boolean;
110
+ /**
111
+ * SessionStart health only ships `checkId` values matching
112
+ * `^sync.[A-Za-z0-9._-]{1,160}$`. A colon (hq-cloud's `company:cmp_…` scope
113
+ * key) becomes the unlabeled `unknown` row in those reports.
114
+ */
115
+ export declare const CLIENT_HEALTH_SYNC_CHECK_ID: RegExp;
116
+ /**
117
+ * Doctor JSON `checkId` for a manifest scope. hq-cloud keys company rows
118
+ * `company:cmp_…`; the colon is replaced so SessionStart health can report
119
+ * the real id instead of `unknown`.
120
+ */
121
+ export declare function manifestCheckIdFromScopeKey(scopeKey: string): string;
122
+ /**
123
+ * Company slug or `company:cmp_…` uid used to resolve per-company health
124
+ * flags from a sync finding. Manifest ids may use a colon or a dot.
125
+ */
126
+ export declare function clientHealthCompanyScopeFromCheckId(checkId: string): string | null;
110
127
  /** True when this journal slug names a company rather than the personal tree. */
111
128
  export declare function isCompanyJournalSlug(slug: string): boolean;
112
129
  /** True when this journal slug names the personal tree or personal vault. */
@@ -194,13 +194,64 @@ const NON_COMPANY_JOURNAL_SLUGS = new Set([
194
194
  PERSONAL_SCOPE_SLUG,
195
195
  PERSONAL_VAULT_SCOPE_SLUG,
196
196
  ]);
197
+ /**
198
+ * SessionStart health only ships `checkId` values matching
199
+ * `^sync.[A-Za-z0-9._-]{1,160}$`. A colon (hq-cloud's `company:cmp_…` scope
200
+ * key) becomes the unlabeled `unknown` row in those reports.
201
+ */
202
+ export const CLIENT_HEALTH_SYNC_CHECK_ID = /^sync\.[A-Za-z0-9._-]{1,160}$/;
203
+ const COMPANY_SCOPE_UID = /^company[.:](cmp_[A-Za-z0-9]{3,128})$/;
197
204
  /** Keep malformed scopes distinct without letting them imitate valid slugs. */
198
205
  function journalSlugForCheckId(slug) {
199
206
  if (NON_COMPANY_JOURNAL_SLUGS.has(slug) || isSafeCompanySlug(slug)) {
200
207
  return slug;
201
208
  }
202
209
  const encoded = Array.from(slug, (character) => character.codePointAt(0).toString(16)).join("-");
203
- return `__hq_invalid_journal_scope__${encoded}`;
210
+ return boundInvalidScopeToken(`__hq_invalid_journal_scope__${encoded}`);
211
+ }
212
+ function boundInvalidScopeToken(token) {
213
+ // `sync.` + token must fit the health-hook 160-char suffix budget.
214
+ const maxSuffix = 160;
215
+ if (token.length <= maxSuffix)
216
+ return token;
217
+ return token.slice(0, maxSuffix);
218
+ }
219
+ /**
220
+ * Doctor JSON `checkId` for a manifest scope. hq-cloud keys company rows
221
+ * `company:cmp_…`; the colon is replaced so SessionStart health can report
222
+ * the real id instead of `unknown`.
223
+ */
224
+ export function manifestCheckIdFromScopeKey(scopeKey) {
225
+ if (scopeKey.startsWith("company:")) {
226
+ return `sync.manifest.${scopeKey.replace(/:/g, ".")}`;
227
+ }
228
+ if (scopeKey === "personal" || isSafeCompanySlug(scopeKey)) {
229
+ return `sync.manifest.${scopeKey}`;
230
+ }
231
+ const encoded = Array.from(scopeKey, (character) => character.codePointAt(0).toString(16)).join("-");
232
+ return `sync.manifest.${boundInvalidScopeToken(`__hq_invalid_scope__${encoded}`)}`;
233
+ }
234
+ /**
235
+ * Company slug or `company:cmp_…` uid used to resolve per-company health
236
+ * flags from a sync finding. Manifest ids may use a colon or a dot.
237
+ */
238
+ export function clientHealthCompanyScopeFromCheckId(checkId) {
239
+ const journalSlug = journalSlugFromCheckId(checkId);
240
+ if (journalSlug && isCompanyJournalSlug(journalSlug) && isSafeCompanySlug(journalSlug)) {
241
+ return journalSlug;
242
+ }
243
+ const manifest = /^sync\.manifest\.(.+)$/.exec(checkId);
244
+ if (!manifest)
245
+ return null;
246
+ const rest = manifest[1];
247
+ const companyUid = COMPANY_SCOPE_UID.exec(rest)?.[1];
248
+ if (companyUid)
249
+ return `company:${companyUid}`;
250
+ if (rest === "personal" || NON_COMPANY_JOURNAL_SLUGS.has(rest))
251
+ return null;
252
+ if (isSafeCompanySlug(rest))
253
+ return rest;
254
+ return null;
204
255
  }
205
256
  /** True when this journal slug names a company rather than the personal tree. */
206
257
  export function isCompanyJournalSlug(slug) {
@@ -553,7 +604,7 @@ function manifestResults(deps, journals) {
553
604
  }
554
605
  const nowMs = deps.now().getTime();
555
606
  const reported = statuses.map((entry) => {
556
- const checkId = `sync.manifest.${entry.scopeKey}`;
607
+ const checkId = manifestCheckIdFromScopeKey(entry.scopeKey);
557
608
  if (!entry.lastUploadAt) {
558
609
  return {
559
610
  status: "UNTESTED",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@indigoai-us/hq-cli",
3
- "version": "5.345.101",
3
+ "version": "5.345.102",
4
4
  "description": "HQ by Indigo management CLI — modules and cloud sync",
5
5
  "main": "dist/index.js",
6
6
  "bin": {