@haus-tech/haus-workflow 0.16.2 → 0.17.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
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.17.0](https://github.com/WeAreHausTech/haus-workflow/compare/v0.16.3...v0.17.0) (2026-06-09)
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
- **catalog:** support curated superpowers skills and commands ([#80](https://github.com/WeAreHausTech/haus-workflow/issues/80)) ([2e49c80](https://github.com/WeAreHausTech/haus-workflow/commit/2e49c80d6780e8ff753536f2d4042b4ce7fa2ae8))
|
|
8
|
+
|
|
9
|
+
## [0.16.3](https://github.com/WeAreHausTech/haus-workflow/compare/v0.16.2...v0.16.3) (2026-06-09)
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
- **install:** keep skill frontmatter valid by stamping marker as a field ([#79](https://github.com/WeAreHausTech/haus-workflow/issues/79)) ([76ddbf1](https://github.com/WeAreHausTech/haus-workflow/commit/76ddbf1248b8844538363dcfd3744cd975d96f52))
|
|
14
|
+
|
|
3
15
|
## [0.16.2](https://github.com/WeAreHausTech/haus-workflow/compare/v0.16.1...v0.16.2) (2026-06-09)
|
|
4
16
|
|
|
5
17
|
## [0.16.1](https://github.com/WeAreHausTech/haus-workflow/compare/v0.16.0...v0.16.1) (2026-06-09)
|
package/dist/cli.js
CHANGED
|
@@ -137,7 +137,7 @@ async function syncRemoteCatalog() {
|
|
|
137
137
|
let unchanged = 0;
|
|
138
138
|
const failed = [];
|
|
139
139
|
for (const item of items) {
|
|
140
|
-
if (item.type !== "skill" && item.type !== "agent" && item.type !== "template" || !item.path)
|
|
140
|
+
if (item.type !== "skill" && item.type !== "agent" && item.type !== "template" && item.type !== "command" || !item.path)
|
|
141
141
|
continue;
|
|
142
142
|
if (!isSafeCatalogPath(item.path)) {
|
|
143
143
|
warn(`Skipping ${item.id}: invalid path "${item.path}"`);
|
|
@@ -1240,7 +1240,7 @@ async function writeClaudeFiles(root, dryRun, selectedIds, opts = {}) {
|
|
|
1240
1240
|
}
|
|
1241
1241
|
}
|
|
1242
1242
|
const sourcePath = catalogItemContentPath(contentRoot, manifestItem);
|
|
1243
|
-
const target = item.type === "agent" ? "agents" : item.type === "template" ? "templates" : "skills";
|
|
1243
|
+
const target = item.type === "agent" ? "agents" : item.type === "template" ? "templates" : item.type === "command" ? "commands" : "skills";
|
|
1244
1244
|
const destination = claudePath(root, target, path12.basename(sourcePath));
|
|
1245
1245
|
if (await fs10.pathExists(sourcePath)) {
|
|
1246
1246
|
if (dryRun) {
|
|
@@ -1549,7 +1549,8 @@ var validation_rules_default = {
|
|
|
1549
1549
|
"baseline",
|
|
1550
1550
|
"project-instructions"
|
|
1551
1551
|
],
|
|
1552
|
-
patternTagSuffixes: ["-patterns"]
|
|
1552
|
+
patternTagSuffixes: ["-patterns"],
|
|
1553
|
+
skillSectionExemptSources: ["curated"]
|
|
1553
1554
|
};
|
|
1554
1555
|
|
|
1555
1556
|
// src/catalog/validation-rules.ts
|
|
@@ -1557,6 +1558,10 @@ var toRegExp = (r) => new RegExp(r.source, r.flags);
|
|
|
1557
1558
|
var FORBIDDEN_TAGS = validation_rules_default.forbiddenTags;
|
|
1558
1559
|
var BANNED_AGENT_PHRASES = validation_rules_default.bannedAgentPhrases;
|
|
1559
1560
|
var REQUIRED_SKILL_SECTIONS = validation_rules_default.requiredSkillSections;
|
|
1561
|
+
var SKILL_SECTION_EXEMPT_SOURCES = validation_rules_default.skillSectionExemptSources;
|
|
1562
|
+
function isVerbatimSuperpowersMarkdownPath(rel) {
|
|
1563
|
+
return rel.replace(/\\/g, "/").includes("/superpowers/");
|
|
1564
|
+
}
|
|
1560
1565
|
var REQUIRED_AGENT_SECTIONS = validation_rules_default.requiredAgentSections;
|
|
1561
1566
|
var RISKY_INSTALL_PATTERNS = validation_rules_default.riskyInstallPatterns.map(toRegExp);
|
|
1562
1567
|
var ALLOWED_NPX_PATTERN = toRegExp(validation_rules_default.allowedNpxPattern);
|
|
@@ -3323,6 +3328,8 @@ import fs15 from "fs-extra";
|
|
|
3323
3328
|
// src/install/header.ts
|
|
3324
3329
|
var MD_PREFIX = "<!-- HAUS-MANAGED";
|
|
3325
3330
|
var MD_SUFFIX = " -->";
|
|
3331
|
+
var FM_FENCE = "---";
|
|
3332
|
+
var FM_KEY = "haus_managed";
|
|
3326
3333
|
function parseAttrs(raw) {
|
|
3327
3334
|
const idMatch = /\bid=(\S+)/.exec(raw);
|
|
3328
3335
|
const vMatch = /\bv=(\S+)/.exec(raw);
|
|
@@ -3330,20 +3337,67 @@ function parseAttrs(raw) {
|
|
|
3330
3337
|
if (!idMatch || !vMatch || !srcMatch) return void 0;
|
|
3331
3338
|
return { stableId: idMatch[1], schemaVersion: vMatch[1], source: srcMatch[1] };
|
|
3332
3339
|
}
|
|
3340
|
+
function isFence(line2) {
|
|
3341
|
+
return (line2 ?? "").replace(/\r$/, "") === FM_FENCE;
|
|
3342
|
+
}
|
|
3343
|
+
function hasFrontmatter(content2) {
|
|
3344
|
+
return isFence(content2.split("\n", 1)[0]);
|
|
3345
|
+
}
|
|
3346
|
+
function frontmatterMarkerValue(content2) {
|
|
3347
|
+
const lines = content2.split("\n");
|
|
3348
|
+
if (!isFence(lines[0])) return void 0;
|
|
3349
|
+
for (let i = 1; i < lines.length; i++) {
|
|
3350
|
+
if (isFence(lines[i])) return void 0;
|
|
3351
|
+
const m = /^haus_managed:\s*"?(.*?)"?\s*$/.exec(lines[i]);
|
|
3352
|
+
if (m) return m[1];
|
|
3353
|
+
}
|
|
3354
|
+
return void 0;
|
|
3355
|
+
}
|
|
3333
3356
|
function parseMarkdownHeader(content2) {
|
|
3334
3357
|
const firstLine = content2.split("\n")[0] ?? "";
|
|
3335
|
-
if (
|
|
3336
|
-
|
|
3358
|
+
if (firstLine.startsWith(MD_PREFIX)) return parseAttrs(firstLine);
|
|
3359
|
+
const fmValue = frontmatterMarkerValue(content2);
|
|
3360
|
+
if (fmValue !== void 0) return parseAttrs(fmValue);
|
|
3361
|
+
return void 0;
|
|
3337
3362
|
}
|
|
3338
3363
|
function buildMarkdownHeader(h) {
|
|
3339
3364
|
return `${MD_PREFIX} id=${h.stableId} v=${h.schemaVersion} source=${h.source}${MD_SUFFIX}`;
|
|
3340
3365
|
}
|
|
3366
|
+
function buildMarkerValue(h) {
|
|
3367
|
+
return `id=${h.stableId} v=${h.schemaVersion} source=${h.source}`;
|
|
3368
|
+
}
|
|
3369
|
+
function stampFrontmatter(content2, h) {
|
|
3370
|
+
const lines = content2.split("\n");
|
|
3371
|
+
let close = -1;
|
|
3372
|
+
for (let i = 1; i < lines.length; i++) {
|
|
3373
|
+
if (isFence(lines[i])) {
|
|
3374
|
+
close = i;
|
|
3375
|
+
break;
|
|
3376
|
+
}
|
|
3377
|
+
}
|
|
3378
|
+
if (close === -1) return content2;
|
|
3379
|
+
const fields2 = [];
|
|
3380
|
+
for (let i = 1; i < close; i++) {
|
|
3381
|
+
if (/^haus_managed:/.test(lines[i])) continue;
|
|
3382
|
+
fields2.push(lines[i]);
|
|
3383
|
+
}
|
|
3384
|
+
const rebuilt = [
|
|
3385
|
+
FM_FENCE,
|
|
3386
|
+
...fields2,
|
|
3387
|
+
`${FM_KEY}: "${buildMarkerValue(h)}"`,
|
|
3388
|
+
...lines.slice(close)
|
|
3389
|
+
// closing fence + body
|
|
3390
|
+
];
|
|
3391
|
+
return rebuilt.join("\n");
|
|
3392
|
+
}
|
|
3341
3393
|
function stampMarkdown(content2, h) {
|
|
3394
|
+
if (hasFrontmatter(content2)) return stampFrontmatter(content2, h);
|
|
3342
3395
|
const header = buildMarkdownHeader(h);
|
|
3343
|
-
const
|
|
3344
|
-
if (
|
|
3345
|
-
const
|
|
3346
|
-
|
|
3396
|
+
const firstLine = content2.split("\n")[0] ?? "";
|
|
3397
|
+
if (firstLine.startsWith(MD_PREFIX)) {
|
|
3398
|
+
const nl = content2.indexOf("\n");
|
|
3399
|
+
const rest = nl === -1 ? "" : content2.slice(nl + 1);
|
|
3400
|
+
return rest === "" ? header : `${header}
|
|
3347
3401
|
${rest}`;
|
|
3348
3402
|
}
|
|
3349
3403
|
return `${header}
|
|
@@ -4081,7 +4135,7 @@ function auditManifestStructure(items) {
|
|
|
4081
4135
|
} else {
|
|
4082
4136
|
seenIds.set(item.id, i);
|
|
4083
4137
|
}
|
|
4084
|
-
if (item.type === "skill" || item.type === "agent" || item.type === "template") {
|
|
4138
|
+
if (item.type === "skill" || item.type === "agent" || item.type === "template" || item.type === "command") {
|
|
4085
4139
|
if (!item.path) {
|
|
4086
4140
|
failures.push(`${item.id}: missing path`);
|
|
4087
4141
|
} else {
|
|
@@ -4119,8 +4173,11 @@ function auditShippedFiles(manifestDir, items) {
|
|
|
4119
4173
|
continue;
|
|
4120
4174
|
}
|
|
4121
4175
|
const text = fs18.readFileSync(skillMd, "utf8");
|
|
4122
|
-
|
|
4123
|
-
|
|
4176
|
+
const skillSectionExempt = SKILL_SECTION_EXEMPT_SOURCES.includes(item.source) && item.whenToUse && item.whenNotToUse;
|
|
4177
|
+
if (!skillSectionExempt) {
|
|
4178
|
+
for (const section of REQUIRED_SKILL_SECTIONS) {
|
|
4179
|
+
if (!text.includes(section)) failures.push(`${item.id}: SKILL.md missing ${section}`);
|
|
4180
|
+
}
|
|
4124
4181
|
}
|
|
4125
4182
|
failures.push(
|
|
4126
4183
|
...auditForbiddenTagsInText(text, `${item.id}: ${path26.relative(manifestDir, skillMd)}`)
|
|
@@ -4149,6 +4206,12 @@ function auditShippedFiles(manifestDir, items) {
|
|
|
4149
4206
|
continue;
|
|
4150
4207
|
}
|
|
4151
4208
|
failures.push(...auditTemplateContent(manifestDir, absPath, item.id));
|
|
4209
|
+
} else if (item.type === "command") {
|
|
4210
|
+
if (!fs18.existsSync(absPath)) {
|
|
4211
|
+
failures.push(`${item.id}: missing command file ${item.path}`);
|
|
4212
|
+
continue;
|
|
4213
|
+
}
|
|
4214
|
+
failures.push(...auditTemplateContent(manifestDir, absPath, item.id));
|
|
4152
4215
|
}
|
|
4153
4216
|
}
|
|
4154
4217
|
return failures;
|
|
@@ -4175,13 +4238,14 @@ function auditTemplateContent(manifestDir, absPath, itemId) {
|
|
|
4175
4238
|
}
|
|
4176
4239
|
function auditMarkdownContent(manifestDir) {
|
|
4177
4240
|
const failures = [];
|
|
4178
|
-
const dirs = ["skills", "agents", "templates"];
|
|
4241
|
+
const dirs = ["skills", "agents", "templates", "commands"];
|
|
4179
4242
|
for (const dir of dirs) {
|
|
4180
4243
|
const abs = path26.join(manifestDir, dir);
|
|
4181
4244
|
if (!fs18.existsSync(abs)) continue;
|
|
4182
4245
|
walkMd(abs, (file) => {
|
|
4183
4246
|
const text = fs18.readFileSync(file, "utf8");
|
|
4184
4247
|
const rel = path26.relative(manifestDir, file);
|
|
4248
|
+
if (isVerbatimSuperpowersMarkdownPath(rel)) return;
|
|
4185
4249
|
const lines = text.split(/\r?\n/);
|
|
4186
4250
|
for (let i = 0; i < lines.length; i++) {
|
|
4187
4251
|
const line2 = lines[i] ?? "";
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
---
|
|
3
2
|
name: haus-workflow
|
|
4
3
|
description: Haus all-in-one workflow skill. Handles project setup, update, catalog refresh, and CLAUDE.md regeneration. Invoke with a task name or without to get a menu.
|
|
5
|
-
|
|
6
4
|
---
|
|
7
5
|
|
|
8
6
|
# haus-workflow
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@haus-tech/haus-workflow",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.0",
|
|
4
4
|
"description": "Haus AI workflow CLI for Claude Code.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -18,9 +18,7 @@
|
|
|
18
18
|
"library/catalog",
|
|
19
19
|
"tests/fixtures/catalog",
|
|
20
20
|
"README.md",
|
|
21
|
-
"CHANGELOG.md"
|
|
22
|
-
"LICENSE",
|
|
23
|
-
"NOTICE"
|
|
21
|
+
"CHANGELOG.md"
|
|
24
22
|
],
|
|
25
23
|
"scripts": {
|
|
26
24
|
"build": "tsup src/cli.ts --format esm --dts --clean --out-dir dist --external @inquirer/checkbox",
|
|
@@ -34,8 +32,6 @@
|
|
|
34
32
|
"typecheck": "tsc --noEmit",
|
|
35
33
|
"typecheck:scripts": "tsc --noEmit --project tsconfig.scripts.json",
|
|
36
34
|
"pack:local": "yarn pack",
|
|
37
|
-
"publish:dry": "npm pack --dry-run",
|
|
38
|
-
"publish:public": "yarn npm publish --access public",
|
|
39
35
|
"release": "GITHUB_TOKEN=$(gh auth token) release-it",
|
|
40
36
|
"release:dry": "GITHUB_TOKEN=$(gh auth token) release-it --dry-run",
|
|
41
37
|
"prepack": "yarn build",
|