@indigoai-us/hq-cli 5.37.0 → 5.37.2

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.
@@ -8,6 +8,14 @@ on:
8
8
  jobs:
9
9
  build:
10
10
  runs-on: ubuntu-latest
11
+ strategy:
12
+ fail-fast: false
13
+ matrix:
14
+ # 20 is the declared engines floor (package.json engines.node >=20),
15
+ # 22 is the current dev/publish baseline. Running the suite on 20
16
+ # enforces the floor so it stays real, not aspirational.
17
+ node-version: [20, 22]
18
+ name: build (node ${{ matrix.node-version }})
11
19
  steps:
12
20
  - uses: actions/checkout@v4
13
21
  - uses: pnpm/action-setup@v4
@@ -15,7 +23,7 @@ jobs:
15
23
  version: 10
16
24
  - uses: actions/setup-node@v4
17
25
  with:
18
- node-version: 22
26
+ node-version: ${{ matrix.node-version }}
19
27
  cache: pnpm
20
28
  - run: pnpm install --frozen-lockfile --config.minimumReleaseAge=1440
21
29
  # generate-dsn.mjs only fatals when GITHUB_JOB=publish, so CI builds with
@@ -34,7 +34,7 @@
34
34
  * from each pack's package.yaml; rationale lives in the layout-fix PR.)
35
35
  */
36
36
 
37
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="d5029b6f-fc42-52ea-9ddd-aaaae682a8f4")}catch(e){}}();
37
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="cbb11285-034d-50c4-917d-797ab226db66")}catch(e){}}();
38
38
  import * as fs from 'fs';
39
39
  import * as os from 'os';
40
40
  import * as path from 'path';
@@ -48,6 +48,7 @@ import semverValid from 'semver/functions/valid.js';
48
48
  import semverValidRange from 'semver/ranges/valid.js';
49
49
  import semverGt from 'semver/functions/gt.js';
50
50
  import { findHqRoot } from '../utils/manifest.js';
51
+ import { readHqVersion } from '../utils/pack-contributions.js';
51
52
  import { safeExtractTarball } from './safe-extract.js';
52
53
  import { vaultApiFetchPublic } from '../utils/vault-api.js';
53
54
  /** Prefix that routes a source through the HQ marketplace transport (US-006). */
@@ -808,18 +809,6 @@ export function validateManifest(payloadDir, hqVersion) {
808
809
  }
809
810
  return m;
810
811
  }
811
- function readHqVersion(hqRoot) {
812
- const p = path.join(hqRoot, 'core.yaml');
813
- if (!fs.existsSync(p))
814
- return null;
815
- try {
816
- const c = yaml.load(fs.readFileSync(p, 'utf-8'));
817
- return c?.hqVersion ?? null;
818
- }
819
- catch {
820
- return null;
821
- }
822
- }
823
812
  // ---------------------------------------------------------------------------
824
813
  // Hooks confirmation
825
814
  // ---------------------------------------------------------------------------
@@ -1015,6 +1004,12 @@ export function runScanPackages(hqRoot, opts = {}) {
1015
1004
  export async function installPack(source, opts = {}) {
1016
1005
  const transport = classify(source);
1017
1006
  const hqRoot = findHqRoot();
1007
+ // `readHqVersion` (shared with `hq packs`) reads the CANONICAL
1008
+ // `core/core.yaml` (hq-core ≥v14), falling back to the legacy
1009
+ // `<root>/core.yaml` only when the nested file is absent. The previous local
1010
+ // reader looked at `<root>/core.yaml` ONLY, so on a post-v12→v15 tree it
1011
+ // picked up a STALE leftover root copy (e.g. hqVersion 12.1.0) and wrongly
1012
+ // rejected packs requiring a newer hqCore (feedback_57d7edcf, symptom b).
1018
1013
  const hqVersion = readHqVersion(hqRoot);
1019
1014
  const say = opts.quiet
1020
1015
  ? (...a) => console.error(...a)
@@ -1081,4 +1076,4 @@ export async function installPack(source, opts = {}) {
1081
1076
  }
1082
1077
  }
1083
1078
  //# sourceMappingURL=pack-install.js.map
1084
- //# debugId=d5029b6f-fc42-52ea-9ddd-aaaae682a8f4
1079
+ //# debugId=cbb11285-034d-50c4-917d-797ab226db66
@@ -28,7 +28,7 @@
28
28
  * - manifest.ts (modules.yaml read/write for provenance)
29
29
  */
30
30
 
31
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="f5046847-a2b9-50e4-9a68-6a81a9e0de2b")}catch(e){}}();
31
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="9b60d0b2-fea1-50bd-8c4e-e39163c38e30")}catch(e){}}();
32
32
  import * as fs from 'fs';
