@haus-tech/haus-workflow 0.29.0 → 0.31.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.
@@ -25,7 +25,7 @@
25
25
  ],
26
26
  "allowedNpxPattern": { "source": "\\bnpx\\s+tsx\\b", "flags": "i" },
27
27
  "anyNpxPattern": { "source": "\\bnpx\\s+\\S+", "flags": "i" },
28
- "npxTsxOnlyExemptTypes": ["agent"],
28
+ "npxTsxOnlyExemptSources": ["curated"],
29
29
  "httpUrlPattern": { "source": "^http:\\/\\/", "flags": "i" },
30
30
  "placeholderPattern": { "source": "\\bTODO\\b|\\bPLACEHOLDER\\b", "flags": "i" },
31
31
  "allowedStacks": [
@@ -131,9 +131,9 @@ seeds: # optional: data sources NOT owned by a manifest repo (e.g. a shared Word
131
131
  - `composer-path` → in `in`'s `composer.json`, set the `dep`'s require to `{ "type": "path", "url": "../<dep-folder>", "options": { "symlink": true } }`, then `composer update <vendor/dep>`.
132
132
  - `yarn-link` → `yarn link` in the `dep` repo, then `yarn link <pkg-name>` in each `in` repo (read `<pkg-name>` from the dep's `package.json`).
133
133
  5. **Env (deterministic):** write each repo's `.env` from known values — no improvising.
134
- 1. **Compute** each repo's values, in this precedence: the workspace `localdev.yml` `env` map (chosen literals + cross-repo `source` values — the single source of truth) → generated secrets (DB passwords/tokens minted this run) → the **dev-defaults table** below for anything still unset.
134
+ 1. **Compute** each repo's values, in this precedence: the workspace `localdev.yml` `env` map (chosen literals + cross-repo `source` values — the single source of truth) → generated secrets (DB passwords/tokens minted this run) → **a value already present locally** in a sibling repo's `.env.example` / `.env` (matched by key, or by the same value under a framework-prefix swap `MIX_` ↔ `VITE_` ↔ `NEXT_PUBLIC_` ↔ `REACT_APP_`) — reuse it: it is already on the machine, so copying it into this repo's local (gitignored) `.env` adds nothing new to git → the **dev-defaults table** below for anything still unset.
135
135
  2. **Write** them into each repo's `.env` (create it if absent; **upsert** keys, never clobbering a value the user already set). These are local dev files — write them directly.
136
- 3. **Real secrets the generator can't mint** (third-party API keys, prod credentials) go in as clearly-marked `KEY=` blanks for the user to fill; report exactly which keys are still blank.
136
+ 3. **Secrets that exist nowhere locally** (third-party API keys, prod credentials, license keys the machine doesn't already have — §1 reuse only applies when the value is present locally) can't be invented, so the flow **explicitly tells the user it needs them** — never silently leaving a blank and proceeding as if set up. Put each in as a clearly-marked `KEY=` blank and report it, naming **which key**, **what it unlocks** (the step or feature that fails without it), and **how to get it manually**: from the provider's own account/dashboard (e.g. the Laravel Nova licence page, the Mediaflow API account), by copying it from the deployed environment's env vars (the server / hosting config), or by asking a colleague who already has it. **NEVER write a secret value into a git-tracked file:** `.env` writes are local and gitignored (fine — reuse freely), but the workspace `localdev.yml` `env` map is committed, so it carries non-secret cross-repo literals only (DB names, ports, host URLs), never credentials. Report all blanks together as one actionable list, not piecemeal.
137
137
 
138
138
  **Dev-defaults table** — used only when neither `localdev.yml` nor a generated secret supplies the value:
139
139
 
@@ -31,13 +31,37 @@ Do this in order:
31
31
  deep read discovered. You MUST run this before the next apply — `haus apply`
32
32
  does not re-calculate recommendations on its own.
33
33
 
34
- 5. **Apply the rest.** Run `haus apply --write` again. It only writes what changed,
35
- so this just adds the newly-matched helpers from step 4.
34
+ 5. **Offer optional helpers.** Read `.haus-workflow/recommendation.json` yourself
35
+ (never show the JSON). Two kinds of optional extras may be listed; offer only
36
+ the ones present, all **unchecked** by default — these are opt-in:
37
+ - **Optional skills & agents** (`optInEligible[]`): workflow/ops/review/design
38
+ helpers that don't auto-install for this stack. Group them by their
39
+ `optInGroup` label and present one `AskUserQuestion` option per group
40
+ (use each item's `purpose` and `tokenEstimate` to describe it in plain
41
+ language, e.g. "Code review workflow — request/receive structured reviews").
42
+ Collect the item ids from **all** the groups the user picked into one list
43
+ and run a **single** `haus recommend --include <id> <id> …` (one command with
44
+ every chosen id). Don't run it once per group — each run rewrites
45
+ `recommendation.json`, so repeated calls would drop the earlier includes.
46
+ - **Project config** (entries in `recommended[]` with `install: false`, e.g.
47
+ Haus ESLint / Prettier baselines): offer each as a plain choice ("Add the
48
+ Haus ESLint baseline"). On confirm, run `haus scaffold <id>`. `haus scaffold`
49
+ **preserves existing config files by default** and tells you when a file
50
+ already exists — only re-run with `haus scaffold <id> --force` if the user
51
+ explicitly chooses to **replace** their current config.
36
52
 
37
- 6. **Confirm.** End with one plain-language line, for example:
53
+ If neither list has anything, skip this step silently — don't ask an empty
54
+ question.
55
+
56
+ 6. **Apply the rest.** Run `haus apply --write` again. It only writes what changed,
57
+ so this adds the newly-matched helpers from step 4 plus any opt-ins from step 5.
58
+
59
+ 7. **Confirm.** End with one plain-language line, for example:
38
60
  "✅ Your project is configured — I wrote your project docs, added N guardrails
39
- and M coding helpers (K matched after reading your code in depth). Run
40
- `/haus-doctor` any time to re-check." Fill the numbers from the apply output.
61
+ and M coding helpers (K matched after reading your code in depth), plus the J
62
+ optional helpers you chose: <name them>. Run `/haus-doctor` any time to
63
+ re-check." Fill the numbers from the apply output, and name the opt-ins the
64
+ user picked in step 5 (omit that clause if they chose none).
41
65
 
42
66
  If anything fails, explain what happened in plain language and what you'll try
43
67
  next — don't dump raw errors.
@@ -26,6 +26,7 @@ The short legacy aliases still work but the names below are canonical.
26
26
  | `project:init` (`setup`, `init`) | _Setup procedure below_ | project | First-time setup of an **existing** repo: adds AI skills, commands, workflow + project docs |
27
27
  | `project:clone [name]` (`clone`) | _Clone procedure below_ | project | No name: clone a **workspace**'s repos from `repos.manifest.json`. With a `name`: find & clone one repo by name from GitHub |
28
28
  | `project:cloneandsetup [name]` (`cloneandsetup`) | _Clone & setup procedure below_ | project | Run `project:clone`, then set up each repo for local dev — deps, databases, cross-repo links, and env — via each repo's `.haus-workflow/localdev.yml` (+ the workspace's order/links/env) |
29
+ | `project:add-skills` (`add-skills`, `opt-in`) | _Add-skills procedure below_ | project | Add optional skills, agents, or config (ESLint/Prettier) to an already-set-up project without re-running full setup |
29
30
  | `project:refresh` (`apply`, `refresh`, `claude-md`, `regenerate`) | `haus apply --write` | project | Re-run setup / refresh `.claude/` context + regenerate root `CLAUDE.md` import block |
30
31
  | `project:doctor` (`doctor`, `check`) | `haus doctor` | project | Check for install drift |
31
32
  | `update` (`upgrade`) | `haus update` | global | Update npm package + catalog + `~/.claude/` (also refreshes this project) |
@@ -51,6 +52,8 @@ Options:
51
52
  (no name: clone a workspace from repos.manifest.json; with a name: find & clone one repo by name from GitHub)
52
53
  5. [project] project:cloneandsetup [name] — clone repos, then set them up for local dev
53
54
  (project:clone, then per-repo deps + databases + cross-repo links + env from localdev.yml)
55
+ 6. [project] project:add-skills — add optional skills, agents, or config to this project
56
+ (offers opt-in helpers matching your stack that aren't installed yet — no full re-setup)
54
57
  ```
55
58
 
56
59
  Map the user's selection to the command from the alias table, then continue to Step 2.
@@ -65,6 +68,8 @@ Run the mapped command via Bash. Quote the exact command you are running before
65
68
 
66
69
  **Exception — `project:cloneandsetup` (`cloneandsetup`):** clone followed by a per-repo setup pass, with confirmations. Skip to **Clone & setup (`project:cloneandsetup`)** under Step 3 and follow it.
67
70
 
71
+ **Exception — `project:add-skills` (`add-skills` / `opt-in`):** a short scan → recommend → choose → apply procedure. Skip to **Add optional skills (`project:add-skills`)** under Step 3 and follow it.
72
+
68
73
  ## Step 3 — Post-run steps
69
74
 
70
75
  After the command completes, follow the relevant post-run steps below.
@@ -82,6 +87,31 @@ After the command completes, follow the relevant post-run steps below.
82
87
 
83
88
  1. Open and follow `~/.claude/commands/haus-cloneandsetup.md` — it runs the full `project:clone` flow, then sets up each cloned repo locally: selects the node version (`nvm install` from `.nvmrc`), enables corepack, installs JS/PHP dependencies, and seeds `.env`, confirming before each phase. It does not start servers.
84
89
 
90
+ ### Add optional skills (`project:add-skills`)
91
+
92
+ For a project that's already set up but where the user wants more helpers later —
93
+ without re-running the full `project:init` flow. Never show raw JSON; offer plain
94
+ choices.
95
+
96
+ 1. Refresh the picture: run `haus scan --json` then `haus recommend` (it re-reads
97
+ `.haus-workflow/deep-context.json` if present).
98
+ 2. Read `.haus-workflow/recommendation.json` and `.haus-workflow/haus.lock.json`
99
+ yourself. Build the choices from items **not already installed** (lock ids):
100
+ - **Optional skills & agents** — `optInEligible[]`, grouped by `optInGroup`
101
+ (each carries `purpose` + `tokenEstimate` for a plain-language label).
102
+ - **Project config** — `recommended[]` entries with `install: false` (Haus
103
+ ESLint / Prettier) whose files aren't already present.
104
+ 3. If nothing is eligible, say so plainly and stop — e.g. "Everything matching
105
+ your stack is already installed" or "No optional helpers for this stack."
106
+ 4. Otherwise present a single `AskUserQuestion` (multi-select, all unchecked)
107
+ with one option per group / config item. Then:
108
+ - Skills/agents → `haus recommend --include <id> <id> …`, then
109
+ `haus apply --write`.
110
+ - Config → `haus scaffold <id>` (add `--force` only if the user chose to
111
+ replace an existing file; scaffold preserves files by default).
112
+ 5. Confirm with the names added and their combined token estimate, e.g.
113
+ "Added 2 optional helpers: Code review workflow, TDD workflow (~3k tokens)."
114
+
85
115
  ### After `haus apply --write`
86
116
 
87
117
  Verify that the root `CLAUDE.md` imports all three haus files:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@haus-tech/haus-workflow",
3
- "version": "0.29.0",
3
+ "version": "0.31.0",
4
4
  "description": "Haus AI workflow CLI for Claude Code.",
5
5
  "type": "module",
6
6
  "bin": {