@haus-tech/haus-workflow 0.27.1 → 0.28.1
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 +9 -0
- package/dist/cli.js +141 -85
- package/library/catalog/manifest.json +943 -40
- package/library/catalog/validation-rules.json +0 -1
- package/library/global/commands/haus-cloneandsetup.md +39 -2
- package/package.json +4 -4
- package/dist/cli.d.ts +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.28.1](https://github.com/WeAreHausTech/haus-workflow/compare/v0.28.0...v0.28.1) (2026-06-17)
|
|
4
|
+
|
|
5
|
+
## [0.28.0](https://github.com/WeAreHausTech/haus-workflow/compare/v0.27.1...v0.28.0) (2026-06-17)
|
|
6
|
+
|
|
7
|
+
### Features
|
|
8
|
+
|
|
9
|
+
- catalog compatibility for curated provenance and deprecations ([#121](https://github.com/WeAreHausTech/haus-workflow/issues/121)) ([1a8a790](https://github.com/WeAreHausTech/haus-workflow/commit/1a8a7902bf7c27462e905d01dfa4d0baac319b57))
|
|
10
|
+
- **cloneandsetup:** add up-front data-access preflight + seed access/empty-ok ([#120](https://github.com/WeAreHausTech/haus-workflow/issues/120)) ([70e32ad](https://github.com/WeAreHausTech/haus-workflow/commit/70e32adba2f5ed25ade170a09d1f0cfb2bd198d7))
|
|
11
|
+
|
|
3
12
|
## [0.27.1](https://github.com/WeAreHausTech/haus-workflow/compare/v0.27.0...v0.27.1) (2026-06-16)
|
|
4
13
|
|
|
5
14
|
### Bug Fixes
|
package/dist/cli.js
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
|
-
import { readFileSync as readFileSync4 } from "fs";
|
|
5
|
-
import path35 from "path";
|
|
4
|
+
import { readFileSync as readFileSync4 } from "node:fs";
|
|
5
|
+
import path35 from "node:path";
|
|
6
6
|
import { Command } from "commander";
|
|
7
7
|
|
|
8
8
|
// src/commands/apply.ts
|
|
9
|
-
import path13 from "path";
|
|
9
|
+
import path13 from "node:path";
|
|
10
10
|
import checkbox from "@inquirer/checkbox";
|
|
11
11
|
|
|
12
12
|
// src/catalog/remote-catalog.ts
|
|
13
|
-
import os from "os";
|
|
14
|
-
import path2 from "path";
|
|
13
|
+
import os from "node:os";
|
|
14
|
+
import path2 from "node:path";
|
|
15
15
|
import fs2 from "fs-extra";
|
|
16
16
|
|
|
17
17
|
// src/utils/fs.ts
|
|
18
|
-
import crypto from "crypto";
|
|
19
|
-
import path from "path";
|
|
18
|
+
import crypto from "node:crypto";
|
|
19
|
+
import path from "node:path";
|
|
20
20
|
import fg from "fast-glob";
|
|
21
21
|
import fs from "fs-extra";
|
|
22
22
|
var MalformedJsonFileError = class extends Error {
|
|
@@ -200,7 +200,6 @@ var validation_rules_default = {
|
|
|
200
200
|
"scss-modules",
|
|
201
201
|
"vue",
|
|
202
202
|
"expressjs",
|
|
203
|
-
"soup-base",
|
|
204
203
|
"laravel",
|
|
205
204
|
"laravel-nova",
|
|
206
205
|
"wordpress",
|
|
@@ -372,14 +371,71 @@ function validateCatalogItem(item, content2) {
|
|
|
372
371
|
return { ok: true };
|
|
373
372
|
}
|
|
374
373
|
|
|
375
|
-
// src/catalog/manifest-
|
|
376
|
-
var
|
|
374
|
+
// src/catalog/manifest-item-fields.ts
|
|
375
|
+
var USE_MODES = /* @__PURE__ */ new Set(["copy", "adapted", "wrapped", "rewritten", "reference-only"]);
|
|
376
|
+
var LICENSE_CONFIDENCES = /* @__PURE__ */ new Set(["high", "medium", "low", "unknown"]);
|
|
377
|
+
var REVIEW_STATUSES = /* @__PURE__ */ new Set([
|
|
378
|
+
"approved",
|
|
379
|
+
"candidate",
|
|
380
|
+
"needs-review",
|
|
381
|
+
"rejected",
|
|
382
|
+
"deprecated"
|
|
383
|
+
]);
|
|
384
|
+
var RISK_LEVELS = /* @__PURE__ */ new Set(["low", "medium", "high", "blocked"]);
|
|
377
385
|
function isNonEmptyString(value) {
|
|
378
386
|
return typeof value === "string" && value.length > 0;
|
|
379
387
|
}
|
|
380
388
|
function isStringArray(value) {
|
|
381
389
|
return Array.isArray(value) && value.every((entry) => typeof entry === "string");
|
|
382
390
|
}
|
|
391
|
+
function validateReferences(itemId, references) {
|
|
392
|
+
if (references === void 0) return null;
|
|
393
|
+
if (!isStringArray(references)) return `${itemId}: references must be a string array`;
|
|
394
|
+
for (const ref of references) {
|
|
395
|
+
if (/^https?:\/\//i.test(ref)) {
|
|
396
|
+
if (!/^https:\/\//i.test(ref)) {
|
|
397
|
+
return `${itemId}: reference must be https:// URL: ${ref}`;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
return null;
|
|
402
|
+
}
|
|
403
|
+
function validateCuratedProvenance(item) {
|
|
404
|
+
if (item.source !== "curated") return null;
|
|
405
|
+
if (!isNonEmptyString(item.reviewStatus)) {
|
|
406
|
+
return `${item.id}: curated item missing reviewStatus`;
|
|
407
|
+
}
|
|
408
|
+
if (!REVIEW_STATUSES.has(item.reviewStatus)) {
|
|
409
|
+
return `${item.id}: invalid reviewStatus "${item.reviewStatus}"`;
|
|
410
|
+
}
|
|
411
|
+
if (!isNonEmptyString(item.riskLevel)) {
|
|
412
|
+
return `${item.id}: curated item missing riskLevel`;
|
|
413
|
+
}
|
|
414
|
+
if (!RISK_LEVELS.has(item.riskLevel)) {
|
|
415
|
+
return `${item.id}: invalid riskLevel "${item.riskLevel}"`;
|
|
416
|
+
}
|
|
417
|
+
if (item.useMode !== void 0 && !USE_MODES.has(String(item.useMode))) {
|
|
418
|
+
return `${item.id}: invalid useMode "${item.useMode}"`;
|
|
419
|
+
}
|
|
420
|
+
if (item.licenseConfidence !== void 0 && !LICENSE_CONFIDENCES.has(String(item.licenseConfidence))) {
|
|
421
|
+
return `${item.id}: invalid licenseConfidence "${item.licenseConfidence}"`;
|
|
422
|
+
}
|
|
423
|
+
if (item.originUrl !== void 0) {
|
|
424
|
+
if (typeof item.originUrl !== "string" || !item.originUrl.startsWith("https://")) {
|
|
425
|
+
return `${item.id}: originUrl must be an https:// URL`;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
return null;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
// src/catalog/manifest-schema.ts
|
|
432
|
+
var POLLUTION_KEYS = /* @__PURE__ */ new Set(["__proto__", "prototype", "constructor"]);
|
|
433
|
+
function isNonEmptyString2(value) {
|
|
434
|
+
return typeof value === "string" && value.length > 0;
|
|
435
|
+
}
|
|
436
|
+
function isStringArray2(value) {
|
|
437
|
+
return Array.isArray(value) && value.every((entry) => typeof entry === "string");
|
|
438
|
+
}
|
|
383
439
|
var REQUIRES_ANY_KEYS = ["stack", "dependency", "packageNamePattern", "role"];
|
|
384
440
|
function isRequiresAnyClause(value) {
|
|
385
441
|
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
@@ -409,7 +465,7 @@ function parseManifest(json) {
|
|
|
409
465
|
return { ok: false, error: "manifest must be an object" };
|
|
410
466
|
}
|
|
411
467
|
const root = data;
|
|
412
|
-
if (!
|
|
468
|
+
if (!isNonEmptyString2(root.version)) {
|
|
413
469
|
return { ok: false, error: "missing version" };
|
|
414
470
|
}
|
|
415
471
|
if (!Array.isArray(root.items)) {
|
|
@@ -424,13 +480,13 @@ function parseManifest(json) {
|
|
|
424
480
|
return { ok: false, error: `item[${i}]: invalid entry` };
|
|
425
481
|
}
|
|
426
482
|
const item = raw;
|
|
427
|
-
if (!
|
|
483
|
+
if (!isNonEmptyString2(item.id)) {
|
|
428
484
|
return { ok: false, error: `item[${i}]: missing id` };
|
|
429
485
|
}
|
|
430
|
-
if (!
|
|
486
|
+
if (!isNonEmptyString2(item.type)) {
|
|
431
487
|
return { ok: false, error: `${item.id}: missing type` };
|
|
432
488
|
}
|
|
433
|
-
if (!
|
|
489
|
+
if (!isNonEmptyString2(item.path)) {
|
|
434
490
|
return { ok: false, error: `${item.id}: missing path` };
|
|
435
491
|
}
|
|
436
492
|
if (seenIds.has(item.id)) {
|
|
@@ -442,18 +498,14 @@ function parseManifest(json) {
|
|
|
442
498
|
return { ok: false, error: `${item.id}: duplicate path "${normPath}"` };
|
|
443
499
|
}
|
|
444
500
|
seenPaths.add(normPath);
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
return { ok: false, error: `${item.id}: curated item missing riskLevel` };
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
if (!isStringArray(item.tags)) {
|
|
501
|
+
const provenanceError = validateCuratedProvenance(item);
|
|
502
|
+
if (provenanceError) return { ok: false, error: provenanceError };
|
|
503
|
+
const referencesError = validateReferences(String(item.id), item.references);
|
|
504
|
+
if (referencesError) return { ok: false, error: referencesError };
|
|
505
|
+
if (!isStringArray2(item.tags)) {
|
|
454
506
|
return { ok: false, error: `${item.id}: tags must be a string array` };
|
|
455
507
|
}
|
|
456
|
-
if (!
|
|
508
|
+
if (!isStringArray2(item.repoRoles)) {
|
|
457
509
|
return { ok: false, error: `${item.id}: repoRoles must be a string array` };
|
|
458
510
|
}
|
|
459
511
|
if (item.requiresAny !== void 0 && !isRequiresAnyArray(item.requiresAny)) {
|
|
@@ -924,17 +976,17 @@ async function getCacheManifestAge() {
|
|
|
924
976
|
}
|
|
925
977
|
|
|
926
978
|
// src/claude/write-claude-files.ts
|
|
927
|
-
import path12 from "path";
|
|
979
|
+
import path12 from "node:path";
|
|
928
980
|
import fs12 from "fs-extra";
|
|
929
981
|
|
|
930
982
|
// src/catalog/load-catalog.ts
|
|
931
|
-
import path4 from "path";
|
|
983
|
+
import path4 from "node:path";
|
|
932
984
|
|
|
933
985
|
// src/utils/paths.ts
|
|
934
|
-
import { existsSync, readFileSync } from "fs";
|
|
935
|
-
import os2 from "os";
|
|
936
|
-
import path3 from "path";
|
|
937
|
-
import { fileURLToPath } from "url";
|
|
986
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
987
|
+
import os2 from "node:os";
|
|
988
|
+
import path3 from "node:path";
|
|
989
|
+
import { fileURLToPath } from "node:url";
|
|
938
990
|
var HAUS_DIR = ".haus-workflow";
|
|
939
991
|
function hausPath(root, ...parts) {
|
|
940
992
|
return path3.join(root, HAUS_DIR, ...parts);
|
|
@@ -1019,7 +1071,7 @@ function catalogItemContentPath(contentRoot, item) {
|
|
|
1019
1071
|
}
|
|
1020
1072
|
|
|
1021
1073
|
// src/update/hash-installed.ts
|
|
1022
|
-
import path5 from "path";
|
|
1074
|
+
import path5 from "node:path";
|
|
1023
1075
|
import fg2 from "fast-glob";
|
|
1024
1076
|
import fs3 from "fs-extra";
|
|
1025
1077
|
|
|
@@ -1150,12 +1202,12 @@ function buildAllowRules() {
|
|
|
1150
1202
|
}
|
|
1151
1203
|
|
|
1152
1204
|
// src/install/settings-merge.ts
|
|
1153
|
-
import path7 from "path";
|
|
1205
|
+
import path7 from "node:path";
|
|
1154
1206
|
import fs5 from "fs-extra";
|
|
1155
1207
|
|
|
1156
1208
|
// src/install/manifest.ts
|
|
1157
|
-
import os3 from "os";
|
|
1158
|
-
import path6 from "path";
|
|
1209
|
+
import os3 from "node:os";
|
|
1210
|
+
import path6 from "node:path";
|
|
1159
1211
|
var MANIFEST_SCHEMA = "haus-install-manifest/1";
|
|
1160
1212
|
function globalClaudeDir() {
|
|
1161
1213
|
return path6.join(os3.homedir(), ".claude");
|
|
@@ -1593,7 +1645,7 @@ async function applyProjectSettingsMerge(root) {
|
|
|
1593
1645
|
}
|
|
1594
1646
|
|
|
1595
1647
|
// src/claude/superpowers-install.ts
|
|
1596
|
-
import path8 from "path";
|
|
1648
|
+
import path8 from "node:path";
|
|
1597
1649
|
import fg3 from "fast-glob";
|
|
1598
1650
|
import fs6 from "fs-extra";
|
|
1599
1651
|
var SUPERPOWERS_ORIGIN_SOURCE_ID = "superpowers-pcvelz";
|
|
@@ -1733,7 +1785,7 @@ async function verifyProjectSettingsHooksContract(root) {
|
|
|
1733
1785
|
}
|
|
1734
1786
|
|
|
1735
1787
|
// src/claude/write-root-claude-md.ts
|
|
1736
|
-
import path9 from "path";
|
|
1788
|
+
import path9 from "node:path";
|
|
1737
1789
|
import fs8 from "fs-extra";
|
|
1738
1790
|
var BLOCK_BEGIN = "<!-- HAUS:BEGIN haus-imports v=1 -->";
|
|
1739
1791
|
var BLOCK_END = "<!-- HAUS:END haus-imports -->";
|
|
@@ -1808,11 +1860,11 @@ async function writeRootClaudeMd(root, dryRun) {
|
|
|
1808
1860
|
}
|
|
1809
1861
|
|
|
1810
1862
|
// src/claude/write-workflow-config.ts
|
|
1811
|
-
import path11 from "path";
|
|
1863
|
+
import path11 from "node:path";
|
|
1812
1864
|
import fs10 from "fs-extra";
|
|
1813
1865
|
|
|
1814
1866
|
// src/claude/derive-workflow-config.ts
|
|
1815
|
-
import path10 from "path";
|
|
1867
|
+
import path10 from "node:path";
|
|
1816
1868
|
import fs9 from "fs-extra";
|
|
1817
1869
|
function binCmd(pm, bin, args) {
|
|
1818
1870
|
const tail = args ? ` ${args}` : "";
|
|
@@ -2131,6 +2183,10 @@ async function writeClaudeFiles(root, dryRun, selectedIds, opts = {}) {
|
|
|
2131
2183
|
for (const item of catalogItems) {
|
|
2132
2184
|
const manifestItem = manifestById.get(item.id);
|
|
2133
2185
|
if (!manifestItem?.path) continue;
|
|
2186
|
+
if (manifestItem.reviewStatus === "deprecated") {
|
|
2187
|
+
warn(`Skipping ${item.id}: reviewStatus is deprecated`);
|
|
2188
|
+
continue;
|
|
2189
|
+
}
|
|
2134
2190
|
if (manifestItem.source === "curated") {
|
|
2135
2191
|
if (manifestItem.reviewStatus !== "approved") {
|
|
2136
2192
|
curatedReviewStatusSkips++;
|
|
@@ -2363,8 +2419,8 @@ async function runCatalogAudit() {
|
|
|
2363
2419
|
}
|
|
2364
2420
|
|
|
2365
2421
|
// src/commands/clone.ts
|
|
2366
|
-
import { existsSync as existsSync2 } from "fs";
|
|
2367
|
-
import path14 from "path";
|
|
2422
|
+
import { existsSync as existsSync2 } from "node:fs";
|
|
2423
|
+
import path14 from "node:path";
|
|
2368
2424
|
|
|
2369
2425
|
// src/utils/exec.ts
|
|
2370
2426
|
import { execa } from "execa";
|
|
@@ -2436,11 +2492,11 @@ async function runClone(url, opts = {}) {
|
|
|
2436
2492
|
}
|
|
2437
2493
|
|
|
2438
2494
|
// src/commands/doctor.ts
|
|
2439
|
-
import path19 from "path";
|
|
2495
|
+
import path19 from "node:path";
|
|
2440
2496
|
import fs14 from "fs-extra";
|
|
2441
2497
|
|
|
2442
2498
|
// src/scanner/scan-project.ts
|
|
2443
|
-
import path18 from "path";
|
|
2499
|
+
import path18 from "node:path";
|
|
2444
2500
|
|
|
2445
2501
|
// src/utils/audit-checks.ts
|
|
2446
2502
|
function isRecord(v) {
|
|
@@ -2467,7 +2523,7 @@ function compareVersions(a, b) {
|
|
|
2467
2523
|
}
|
|
2468
2524
|
|
|
2469
2525
|
// src/scanner/detect-package-manager.ts
|
|
2470
|
-
import path15 from "path";
|
|
2526
|
+
import path15 from "node:path";
|
|
2471
2527
|
import fs13 from "fs-extra";
|
|
2472
2528
|
function detectPackageManager(root, packageManagerField) {
|
|
2473
2529
|
const field = String(packageManagerField ?? "").trim();
|
|
@@ -2690,7 +2746,7 @@ function runDetection(ctx, rules = STACK_RULES) {
|
|
|
2690
2746
|
}
|
|
2691
2747
|
|
|
2692
2748
|
// src/scanner/detection.ts
|
|
2693
|
-
import path16 from "path";
|
|
2749
|
+
import path16 from "node:path";
|
|
2694
2750
|
var UNSUPPORTED_MARKERS = {
|
|
2695
2751
|
"requirements.txt": "python",
|
|
2696
2752
|
"pyproject.toml": "python",
|
|
@@ -2750,8 +2806,8 @@ function collectUnsupportedSignals(files) {
|
|
|
2750
2806
|
}
|
|
2751
2807
|
|
|
2752
2808
|
// src/scanner/render.ts
|
|
2753
|
-
import { readFile } from "fs/promises";
|
|
2754
|
-
import path17 from "path";
|
|
2809
|
+
import { readFile } from "node:fs/promises";
|
|
2810
|
+
import path17 from "node:path";
|
|
2755
2811
|
async function buildContentBlob(root, files) {
|
|
2756
2812
|
const candidates = files.filter(
|
|
2757
2813
|
(f) => f.endsWith(".ts") || f.endsWith(".js") || f.endsWith(".php") || f.endsWith(".json") || f.endsWith(".yml") || f.endsWith(".yaml")
|
|
@@ -3254,7 +3310,7 @@ async function runExplainRecommendation(options) {
|
|
|
3254
3310
|
}
|
|
3255
3311
|
|
|
3256
3312
|
// src/commands/guard.ts
|
|
3257
|
-
import { readFileSync as readFileSync2 } from "fs";
|
|
3313
|
+
import { readFileSync as readFileSync2 } from "node:fs";
|
|
3258
3314
|
|
|
3259
3315
|
// src/security/guard-bash.ts
|
|
3260
3316
|
function matchesDenyToken(command, denyPhrase) {
|
|
@@ -3324,12 +3380,12 @@ async function runGuard(kind, _options) {
|
|
|
3324
3380
|
}
|
|
3325
3381
|
|
|
3326
3382
|
// src/commands/init.ts
|
|
3327
|
-
import path20 from "path";
|
|
3383
|
+
import path20 from "node:path";
|
|
3328
3384
|
import fs15 from "fs-extra";
|
|
3329
3385
|
|
|
3330
3386
|
// src/utils/prompts.ts
|
|
3331
|
-
import { stdin as input, stdout as output } from "process";
|
|
3332
|
-
import readline from "readline/promises";
|
|
3387
|
+
import { stdin as input, stdout as output } from "node:process";
|
|
3388
|
+
import readline from "node:readline/promises";
|
|
3333
3389
|
async function ask(question) {
|
|
3334
3390
|
const rl = readline.createInterface({ input, output });
|
|
3335
3391
|
try {
|
|
@@ -3446,6 +3502,10 @@ async function recommend(root, context) {
|
|
|
3446
3502
|
skip(item.id, "unsupported-policy", "Unsupported stack policy");
|
|
3447
3503
|
continue;
|
|
3448
3504
|
}
|
|
3505
|
+
if (item.reviewStatus === "deprecated") {
|
|
3506
|
+
skip(item.id, "deprecated", "Catalog item is deprecated", "reviewStatus:deprecated");
|
|
3507
|
+
continue;
|
|
3508
|
+
}
|
|
3449
3509
|
if (item.source === "curated") {
|
|
3450
3510
|
const rs = item.reviewStatus;
|
|
3451
3511
|
if (!rs || rs !== "approved") {
|
|
@@ -3684,8 +3744,8 @@ async function runInit(options) {
|
|
|
3684
3744
|
}
|
|
3685
3745
|
|
|
3686
3746
|
// src/install/apply.ts
|
|
3687
|
-
import crypto2 from "crypto";
|
|
3688
|
-
import path21 from "path";
|
|
3747
|
+
import crypto2 from "node:crypto";
|
|
3748
|
+
import path21 from "node:path";
|
|
3689
3749
|
import fs16 from "fs-extra";
|
|
3690
3750
|
|
|
3691
3751
|
// src/install/header.ts
|
|
@@ -4076,7 +4136,7 @@ async function runScan(options) {
|
|
|
4076
4136
|
}
|
|
4077
4137
|
|
|
4078
4138
|
// src/commands/undo.ts
|
|
4079
|
-
import path22 from "path";
|
|
4139
|
+
import path22 from "node:path";
|
|
4080
4140
|
import fs17 from "fs-extra";
|
|
4081
4141
|
|
|
4082
4142
|
// src/claude/managed-paths.ts
|
|
@@ -4201,8 +4261,8 @@ User-owned .claude/ files will be preserved.`
|
|
|
4201
4261
|
}
|
|
4202
4262
|
|
|
4203
4263
|
// src/install/uninstall.ts
|
|
4204
|
-
import crypto3 from "crypto";
|
|
4205
|
-
import path23 from "path";
|
|
4264
|
+
import crypto3 from "node:crypto";
|
|
4265
|
+
import path23 from "node:path";
|
|
4206
4266
|
import fs18 from "fs-extra";
|
|
4207
4267
|
async function runUninstall(options = {}) {
|
|
4208
4268
|
const { force = false } = options;
|
|
@@ -4277,7 +4337,7 @@ async function runUninstallCommand(options) {
|
|
|
4277
4337
|
}
|
|
4278
4338
|
|
|
4279
4339
|
// src/commands/update.ts
|
|
4280
|
-
import path25 from "path";
|
|
4340
|
+
import path25 from "node:path";
|
|
4281
4341
|
|
|
4282
4342
|
// src/claude/refresh-project.ts
|
|
4283
4343
|
import fs19 from "fs-extra";
|
|
@@ -4316,8 +4376,8 @@ function summarizeLockDiff(before, after) {
|
|
|
4316
4376
|
}
|
|
4317
4377
|
|
|
4318
4378
|
// src/update/lockfile.ts
|
|
4319
|
-
import { mkdir, readFile as readFile2, copyFile } from "fs/promises";
|
|
4320
|
-
import path24 from "path";
|
|
4379
|
+
import { mkdir, readFile as readFile2, copyFile } from "node:fs/promises";
|
|
4380
|
+
import path24 from "node:path";
|
|
4321
4381
|
async function checkLock(root) {
|
|
4322
4382
|
const lock = await readJson(hausPath(root, "haus.lock.json")) ?? [];
|
|
4323
4383
|
const hasValidVersions = lock.every(
|
|
@@ -4489,11 +4549,11 @@ async function detectGlobalInstallDrift() {
|
|
|
4489
4549
|
}
|
|
4490
4550
|
|
|
4491
4551
|
// src/commands/validate-catalog.ts
|
|
4492
|
-
import path27 from "path";
|
|
4552
|
+
import path27 from "node:path";
|
|
4493
4553
|
|
|
4494
4554
|
// src/catalog/validate-core.ts
|
|
4495
|
-
import fs20 from "fs";
|
|
4496
|
-
import path26 from "path";
|
|
4555
|
+
import fs20 from "node:fs";
|
|
4556
|
+
import path26 from "node:path";
|
|
4497
4557
|
var ITEM_SEMVER_RE = /^\d+\.\d+\.\d+$/;
|
|
4498
4558
|
var MANIFEST_SEMVER_RE = /^\d+\.\d+\.\d+(?:-[\w.-]+)?(?:\+[\w.-]+)?$/;
|
|
4499
4559
|
function isSafeCatalogPath2(itemPath) {
|
|
@@ -4527,6 +4587,10 @@ function auditManifestStructure(manifestVersion, items) {
|
|
|
4527
4587
|
failures.push(`item[${i}]: missing id`);
|
|
4528
4588
|
continue;
|
|
4529
4589
|
}
|
|
4590
|
+
const provenanceError = validateCuratedProvenance(item);
|
|
4591
|
+
if (provenanceError) failures.push(provenanceError);
|
|
4592
|
+
const referencesError = validateReferences(item.id, item.references);
|
|
4593
|
+
if (referencesError) failures.push(referencesError);
|
|
4530
4594
|
if (!item.type) {
|
|
4531
4595
|
failures.push(`${item.id}: missing type`);
|
|
4532
4596
|
continue;
|
|
@@ -4554,19 +4618,11 @@ function auditManifestStructure(manifestVersion, items) {
|
|
|
4554
4618
|
else seenPaths.set(norm, item.id);
|
|
4555
4619
|
}
|
|
4556
4620
|
const isHaus = item.source === "haus";
|
|
4557
|
-
const
|
|
4558
|
-
if (!isHaus && !
|
|
4559
|
-
failures.push(
|
|
4560
|
-
|
|
4561
|
-
|
|
4562
|
-
if (/^https?:\/\//i.test(ref)) {
|
|
4563
|
-
if (!ref.startsWith("https://")) {
|
|
4564
|
-
failures.push(`${item.id}: reference must be https:// URL: ${ref}`);
|
|
4565
|
-
}
|
|
4566
|
-
if (HTTP_URL_PATTERN.test(ref)) {
|
|
4567
|
-
failures.push(`${item.id}: reference uses insecure http:// URL: ${ref}`);
|
|
4568
|
-
}
|
|
4569
|
-
}
|
|
4621
|
+
const isCuratedUsableState = item.source === "curated" && (item.reviewStatus === "approved" || item.reviewStatus === "deprecated");
|
|
4622
|
+
if (!isHaus && !isCuratedUsableState) {
|
|
4623
|
+
failures.push(
|
|
4624
|
+
`${item.id}: source must be "haus" or curated with reviewStatus "approved"/"deprecated"`
|
|
4625
|
+
);
|
|
4570
4626
|
}
|
|
4571
4627
|
}
|
|
4572
4628
|
}
|
|
@@ -4714,8 +4770,8 @@ async function runValidateCatalog(manifestPath2) {
|
|
|
4714
4770
|
}
|
|
4715
4771
|
|
|
4716
4772
|
// src/commands/workspace.ts
|
|
4717
|
-
import { existsSync as existsSync5, statSync as statSync2 } from "fs";
|
|
4718
|
-
import path34 from "path";
|
|
4773
|
+
import { existsSync as existsSync5, statSync as statSync2 } from "node:fs";
|
|
4774
|
+
import path34 from "node:path";
|
|
4719
4775
|
|
|
4720
4776
|
// src/commands/workspace/aggregate.ts
|
|
4721
4777
|
async function writeWorkspaceArtifacts(workspaceRoot, repos, relationships = []) {
|
|
@@ -4769,7 +4825,7 @@ ${summaries.map(
|
|
|
4769
4825
|
}
|
|
4770
4826
|
|
|
4771
4827
|
// src/commands/workspace/config.ts
|
|
4772
|
-
import path28 from "path";
|
|
4828
|
+
import path28 from "node:path";
|
|
4773
4829
|
import YAML from "yaml";
|
|
4774
4830
|
var WORKSPACE_FILE = "haus.workspace.yaml";
|
|
4775
4831
|
function parseWorkspaceConfig(text) {
|
|
@@ -4796,7 +4852,7 @@ async function readWorkspaceConfig(workspaceRoot) {
|
|
|
4796
4852
|
}
|
|
4797
4853
|
|
|
4798
4854
|
// src/commands/workspace/discover.ts
|
|
4799
|
-
import path29 from "path";
|
|
4855
|
+
import path29 from "node:path";
|
|
4800
4856
|
import fg4 from "fast-glob";
|
|
4801
4857
|
import YAML2 from "yaml";
|
|
4802
4858
|
var DEFAULT_MAX_DEPTH = 3;
|
|
@@ -4919,12 +4975,12 @@ async function runDiscover(workspaceRoot, opts = {}) {
|
|
|
4919
4975
|
}
|
|
4920
4976
|
|
|
4921
4977
|
// src/commands/workspace/doctor.ts
|
|
4922
|
-
import { existsSync as existsSync3 } from "fs";
|
|
4923
|
-
import path31 from "path";
|
|
4978
|
+
import { existsSync as existsSync3 } from "node:fs";
|
|
4979
|
+
import path31 from "node:path";
|
|
4924
4980
|
|
|
4925
4981
|
// src/commands/workspace/manifest.ts
|
|
4926
|
-
import { readFileSync as readFileSync3 } from "fs";
|
|
4927
|
-
import path30 from "path";
|
|
4982
|
+
import { readFileSync as readFileSync3 } from "node:fs";
|
|
4983
|
+
import path30 from "node:path";
|
|
4928
4984
|
var MANIFEST_FILE = "workspace.manifest.json";
|
|
4929
4985
|
function manifestPath(workspaceRoot) {
|
|
4930
4986
|
return hausPath(workspaceRoot, MANIFEST_FILE);
|
|
@@ -5070,11 +5126,11 @@ function emit(args) {
|
|
|
5070
5126
|
}
|
|
5071
5127
|
|
|
5072
5128
|
// src/commands/workspace/setup.ts
|
|
5073
|
-
import { existsSync as existsSync4, statSync } from "fs";
|
|
5074
|
-
import path33 from "path";
|
|
5129
|
+
import { existsSync as existsSync4, statSync } from "node:fs";
|
|
5130
|
+
import path33 from "node:path";
|
|
5075
5131
|
|
|
5076
5132
|
// src/claude/write-workspace-claude-md.ts
|
|
5077
|
-
import path32 from "path";
|
|
5133
|
+
import path32 from "node:path";
|
|
5078
5134
|
import fs21 from "fs-extra";
|
|
5079
5135
|
function buildWorkspaceImportBlock(client, members) {
|
|
5080
5136
|
const memberLines = members.map((m) => `- ${m.name} (${m.path})`);
|