33
33
  import * as os from 'os';
34
34
  import * as path from 'path';
@@ -40,6 +40,7 @@ import { ensureCognitoToken } from '../utils/cognito-session.js';
40
40
  import { vaultApiFetch } from '../utils/vault-api.js';
41
41
  import { validateManifest } from './pack-install.js';
42
42
  import { findHqRoot, readManifest, writeManifest } from '../utils/manifest.js';
43
+ import { readHqVersion } from '../utils/pack-contributions.js';
43
44
  /**
44
45
  * Decode a Cognito idToken's payload (no signature verification — this is a
45
46
  * local read of an already-trusted cached token, mirroring whoami.ts/login.ts).
@@ -321,18 +322,6 @@ export async function runPublish(targetPath, deps) {
321
322
  // ---------------------------------------------------------------------------
322
323
  // Command wiring
323
324
  // ---------------------------------------------------------------------------
324
- function readHqVersion(hqRoot) {
325
- const p = path.join(hqRoot, 'core.yaml');
326
- if (!fs.existsSync(p))
327
- return null;
328
- try {
329
- const c = yaml.load(fs.readFileSync(p, 'utf-8'));
330
- return c?.hqVersion ?? null;
331
- }
332
- catch {
333
- return null;
334
- }
335
- }
336
325
  export function registerPublishCommand(program) {
337
326
  program
338
327
  .command('publish <path>')
@@ -378,4 +367,4 @@ export function registerPublishCommand(program) {
378
367
  });
379
368
  }
380
369
  //# sourceMappingURL=publish.js.map
381
- //# debugId=f5046847-a2b9-50e4-9a68-6a81a9e0de2b
370
+ //# debugId=9b60d0b2-fea1-50bd-8c4e-e39163c38e30
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@indigoai-us/hq-cli",
3
- "version": "5.37.0",
3
+ "version": "5.37.2",
4
4
  "description": "HQ by Indigo management CLI \u2014 modules and cloud sync",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -49,6 +49,6 @@
49
49
  "license": "MIT",
50
50
  "type": "module",
51
51
  "engines": {
52
- "node": ">=22.0.0"
52
+ "node": ">=20.0.0"
53
53
  }
54
54
  }
@@ -53,6 +53,7 @@ import semverValid from 'semver/functions/valid.js';
53
53
  import semverValidRange from 'semver/ranges/valid.js';
54
54
  import semverGt from 'semver/functions/gt.js';
55
55
  import { findHqRoot } from '../utils/manifest.js';
56
+ import { readHqVersion } from '../utils/pack-contributions.js';
56
57
  import { safeExtractTarball } from './safe-extract.js';
57
58
  import { vaultApiFetchPublic } from '../utils/vault-api.js';
58
59
  import type { PackManifest, PackContributeKey } from '../types.js';
@@ -1086,17 +1087,6 @@ export function validateManifest(
1086
1087
  return m as PackManifest;
1087
1088
  }
1088
1089
 
1089
- function readHqVersion(hqRoot: string): string | null {
1090
- const p = path.join(hqRoot, 'core.yaml');
1091
- if (!fs.existsSync(p)) return null;
1092
- try {
1093
- const c = yaml.load(fs.readFileSync(p, 'utf-8')) as { hqVersion?: string };
1094
- return c?.hqVersion ?? null;
1095
- } catch {
1096
- return null;
1097
- }
1098
- }
1099
-
1100
1090
  // ---------------------------------------------------------------------------
1101
1091
  // Hooks confirmation
1102
1092
  // ---------------------------------------------------------------------------
@@ -1368,6 +1358,12 @@ export async function installPack(
1368
1358
  ): Promise<void> {
1369
1359
  const transport = classify(source);
1370
1360
  const hqRoot = findHqRoot();
1361
+ // `readHqVersion` (shared with `hq packs`) reads the CANONICAL
1362
+ // `core/core.yaml` (hq-core ≥v14), falling back to the legacy
1363
+ // `<root>/core.yaml` only when the nested file is absent. The previous local
1364
+ // reader looked at `<root>/core.yaml` ONLY, so on a post-v12→v15 tree it
1365
+ // picked up a STALE leftover root copy (e.g. hqVersion 12.1.0) and wrongly
1366
+ // rejected packs requiring a newer hqCore (feedback_57d7edcf, symptom b).
1371
1367
  const hqVersion = readHqVersion(hqRoot);
1372
1368
  const say: (...a: unknown[]) => void = opts.quiet
1373
1369
  ? (...a) => console.error(...a)
@@ -40,6 +40,7 @@ import { ensureCognitoToken } from '../utils/cognito-session.js';
40
40
  import { vaultApiFetch } from '../utils/vault-api.js';
41
41
  import { validateManifest } from './pack-install.js';
42
42
  import { findHqRoot, readManifest, writeManifest } from '../utils/manifest.js';
43
+ import { readHqVersion } from '../utils/pack-contributions.js';
43
44
  import type { PackManifest, PackModuleDefinition, ModulesManifest } from '../types.js';
44
45
 
45
46
  // ---------------------------------------------------------------------------
@@ -461,17 +462,6 @@ export async function runPublish(
461
462
  // Command wiring
462
463
  // ---------------------------------------------------------------------------
463
464
 
464
- function readHqVersion(hqRoot: string): string | null {
465
- const p = path.join(hqRoot, 'core.yaml');
466
- if (!fs.existsSync(p)) return null;
467
- try {
468
- const c = yaml.load(fs.readFileSync(p, 'utf-8')) as { hqVersion?: string };
469
- return c?.hqVersion ?? null;
470
- } catch {
471
- return null;
472
- }
473
- }
474
-
475
465
  export function registerPublishCommand(program: Command): void {
476
466
  program
477
467
  .command('publish <path>')
@@ -18,6 +18,7 @@ import {
18
18
  listInstalledPacks,
19
19
  unwirePack,
20
20
  packagesDir,
21
+ readHqVersion,
21
22
  type WiredLink,
22
23
  } from './pack-contributions.js';
23
24
  import type { PackContributeKey } from '../types.js';
@@ -206,3 +207,53 @@ describe('listInstalledPacks', () => {
206
207
  expect(packs[0].error).toMatch(/invalid/i);
207
208
  });
208
209
  });
210
+
211
+ describe('readHqVersion: v15 layout awareness (feedback_57d7edcf, symptom b)', () => {
212
+ let hqRoot: string;
213
+
214
+ beforeEach(() => {
215
+ hqRoot = mkTmp('hq-readhqversion-');
216
+ });
217
+
218
+ afterEach(() => {
219
+ fs.rmSync(hqRoot, { recursive: true, force: true });
220
+ });
221
+
222
+ it('reads the CANONICAL core/core.yaml on a v14+/v15 layout', () => {
223
+ fs.mkdirSync(path.join(hqRoot, 'core'), { recursive: true });
224
+ fs.writeFileSync(
225
+ path.join(hqRoot, 'core', 'core.yaml'),
226
+ 'version: 1\nhqVersion: "15.0.11"\n',
227
+ );
228
+ expect(readHqVersion(hqRoot)).toBe('15.0.11');
229
+ });
230
+
231
+ it('PREFERS canonical core/core.yaml over a STALE leftover root core.yaml', () => {
232
+ // The exact reported failure: post-v12→v15 reshape moved core.yaml under
233
+ // core/, but a stale root copy (hqVersion 12.1.0) lingered. The version
234
+ // read MUST report the canonical 15.x, not the stale root 12.1.0 — else
235
+ // `hq install` wrongly rejects packs requiring hqCore >=15.
236
+ fs.mkdirSync(path.join(hqRoot, 'core'), { recursive: true });
237
+ fs.writeFileSync(
238
+ path.join(hqRoot, 'core', 'core.yaml'),
239
+ 'version: 1\nhqVersion: "15.0.11"\n',
240
+ );
241
+ fs.writeFileSync(
242
+ path.join(hqRoot, 'core.yaml'),
243
+ 'version: 1\nhqVersion: "12.1.0"\n',
244
+ );
245
+ expect(readHqVersion(hqRoot)).toBe('15.0.11');
246
+ });
247
+
248
+ it('falls back to the legacy root core.yaml when no nested core/core.yaml exists', () => {
249
+ fs.writeFileSync(
250
+ path.join(hqRoot, 'core.yaml'),
251
+ 'version: 1\nhqVersion: "13.4.0"\n',
252
+ );
253
+ expect(readHqVersion(hqRoot)).toBe('13.4.0');
254
+ });
255
+
256
+ it('returns null when neither core/core.yaml nor root core.yaml exists', () => {
257
+ expect(readHqVersion(hqRoot)).toBeNull();
258
+ });
259
+ });