@indigoai-us/hq-cli 5.77.14 → 5.78.0
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 +23 -0
- package/assets/scaffold/core/scripts/archive-old-threads.sh +86 -0
- package/assets/scaffold/core/scripts/backfill-company-skill-mirrors.sh +73 -0
- package/assets/scaffold/core/scripts/backfill-workspace-mirror.sh +51 -0
- package/assets/scaffold/core/scripts/codex-skill-bridge.sh +550 -0
- package/assets/scaffold/core/scripts/detect-stale-core-policy-mirror.sh +185 -0
- package/assets/scaffold/core/scripts/hq-status-summary.sh +187 -0
- package/assets/scaffold/core/scripts/ontology-readme-drift.sh +264 -0
- package/assets/scaffold/core/scripts/qmd-reindex-after-sync.sh +93 -0
- package/assets/scaffold/core/scripts/rebuild-all-indexes.sh +69 -0
- package/assets/scaffold/core/scripts/rebuild-companies-index.sh +206 -0
- package/assets/scaffold/core/scripts/rebuild-company-knowledge-index.sh +127 -0
- package/assets/scaffold/core/scripts/rebuild-orchestrator-index.sh +86 -0
- package/assets/scaffold/core/scripts/rebuild-projects-index.sh +105 -0
- package/assets/scaffold/core/scripts/rebuild-public-knowledge-index.sh +83 -0
- package/assets/scaffold/core/scripts/rebuild-reports-index.sh +114 -0
- package/assets/scaffold/core/scripts/rebuild-social-drafts-index.sh +135 -0
- package/assets/scaffold/core/scripts/rebuild-threads-index.sh +82 -0
- package/assets/scaffold/core/scripts/rebuild-workers-index.sh +97 -0
- package/assets/scaffold/core/scripts/resize-screenshot.sh +47 -0
- package/assets/scaffold/core/scripts/token-usage-report.sh +254 -0
- package/assets/scaffold/core/scripts/worktree.sh +136 -0
- package/dist/commands/agents.js +28 -12
- package/dist/commands/api-keys.js +100 -20
- package/dist/commands/core.d.ts +90 -0
- package/dist/commands/core.js +279 -0
- package/dist/commands/files-browse.d.ts +21 -0
- package/dist/commands/files-browse.js +145 -24
- package/dist/commands/files.js +33 -7
- package/dist/commands/members.js +16 -5
- package/dist/commands/pack-install.d.ts +14 -0
- package/dist/commands/pack-install.js +42 -2
- package/dist/commands/pkg-install.js +39 -2
- package/dist/commands/run.js +6 -2
- package/dist/commands/secrets.js +120 -65
- package/dist/main.js +6 -0
- package/dist/utils/api-key-command-gate.d.ts +45 -0
- package/dist/utils/api-key-command-gate.js +51 -0
- package/dist/utils/hq-roots.d.ts +91 -0
- package/dist/utils/hq-roots.js +212 -0
- package/dist/utils/resolve-vault-credential.d.ts +63 -3
- package/dist/utils/resolve-vault-credential.js +152 -6
- package/dist/utils/run-bundled-script.d.ts +66 -0
- package/dist/utils/run-bundled-script.js +80 -0
- package/dist/utils/vault-api.d.ts +21 -0
- package/dist/utils/vault-api.js +74 -3
- package/package.json +7 -1
- package/.claude/policies/hq-cli-interactive-reads-use-sts-vend.md +0 -49
- package/.github/workflows/ci.yml +0 -46
- package/.github/workflows/publish.yml +0 -36
- package/.github/workflows/scripts/smoke-test-pkg.sh +0 -97
- package/e2e/cli.test.ts +0 -128
- package/eslint.config.js +0 -37
- package/pnpm-workspace.yaml +0 -4
- package/scripts/chmod-bins.mjs +0 -49
- package/scripts/generate-dsn.mjs +0 -26
- package/scripts/generate-scan-packages-table.mjs +0 -113
- package/scripts/smoke-sources-signals.sh +0 -103
- package/src/bin/hq-auth-refresh.ts +0 -43
- package/src/cli-version.ts +0 -13
- package/src/commands/__fixtures__/make-tar.ts +0 -126
- package/src/commands/_patterns.ts +0 -10
- package/src/commands/add.ts +0 -75
- package/src/commands/agents.test.ts +0 -527
- package/src/commands/agents.ts +0 -923
- package/src/commands/api-keys.test.ts +0 -291
- package/src/commands/api-keys.ts +0 -382
- package/src/commands/artifact-verify.test.ts +0 -177
- package/src/commands/auth.test.ts +0 -82
- package/src/commands/auth.ts +0 -213
- package/src/commands/billing.test.ts +0 -158
- package/src/commands/billing.ts +0 -146
- package/src/commands/channels.test.ts +0 -74
- package/src/commands/channels.ts +0 -91
- package/src/commands/cloud-demote.test.ts +0 -401
- package/src/commands/cloud-demote.ts +0 -278
- package/src/commands/cloud-provision.test.ts +0 -1117
- package/src/commands/cloud-provision.ts +0 -942
- package/src/commands/cloud.pull-all.test.ts +0 -711
- package/src/commands/cloud.pull-per-company.test.ts +0 -188
- package/src/commands/cloud.push-all.test.ts +0 -485
- package/src/commands/cloud.scope-excluded-warning.test.ts +0 -22
- package/src/commands/cloud.selectors.test.ts +0 -208
- package/src/commands/cloud.status.test.ts +0 -160
- package/src/commands/cloud.test.ts +0 -41
- package/src/commands/cloud.ts +0 -2130
- package/src/commands/company.test.ts +0 -202
- package/src/commands/company.ts +0 -148
- package/src/commands/creators.test.ts +0 -60
- package/src/commands/creators.ts +0 -117
- package/src/commands/crm.test.ts +0 -179
- package/src/commands/crm.ts +0 -236
- package/src/commands/db-migrate.ts +0 -55
- package/src/commands/db-provision.ts +0 -114
- package/src/commands/db-sql.ts +0 -124
- package/src/commands/db-status.ts +0 -108
- package/src/commands/db.ts +0 -26
- package/src/commands/dm.test.ts +0 -748
- package/src/commands/dm.ts +0 -1226
- package/src/commands/feedback.test.ts +0 -413
- package/src/commands/feedback.ts +0 -169
- package/src/commands/files-browse.test.ts +0 -1249
- package/src/commands/files-browse.ts +0 -1506
- package/src/commands/files-delete.test.ts +0 -484
- package/src/commands/files-recovery.test.ts +0 -370
- package/src/commands/files.test.ts +0 -722
- package/src/commands/files.ts +0 -1446
- package/src/commands/group-grants.test.ts +0 -330
- package/src/commands/group-grants.ts +0 -455
- package/src/commands/groups.test.ts +0 -44
- package/src/commands/groups.ts +0 -368
- package/src/commands/integrations.test.ts +0 -633
- package/src/commands/integrations.ts +0 -507
- package/src/commands/list.ts +0 -85
- package/src/commands/login.ts +0 -52
- package/src/commands/logout.ts +0 -30
- package/src/commands/marketplace-install.test.ts +0 -543
- package/src/commands/marketplace-security.test.ts +0 -646
- package/src/commands/mcp-registration.test.ts +0 -2787
- package/src/commands/mcp-registration.ts +0 -2612
- package/src/commands/mcp-status.test.ts +0 -483
- package/src/commands/mcp-status.ts +0 -575
- package/src/commands/mcp-status.us011.test.ts +0 -243
- package/src/commands/meetings.test.ts +0 -522
- package/src/commands/meetings.ts +0 -789
- package/src/commands/members.test.ts +0 -1474
- package/src/commands/members.ts +0 -1181
- package/src/commands/onboard-identity-guard.test.ts +0 -99
- package/src/commands/onboard-identity-guard.ts +0 -103
- package/src/commands/onboard-join.test.ts +0 -96
- package/src/commands/onboard-join.ts +0 -101
- package/src/commands/onboard-warning.test.ts +0 -26
- package/src/commands/onboard-warning.ts +0 -12
- package/src/commands/onboard.ts +0 -267
- package/src/commands/outposts-heartbeat.test.ts +0 -299
- package/src/commands/outposts-heartbeat.ts +0 -310
- package/src/commands/outposts-replica-sync.test.ts +0 -272
- package/src/commands/outposts-self-deploy.test.ts +0 -243
- package/src/commands/outposts.test.ts +0 -1039
- package/src/commands/outposts.ts +0 -1935
- package/src/commands/pack-install-secret-authorization.test.ts +0 -115
- package/src/commands/pack-install.test.ts +0 -1469
- package/src/commands/pack-install.ts +0 -2256
- package/src/commands/pack-update-cache.test.ts +0 -149
- package/src/commands/packs-update-api-key.test.ts +0 -105
- package/src/commands/packs.test.ts +0 -88
- package/src/commands/packs.ts +0 -622
- package/src/commands/people.test.ts +0 -807
- package/src/commands/people.ts +0 -422
- package/src/commands/pkg-install.dispatch.test.ts +0 -103
- package/src/commands/pkg-install.ts +0 -221
- package/src/commands/pkg-list.test.ts +0 -79
- package/src/commands/pkg-list.ts +0 -13
- package/src/commands/pkg-remove.ts +0 -71
- package/src/commands/pkg-update.ts +0 -189
- package/src/commands/publish.test.ts +0 -650
- package/src/commands/publish.ts +0 -580
- package/src/commands/reindex.test.ts +0 -259
- package/src/commands/reindex.ts +0 -274
- package/src/commands/rescue.test.ts +0 -39
- package/src/commands/rescue.ts +0 -210
- package/src/commands/run.env-local.test.ts +0 -88
- package/src/commands/run.test.ts +0 -45
- package/src/commands/run.ts +0 -190
- package/src/commands/safe-extract.test.ts +0 -459
- package/src/commands/safe-extract.ts +0 -444
- package/src/commands/secrets-scope.test.ts +0 -56
- package/src/commands/secrets-scope.ts +0 -32
- package/src/commands/secrets.parse-destination.test.ts +0 -38
- package/src/commands/secrets.test.ts +0 -2050
- package/src/commands/secrets.ts +0 -2249
- package/src/commands/signals.ts +0 -351
- package/src/commands/skill.test.ts +0 -770
- package/src/commands/skill.ts +0 -796
- package/src/commands/sources.ts +0 -362
- package/src/commands/sync-mode.test.ts +0 -366
- package/src/commands/sync-mode.ts +0 -387
- package/src/commands/sync-narrow.test.ts +0 -633
- package/src/commands/sync-narrow.ts +0 -555
- package/src/commands/sync.ts +0 -165
- package/src/commands/team-sync.ts +0 -628
- package/src/commands/update.ts +0 -71
- package/src/commands/whoami.ts +0 -83
- package/src/commands/workers.test.ts +0 -158
- package/src/commands/workers.ts +0 -301
- package/src/index.test.ts +0 -32
- package/src/index.ts +0 -20
- package/src/lib/db/control-plane.test.ts +0 -59
- package/src/lib/db/control-plane.ts +0 -113
- package/src/lib/db/local.test.ts +0 -81
- package/src/lib/db/local.ts +0 -148
- package/src/lib/db/migrate.test.ts +0 -133
- package/src/lib/db/migrate.ts +0 -137
- package/src/lib/db/paths.test.ts +0 -112
- package/src/lib/db/paths.ts +0 -128
- package/src/lib/db/remote-engine.test.ts +0 -44
- package/src/lib/db/remote-engine.ts +0 -148
- package/src/lib/db/remote-sql.test.ts +0 -32
- package/src/lib/db/remote-sql.ts +0 -62
- package/src/lib/db/sql.test.ts +0 -106
- package/src/lib/db/sql.ts +0 -192
- package/src/lib/hq-cloud-dep.smoke.test.ts +0 -75
- package/src/lib/local-tree-diff.test.ts +0 -301
- package/src/lib/local-tree-diff.ts +0 -362
- package/src/lib/narrow-hint-banner.test.ts +0 -235
- package/src/lib/narrow-hint-banner.ts +0 -212
- package/src/lib/plan-limit-nag.test.ts +0 -317
- package/src/lib/plan-limit-nag.ts +0 -264
- package/src/main.ts +0 -371
- package/src/node-preflight.test.ts +0 -60
- package/src/node-preflight.ts +0 -67
- package/src/outpost/session-heartbeat-bounds.test.ts +0 -195
- package/src/outpost/session-heartbeat-guard.test.ts +0 -105
- package/src/outpost/session-heartbeat-publisher.test.ts +0 -178
- package/src/outpost/session-heartbeat-publisher.ts +0 -186
- package/src/outpost/session-heartbeat-retain-guard.test.ts +0 -126
- package/src/outpost/session-heartbeat.test.ts +0 -459
- package/src/outpost/session-heartbeat.ts +0 -877
- package/src/packaging.test.ts +0 -109
- package/src/run/__fixtures__/discover-schemas/example.env.schema +0 -4
- package/src/run/discover-schemas.test.ts +0 -153
- package/src/run/discover-schemas.ts +0 -79
- package/src/run/hq-plugin.test.ts +0 -371
- package/src/run/hq-plugin.ts +0 -277
- package/src/run/varlock-shape.test.ts +0 -57
- package/src/schemas/hq-package.schema.json +0 -155
- package/src/sentry-before-send.test.ts +0 -359
- package/src/sentry-before-send.ts +0 -221
- package/src/sentry-epipe.test.ts +0 -37
- package/src/sentry-release.test.ts +0 -54
- package/src/sentry.test.ts +0 -24
- package/src/sentry.ts +0 -54
- package/src/strategies/link.ts +0 -62
- package/src/strategies/merge.ts +0 -142
- package/src/types.ts +0 -146
- package/src/utils/__fixtures__/scan-packages.generated-block.sh +0 -23
- package/src/utils/auth-error.test.ts +0 -40
- package/src/utils/auth-error.ts +0 -42
- package/src/utils/billing-gate.test.ts +0 -95
- package/src/utils/billing-gate.ts +0 -228
- package/src/utils/breadcrumb-buffer.ts +0 -18
- package/src/utils/cli-telemetry.test.ts +0 -153
- package/src/utils/cli-telemetry.ts +0 -61
- package/src/utils/cognito-session.machine.test.ts +0 -109
- package/src/utils/cognito-session.refresh.test.ts +0 -84
- package/src/utils/cognito-session.test.ts +0 -328
- package/src/utils/cognito-session.ts +0 -448
- package/src/utils/company-selection-error.test.ts +0 -42
- package/src/utils/company-selection-error.ts +0 -45
- package/src/utils/contribution-table.ts +0 -83
- package/src/utils/environmental-error.test.ts +0 -45
- package/src/utils/environmental-error.ts +0 -39
- package/src/utils/epipe.test.ts +0 -28
- package/src/utils/epipe.ts +0 -29
- package/src/utils/expected-cli-error.test.ts +0 -28
- package/src/utils/expected-cli-error.ts +0 -39
- package/src/utils/feedback-diagnostics.test.ts +0 -183
- package/src/utils/feedback-diagnostics.ts +0 -123
- package/src/utils/feedback-screenshots.test.ts +0 -134
- package/src/utils/feedback-screenshots.ts +0 -124
- package/src/utils/feedback-versions.test.ts +0 -98
- package/src/utils/feedback-versions.ts +0 -68
- package/src/utils/git.ts +0 -74
- package/src/utils/integrity.ts +0 -59
- package/src/utils/intercepted-process-exit.test.ts +0 -37
- package/src/utils/intercepted-process-exit.ts +0 -36
- package/src/utils/login-provider.test.ts +0 -42
- package/src/utils/login-provider.ts +0 -30
- package/src/utils/manifest.test.ts +0 -167
- package/src/utils/manifest.ts +0 -131
- package/src/utils/pack-contributions.test.ts +0 -603
- package/src/utils/pack-contributions.ts +0 -450
- package/src/utils/people.ts +0 -215
- package/src/utils/registry-client.ts +0 -204
- package/src/utils/registry.ts +0 -90
- package/src/utils/resolve-vault-credential.test.ts +0 -69
- package/src/utils/resolve-vault-credential.ts +0 -60
- package/src/utils/sandbox-runner-client.test.ts +0 -279
- package/src/utils/sandbox-runner-client.ts +0 -260
- package/src/utils/secrets-cache.ts +0 -183
- package/src/utils/sentry-identity.ts +0 -45
- package/src/utils/settle-with-timeout.test.ts +0 -21
- package/src/utils/settle-with-timeout.ts +0 -22
- package/src/utils/user-yaml-error.test.ts +0 -24
- package/src/utils/user-yaml-error.ts +0 -30
- package/src/utils/vault-api.test.ts +0 -536
- package/src/utils/vault-api.ts +0 -382
- package/src/utils/version-check.test.ts +0 -176
- package/src/utils/version-check.ts +0 -155
- package/src/utils/version-gate.test.ts +0 -1024
- package/src/utils/version-gate.ts +0 -702
- package/test/commands/db-tenant-isolation.test.ts +0 -94
- package/test/commands/db.test.ts +0 -85
- package/test/commands/signals.test.ts +0 -207
- package/test/commands/sources.test.ts +0 -231
- package/test/e2e/smoke-install-mcp.sh +0 -113
- package/test/fixtures/hq-pack-smoke-mcp/mcp/smoke-http.json +0 -1
- package/test/fixtures/hq-pack-smoke-mcp/package.yaml +0 -11
- package/test/fixtures/signals/action_item/sample.md +0 -16
- package/test/fixtures/signals/summary/sample.md +0 -12
- package/test/fixtures/sources/meetings/sample.md +0 -25
- package/test/helpers/cli-runner.ts +0 -150
- package/test/helpers/s3-list-mock.ts +0 -79
- package/test/helpers/vault-service-mock.ts +0 -295
- package/test/sources-signals/smoke.test.ts +0 -228
- package/tsconfig.json +0 -20
- package/vitest.config.ts +0 -11
- package/vitest.e2e.config.ts +0 -7
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Regression tests for manifest path resolution.
|
|
3
|
-
*
|
|
4
|
-
* Bug caught during hq-core-split S3 testing (2026-04-21): prior to this
|
|
5
|
-
* fix, `getManifestPath()` returned a flat path (`{hqRoot}/modules.yaml`),
|
|
6
|
-
* but real HQ installs use the nested layout (`{hqRoot}/modules/modules.yaml`).
|
|
7
|
-
* Running `hq install` against a real HQ would silently create a shadow
|
|
8
|
-
* manifest at the root, orphaning the canonical nested one.
|
|
9
|
-
*
|
|
10
|
-
* These tests lock in:
|
|
11
|
-
* 1. Nested layout is preferred when it exists.
|
|
12
|
-
* 2. Flat layout is honored when (and only when) it already exists.
|
|
13
|
-
* 3. Fresh HQs default to writing the nested form — never shadow-writing
|
|
14
|
-
* a root-level `modules.yaml`.
|
|
15
|
-
* 4. Read/write round-trips correctly against the nested layout.
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
19
|
-
import * as fs from 'node:fs';
|
|
20
|
-
import * as os from 'node:os';
|
|
21
|
-
import * as path from 'node:path';
|
|
22
|
-
import * as yaml from 'js-yaml';
|
|
23
|
-
|
|
24
|
-
import {
|
|
25
|
-
addModule,
|
|
26
|
-
getManifestPath,
|
|
27
|
-
readManifest,
|
|
28
|
-
writeManifest,
|
|
29
|
-
} from './manifest.js';
|
|
30
|
-
import type { ModulesManifest } from '../types.js';
|
|
31
|
-
import { isExpectedUserError } from './expected-cli-error.js';
|
|
32
|
-
|
|
33
|
-
let tmpRoot: string;
|
|
34
|
-
|
|
35
|
-
beforeEach(() => {
|
|
36
|
-
tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'hq-manifest-test-'));
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
afterEach(() => {
|
|
40
|
-
fs.rmSync(tmpRoot, { recursive: true, force: true });
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
const sampleManifest: ModulesManifest = {
|
|
44
|
-
version: '1',
|
|
45
|
-
modules: [
|
|
46
|
-
{
|
|
47
|
-
name: 'knowledge-public-hq-core',
|
|
48
|
-
repo: 'https://github.com/indigoai-us/knowledge-public-hq-core.git',
|
|
49
|
-
strategy: 'link',
|
|
50
|
-
paths: [
|
|
51
|
-
{
|
|
52
|
-
src: '.',
|
|
53
|
-
dest: 'knowledge/public/hq-core',
|
|
54
|
-
},
|
|
55
|
-
],
|
|
56
|
-
},
|
|
57
|
-
],
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
describe('getManifestPath', () => {
|
|
61
|
-
it('prefers nested modules/modules.yaml when it exists', () => {
|
|
62
|
-
const nested = path.join(tmpRoot, 'modules', 'modules.yaml');
|
|
63
|
-
fs.mkdirSync(path.dirname(nested), { recursive: true });
|
|
64
|
-
fs.writeFileSync(nested, yaml.dump(sampleManifest));
|
|
65
|
-
|
|
66
|
-
expect(getManifestPath(tmpRoot)).toBe(nested);
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
it('honors legacy flat modules.yaml when only the flat form exists', () => {
|
|
70
|
-
// Legacy fixtures / very old HQ instances may pre-date the nested layout.
|
|
71
|
-
const flat = path.join(tmpRoot, 'modules.yaml');
|
|
72
|
-
fs.writeFileSync(flat, yaml.dump(sampleManifest));
|
|
73
|
-
|
|
74
|
-
expect(getManifestPath(tmpRoot)).toBe(flat);
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it('defaults to nested path on a fresh HQ (neither file exists)', () => {
|
|
78
|
-
// Regression: previously returned the flat path, which meant writeManifest
|
|
79
|
-
// created a shadow root-level manifest on real HQs.
|
|
80
|
-
expect(getManifestPath(tmpRoot)).toBe(
|
|
81
|
-
path.join(tmpRoot, 'modules', 'modules.yaml'),
|
|
82
|
-
);
|
|
83
|
-
});
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
describe('readManifest / writeManifest round-trip', () => {
|
|
87
|
-
it('surfaces malformed user YAML with the manifest file and location', () => {
|
|
88
|
-
const nested = path.join(tmpRoot, 'modules', 'modules.yaml');
|
|
89
|
-
fs.mkdirSync(path.dirname(nested), { recursive: true });
|
|
90
|
-
fs.writeFileSync(nested, 'modules:\n - name: hq\n bad: indentation\n');
|
|
91
|
-
|
|
92
|
-
const error = (() => {
|
|
93
|
-
try {
|
|
94
|
-
readManifest(tmpRoot);
|
|
95
|
-
} catch (err) {
|
|
96
|
-
return err;
|
|
97
|
-
}
|
|
98
|
-
throw new Error('expected malformed YAML to throw');
|
|
99
|
-
})();
|
|
100
|
-
|
|
101
|
-
expect(isExpectedUserError(error)).toBe(true);
|
|
102
|
-
expect((error as Error).message).toContain(`${nested}:3:2`);
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
it('round-trips against the nested layout', () => {
|
|
106
|
-
writeManifest(tmpRoot, sampleManifest);
|
|
107
|
-
|
|
108
|
-
const nested = path.join(tmpRoot, 'modules', 'modules.yaml');
|
|
109
|
-
expect(fs.existsSync(nested)).toBe(true);
|
|
110
|
-
|
|
111
|
-
const roundTripped = readManifest(tmpRoot);
|
|
112
|
-
expect(roundTripped).toEqual(sampleManifest);
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
it('writes into the nested modules/ dir on fresh HQs (creates dir)', () => {
|
|
116
|
-
// The nested dir does not exist yet — writeManifest must mkdir-p.
|
|
117
|
-
expect(fs.existsSync(path.join(tmpRoot, 'modules'))).toBe(false);
|
|
118
|
-
|
|
119
|
-
writeManifest(tmpRoot, sampleManifest);
|
|
120
|
-
|
|
121
|
-
expect(fs.existsSync(path.join(tmpRoot, 'modules'))).toBe(true);
|
|
122
|
-
expect(fs.existsSync(path.join(tmpRoot, 'modules', 'modules.yaml'))).toBe(
|
|
123
|
-
true,
|
|
124
|
-
);
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
it('does NOT shadow-write a root-level modules.yaml on fresh HQs', () => {
|
|
128
|
-
// This is the original bug: pre-fix, writeManifest on a fresh HQ created
|
|
129
|
-
// `{hqRoot}/modules.yaml`, which shadowed the canonical nested manifest.
|
|
130
|
-
writeManifest(tmpRoot, sampleManifest);
|
|
131
|
-
|
|
132
|
-
expect(fs.existsSync(path.join(tmpRoot, 'modules.yaml'))).toBe(false);
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
it('rewrites into the flat layout when flat already exists (legacy compat)', () => {
|
|
136
|
-
const flat = path.join(tmpRoot, 'modules.yaml');
|
|
137
|
-
fs.writeFileSync(flat, yaml.dump({ version: '1', modules: [] }));
|
|
138
|
-
|
|
139
|
-
writeManifest(tmpRoot, sampleManifest);
|
|
140
|
-
|
|
141
|
-
// Flat stays flat; no silent migration to nested, no shadow write.
|
|
142
|
-
expect(fs.existsSync(flat)).toBe(true);
|
|
143
|
-
expect(
|
|
144
|
-
fs.existsSync(path.join(tmpRoot, 'modules', 'modules.yaml')),
|
|
145
|
-
).toBe(false);
|
|
146
|
-
|
|
147
|
-
const reread = readManifest(tmpRoot);
|
|
148
|
-
expect(reread).toEqual(sampleManifest);
|
|
149
|
-
});
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
describe('addModule', () => {
|
|
153
|
-
it('appends to the existing nested manifest without creating a flat shadow', () => {
|
|
154
|
-
writeManifest(tmpRoot, sampleManifest);
|
|
155
|
-
|
|
156
|
-
addModule(tmpRoot, {
|
|
157
|
-
name: 'knowledge-public-testing',
|
|
158
|
-
repo: 'https://github.com/indigoai-us/knowledge-public-testing.git',
|
|
159
|
-
strategy: 'link',
|
|
160
|
-
paths: [{ src: '.', dest: 'knowledge/public/testing' }],
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
const after = readManifest(tmpRoot);
|
|
164
|
-
expect(after?.modules).toHaveLength(2);
|
|
165
|
-
expect(fs.existsSync(path.join(tmpRoot, 'modules.yaml'))).toBe(false);
|
|
166
|
-
});
|
|
167
|
-
});
|
package/src/utils/manifest.ts
DELETED
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
import * as fs from 'fs';
|
|
2
|
-
import * as path from 'path';
|
|
3
|
-
import * as yaml from 'js-yaml';
|
|
4
|
-
import type { ModulesManifest, ModuleDefinition, ModuleLock, SyncState } from '../types.js';
|
|
5
|
-
import { parseUserYaml } from './user-yaml-error.js';
|
|
6
|
-
|
|
7
|
-
const MANIFEST_FILE = 'modules.yaml';
|
|
8
|
-
const LOCK_FILE = 'modules.lock';
|
|
9
|
-
const STATE_FILE = '.hq-sync-state.json';
|
|
10
|
-
|
|
11
|
-
export function findHqRoot(): string {
|
|
12
|
-
let dir = process.cwd();
|
|
13
|
-
while (dir !== '/') {
|
|
14
|
-
if (fs.existsSync(path.join(dir, '.claude')) || fs.existsSync(path.join(dir, 'workers'))) {
|
|
15
|
-
return dir;
|
|
16
|
-
}
|
|
17
|
-
dir = path.dirname(dir);
|
|
18
|
-
}
|
|
19
|
-
return process.cwd();
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Resolve the manifest path for a given HQ root.
|
|
24
|
-
*
|
|
25
|
-
* The canonical layout is nested: `{hqRoot}/modules/modules.yaml` (catalog)
|
|
26
|
-
* alongside `{hqRoot}/modules/<module-name>/` (clone targets).
|
|
27
|
-
*
|
|
28
|
-
* Legacy fixtures and very old HQ instances may have the flat layout
|
|
29
|
-
* (`{hqRoot}/modules.yaml`); we honor that if — and only if — the flat file
|
|
30
|
-
* already exists. On fresh HQs we default to the nested form so we never
|
|
31
|
-
* silently create a second shadow manifest at the root.
|
|
32
|
-
*
|
|
33
|
-
* Exported for tests.
|
|
34
|
-
*/
|
|
35
|
-
export function getManifestPath(hqRoot: string): string {
|
|
36
|
-
const nested = path.join(hqRoot, 'modules', MANIFEST_FILE);
|
|
37
|
-
const flat = path.join(hqRoot, MANIFEST_FILE);
|
|
38
|
-
if (fs.existsSync(nested)) return nested;
|
|
39
|
-
if (fs.existsSync(flat)) return flat;
|
|
40
|
-
return nested; // default for fresh HQs — see getModulesDir()
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export function getLockPath(hqRoot: string): string {
|
|
44
|
-
return path.join(hqRoot, LOCK_FILE);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export function getStatePath(hqRoot: string): string {
|
|
48
|
-
return path.join(hqRoot, STATE_FILE);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export function getModulesDir(hqRoot: string): string {
|
|
52
|
-
return path.join(hqRoot, 'modules');
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export function readManifest(hqRoot: string): ModulesManifest | null {
|
|
56
|
-
const manifestPath = getManifestPath(hqRoot);
|
|
57
|
-
if (!fs.existsSync(manifestPath)) {
|
|
58
|
-
return null;
|
|
59
|
-
}
|
|
60
|
-
const content = fs.readFileSync(manifestPath, 'utf-8');
|
|
61
|
-
return parseUserYaml<ModulesManifest>(content, manifestPath);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export function writeManifest(hqRoot: string, manifest: ModulesManifest): void {
|
|
65
|
-
const manifestPath = getManifestPath(hqRoot);
|
|
66
|
-
// Ensure the parent directory exists — on a fresh HQ the nested
|
|
67
|
-
// `modules/` dir may not yet be present, and fs.writeFileSync does not
|
|
68
|
-
// auto-mkdir. Safe no-op when the dir already exists.
|
|
69
|
-
fs.mkdirSync(path.dirname(manifestPath), { recursive: true });
|
|
70
|
-
const content = yaml.dump(manifest, { lineWidth: -1 });
|
|
71
|
-
fs.writeFileSync(manifestPath, content);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export function readLock(hqRoot: string): ModuleLock | null {
|
|
75
|
-
const lockPath = getLockPath(hqRoot);
|
|
76
|
-
if (!fs.existsSync(lockPath)) {
|
|
77
|
-
return null;
|
|
78
|
-
}
|
|
79
|
-
const content = fs.readFileSync(lockPath, 'utf-8');
|
|
80
|
-
return parseUserYaml<ModuleLock>(content, lockPath);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export function writeLock(hqRoot: string, lock: ModuleLock): void {
|
|
84
|
-
const lockPath = getLockPath(hqRoot);
|
|
85
|
-
const content = yaml.dump(lock, { lineWidth: -1 });
|
|
86
|
-
fs.writeFileSync(lockPath, content);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export function readState(hqRoot: string): SyncState | null {
|
|
90
|
-
const statePath = getStatePath(hqRoot);
|
|
91
|
-
if (!fs.existsSync(statePath)) {
|
|
92
|
-
return null;
|
|
93
|
-
}
|
|
94
|
-
const content = fs.readFileSync(statePath, 'utf-8');
|
|
95
|
-
return JSON.parse(content) as SyncState;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
export function writeState(hqRoot: string, state: SyncState): void {
|
|
99
|
-
const statePath = getStatePath(hqRoot);
|
|
100
|
-
fs.writeFileSync(statePath, JSON.stringify(state, null, 2));
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
export function addModule(hqRoot: string, module: ModuleDefinition): void {
|
|
104
|
-
let manifest = readManifest(hqRoot);
|
|
105
|
-
if (!manifest) {
|
|
106
|
-
manifest = { version: '1', modules: [] };
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Check for duplicates
|
|
110
|
-
if (manifest.modules.some(m => m.name === module.name)) {
|
|
111
|
-
throw new Error(`Module "${module.name}" already exists`);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
manifest.modules.push(module);
|
|
115
|
-
writeManifest(hqRoot, manifest);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
export function parseRepoName(repoUrl: string): string {
|
|
119
|
-
// Extract repo name from URL
|
|
120
|
-
// https://github.com/user/repo.git -> repo
|
|
121
|
-
// git@github.com:user/repo.git -> repo
|
|
122
|
-
const match = repoUrl.match(/[\/:]([^\/]+?)(\.git)?$/);
|
|
123
|
-
if (!match) {
|
|
124
|
-
throw new Error(`Cannot parse repo name from: ${repoUrl}`);
|
|
125
|
-
}
|
|
126
|
-
return match[1];
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
export function isValidRepoUrl(url: string): boolean {
|
|
130
|
-
return url.startsWith('https://') || url.startsWith('git@');
|
|
131
|
-
}
|