@indigoai-us/hq-cli 5.299.0 → 5.301.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 +26 -0
- package/assets/scaffold/core/scripts/token-usage-report.sh +9 -0
- package/dist/command-catalog.generated.d.ts +32 -6
- package/dist/command-catalog.generated.js +38 -6
- package/dist/commands/__fixtures__/access-vault.d.ts +2 -0
- package/dist/commands/__fixtures__/access-vault.js +1 -1
- package/dist/commands/access.d.ts +2 -1
- package/dist/commands/access.js +58 -49
- package/dist/commands/cloud-provision.js +51 -2
- package/dist/commands/cloud.js +12 -7
- package/dist/commands/core-company-index-scope-flag.d.ts +3 -0
- package/dist/commands/core-company-index-scope-flag.js +6 -0
- package/dist/commands/core-job-native-utils.d.ts +6 -0
- package/dist/commands/core-job-native-utils.js +80 -0
- package/dist/commands/core-job-native.d.ts +2 -4
- package/dist/commands/core-job-native.js +6 -10
- package/dist/commands/core-job-notify-native.d.ts +36 -0
- package/dist/commands/core-job-notify-native.js +359 -0
- package/dist/commands/core-job-remediate-native.d.ts +26 -0
- package/dist/commands/core-job-remediate-native.js +374 -0
- package/dist/commands/core.js +26 -8
- package/dist/commands/files.d.ts +1 -0
- package/dist/commands/files.js +90 -14
- package/dist/commands/integrations-api.d.ts +6 -6
- package/dist/commands/integrations-api.js +4 -13
- package/dist/commands/integrations-manage.js +1 -4
- package/dist/commands/lanes-message.js +78 -37
- package/dist/commands/lanes-resume.js +247 -210
- package/dist/commands/lanes-shared.d.ts +5 -1
- package/dist/commands/lanes.d.ts +4 -0
- package/dist/commands/lanes.js +7 -4
- package/dist/commands/meetings.js +35 -16
- package/dist/commands/safe-extract.d.ts +4 -4
- package/dist/commands/safe-extract.js +6 -7
- package/dist/lib/core-utils/token-usage-report.js +17 -3
- package/dist/lib/index-render/companies.d.ts +4 -1
- package/dist/lib/index-render/companies.js +66 -3
- package/dist/lib/index-render/index.d.ts +1 -0
- package/dist/lib/index-render/index.js +2 -1
- package/dist/lib/index-render/shared.d.ts +1 -1
- package/dist/lib/index-render/shared.js +4 -2
- package/dist/lib/lanes/reconcile.js +22 -4
- package/dist/lib/lanes/story-switch.d.ts +21 -0
- package/dist/lib/lanes/story-switch.js +75 -0
- package/dist/lib/lanes/types.d.ts +25 -0
- package/dist/lib/lanes/types.js +1 -1
- package/dist/lib/lanes/watcher.js +15 -4
- package/dist/lib/mesh/live/daemon/mqtt-events.d.ts +7 -0
- package/dist/lib/mesh/live/daemon/mqtt-events.js +2 -0
- package/dist/lib/mesh/live/daemon/mqtt-events.test-d.d.ts +2 -0
- package/dist/lib/mesh/live/daemon/mqtt-events.test-d.js +10 -0
- package/dist/lib/mesh/live/daemon/presence.d.ts +2 -2
- package/dist/lib/mesh/live/daemon/work-subscribe.d.ts +2 -2
- package/dist/utils/self-update.js +51 -4
- package/dist/utils/staged-npm-install.d.ts +16 -0
- package/dist/utils/staged-npm-install.js +264 -0
- package/dist/utils/update-command-supervisor.cjs +53 -1
- package/dist/utils/version-gate.d.ts +8 -0
- package/dist/utils/version-gate.js +82 -15
- package/package.json +2 -2
- package/dist/lib/install-path-compatibility-flag.d.ts +0 -9
- package/dist/lib/install-path-compatibility-flag.js +0 -12
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,32 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [5.301.0] — 2026-10-01
|
|
6
|
+
- `hq meetings transcript` and `hq meetings notes` stop a stalled document download after two minutes and say so, instead of waiting forever.
|
|
7
|
+
|
|
8
|
+
- Keep `hq access` from reporting a denied vault path as missing or exposing matching paths.
|
|
9
|
+
- Fix self-updates for npm installs whose global prefix contains spaces.
|
|
10
|
+
- `hq files acl companies/<slug>` and `hq files unshare companies/<slug> --with ...` now handle ACL rows at that exact company path instead of treating it as the vault root.
|
|
11
|
+
- Add native hq core job notify and remediate commands behind core-native-jobs, retaining bundled shell companions.
|
|
12
|
+
- Allow owners to disconnect custom Factory connections without installation records, and send the company UID required by the revoked-connection purge endpoint.
|
|
13
|
+
- Fail company provisioning when its initial sync reports per-file upload failures, while retaining the successful upload count in failure details.
|
|
14
|
+
- Treat plan-limited files as initial-sync failures and keep provisioning progress snapshots updated.
|
|
15
|
+
- Preserve story attribution after a message is durably queued by lane admission or an account move.
|
|
16
|
+
- The token usage report accepts `--project-dir <path>` to read one Claude activity folder instead of the default folders.
|
|
17
|
+
|
|
18
|
+
## [5.300.0] — 2026-09-30
|
|
19
|
+
- `hq files unshare --with agt_...` removes a grant made to an agent. Before, agent uids were rejected as invalid principals.
|
|
20
|
+
- With the default-off hq-flags gate `files.share-empty-prefix-warning`, `hq files share` warns when a granted prefix has no files. A failed or timed-out list check does not block the grant.
|
|
21
|
+
- Recognize pnpm v11+ global installs and handle Windows drive-path tar archives without waiting for the asynchronous feature-flag snapshot.
|
|
22
|
+
- Self-update failure reports now include the npm error code and a sanitized reason.
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
|
|
26
|
+
- `hq core rebuild-index companies --company <slug>` scopes the generated write to that company (behind the default-off `cli.rebuild-index-company-scope` flag), and `--help` exits without reading or writing company indexes. The unscoped run also ignores orchestrator state tied to another company's PRD.
|
|
27
|
+
|
|
28
|
+
- Lane messages and resumes that switch project or story attribution now tell the provider which story is active. Reused completion artifacts no longer close the new story.
|
|
29
|
+
- Make signed-out `hq sync` commands fail fast with `hq login` guidance when stdin or stdout is not a terminal, while keeping browser login in a terminal.
|
|
30
|
+
|
|
5
31
|
## [5.299.0] — 2026-09-30
|
|
6
32
|
- Add `hq lanes accounts clear-quota` and clear future quota marks after successful lane turns.
|
|
7
33
|
- On macOS, `hq daemon` retires a loaded legacy mesh LaunchAgent even when its plist is missing, and daemon uninstall boots the job out before deleting its plist. Mesh-owner wait logs now repeat at most every ten minutes.
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
# scripts/token-usage-report.sh --last 14 # last 14 days
|
|
6
6
|
# scripts/token-usage-report.sh --since 2026-05-01
|
|
7
7
|
# scripts/token-usage-report.sh --json # machine-readable
|
|
8
|
+
# scripts/token-usage-report.sh --project-dir <path> # read one activity folder
|
|
8
9
|
#
|
|
9
10
|
# Effective tokens weighting (matches weekly rate-limit volume):
|
|
10
11
|
# input + 5×output + 1.25×cache_creation + 0.1×cache_read
|
|
@@ -24,6 +25,14 @@ while [ $# -gt 0 ]; do
|
|
|
24
25
|
--last) LAST_DAYS="$2"; shift 2 ;;
|
|
25
26
|
--since) SINCE="$2"; shift 2 ;;
|
|
26
27
|
--json) JSON_MODE=1; shift ;;
|
|
28
|
+
--project-dir)
|
|
29
|
+
if [ "$#" -lt 2 ] || [ -z "$2" ]; then
|
|
30
|
+
echo "token-usage-report: --project-dir requires a path" >&2
|
|
31
|
+
exit 1
|
|
32
|
+
fi
|
|
33
|
+
PROJECT_DIR="$2"
|
|
34
|
+
shift 2
|
|
35
|
+
;;
|
|
27
36
|
--compare-windows) shift ;; # flag, presence triggers compare mode via --before/--after
|
|
28
37
|
--before) COMPARE_BEFORE="$2"; shift 2 ;;
|
|
29
38
|
--after) COMPARE_AFTER="$2"; shift 2 ;;
|
|
@@ -1713,7 +1713,7 @@ export declare const COMMAND_CATALOG: readonly [{
|
|
|
1713
1713
|
}];
|
|
1714
1714
|
readonly options: readonly [{
|
|
1715
1715
|
readonly flags: "--with <principal>";
|
|
1716
|
-
readonly description: "Person uid, email address, group id, or '@all' to remove the grant";
|
|
1716
|
+
readonly description: "Person uid, agent uid, email address, group id, or '@all' to remove the grant";
|
|
1717
1717
|
}];
|
|
1718
1718
|
readonly subcommands: readonly [];
|
|
1719
1719
|
}, {
|
|
@@ -5620,13 +5620,26 @@ export declare const COMMAND_CATALOG: readonly [{
|
|
|
5620
5620
|
}];
|
|
5621
5621
|
}, {
|
|
5622
5622
|
readonly name: "job";
|
|
5623
|
-
readonly description: "Run or
|
|
5623
|
+
readonly description: "Run, inspect, notify, or remediate one scheduled job";
|
|
5624
5624
|
readonly aliases: readonly [];
|
|
5625
5625
|
readonly hidden: false;
|
|
5626
5626
|
readonly usage: "[options] [command]";
|
|
5627
5627
|
readonly arguments: readonly [];
|
|
5628
5628
|
readonly options: readonly [];
|
|
5629
5629
|
readonly subcommands: readonly [{
|
|
5630
|
+
readonly name: "notify";
|
|
5631
|
+
readonly description: "Send a scheduled-job status alert to its owner";
|
|
5632
|
+
readonly aliases: readonly [];
|
|
5633
|
+
readonly hidden: false;
|
|
5634
|
+
readonly usage: "[args...]";
|
|
5635
|
+
readonly arguments: readonly [{
|
|
5636
|
+
readonly name: "args";
|
|
5637
|
+
readonly required: false;
|
|
5638
|
+
readonly variadic: true;
|
|
5639
|
+
}];
|
|
5640
|
+
readonly options: readonly [];
|
|
5641
|
+
readonly subcommands: readonly [];
|
|
5642
|
+
}, {
|
|
5630
5643
|
readonly name: "probe";
|
|
5631
5644
|
readonly description: "Check scheduled-job requirements and report readiness";
|
|
5632
5645
|
readonly aliases: readonly [];
|
|
@@ -5639,6 +5652,19 @@ export declare const COMMAND_CATALOG: readonly [{
|
|
|
5639
5652
|
}];
|
|
5640
5653
|
readonly options: readonly [];
|
|
5641
5654
|
readonly subcommands: readonly [];
|
|
5655
|
+
}, {
|
|
5656
|
+
readonly name: "remediate";
|
|
5657
|
+
readonly description: "Run bounded remediation for a scheduled-job failure";
|
|
5658
|
+
readonly aliases: readonly [];
|
|
5659
|
+
readonly hidden: false;
|
|
5660
|
+
readonly usage: "[args...]";
|
|
5661
|
+
readonly arguments: readonly [{
|
|
5662
|
+
readonly name: "args";
|
|
5663
|
+
readonly required: false;
|
|
5664
|
+
readonly variadic: true;
|
|
5665
|
+
}];
|
|
5666
|
+
readonly options: readonly [];
|
|
5667
|
+
readonly subcommands: readonly [];
|
|
5642
5668
|
}, {
|
|
5643
5669
|
readonly name: "run";
|
|
5644
5670
|
readonly description: "Run a scheduled job";
|
|
@@ -8509,10 +8535,10 @@ export declare const COMMAND_CATALOG: readonly [{
|
|
|
8509
8535
|
readonly description: "Message text";
|
|
8510
8536
|
}, {
|
|
8511
8537
|
readonly flags: "--project <slug>";
|
|
8512
|
-
readonly description: "Re-point project attribution
|
|
8538
|
+
readonly description: "Re-point project attribution; a changed story is named in the resumed prompt";
|
|
8513
8539
|
}, {
|
|
8514
8540
|
readonly flags: "--story <id>";
|
|
8515
|
-
readonly description: "Re-point story attribution
|
|
8541
|
+
readonly description: "Re-point story attribution; a changed story is named in the resumed prompt";
|
|
8516
8542
|
}, {
|
|
8517
8543
|
readonly flags: "--account <id>";
|
|
8518
8544
|
readonly description: "Move the lane's session to this account of its provider before the message resumes it";
|
|
@@ -8602,10 +8628,10 @@ export declare const COMMAND_CATALOG: readonly [{
|
|
|
8602
8628
|
readonly description: "Required explanation for resuming from failed";
|
|
8603
8629
|
}, {
|
|
8604
8630
|
readonly flags: "--project <slug>";
|
|
8605
|
-
readonly description: "Re-point project attribution
|
|
8631
|
+
readonly description: "Re-point project attribution; a changed story is named in the resumed prompt";
|
|
8606
8632
|
}, {
|
|
8607
8633
|
readonly flags: "--story <id>";
|
|
8608
|
-
readonly description: "Re-point story attribution
|
|
8634
|
+
readonly description: "Re-point story attribution; a changed story is named in the resumed prompt";
|
|
8609
8635
|
}, {
|
|
8610
8636
|
readonly flags: "--account <id>";
|
|
8611
8637
|
readonly description: "Move the lane's session to this account of its provider before resuming";
|
|
@@ -2185,7 +2185,7 @@ export const COMMAND_CATALOG = [
|
|
|
2185
2185
|
"options": [
|
|
2186
2186
|
{
|
|
2187
2187
|
"flags": "--with <principal>",
|
|
2188
|
-
"description": "Person uid, email address, group id, or '@all' to remove the grant"
|
|
2188
|
+
"description": "Person uid, agent uid, email address, group id, or '@all' to remove the grant"
|
|
2189
2189
|
}
|
|
2190
2190
|
],
|
|
2191
2191
|
"subcommands": []
|
|
@@ -7246,13 +7246,29 @@ export const COMMAND_CATALOG = [
|
|
|
7246
7246
|
},
|
|
7247
7247
|
{
|
|
7248
7248
|
"name": "job",
|
|
7249
|
-
"description": "Run or
|
|
7249
|
+
"description": "Run, inspect, notify, or remediate one scheduled job",
|
|
7250
7250
|
"aliases": [],
|
|
7251
7251
|
"hidden": false,
|
|
7252
7252
|
"usage": "[options] [command]",
|
|
7253
7253
|
"arguments": [],
|
|
7254
7254
|
"options": [],
|
|
7255
7255
|
"subcommands": [
|
|
7256
|
+
{
|
|
7257
|
+
"name": "notify",
|
|
7258
|
+
"description": "Send a scheduled-job status alert to its owner",
|
|
7259
|
+
"aliases": [],
|
|
7260
|
+
"hidden": false,
|
|
7261
|
+
"usage": "[args...]",
|
|
7262
|
+
"arguments": [
|
|
7263
|
+
{
|
|
7264
|
+
"name": "args",
|
|
7265
|
+
"required": false,
|
|
7266
|
+
"variadic": true
|
|
7267
|
+
}
|
|
7268
|
+
],
|
|
7269
|
+
"options": [],
|
|
7270
|
+
"subcommands": []
|
|
7271
|
+
},
|
|
7256
7272
|
{
|
|
7257
7273
|
"name": "probe",
|
|
7258
7274
|
"description": "Check scheduled-job requirements and report readiness",
|
|
@@ -7269,6 +7285,22 @@ export const COMMAND_CATALOG = [
|
|
|
7269
7285
|
"options": [],
|
|
7270
7286
|
"subcommands": []
|
|
7271
7287
|
},
|
|
7288
|
+
{
|
|
7289
|
+
"name": "remediate",
|
|
7290
|
+
"description": "Run bounded remediation for a scheduled-job failure",
|
|
7291
|
+
"aliases": [],
|
|
7292
|
+
"hidden": false,
|
|
7293
|
+
"usage": "[args...]",
|
|
7294
|
+
"arguments": [
|
|
7295
|
+
{
|
|
7296
|
+
"name": "args",
|
|
7297
|
+
"required": false,
|
|
7298
|
+
"variadic": true
|
|
7299
|
+
}
|
|
7300
|
+
],
|
|
7301
|
+
"options": [],
|
|
7302
|
+
"subcommands": []
|
|
7303
|
+
},
|
|
7272
7304
|
{
|
|
7273
7305
|
"name": "run",
|
|
7274
7306
|
"description": "Run a scheduled job",
|
|
@@ -10972,11 +11004,11 @@ export const COMMAND_CATALOG = [
|
|
|
10972
11004
|
},
|
|
10973
11005
|
{
|
|
10974
11006
|
"flags": "--project <slug>",
|
|
10975
|
-
"description": "Re-point project attribution
|
|
11007
|
+
"description": "Re-point project attribution; a changed story is named in the resumed prompt"
|
|
10976
11008
|
},
|
|
10977
11009
|
{
|
|
10978
11010
|
"flags": "--story <id>",
|
|
10979
|
-
"description": "Re-point story attribution
|
|
11011
|
+
"description": "Re-point story attribution; a changed story is named in the resumed prompt"
|
|
10980
11012
|
},
|
|
10981
11013
|
{
|
|
10982
11014
|
"flags": "--account <id>",
|
|
@@ -11094,11 +11126,11 @@ export const COMMAND_CATALOG = [
|
|
|
11094
11126
|
},
|
|
11095
11127
|
{
|
|
11096
11128
|
"flags": "--project <slug>",
|
|
11097
|
-
"description": "Re-point project attribution
|
|
11129
|
+
"description": "Re-point project attribution; a changed story is named in the resumed prompt"
|
|
11098
11130
|
},
|
|
11099
11131
|
{
|
|
11100
11132
|
"flags": "--story <id>",
|
|
11101
|
-
"description": "Re-point story attribution
|
|
11133
|
+
"description": "Re-point story attribution; a changed story is named in the resumed prompt"
|
|
11102
11134
|
},
|
|
11103
11135
|
{
|
|
11104
11136
|
"flags": "--account <id>",
|
|
@@ -82,6 +82,8 @@ export interface MakeAccessFixtureOptions {
|
|
|
82
82
|
* without read on the prefix — the server refuses to enumerate.
|
|
83
83
|
*/
|
|
84
84
|
listDenied?: boolean;
|
|
85
|
+
/** present-denied only: let a test isolate list denial from vend denial. */
|
|
86
|
+
vendDenied?: boolean;
|
|
85
87
|
/** Deny only the ROOT (prefix "") list — the caller can read the prefix but not enumerate the bucket. */
|
|
86
88
|
rootListDenied?: boolean;
|
|
87
89
|
}
|
|
@@ -93,7 +93,7 @@ export function makeAccessFixture(opts) {
|
|
|
93
93
|
if (opts.state === "missing") {
|
|
94
94
|
throw attachStatus(new Error("not found (404)"), 404);
|
|
95
95
|
}
|
|
96
|
-
if (opts.state === "present-denied") {
|
|
96
|
+
if (opts.state === "present-denied" && opts.vendDenied !== false) {
|
|
97
97
|
throw attachStatus(new Error("caller lacks read on this prefix (403)"), 403);
|
|
98
98
|
}
|
|
99
99
|
return FAKE_VEND;
|
|
@@ -122,7 +122,8 @@ export interface RunAccessResult {
|
|
|
122
122
|
outcome: AccessOutcome;
|
|
123
123
|
path: string;
|
|
124
124
|
company: string;
|
|
125
|
-
|
|
125
|
+
/** Omitted when an authorization denial leaves vault existence unknown. */
|
|
126
|
+
exists?: boolean;
|
|
126
127
|
grantor?: AccessGrantor;
|
|
127
128
|
candidates?: string[];
|
|
128
129
|
steps: string[];
|
package/dist/commands/access.js
CHANGED
|
@@ -52,7 +52,7 @@ export function formatAccessOutcome(result) {
|
|
|
52
52
|
lines.push(result.path);
|
|
53
53
|
break;
|
|
54
54
|
case "no-access":
|
|
55
|
-
lines.push(`
|
|
55
|
+
lines.push(`You do not have read access to this path.`);
|
|
56
56
|
lines.push(result.path);
|
|
57
57
|
break;
|
|
58
58
|
case "pending-confirmation":
|
|
@@ -236,72 +236,81 @@ export async function runAccess(input) {
|
|
|
236
236
|
const bucket = entity?.bucketName ?? `hq-vault-cmp-${slug}`;
|
|
237
237
|
const s3 = deps.companyClient({ companyUid: deps.companyUid });
|
|
238
238
|
let listDenied = false;
|
|
239
|
-
const prefixList = await listKeys(s3, bucket, relative);
|
|
240
|
-
const exact = prefixList.keys.find((k) => k === relative);
|
|
241
239
|
let key;
|
|
242
|
-
if (
|
|
243
|
-
// The
|
|
244
|
-
//
|
|
245
|
-
// it for the grantor.
|
|
240
|
+
if (vendDenied) {
|
|
241
|
+
// The caller is denied at the company boundary. Do not use list results to
|
|
242
|
+
// resolve or disclose matching keys, even if a separate listing succeeds.
|
|
246
243
|
listDenied = true;
|
|
247
244
|
key = relative;
|
|
248
|
-
steps.push("list: 403 (no-access)");
|
|
249
|
-
}
|
|
250
|
-
else if (exact) {
|
|
251
|
-
key = exact;
|
|
252
|
-
steps.push("resolve: exact key");
|
|
253
|
-
steps.push("list: 1 hit");
|
|
245
|
+
steps.push("list: skipped after vend 403 (no-access)");
|
|
254
246
|
}
|
|
255
247
|
else {
|
|
256
|
-
const
|
|
257
|
-
const
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
const fuzzy = pool.filter((k) => k.toLowerCase().includes(q));
|
|
263
|
-
if (allList.denied && fuzzy.length === 0) {
|
|
248
|
+
const prefixList = await listKeys(s3, bucket, relative);
|
|
249
|
+
const exact = prefixList.keys.find((k) => k === relative);
|
|
250
|
+
if (prefixList.denied) {
|
|
251
|
+
// The server refused to enumerate — the caller has no read on this
|
|
252
|
+
// prefix. Keep the target as the key so the request rung can still name
|
|
253
|
+
// it for the grantor.
|
|
264
254
|
listDenied = true;
|
|
265
255
|
key = relative;
|
|
266
256
|
steps.push("list: 403 (no-access)");
|
|
267
257
|
}
|
|
268
|
-
else if (
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
path: anchored(relative) || input.target,
|
|
272
|
-
company: slug,
|
|
273
|
-
exists: false,
|
|
274
|
-
steps,
|
|
275
|
-
}, finishCtx);
|
|
276
|
-
emit(input, result, log);
|
|
277
|
-
return result;
|
|
278
|
-
}
|
|
279
|
-
else if (fuzzy.length === 1) {
|
|
280
|
-
key = fuzzy[0];
|
|
281
|
-
steps.push("resolve: fuzzy (1 hit)");
|
|
258
|
+
else if (exact) {
|
|
259
|
+
key = exact;
|
|
260
|
+
steps.push("resolve: exact key");
|
|
282
261
|
steps.push("list: 1 hit");
|
|
283
262
|
}
|
|
284
263
|
else {
|
|
285
|
-
const
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
264
|
+
const allList = await listKeys(s3, bucket, "");
|
|
265
|
+
const q = relative.toLowerCase();
|
|
266
|
+
// A root-list 403 only says the caller cannot enumerate the WHOLE bucket.
|
|
267
|
+
// The prefix list above succeeded, so fuzzy-match within it first; the
|
|
268
|
+
// root denial is the verdict only when the readable prefix has no match.
|
|
269
|
+
const pool = allList.denied ? prefixList.keys : allList.keys;
|
|
270
|
+
const fuzzy = pool.filter((k) => k.toLowerCase().includes(q));
|
|
271
|
+
if (allList.denied && fuzzy.length === 0) {
|
|
272
|
+
listDenied = true;
|
|
273
|
+
key = relative;
|
|
274
|
+
steps.push("list: 403 (no-access)");
|
|
290
275
|
}
|
|
291
|
-
if (
|
|
292
|
-
|
|
293
|
-
|
|
276
|
+
else if (fuzzy.length === 0) {
|
|
277
|
+
steps.push("list: 0 hits");
|
|
278
|
+
const result = finish("never-existed", {
|
|
279
|
+
path: anchored(relative) || input.target,
|
|
294
280
|
company: slug,
|
|
295
281
|
exists: false,
|
|
296
|
-
candidates,
|
|
297
282
|
steps,
|
|
298
283
|
}, finishCtx);
|
|
299
284
|
emit(input, result, log);
|
|
300
285
|
return result;
|
|
301
286
|
}
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
287
|
+
else if (fuzzy.length === 1) {
|
|
288
|
+
key = fuzzy[0];
|
|
289
|
+
steps.push("resolve: fuzzy (1 hit)");
|
|
290
|
+
steps.push("list: 1 hit");
|
|
291
|
+
}
|
|
292
|
+
else {
|
|
293
|
+
const candidates = fuzzy.map(anchored);
|
|
294
|
+
steps.push(`list: ${fuzzy.length} hits`);
|
|
295
|
+
let picked = null;
|
|
296
|
+
if (deps.pick) {
|
|
297
|
+
picked = await deps.pick(candidates);
|
|
298
|
+
}
|
|
299
|
+
if (!picked) {
|
|
300
|
+
const result = finish("ambiguous", {
|
|
301
|
+
path: input.target,
|
|
302
|
+
company: slug,
|
|
303
|
+
exists: false,
|
|
304
|
+
candidates,
|
|
305
|
+
steps,
|
|
306
|
+
}, finishCtx);
|
|
307
|
+
emit(input, result, log);
|
|
308
|
+
return result;
|
|
309
|
+
}
|
|
310
|
+
const stripped = normalizeTarget(picked, slug);
|
|
311
|
+
key = stripped;
|
|
312
|
+
steps.push("resolve: pick");
|
|
313
|
+
}
|
|
305
314
|
}
|
|
306
315
|
}
|
|
307
316
|
const resolvedKey = key;
|
|
@@ -524,7 +533,7 @@ export async function runAccess(input) {
|
|
|
524
533
|
const result = finish(outcome, {
|
|
525
534
|
path: resolvedPath,
|
|
526
535
|
company: slug,
|
|
527
|
-
exists: true,
|
|
536
|
+
...(vendDenied || listDenied ? {} : { exists: true }),
|
|
528
537
|
steps,
|
|
529
538
|
...(fixed ? { fixed, localPath } : {}),
|
|
530
539
|
...(grantor ? { grantor } : {}),
|
|
@@ -541,7 +550,7 @@ function emit(input, result, log) {
|
|
|
541
550
|
outcome: result.outcome,
|
|
542
551
|
path: result.path,
|
|
543
552
|
company: result.company,
|
|
544
|
-
exists: result.exists,
|
|
553
|
+
...(result.exists !== undefined ? { exists: result.exists } : {}),
|
|
545
554
|
steps: result.steps,
|
|
546
555
|
};
|
|
547
556
|
if (result.grantor)
|
|
@@ -32,7 +32,7 @@ import * as fs from "node:fs";
|
|
|
32
32
|
import * as path from "node:path";
|
|
33
33
|
import * as yaml from "js-yaml";
|
|
34
34
|
import { parseUserYaml } from "../utils/user-yaml-error.js";
|
|
35
|
-
import { share } from "@indigoai-us/hq-cloud";
|
|
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
37
|
/** Custom error class so the CLI runner can map to exit codes. */
|
|
38
38
|
export class ProvisionError extends Error {
|
|
@@ -421,7 +421,32 @@ async function safeBody(res) {
|
|
|
421
421
|
}
|
|
422
422
|
}
|
|
423
423
|
// ── Default initial-sync runner (wraps share()) ──────────────────────────────
|
|
424
|
+
const INITIAL_SYNC_ERROR_FIELD_LIMIT = 240;
|
|
425
|
+
function truncateInitialSyncErrorField(value) {
|
|
426
|
+
return value.length <= INITIAL_SYNC_ERROR_FIELD_LIMIT
|
|
427
|
+
? value
|
|
428
|
+
: `${value.slice(0, INITIAL_SYNC_ERROR_FIELD_LIMIT - 1)}…`;
|
|
429
|
+
}
|
|
430
|
+
class InitialSyncUploadFailureError extends Error {
|
|
431
|
+
filesUploaded;
|
|
432
|
+
constructor(filesUploaded, failureCount, firstFailure) {
|
|
433
|
+
const detail = `${truncateInitialSyncErrorField(firstFailure.path)}: ` +
|
|
434
|
+
truncateInitialSyncErrorField(firstFailure.message);
|
|
435
|
+
const failureLabel = failureCount === 1
|
|
436
|
+
? "upload failure"
|
|
437
|
+
: "upload failures";
|
|
438
|
+
super(`${failureCount} ${failureLabel}; first failure: ${detail}`);
|
|
439
|
+
this.filesUploaded = filesUploaded;
|
|
440
|
+
this.name = "InitialSyncUploadFailureError";
|
|
441
|
+
}
|
|
442
|
+
}
|
|
424
443
|
async function defaultRunInitialSync(args) {
|
|
444
|
+
let failureCount = 0;
|
|
445
|
+
let firstFailure;
|
|
446
|
+
const recordProgress = createSyncProgressRecorder({
|
|
447
|
+
company: args.slug,
|
|
448
|
+
phase: "push",
|
|
449
|
+
});
|
|
425
450
|
const result = await share({
|
|
426
451
|
paths: [companyDirPath(args.hqRoot, args.slug)],
|
|
427
452
|
company: args.slug,
|
|
@@ -429,7 +454,25 @@ async function defaultRunInitialSync(args) {
|
|
|
429
454
|
onConflict: "keep",
|
|
430
455
|
vaultConfig: buildVaultConfig(args.accessToken),
|
|
431
456
|
hqRoot: args.hqRoot,
|
|
457
|
+
progressRecorder: (event) => {
|
|
458
|
+
recordProgress(event);
|
|
459
|
+
if (event.type === "plan-limit") {
|
|
460
|
+
failureCount += Math.max(1, event.count ?? 0, event.paths?.length ?? 0);
|
|
461
|
+
firstFailure ??= {
|
|
462
|
+
path: event.paths?.[0] ?? "plan limit",
|
|
463
|
+
message: event.message ?? "plan limit refused upload",
|
|
464
|
+
};
|
|
465
|
+
return;
|
|
466
|
+
}
|
|
467
|
+
if (event.type !== "error" || event.diagnostic === true)
|
|
468
|
+
return;
|
|
469
|
+
failureCount++;
|
|
470
|
+
firstFailure ??= { path: event.path, message: event.message };
|
|
471
|
+
},
|
|
432
472
|
});
|
|
473
|
+
if (failureCount > 0 && firstFailure) {
|
|
474
|
+
throw new InitialSyncUploadFailureError(result.filesUploaded, failureCount, firstFailure);
|
|
475
|
+
}
|
|
433
476
|
return {
|
|
434
477
|
filesUploaded: result.filesUploaded,
|
|
435
478
|
bytesUploaded: result.bytesUploaded,
|
|
@@ -654,7 +697,13 @@ export async function provisionCompany(options) {
|
|
|
654
697
|
created_entity: createdEntity,
|
|
655
698
|
manifest_patched: true,
|
|
656
699
|
config_written: true,
|
|
657
|
-
initial_sync: {
|
|
700
|
+
initial_sync: {
|
|
701
|
+
ok: false,
|
|
702
|
+
error: msg,
|
|
703
|
+
...(err instanceof InitialSyncUploadFailureError
|
|
704
|
+
? { files_uploaded: err.filesUploaded }
|
|
705
|
+
: {}),
|
|
706
|
+
},
|
|
658
707
|
});
|
|
659
708
|
}
|
|
660
709
|
}
|
package/dist/commands/cloud.js
CHANGED
|
@@ -53,6 +53,11 @@ export class SyncExitError extends Error {
|
|
|
53
53
|
this.health = opts.health ?? "failed";
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
|
+
async function ensureSyncCognitoToken() {
|
|
57
|
+
return ensureCognitoToken({
|
|
58
|
+
interactive: process.stdin.isTTY === true && process.stdout.isTTY === true,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
56
61
|
/**
|
|
57
62
|
* Preserve the vault's typed write-scope refusal at the CLI boundary. This is
|
|
58
63
|
* deliberately duck-typed so hq-cli remains compatible while hq-cloud and the
|
|
@@ -845,11 +850,11 @@ export function registerCloudCommands(program) {
|
|
|
845
850
|
}
|
|
846
851
|
// Upload creds are pre-vended in entityContext, but prefix filtering
|
|
847
852
|
// still needs vault-service membership/grant resolution.
|
|
848
|
-
const accessToken = await
|
|
853
|
+
const accessToken = await ensureSyncCognitoToken();
|
|
849
854
|
scopeVaultConfig = buildVaultConfig(accessToken);
|
|
850
855
|
}
|
|
851
856
|
else {
|
|
852
|
-
const accessToken = await
|
|
857
|
+
const accessToken = await ensureSyncCognitoToken();
|
|
853
858
|
vaultConfig = buildVaultConfig(accessToken);
|
|
854
859
|
scopeVaultConfig = vaultConfig;
|
|
855
860
|
}
|
|
@@ -1064,7 +1069,7 @@ export function registerCloudCommands(program) {
|
|
|
1064
1069
|
console.log(chalk.bold("\nHQ Sync — Pull"));
|
|
1065
1070
|
console.log(` HQ root: ${options.hqRoot}`);
|
|
1066
1071
|
console.log(` Company: ${options.company ?? "(from .hq/config.json)"}\n`);
|
|
1067
|
-
const accessToken = await
|
|
1072
|
+
const accessToken = await ensureSyncCognitoToken();
|
|
1068
1073
|
const vaultConfig = buildVaultConfig(accessToken);
|
|
1069
1074
|
// US-011 (2026-05-21 fix): resolve the caller's sync-config for
|
|
1070
1075
|
// the targeted membership BEFORE the pull, so we can (a) emit the
|
|
@@ -1368,7 +1373,7 @@ async function runPullAll(hqRoot, onConflict, modeAllOverride, skipPersonal, for
|
|
|
1368
1373
|
console.log("");
|
|
1369
1374
|
let result;
|
|
1370
1375
|
try {
|
|
1371
|
-
const accessToken = await
|
|
1376
|
+
const accessToken = await ensureSyncCognitoToken();
|
|
1372
1377
|
const vaultConfig = buildVaultConfig(accessToken);
|
|
1373
1378
|
const realClient = new VaultClient(vaultConfig);
|
|
1374
1379
|
const adapter = {
|
|
@@ -1461,7 +1466,7 @@ export async function runPullPersonal(hqRoot, onConflict) {
|
|
|
1461
1466
|
console.log(` HQ root: ${hqRoot}`);
|
|
1462
1467
|
console.log(` Strategy: ${onConflict ?? "(interactive)"}\n`);
|
|
1463
1468
|
try {
|
|
1464
|
-
const accessToken = await
|
|
1469
|
+
const accessToken = await ensureSyncCognitoToken();
|
|
1465
1470
|
const vaultConfig = buildVaultConfig(accessToken);
|
|
1466
1471
|
const client = new VaultClient(vaultConfig);
|
|
1467
1472
|
const personalUid = await resolveCanonicalPersonUid({
|
|
@@ -1509,7 +1514,7 @@ async function runPushAll(hqRoot, message, onConflict, skipPersonal) {
|
|
|
1509
1514
|
console.log("");
|
|
1510
1515
|
let result;
|
|
1511
1516
|
try {
|
|
1512
|
-
const accessToken = await
|
|
1517
|
+
const accessToken = await ensureSyncCognitoToken();
|
|
1513
1518
|
const vaultConfig = buildVaultConfig(accessToken);
|
|
1514
1519
|
const realClient = new VaultClient(vaultConfig);
|
|
1515
1520
|
const author = resolveUploadAuthor();
|
|
@@ -1637,7 +1642,7 @@ async function runNowSingle(hqRoot, company, personal, message, onConflict, mode
|
|
|
1637
1642
|
console.log(` Target: ${personal ? "(personal)" : (company ?? "(active company)")}`);
|
|
1638
1643
|
console.log(` Strategy: ${onConflict ?? "(interactive)"}\n`);
|
|
1639
1644
|
try {
|
|
1640
|
-
const accessToken = await
|
|
1645
|
+
const accessToken = await ensureSyncCognitoToken();
|
|
1641
1646
|
const vaultConfig = buildVaultConfig(accessToken);
|
|
1642
1647
|
const author = resolveUploadAuthor();
|
|
1643
1648
|
// Resolve the target. For --personal, look up the canonical person and
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { resolveProcessFlagGate } from "../lib/flag-registry.js";
|
|
2
|
+
export const CORE_COMPANY_INDEX_SCOPE_FLAG = "cli.rebuild-index-company-scope";
|
|
3
|
+
export function coreCompanyIndexScopeEnabled() {
|
|
4
|
+
return resolveProcessFlagGate(CORE_COMPANY_INDEX_SCOPE_FLAG, { fallback: false }, () => false);
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=core-company-index-scope-flag.js.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
/** Preserve raw argv (including the option terminator) through Commander. */
|
|
3
|
+
export declare function rawJobArgumentsForCommand(command: Command, fallback: string[], raw?: string[]): string[];
|
|
4
|
+
/** Shared gated registration path for each leaf in the singular job group. */
|
|
5
|
+
export declare function registerCoreJobLeaf(group: Command, core: Command, name: string, asset: string, summary: string, run: (args: string[], hqRoot: string) => number, canUseLiveRoot: (args: string[]) => boolean, valueOptions: readonly string[], booleanOptions?: readonly string[]): void;
|
|
6
|
+
//# sourceMappingURL=core-job-native-utils.d.ts.map
|