@indigoai-us/hq-cli 5.311.3 → 5.311.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.
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [5.311.4] — 2026-10-02
|
|
6
|
+
- Preserve existing local company starter files during cloud provisioning by having the CLI request that hq-pro skip blank starter seeding; older servers are detected before company creation.
|
|
7
|
+
|
|
5
8
|
## [5.311.3] — 2026-10-01
|
|
6
9
|
- Match company file access checks against the company-anchored paths printed by `hq files browse`.
|
|
7
10
|
- Record a placement resolved to the current host as local so the lane starts without dispatching back through Outpost pickup.
|
|
@@ -135,6 +135,8 @@ export interface VaultClient {
|
|
|
135
135
|
checkSlugInMyNamespace(slug: string): Promise<{
|
|
136
136
|
available: boolean;
|
|
137
137
|
conflictingCompanyUid?: string;
|
|
138
|
+
/** Older hq-pro servers omit this field; absence means unsupported. */
|
|
139
|
+
skipStarterSeedSupported?: boolean;
|
|
138
140
|
}>;
|
|
139
141
|
/** Fetch a company entity by uid. Used to materialize the entity
|
|
140
142
|
* after `checkSlugInMyNamespace` reports a same-namespace collision. */
|
|
@@ -143,6 +145,7 @@ export interface VaultClient {
|
|
|
143
145
|
slug: string;
|
|
144
146
|
name: string;
|
|
145
147
|
ownerUid?: string;
|
|
148
|
+
skipStarterSeed?: boolean;
|
|
146
149
|
}): Promise<VaultEntity>;
|
|
147
150
|
/**
|
|
148
151
|
* Soft-tombstone a company (`DELETE /entity/{uid}`). Owner-only. Leaves the
|
|
@@ -34,6 +34,25 @@ import * as yaml from "js-yaml";
|
|
|
34
34
|
import { parseUserYaml } from "../utils/user-yaml-error.js";
|
|
35
35
|
import { createSyncProgressRecorder, share, } from "@indigoai-us/hq-cloud";
|
|
36
36
|
import { DEFAULT_HQ_ROOT, DEFAULT_VAULT_API_URL, ensureCognitoToken, buildVaultConfig, } from "../utils/cognito-session.js";
|
|
37
|
+
const SHARED_COMPANY_STARTER_PATHS = [
|
|
38
|
+
"README.md",
|
|
39
|
+
"board.json",
|
|
40
|
+
"knowledge/README.md",
|
|
41
|
+
"knowledge/design-styles/packs/.gitkeep",
|
|
42
|
+
"people/.gitkeep",
|
|
43
|
+
"policies/.gitkeep",
|
|
44
|
+
"projects/.gitkeep",
|
|
45
|
+
"repos/.gitkeep",
|
|
46
|
+
"skills/.gitkeep",
|
|
47
|
+
"sources/meetings/source.yaml",
|
|
48
|
+
"workspace/.gitignore",
|
|
49
|
+
"workspace/index.jsonl",
|
|
50
|
+
"workspace/sessions/.gitkeep",
|
|
51
|
+
];
|
|
52
|
+
function hasLocalSharedStarterPath(hqRoot, slug) {
|
|
53
|
+
const companyDir = path.join(hqRoot, "companies", slug);
|
|
54
|
+
return SHARED_COMPANY_STARTER_PATHS.some((relativePath) => fs.existsSync(path.join(companyDir, relativePath)));
|
|
55
|
+
}
|
|
37
56
|
/** Custom error class so the CLI runner can map to exit codes. */
|
|
38
57
|
export class ProvisionError extends Error {
|
|
39
58
|
code;
|
|
@@ -333,7 +352,11 @@ export function createDefaultVaultClient(apiUrl, accessToken) {
|
|
|
333
352
|
const body = await safeBody(res);
|
|
334
353
|
throw new ProvisionError(1, `Vault GET /entity/check-slug/me failed: ${res.status} ${res.statusText} — ${body}`);
|
|
335
354
|
}
|
|
336
|
-
|
|
355
|
+
const data = (await res.json());
|
|
356
|
+
return {
|
|
357
|
+
...data,
|
|
358
|
+
skipStarterSeedSupported: data.skipStarterSeedSupported === true,
|
|
359
|
+
};
|
|
337
360
|
});
|
|
338
361
|
},
|
|
339
362
|
async getCompanyByUid(uid) {
|
|
@@ -359,6 +382,8 @@ export function createDefaultVaultClient(apiUrl, accessToken) {
|
|
|
359
382
|
};
|
|
360
383
|
if (input.ownerUid)
|
|
361
384
|
body.ownerUid = input.ownerUid;
|
|
385
|
+
if (input.skipStarterSeed)
|
|
386
|
+
body.skipStarterSeed = true;
|
|
362
387
|
return withVaultRequest(url, {
|
|
363
388
|
method: "POST",
|
|
364
389
|
headers,
|
|
@@ -548,6 +573,7 @@ export async function provisionCompany(options) {
|
|
|
548
573
|
// match the caller's own person UID(s) from `listMyPersonEntities`.
|
|
549
574
|
const callerOwnedUids = new Set(persons.map((p) => p.uid));
|
|
550
575
|
const callerIsOwner = !options.ownerUid || callerOwnedUids.has(options.ownerUid);
|
|
576
|
+
const hasLocalSharedStarterFiles = hasLocalSharedStarterPath(options.hqRoot, options.slug);
|
|
551
577
|
let entity;
|
|
552
578
|
let createdEntity = false;
|
|
553
579
|
if (callerIsOwner) {
|
|
@@ -557,17 +583,24 @@ export async function provisionCompany(options) {
|
|
|
557
583
|
entity = await vaultClient.getCompanyByUid(slugCheck.conflictingCompanyUid);
|
|
558
584
|
}
|
|
559
585
|
else {
|
|
586
|
+
if (hasLocalSharedStarterFiles && !slugCheck.skipStarterSeedSupported) {
|
|
587
|
+
throw new ProvisionError(1, "This hq-pro server does not support preserving local starter files during cloud provisioning; update hq-pro and retry");
|
|
588
|
+
}
|
|
560
589
|
log(`slug available in caller's namespace — creating vault entity`);
|
|
561
590
|
entity = await vaultClient.createCompanyEntity({
|
|
562
591
|
slug: options.slug,
|
|
563
592
|
name: options.name ?? options.slug,
|
|
564
593
|
ownerUid: options.ownerUid,
|
|
594
|
+
...(hasLocalSharedStarterFiles ? { skipStarterSeed: true } : {}),
|
|
565
595
|
});
|
|
566
596
|
createdEntity = true;
|
|
567
597
|
log(`created vault entity uid=${entity.uid}`);
|
|
568
598
|
}
|
|
569
599
|
}
|
|
570
600
|
else {
|
|
601
|
+
if (hasLocalSharedStarterFiles) {
|
|
602
|
+
throw new ProvisionError(1, "Cannot preserve local starter files when provisioning for a different owner");
|
|
603
|
+
}
|
|
571
604
|
log(`--owner ${options.ownerUid} differs from caller's person(s); skipping namespace pre-check (server authoritatively gates per-target-namespace)`);
|
|
572
605
|
entity = await vaultClient.createCompanyEntity({
|
|
573
606
|
slug: options.slug,
|