@indigoai-us/hq-cli 5.273.0-alpha.0 → 5.273.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 +25 -2
- package/dist/command-catalog.generated.d.ts +11 -536
- package/dist/command-catalog.generated.js +14 -691
- package/dist/commands/daemon.d.ts +0 -3
- package/dist/commands/daemon.js +1 -173
- package/dist/commands/lanes-checks.d.ts +0 -1
- package/dist/commands/lanes-checks.js +217 -54
- package/dist/commands/lanes-hold.js +40 -2
- package/dist/commands/lanes-message.js +98 -14
- package/dist/commands/lanes-shared.d.ts +3 -2
- package/dist/commands/lanes.d.ts +2 -4
- package/dist/commands/lanes.js +3 -23
- package/dist/commands/sync-mode.d.ts +0 -11
- package/dist/commands/sync-mode.js +0 -30
- package/dist/lib/daemon/catalog.d.ts +2 -18
- package/dist/lib/daemon/catalog.js +2 -18
- package/dist/lib/daemon/config.d.ts +0 -6
- package/dist/lib/daemon/config.js +2 -15
- package/dist/lib/daemon/requests.d.ts +0 -4
- package/dist/lib/daemon/requests.js +0 -2
- package/dist/lib/daemon/run.js +19 -78
- package/dist/lib/daemon/supervisor.d.ts +0 -8
- package/dist/lib/daemon/supervisor.js +1 -101
- package/dist/lib/doctor/checks/scaffold-cli-floor.d.ts +7 -0
- package/dist/lib/doctor/checks/scaffold-cli-floor.js +73 -0
- package/dist/lib/doctor/registry.js +2 -0
- package/dist/lib/flag-registry-worker-source.generated.d.ts +1 -1
- package/dist/lib/flag-registry-worker-source.generated.js +1 -1
- package/dist/lib/lanes/hire-grant-dispatch.d.ts +6 -1
- package/dist/lib/lanes/hire-grant-dispatch.js +78 -3
- package/dist/lib/lanes/keep-alive.d.ts +3 -2
- package/dist/lib/lanes/keep-alive.js +2 -2
- package/dist/lib/lanes/merge-command.d.ts +1 -0
- package/dist/lib/lanes/merge-command.js +299 -33
- package/dist/lib/lanes/orphans.d.ts +7 -0
- package/dist/lib/lanes/orphans.js +39 -4
- package/dist/lib/lanes/tracker-store.d.ts +2 -18
- package/dist/lib/lanes/tracker-store.js +1 -172
- package/dist/lib/scaffold-cli-floor.d.ts +9 -0
- package/dist/lib/scaffold-cli-floor.js +50 -0
- package/package.json +2 -2
- package/dist/commands/lanes-import.d.ts +0 -14
- package/dist/commands/lanes-import.js +0 -1210
- package/dist/commands/lanes-tracker.d.ts +0 -18
- package/dist/commands/lanes-tracker.js +0 -452
- package/dist/lib/daemon/sync-runner.d.ts +0 -58
- package/dist/lib/daemon/sync-runner.js +0 -277
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { LanesError } from "./errors.js";
|
|
2
2
|
import { isTerminalLaneState } from "./types.js";
|
|
3
3
|
export const DEFAULT_ORPHAN_MIN_AGE_MINUTES = 30;
|
|
4
|
+
export const DEFAULT_ORPHAN_USER_IDLE_HOURS = 72;
|
|
4
5
|
const LIVE_LANE_STATES = new Set(["running", "queued", "blocked", "awaiting_input"]);
|
|
5
6
|
export function parseOrphanMinAge(value) {
|
|
6
7
|
if (value === undefined)
|
|
@@ -14,6 +15,18 @@ export function parseOrphanMinAge(value) {
|
|
|
14
15
|
}
|
|
15
16
|
return minutes;
|
|
16
17
|
}
|
|
18
|
+
export function parseOrphanUserIdleHours(value) {
|
|
19
|
+
if (value === undefined)
|
|
20
|
+
return DEFAULT_ORPHAN_USER_IDLE_HOURS;
|
|
21
|
+
if (!/^(0|[1-9]\d*)$/.test(value)) {
|
|
22
|
+
throw new LanesError("orphan_user_idle_hours_invalid", "User-senior idle hours must be a non-negative whole number", { value });
|
|
23
|
+
}
|
|
24
|
+
const hours = Number(value);
|
|
25
|
+
if (!Number.isSafeInteger(hours) || hours > Math.floor(Number.MAX_SAFE_INTEGER / 3_600_000)) {
|
|
26
|
+
throw new LanesError("orphan_user_idle_hours_invalid", "User-senior idle hours are outside the supported range", { value });
|
|
27
|
+
}
|
|
28
|
+
return hours;
|
|
29
|
+
}
|
|
17
30
|
export function findOrphanLanes(input) {
|
|
18
31
|
const nowMs = input.now.getTime();
|
|
19
32
|
if (!Number.isFinite(nowMs)) {
|
|
@@ -21,12 +34,24 @@ export function findOrphanLanes(input) {
|
|
|
21
34
|
}
|
|
22
35
|
const byId = new Map(input.lanes.map((lane) => [lane.lane_id, lane]));
|
|
23
36
|
const minAgeMs = input.minAgeMinutes * 60_000;
|
|
37
|
+
const userIdleMs = input.userIdleHours * 3_600_000;
|
|
24
38
|
const findings = [];
|
|
25
39
|
for (const lane of input.lanes) {
|
|
40
|
+
if (!input.candidateLaneIds.has(lane.lane_id))
|
|
41
|
+
continue;
|
|
26
42
|
if (!LIVE_LANE_STATES.has(lane.state))
|
|
27
43
|
continue;
|
|
28
|
-
if (lane.keep_alive_standing === true
|
|
44
|
+
if (lane.keep_alive_standing === true)
|
|
29
45
|
continue;
|
|
46
|
+
let userLastActivity;
|
|
47
|
+
if (lane.senior.kind === "user") {
|
|
48
|
+
userLastActivity = input.lastActivityAt(lane);
|
|
49
|
+
if (!Number.isFinite(userLastActivity)) {
|
|
50
|
+
throw new LanesError("orphan_lane_timestamp_invalid", `Lane ${lane.lane_id} has an invalid last activity timestamp`, { lane_id: lane.lane_id, field: "last_activity" });
|
|
51
|
+
}
|
|
52
|
+
if (userLastActivity > nowMs || nowMs - userLastActivity < userIdleMs || input.hasOpenStory(lane))
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
30
55
|
const createdAt = Date.parse(lane.created_at);
|
|
31
56
|
if (!Number.isFinite(createdAt)) {
|
|
32
57
|
throw new LanesError("orphan_lane_timestamp_invalid", `Lane ${lane.lane_id} has an invalid created_at timestamp`, { lane_id: lane.lane_id, field: "created_at" });
|
|
@@ -38,20 +63,29 @@ export function findOrphanLanes(input) {
|
|
|
38
63
|
if (ageMs < minAgeMs)
|
|
39
64
|
continue;
|
|
40
65
|
let seniorState;
|
|
41
|
-
|
|
66
|
+
let reason;
|
|
67
|
+
if (lane.senior.kind === "user") {
|
|
68
|
+
seniorState = "user_idle";
|
|
69
|
+
reason = "user_idle";
|
|
70
|
+
}
|
|
71
|
+
else if (lane.senior.kind === "lane") {
|
|
42
72
|
const senior = byId.get(lane.senior.id ?? "");
|
|
43
73
|
if (!senior) {
|
|
44
74
|
seniorState = "missing";
|
|
75
|
+
reason = "senior_missing";
|
|
45
76
|
}
|
|
46
77
|
else if (isTerminalLaneState(senior.state)) {
|
|
47
78
|
seniorState = senior.state;
|
|
79
|
+
reason = "senior_ended";
|
|
48
80
|
}
|
|
49
81
|
}
|
|
50
82
|
else if (lane.senior.kind === "session" && lane.senior.id !== undefined) {
|
|
51
|
-
if (input.sessionState(lane.senior.id, input.now) === "ended")
|
|
83
|
+
if (input.sessionState(lane.senior.id, input.now) === "ended") {
|
|
52
84
|
seniorState = "ended";
|
|
85
|
+
reason = "senior_ended";
|
|
86
|
+
}
|
|
53
87
|
}
|
|
54
|
-
if (seniorState === undefined)
|
|
88
|
+
if (seniorState === undefined || reason === undefined)
|
|
55
89
|
continue;
|
|
56
90
|
findings.push({
|
|
57
91
|
lane_id: lane.lane_id,
|
|
@@ -60,6 +94,7 @@ export function findOrphanLanes(input) {
|
|
|
60
94
|
age_minutes: Math.floor(ageMs / 60_000),
|
|
61
95
|
account: lane.account ?? null,
|
|
62
96
|
host: { ...lane.host },
|
|
97
|
+
reason,
|
|
63
98
|
});
|
|
64
99
|
}
|
|
65
100
|
return findings.sort((a, b) => b.age_minutes - a.age_minutes || a.lane_id.localeCompare(b.lane_id));
|
|
@@ -10,25 +10,9 @@ export interface TrackerRecord {
|
|
|
10
10
|
updated_at: string;
|
|
11
11
|
[key: string]: unknown;
|
|
12
12
|
}
|
|
13
|
-
export interface
|
|
14
|
-
kind: TrackerKind;
|
|
15
|
-
id?: string;
|
|
16
|
-
company: string;
|
|
17
|
-
project_id: string;
|
|
18
|
-
[key: string]: unknown;
|
|
19
|
-
}
|
|
20
|
-
export type StoreValue<T> = T | Promise<T>;
|
|
21
|
-
export interface TrackerStore {
|
|
22
|
-
read(kind: TrackerKind, id: string): StoreValue<TrackerRecord | null>;
|
|
23
|
-
list(kind: TrackerKind): StoreValue<TrackerRecord[]>;
|
|
24
|
-
create(record: TrackerRecordInput): StoreValue<TrackerRecord>;
|
|
25
|
-
update(kind: TrackerKind, id: string, expectedVersion: number, change: (current: TrackerRecord) => TrackerRecord): StoreValue<TrackerRecord>;
|
|
26
|
-
}
|
|
27
|
-
export interface LocalTrackerStore extends TrackerStore {
|
|
13
|
+
export interface LocalTrackerStore {
|
|
28
14
|
read(kind: TrackerKind, id: string): TrackerRecord | null;
|
|
29
15
|
list(kind: TrackerKind): TrackerRecord[];
|
|
30
|
-
create(record: TrackerRecordInput): TrackerRecord;
|
|
31
|
-
update(kind: TrackerKind, id: string, expectedVersion: number, change: (current: TrackerRecord) => TrackerRecord): TrackerRecord;
|
|
32
16
|
}
|
|
33
|
-
export declare function createLocalTrackerStore(projectDirectory: string
|
|
17
|
+
export declare function createLocalTrackerStore(projectDirectory: string): LocalTrackerStore;
|
|
34
18
|
//# sourceMappingURL=tracker-store.d.ts.map
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
-
import { randomUUID } from "node:crypto";
|
|
4
3
|
import { LanesError } from "./errors.js";
|
|
5
4
|
const KIND_SET = new Set(["blocker", "kpi", "okr", "directive"]);
|
|
6
5
|
const ID_RE = /^[a-zA-Z0-9][a-zA-Z0-9._-]{0,127}$/;
|
|
@@ -18,25 +17,6 @@ function recordPath(root, kind, id) {
|
|
|
18
17
|
throw storeError("tracker_kind_invalid", "Unknown tracker record kind", { kind });
|
|
19
18
|
return path.join(root, kind, `${id}.json`);
|
|
20
19
|
}
|
|
21
|
-
function assertRealDirectory(directory) {
|
|
22
|
-
try {
|
|
23
|
-
const stat = fs.lstatSync(directory);
|
|
24
|
-
if (!stat.isDirectory() || stat.isSymbolicLink()) {
|
|
25
|
-
throw storeError("tracker_store_path_invalid", "Tracker storage path must be a real directory", { path: directory });
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
catch (err) {
|
|
29
|
-
if (err.code !== "ENOENT")
|
|
30
|
-
throw err;
|
|
31
|
-
fs.mkdirSync(directory, { mode: 0o700 });
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
function ensureKindDirectory(root, kind) {
|
|
35
|
-
assertRealDirectory(root);
|
|
36
|
-
const directory = path.join(root, kind);
|
|
37
|
-
assertRealDirectory(directory);
|
|
38
|
-
return directory;
|
|
39
|
-
}
|
|
40
20
|
function existingKindDirectory(root, kind) {
|
|
41
21
|
try {
|
|
42
22
|
const rootStat = fs.lstatSync(root);
|
|
@@ -86,105 +66,7 @@ function parseRecord(text, expectedKind, id, file) {
|
|
|
86
66
|
}
|
|
87
67
|
return record;
|
|
88
68
|
}
|
|
89
|
-
function
|
|
90
|
-
const dir = path.dirname(file);
|
|
91
|
-
const temp = path.join(dir, `.${path.basename(file)}.${randomUUID()}.tmp`);
|
|
92
|
-
try {
|
|
93
|
-
fs.writeFileSync(temp, contents, { encoding: "utf8", flag: "wx", mode: 0o600 });
|
|
94
|
-
// link is an atomic create-if-absent operation; rename would overwrite a
|
|
95
|
-
// concurrent creator's record if a generated id ever collided.
|
|
96
|
-
fs.linkSync(temp, file);
|
|
97
|
-
}
|
|
98
|
-
catch (err) {
|
|
99
|
-
if (err.code === "EEXIST") {
|
|
100
|
-
throw storeError("tracker_record_exists", "Tracker record id already exists", { path: file });
|
|
101
|
-
}
|
|
102
|
-
throw err;
|
|
103
|
-
}
|
|
104
|
-
finally {
|
|
105
|
-
removeTempFile(temp);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
function removeTempFile(file) {
|
|
109
|
-
try {
|
|
110
|
-
fs.unlinkSync(file);
|
|
111
|
-
}
|
|
112
|
-
catch (err) {
|
|
113
|
-
if (err.code !== "ENOENT")
|
|
114
|
-
throw err;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
function withRecordLock(file, action) {
|
|
118
|
-
const lock = `${file}.lock`;
|
|
119
|
-
let fd;
|
|
120
|
-
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
121
|
-
try {
|
|
122
|
-
fd = fs.openSync(lock, "wx", 0o600);
|
|
123
|
-
fs.writeSync(fd, `${process.pid}\n`);
|
|
124
|
-
break;
|
|
125
|
-
}
|
|
126
|
-
catch (err) {
|
|
127
|
-
if (err.code !== "EEXIST")
|
|
128
|
-
throw err;
|
|
129
|
-
// Recover a lock only when it is old and its owner is gone. Rechecking
|
|
130
|
-
// inode and mtime before unlinking avoids deleting a freshly replaced lock.
|
|
131
|
-
let first;
|
|
132
|
-
try {
|
|
133
|
-
first = fs.lstatSync(lock);
|
|
134
|
-
}
|
|
135
|
-
catch (statError) {
|
|
136
|
-
if (statError.code === "ENOENT")
|
|
137
|
-
continue;
|
|
138
|
-
throw statError;
|
|
139
|
-
}
|
|
140
|
-
if (Date.now() - first.mtimeMs < 5 * 60_000) {
|
|
141
|
-
throw storeError("tracker_write_busy", "Tracker record is being updated; retry the command", { path: file });
|
|
142
|
-
}
|
|
143
|
-
let owner = null;
|
|
144
|
-
try {
|
|
145
|
-
const raw = fs.readFileSync(lock, "utf8").trim();
|
|
146
|
-
const parsed = Number(raw);
|
|
147
|
-
if (Number.isSafeInteger(parsed) && parsed > 0)
|
|
148
|
-
owner = parsed;
|
|
149
|
-
}
|
|
150
|
-
catch (readError) {
|
|
151
|
-
if (readError.code !== "ENOENT")
|
|
152
|
-
throw readError;
|
|
153
|
-
}
|
|
154
|
-
if (owner !== null) {
|
|
155
|
-
try {
|
|
156
|
-
process.kill(owner, 0);
|
|
157
|
-
throw storeError("tracker_write_busy", "Tracker record is being updated; retry the command", { path: file });
|
|
158
|
-
}
|
|
159
|
-
catch (probeError) {
|
|
160
|
-
if (probeError instanceof LanesError)
|
|
161
|
-
throw probeError;
|
|
162
|
-
if (probeError.code !== "ESRCH")
|
|
163
|
-
throw probeError;
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
try {
|
|
167
|
-
const second = fs.lstatSync(lock);
|
|
168
|
-
if (second.ino === first.ino && second.dev === first.dev && second.mtimeMs === first.mtimeMs)
|
|
169
|
-
fs.unlinkSync(lock);
|
|
170
|
-
}
|
|
171
|
-
catch (unlinkError) {
|
|
172
|
-
if (unlinkError.code !== "ENOENT")
|
|
173
|
-
throw unlinkError;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
if (fd === undefined)
|
|
178
|
-
throw storeError("tracker_write_busy", "Tracker record is being updated; retry the command", { path: file });
|
|
179
|
-
try {
|
|
180
|
-
return action();
|
|
181
|
-
}
|
|
182
|
-
finally {
|
|
183
|
-
fs.closeSync(fd);
|
|
184
|
-
fs.unlinkSync(lock);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
export function createLocalTrackerStore(projectDirectory, now = () => new Date()) {
|
|
69
|
+
export function createLocalTrackerStore(projectDirectory) {
|
|
188
70
|
const root = path.join(projectDirectory, "tracker");
|
|
189
71
|
const read = (kind, id) => {
|
|
190
72
|
const file = recordPath(root, kind, id);
|
|
@@ -219,59 +101,6 @@ export function createLocalTrackerStore(projectDirectory, now = () => new Date()
|
|
|
219
101
|
.filter((record) => record !== null)
|
|
220
102
|
.sort((a, b) => b.updated_at.localeCompare(a.updated_at) || a.id.localeCompare(b.id));
|
|
221
103
|
},
|
|
222
|
-
create(input) {
|
|
223
|
-
const kind = input.kind;
|
|
224
|
-
const directory = ensureKindDirectory(root, kind);
|
|
225
|
-
const id = typeof input.id === "string" && input.id ? input.id : randomUUID();
|
|
226
|
-
const time = now().toISOString();
|
|
227
|
-
const record = {
|
|
228
|
-
...input,
|
|
229
|
-
schema_version: "hq-lanes-tracker-record.v1",
|
|
230
|
-
kind,
|
|
231
|
-
id,
|
|
232
|
-
company: input.company,
|
|
233
|
-
project_id: input.project_id,
|
|
234
|
-
version: 1,
|
|
235
|
-
created_at: time,
|
|
236
|
-
updated_at: time,
|
|
237
|
-
};
|
|
238
|
-
writeExclusive(path.join(directory, `${id}.json`), `${JSON.stringify(record, null, 2)}\n`);
|
|
239
|
-
return record;
|
|
240
|
-
},
|
|
241
|
-
update(kind, id, expectedVersion, change) {
|
|
242
|
-
const file = recordPath(root, kind, id);
|
|
243
|
-
const directory = ensureKindDirectory(root, kind);
|
|
244
|
-
return withRecordLock(file, () => {
|
|
245
|
-
const current = read(kind, id);
|
|
246
|
-
if (!current)
|
|
247
|
-
throw storeError("tracker_record_not_found", `Tracker ${kind} record ${id} was not found`, { kind, id });
|
|
248
|
-
if (current.version !== expectedVersion) {
|
|
249
|
-
throw storeError("tracker_version_conflict", `Tracker record version conflict: expected ${expectedVersion}, found ${current.version}`, {
|
|
250
|
-
kind, id, expected: expectedVersion, actual: current.version,
|
|
251
|
-
});
|
|
252
|
-
}
|
|
253
|
-
const changed = change(current);
|
|
254
|
-
if (changed.id !== current.id || changed.kind !== current.kind || changed.company !== current.company || changed.project_id !== current.project_id || changed.created_at !== current.created_at) {
|
|
255
|
-
throw storeError("tracker_update_invalid", "Tracker update cannot change record identity", { kind, id });
|
|
256
|
-
}
|
|
257
|
-
const next = {
|
|
258
|
-
...changed,
|
|
259
|
-
schema_version: "hq-lanes-tracker-record.v1",
|
|
260
|
-
version: current.version + 1,
|
|
261
|
-
created_at: current.created_at,
|
|
262
|
-
updated_at: now().toISOString(),
|
|
263
|
-
};
|
|
264
|
-
const temp = path.join(directory, `.${id}.${randomUUID()}.tmp`);
|
|
265
|
-
try {
|
|
266
|
-
fs.writeFileSync(temp, `${JSON.stringify(next, null, 2)}\n`, { encoding: "utf8", flag: "wx", mode: 0o600 });
|
|
267
|
-
fs.renameSync(temp, file);
|
|
268
|
-
}
|
|
269
|
-
finally {
|
|
270
|
-
removeTempFile(temp);
|
|
271
|
-
}
|
|
272
|
-
return next;
|
|
273
|
-
});
|
|
274
|
-
},
|
|
275
104
|
};
|
|
276
105
|
}
|
|
277
106
|
//# sourceMappingURL=tracker-store.js.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const SCAFFOLD_CLI_UPGRADE_COMMAND = "npm install -g @indigoai-us/hq-cli@latest";
|
|
2
|
+
export type ScaffoldCliFloorComparison = {
|
|
3
|
+
status: "pass" | "fail" | "warn" | "skip";
|
|
4
|
+
message: string;
|
|
5
|
+
remediation?: string;
|
|
6
|
+
};
|
|
7
|
+
/** Compare an installed CLI version with the scaffold's supported floor. */
|
|
8
|
+
export declare function compareScaffoldCliFloor(required: unknown, currentVersion: string): ScaffoldCliFloorComparison;
|
|
9
|
+
//# sourceMappingURL=scaffold-cli-floor.d.ts.map
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import semver from "semver";
|
|
2
|
+
export const SCAFFOLD_CLI_UPGRADE_COMMAND = "npm install -g @indigoai-us/hq-cli@latest";
|
|
3
|
+
const MINIMUM_VERSION_RANGE = /^>=(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/;
|
|
4
|
+
/** Compare an installed CLI version with the scaffold's supported floor. */
|
|
5
|
+
export function compareScaffoldCliFloor(required, currentVersion) {
|
|
6
|
+
if (required === undefined) {
|
|
7
|
+
return {
|
|
8
|
+
status: "skip",
|
|
9
|
+
message: "No requiresHqCli floor is declared.",
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
const renderedRequired = renderValue(required);
|
|
13
|
+
if (typeof required !== "string" ||
|
|
14
|
+
!MINIMUM_VERSION_RANGE.test(required) ||
|
|
15
|
+
!semver.validRange(required)) {
|
|
16
|
+
return {
|
|
17
|
+
status: "warn",
|
|
18
|
+
message: `requiresHqCli has unsupported value ${renderedRequired}; expected a range in the form \">=X.Y.Z\".`,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
if (!semver.valid(currentVersion)) {
|
|
22
|
+
return {
|
|
23
|
+
status: "warn",
|
|
24
|
+
message: `The running hq-cli version ${renderValue(currentVersion)} is not valid SemVer, so the scaffold CLI floor could not be checked.`,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
if (semver.satisfies(currentVersion, required, { includePrerelease: true })) {
|
|
28
|
+
return {
|
|
29
|
+
status: "pass",
|
|
30
|
+
message: `hq-cli ${currentVersion} satisfies the scaffold requirement ${required}.`,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
const minimum = required.slice(2);
|
|
34
|
+
return {
|
|
35
|
+
status: "fail",
|
|
36
|
+
message: `This scaffold requires hq-cli >= ${minimum} (found ${currentVersion}).`,
|
|
37
|
+
remediation: SCAFFOLD_CLI_UPGRADE_COMMAND,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function renderValue(value) {
|
|
41
|
+
if (typeof value === "string")
|
|
42
|
+
return JSON.stringify(value);
|
|
43
|
+
try {
|
|
44
|
+
return JSON.stringify(value) ?? String(value);
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return String(value);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=scaffold-cli-floor.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@indigoai-us/hq-cli",
|
|
3
|
-
"version": "5.273.0
|
|
3
|
+
"version": "5.273.0",
|
|
4
4
|
"description": "HQ by Indigo management CLI — modules and cloud sync",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"@aws-sdk/client-iot-data-plane": "^3.1096.0",
|
|
46
46
|
"@aws-sdk/client-s3": "^3.1049.0",
|
|
47
|
-
"@indigoai-us/hq-cloud": "~6.18.
|
|
47
|
+
"@indigoai-us/hq-cloud": "~6.18.10",
|
|
48
48
|
"@indigoai-us/hq-flags-client": "^0.1.2",
|
|
49
49
|
"@sentry/node": "^10.49.0",
|
|
50
50
|
"@tobilu/qmd": "2.5.3",
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { Command } from "commander";
|
|
2
|
-
import { type TrackerStore } from "../lib/lanes/tracker-store.js";
|
|
3
|
-
import type { LaneCompanyRef } from "../lib/lanes/types.js";
|
|
4
|
-
type WrapHandler = <Args extends unknown[]>(action: (...args: Args) => Promise<void>) => (...args: Args) => Promise<void>;
|
|
5
|
-
export interface LaneTrackerImportDeps {
|
|
6
|
-
hqRoot: () => string;
|
|
7
|
-
resolveCompany: (company?: string) => Promise<LaneCompanyRef>;
|
|
8
|
-
trackerEnabled: (company: LaneCompanyRef) => boolean | Promise<boolean>;
|
|
9
|
-
now: () => Date;
|
|
10
|
-
store?: (projectDirectory: string) => TrackerStore;
|
|
11
|
-
}
|
|
12
|
-
export declare function registerLaneTrackerImportCommand(parent: Command, deps: LaneTrackerImportDeps, wrap: WrapHandler): void;
|
|
13
|
-
export {};
|
|
14
|
-
//# sourceMappingURL=lanes-import.d.ts.map
|