@haus-tech/haus-workflow 5.5.0 → 5.6.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
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [5.6.1](https://github.com/WeAreHausTech/haus-workflow/compare/v5.6.0...v5.6.1) (2026-09-16)
|
|
4
|
+
|
|
5
|
+
### Bug Fixes
|
|
6
|
+
|
|
7
|
+
- **security:** allow gh pr merge and read-only gh verbs, deny the --admin bypass ([#562](https://github.com/WeAreHausTech/haus-workflow/issues/562)) ([00a8c95](https://github.com/WeAreHausTech/haus-workflow/commit/00a8c95dbc49dea5863d15b9812f038dfde036bb)), closes [#545](https://github.com/WeAreHausTech/haus-workflow/issues/545)
|
|
8
|
+
|
|
9
|
+
## [5.6.0](https://github.com/WeAreHausTech/haus-workflow/compare/v5.5.0...v5.6.0) (2026-09-13)
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
- **poc:** what the second PoC run rubbed against ([#557](https://github.com/WeAreHausTech/haus-workflow/issues/557)) ([8b37668](https://github.com/WeAreHausTech/haus-workflow/commit/8b37668bfd0a9a99f7be32cd4863ead8bcf96b27))
|
|
14
|
+
|
|
3
15
|
## [5.5.0](https://github.com/WeAreHausTech/haus-workflow/compare/v5.4.0...v5.5.0) (2026-09-12)
|
|
4
16
|
|
|
5
17
|
### Features
|
package/dist/cli.js
CHANGED
|
@@ -2942,6 +2942,7 @@ var PROFILES = {
|
|
|
2942
2942
|
workflowTemplateRel: WORKFLOW_TEMPLATE_REL,
|
|
2943
2943
|
writesCiGate: true,
|
|
2944
2944
|
writesDecisionsSeed: true,
|
|
2945
|
+
runsDocsPass: true,
|
|
2945
2946
|
droppedHookCommands: [],
|
|
2946
2947
|
workflowConfig: "standard"
|
|
2947
2948
|
},
|
|
@@ -2950,6 +2951,7 @@ var PROFILES = {
|
|
|
2950
2951
|
workflowTemplateRel: "templates/agentic-workflow-poc.md",
|
|
2951
2952
|
writesCiGate: false,
|
|
2952
2953
|
writesDecisionsSeed: false,
|
|
2954
|
+
runsDocsPass: false,
|
|
2953
2955
|
droppedHookCommands: ["haus decisions guard --from-hook", "haus decisions suggest --from-hook"],
|
|
2954
2956
|
workflowConfig: "poc"
|
|
2955
2957
|
}
|
|
@@ -3381,8 +3383,42 @@ var ALLOWED_SUBCOMMANDS = [
|
|
|
3381
3383
|
"workspace worktree list",
|
|
3382
3384
|
"workspace worktree doctor"
|
|
3383
3385
|
];
|
|
3386
|
+
var ALLOWED_COMMANDS = [
|
|
3387
|
+
// Merging the PR is the last step of the house loop, and where a deploy builds `main`'s
|
|
3388
|
+
// SHA it is a precondition of deploying at all. The auto mode classifier blocked it
|
|
3389
|
+
// mid-run with no rule available to pre-authorize it (#545). Its dangerous form —
|
|
3390
|
+
// `--admin`, the only way past branch protection and required reviews — is deny-tier in
|
|
3391
|
+
// `DENY_COMMANDS` and caught in any spelling by the runtime guard, which outranks this
|
|
3392
|
+
// rule. The repo's own branch protection stays the review gate.
|
|
3393
|
+
"gh pr merge",
|
|
3394
|
+
// Read-only verbs. `gh` is absent from Claude Code's built-in read-only command set
|
|
3395
|
+
// (`ls`, `cat`, `grep`, read-only `git`, …), so each of these otherwise costs a
|
|
3396
|
+
// classifier round-trip mid-run — on `gh run watch`, once per CI wait. Nothing under
|
|
3397
|
+
// these prefixes writes, so there is no dangerous form left to gate.
|
|
3398
|
+
"gh pr view",
|
|
3399
|
+
"gh pr list",
|
|
3400
|
+
"gh pr diff",
|
|
3401
|
+
"gh pr checks",
|
|
3402
|
+
"gh run list",
|
|
3403
|
+
"gh run view",
|
|
3404
|
+
"gh run watch",
|
|
3405
|
+
"gh issue view",
|
|
3406
|
+
"gh issue list",
|
|
3407
|
+
"gh repo view",
|
|
3408
|
+
"gh label list",
|
|
3409
|
+
// Prints who you are authenticated as; `gh auth token`, which prints the credential
|
|
3410
|
+
// itself, is a different leaf and stays out.
|
|
3411
|
+
"gh auth status",
|
|
3412
|
+
"gh search prs",
|
|
3413
|
+
"gh search issues"
|
|
3414
|
+
];
|
|
3384
3415
|
function buildAllowRules() {
|
|
3385
|
-
return [
|
|
3416
|
+
return [
|
|
3417
|
+
.../* @__PURE__ */ new Set([
|
|
3418
|
+
...ALLOWED_SUBCOMMANDS.map((sub) => `Bash(haus ${sub}:*)`),
|
|
3419
|
+
...ALLOWED_COMMANDS.map((command) => `Bash(${command}:*)`)
|
|
3420
|
+
])
|
|
3421
|
+
];
|
|
3386
3422
|
}
|
|
3387
3423
|
|
|
3388
3424
|
// src/install/settings-merge.ts
|
|
@@ -3720,6 +3756,9 @@ var DENY_COMMANDS = [
|
|
|
3720
3756
|
// Skipping the hooks is a NEVER rule in WORKFLOW.md and was missing from every tier.
|
|
3721
3757
|
"git commit --no-verify",
|
|
3722
3758
|
"git push --no-verify",
|
|
3759
|
+
// `gh pr merge` is allow-tier so an unattended run can land its own PR; this is the
|
|
3760
|
+
// one form that merges past branch protection and required reviews (#545, ADR-0126).
|
|
3761
|
+
"gh pr merge --admin",
|
|
3723
3762
|
...RUNTIME_ONLY_DENY_COMMANDS,
|
|
3724
3763
|
"npm publish",
|
|
3725
3764
|
// Classic v1 syntax alongside the Berry `yarn npm publish` form.
|
|
@@ -7695,9 +7734,9 @@ async function readScannedMarkdown(root) {
|
|
|
7695
7734
|
}
|
|
7696
7735
|
|
|
7697
7736
|
// src/decisions/doctor.ts
|
|
7698
|
-
init_fs();
|
|
7699
7737
|
import path40 from "node:path";
|
|
7700
7738
|
import fs38 from "fs-extra";
|
|
7739
|
+
init_fs();
|
|
7701
7740
|
|
|
7702
7741
|
// src/decisions/check.ts
|
|
7703
7742
|
init_fs();
|
|
@@ -8165,19 +8204,21 @@ async function listDecisionNumbers(decisionsDir) {
|
|
|
8165
8204
|
}
|
|
8166
8205
|
|
|
8167
8206
|
// src/decisions/doctor.ts
|
|
8168
|
-
async function auditDecisionsLayout(root) {
|
|
8207
|
+
async function auditDecisionsLayout(root, profile) {
|
|
8169
8208
|
const findings = [];
|
|
8170
8209
|
const primary = path40.join(root, DECISIONS_TRIGGERS.decisionsDir);
|
|
8171
8210
|
const legacy = path40.join(root, DECISIONS_TRIGGERS.legacyDecisionsDir ?? "docs/adr");
|
|
8172
8211
|
const hasPrimary = await fs38.pathExists(primary);
|
|
8173
8212
|
const hasLegacy = await fs38.pathExists(legacy);
|
|
8174
8213
|
if (!hasPrimary && hasLegacy) {
|
|
8175
|
-
|
|
8176
|
-
|
|
8177
|
-
|
|
8178
|
-
|
|
8179
|
-
|
|
8180
|
-
|
|
8214
|
+
if (PROFILES[profile].writesDecisionsSeed) {
|
|
8215
|
+
findings.push({
|
|
8216
|
+
level: "advisory",
|
|
8217
|
+
line: `- DECISIONS: legacy ${DECISIONS_TRIGGERS.legacyDecisionsDir}/ present \u2014 migrate to docs/decisions/`,
|
|
8218
|
+
sentence: "Decision records still live under the legacy docs/adr/ path",
|
|
8219
|
+
fix: `git mv ${DECISIONS_TRIGGERS.legacyDecisionsDir} ${DECISIONS_TRIGGERS.decisionsDir}`
|
|
8220
|
+
});
|
|
8221
|
+
}
|
|
8181
8222
|
return findings;
|
|
8182
8223
|
}
|
|
8183
8224
|
if (!hasPrimary) return findings;
|
|
@@ -9535,7 +9576,7 @@ async function runDoctor(options) {
|
|
|
9535
9576
|
if (docsSkillInstalled) {
|
|
9536
9577
|
if (await fs41.pathExists(path49.join(root, "docs", "SUMMARY.md"))) {
|
|
9537
9578
|
ok("- PROJECT DOCS: OK (docs/SUMMARY.md present)");
|
|
9538
|
-
} else {
|
|
9579
|
+
} else if (PROFILES[profile].runsDocsPass) {
|
|
9539
9580
|
suggest(
|
|
9540
9581
|
"- PROJECT DOCS: docs/SUMMARY.md missing \u2014 run the writing-documentation skill (`/docs` in Claude Code) to generate the project docs",
|
|
9541
9582
|
"The project docs index (docs/SUMMARY.md) has not been generated yet",
|
|
@@ -9599,7 +9640,7 @@ async function runDoctor(options) {
|
|
|
9599
9640
|
} else {
|
|
9600
9641
|
ok("- GITIGNORE (haus content): OK (.claude/ and .haus-workflow/ are tracked)");
|
|
9601
9642
|
}
|
|
9602
|
-
for (const finding of await auditDecisionsLayout(root)) {
|
|
9643
|
+
for (const finding of await auditDecisionsLayout(root, profile)) {
|
|
9603
9644
|
if (finding.level === "ok") ok(finding.line);
|
|
9604
9645
|
else suggest(finding.line, finding.sentence, finding.fix);
|
|
9605
9646
|
}
|
|
@@ -11864,6 +11905,32 @@ function isPackagePublish(words) {
|
|
|
11864
11905
|
if (RUN_SCRIPT_VERBS.some((verb) => hasWord(words, verb))) return false;
|
|
11865
11906
|
return !words.some((word) => word === "--dry-run" || word === "--dry-run=true");
|
|
11866
11907
|
}
|
|
11908
|
+
var GH_TEXT_FLAGS = /* @__PURE__ */ new Set([
|
|
11909
|
+
"-b",
|
|
11910
|
+
"--body",
|
|
11911
|
+
"-F",
|
|
11912
|
+
"--body-file",
|
|
11913
|
+
"-t",
|
|
11914
|
+
"--subject",
|
|
11915
|
+
"-R",
|
|
11916
|
+
"--repo"
|
|
11917
|
+
]);
|
|
11918
|
+
var ADMIN_MERGE_FLAGS = /* @__PURE__ */ new Set(["--admin", "--admin=true", "--admin=1"]);
|
|
11919
|
+
function isProtectionBypassMerge(words) {
|
|
11920
|
+
if (commandName(words) !== "gh") return false;
|
|
11921
|
+
const args = [];
|
|
11922
|
+
for (let i = 1; i < words.length; i += 1) {
|
|
11923
|
+
const word = words[i];
|
|
11924
|
+
if (GH_TEXT_FLAGS.has(word)) {
|
|
11925
|
+
i += 1;
|
|
11926
|
+
continue;
|
|
11927
|
+
}
|
|
11928
|
+
args.push(word);
|
|
11929
|
+
}
|
|
11930
|
+
const operands = args.filter((word) => !word.startsWith("-")).map((word) => word.toLowerCase());
|
|
11931
|
+
if (operands[0] !== "pr" || operands[1] !== "merge") return false;
|
|
11932
|
+
return args.some((word) => ADMIN_MERGE_FLAGS.has(word.toLowerCase()));
|
|
11933
|
+
}
|
|
11867
11934
|
var PRIVILEGE_ESCALATORS = /* @__PURE__ */ new Set(["sudo", "doas", "pkexec"]);
|
|
11868
11935
|
function isPrivilegeEscalation(words) {
|
|
11869
11936
|
return PRIVILEGE_ESCALATORS.has(commandName(words));
|
|
@@ -11883,7 +11950,8 @@ var SEGMENT_MATCHERS = [
|
|
|
11883
11950
|
{ name: "a force push", matches: isForcePush },
|
|
11884
11951
|
{ name: "a commit or push that skips the hooks", matches: isHookBypass },
|
|
11885
11952
|
{ name: "a recursive permission change", matches: isRecursiveChmod },
|
|
11886
|
-
{ name: "a package publish", matches: isPackagePublish }
|
|
11953
|
+
{ name: "a package publish", matches: isPackagePublish },
|
|
11954
|
+
{ name: "a merge that bypasses branch protection", matches: isProtectionBypassMerge }
|
|
11887
11955
|
];
|
|
11888
11956
|
function matchDangerousCommandShape(command) {
|
|
11889
11957
|
for (const segment of parseShellSegments(command)) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "6.5.
|
|
2
|
+
"version": "6.5.1",
|
|
3
3
|
"manifestFormat": 2,
|
|
4
4
|
"globalPlugins": [
|
|
5
5
|
{
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
},
|
|
57
57
|
{
|
|
58
58
|
"id": "haus.agentic-workflow-poc",
|
|
59
|
-
"version": "1.0.
|
|
59
|
+
"version": "1.0.1",
|
|
60
60
|
"source": "haus",
|
|
61
61
|
"type": "template",
|
|
62
62
|
"path": "templates/agentic-workflow-poc.md",
|
|
@@ -68,8 +68,8 @@
|
|
|
68
68
|
"repoRoles": [],
|
|
69
69
|
"ecosystem": "general",
|
|
70
70
|
"installMode": "copy-selected",
|
|
71
|
-
"tokenEstimate":
|
|
72
|
-
"tokenBudget":
|
|
71
|
+
"tokenEstimate": 2187,
|
|
72
|
+
"tokenBudget": 2844,
|
|
73
73
|
"default": false,
|
|
74
74
|
"reviewStatus": "approved",
|
|
75
75
|
"riskLevel": "low"
|
|
@@ -67,13 +67,15 @@ A description argument ("a frontend app for shopping") goes straight to Phase 1.
|
|
|
67
67
|
No-argument invocation: ask "What do you want to build?" as free text. Do not present
|
|
68
68
|
a stack menu.
|
|
69
69
|
|
|
70
|
-
**PoC:** the
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
70
|
+
**PoC:** upgrading the haus package rewrites this very file, so if the CLI gets upgraded
|
|
71
|
+
mid-flow, re-read `references/new.md` from disk before continuing rather than carrying on
|
|
72
|
+
from what is already in context. The mode itself is already settled by now, either the
|
|
73
|
+
trigger phrase in the request or the question asked in `## PoC mode` above, so decide the
|
|
74
|
+
way in next: `git rev-parse --is-inside-work-tree` and `ls -A`: an empty directory or a
|
|
75
|
+
git repo means the cwd IS the project (manual rails in Phase 3); anything else means the
|
|
76
|
+
cwd is a parent folder (fast path). A git repo with a remote (`git remote -v`) keeps it;
|
|
77
|
+
one without gets a new private repo in Phase 3, unless local-only is chosen in Phase 1.
|
|
78
|
+
The workspace question above applies unchanged.
|
|
77
79
|
|
|
78
80
|
## Phase 1 — Elicit (at most 5 AskUserQuestion rounds)
|
|
79
81
|
|
|
@@ -149,7 +151,10 @@ Check the registry first: `haus new --list --json`.
|
|
|
149
151
|
3. Manual rails: `git init` (if the scaffolder didn't), `git branch -M main`, initial
|
|
150
152
|
commit; then `gh repo create` (confirm first) unless the user declined a repo.
|
|
151
153
|
|
|
152
|
-
**PoC:** two ways in, decided already in Phase 0 by what the cwd was.
|
|
154
|
+
**PoC:** two ways in, decided already in Phase 0 by what the cwd was. Before either
|
|
155
|
+
path's own first commit below, check whatever commit hook a scaffold's files already
|
|
156
|
+
ship (husky, commitlint, lefthook): reading its message-format rules now means finding
|
|
157
|
+
out what it wants before the first commit, not after it rejects one.
|
|
153
158
|
|
|
154
159
|
- **cwd is the project:** the registry is not used, because `haus new` creates
|
|
155
160
|
`<parent>/<name>` and refuses an existing directory. Run the official scaffolder into
|
|
@@ -166,6 +171,16 @@ repo create`. Carry `--dir` through from Phase 0 for a workspace member; without
|
|
|
166
171
|
PoC still lands in the cwd, exactly like production. The chained init records the
|
|
167
172
|
profile and writes the PoC standard; nothing more to do for the profile in Phase 4.
|
|
168
173
|
|
|
174
|
+
Whichever way in, the profile governs what haus installs and nothing else: a vendor
|
|
175
|
+
starter's own ceremony arrives untouched and no profile can subtract it. Right after the
|
|
176
|
+
first commit, list what came with the scaffold, naming at least its `test` script and
|
|
177
|
+
test directories, any `playwright.config.ts`, commit hooks (husky, commitlint, lefthook),
|
|
178
|
+
CI workflows, and a decisions or `docs/adr/` folder; tell the user in one line what
|
|
179
|
+
stays. Nothing gets deleted: removing files a vendor starter shipped is a surprise in
|
|
180
|
+
someone else's repo, not this flow's call to make. What stays is inert, not authority:
|
|
181
|
+
never run or extend a starter's test suite, and never read its presence as permission to
|
|
182
|
+
add tests.
|
|
183
|
+
|
|
169
184
|
## Phase 4 — Context install
|
|
170
185
|
|
|
171
186
|
Everything from here on runs inside the new project directory — `cd` into it first and
|
|
@@ -199,23 +214,49 @@ stay there.
|
|
|
199
214
|
directory).
|
|
200
215
|
2. Read: `haus init --json --dry-run --profile poc`; on the zero-signal refusal, confirm
|
|
201
216
|
and re-run with `--force` as above.
|
|
202
|
-
3.
|
|
217
|
+
3. Add a `"manus"` key to package.json scripts now, before the write step, even as a
|
|
218
|
+
placeholder (`"manus": "playwright test"`). `haus apply --write` derives the PoC's
|
|
219
|
+
only gate command in `.haus-workflow/workflow-config.md` from whether that key
|
|
220
|
+
exists, not from its final body, and with no key at all it falls back to a Playwright
|
|
221
|
+
invocation that resolves against whatever default config the scaffold shipped and
|
|
222
|
+
finds no tests at all. The skeleton below fills in the real body once the runner
|
|
223
|
+
config is decided; what matters here is that the key exists first.
|
|
224
|
+
4. Write: `haus apply --write`. It reads the profile: `.haus-workflow/WORKFLOW.md` now
|
|
203
225
|
starts with `# PoC Workflow Standard`, and there is no `.github/workflows/haus-gate.yml`.
|
|
204
226
|
|
|
205
|
-
Fast path: the chained init already
|
|
206
|
-
|
|
227
|
+
Fast path: the chained init already ran `haus apply --write` inside Phase 3, before this
|
|
228
|
+
phase's `"manus"` script exists, so `.haus-workflow/workflow-config.md`'s "Run the manus"
|
|
229
|
+
line was derived from the fallback command. That file is project-owned and never
|
|
230
|
+
rewritten after its first write, exactly as its own header says, so adding the script
|
|
231
|
+
afterward will not fix it. Once the skeleton below has added the `manus` script and
|
|
232
|
+
decided the runner config, open `.haus-workflow/workflow-config.md` yourself and correct
|
|
233
|
+
that one line to `yarn run manus` / `npm run manus` / `pnpm run manus` (the project's
|
|
234
|
+
package manager) either way, whether the script ended up `"playwright test"` or
|
|
235
|
+
`"playwright test -c playwright.manus.config.ts"`: the line only needs to delegate to
|
|
236
|
+
the script, which already points at the right config. Also check that
|
|
237
|
+
`.haus-workflow/haus.config.json` says `"profile": "poc"`.
|
|
207
238
|
|
|
208
239
|
Then the demo skeleton, instead of SPEC.md and the walking-skeleton plan:
|
|
209
240
|
|
|
210
241
|
- `yarn add -D @playwright/test` (or the project's package manager), then
|
|
211
242
|
`npx playwright install chromium` (a download: ask first).
|
|
212
|
-
-
|
|
213
|
-
from `PORT` (default 3000),
|
|
214
|
-
from the same port.
|
|
243
|
+
- The runner config. If the repo has no `playwright.config.ts`, write one with a
|
|
244
|
+
`webServer` that starts the dev server and takes its port from `PORT` (default 3000),
|
|
245
|
+
`testDir: 'demo'`, `reporter: 'line'`, `use.baseURL` from the same port. If the
|
|
246
|
+
scaffold already shipped a `playwright.config.ts`, which a vendor starter usually has
|
|
247
|
+
and points at its own e2e suite, leave that file alone and write
|
|
248
|
+
`playwright.manus.config.ts` beside it with the same contents instead: two configs is
|
|
249
|
+
the correct outcome, the starter's suite tests the starter and the manus tests the
|
|
250
|
+
demo. Either way, the config's own `webServer` owns the dev server: never start the
|
|
251
|
+
dev server yourself in the background and then run the manus against it, or every
|
|
252
|
+
round starts by hunting the process holding the port.
|
|
215
253
|
- `demo/manus.spec.ts` with the header comment `// The manus. One test per point in
|
|
216
254
|
docs/MANUS.md, same titles, same order. test.fixme() for points decided but not built.`
|
|
217
255
|
and no tests yet.
|
|
218
|
-
- `"manus":
|
|
256
|
+
- The `"manus"` script: on the manual path fill in the key added in step 3, and on the fast
|
|
257
|
+
path add it here. Either way its body is `"playwright test"` when the repo had no
|
|
258
|
+
config of its own, or `"playwright test -c playwright.manus.config.ts"` when the
|
|
259
|
+
starter's config forced the second file.
|
|
219
260
|
- `docs/MANUS.md`:
|
|
220
261
|
|
|
221
262
|
```markdown
|
|
@@ -262,7 +303,19 @@ Commit the skeleton on `main` (`chore(poc): demo skeleton`).
|
|
|
262
303
|
**PoC:** now, with the PoC standard loaded, invoke superpowers:brainstorming. A new
|
|
263
304
|
project is architectural, so it ends in a written design: tell the skill the spec
|
|
264
305
|
location is `docs/MANUS.md` (numbered points in show order, each with what the customer
|
|
265
|
-
sees and what proves it; keep the `Demo:` header).
|
|
306
|
+
sees and what proves it; keep the `Demo:` header).
|
|
307
|
+
|
|
308
|
+
Before the plan, probe. For every drafted point, run the smallest real query that
|
|
309
|
+
produces that point's proof against the system the demo will use: one GraphQL query, one
|
|
310
|
+
API call, one page load. Do it before any code is written, not when the feature is half
|
|
311
|
+
built. A point whose proof the system cannot produce today goes straight to Parked in
|
|
312
|
+
`docs/MANUS.md` with the one sentence that says what is missing, and the user hears it
|
|
313
|
+
before the plan exists. If the probe kills the system chosen in Phase 1, stop and ask:
|
|
314
|
+
the manus is the scope ceiling, and what it runs against is part of the manus. Do not
|
|
315
|
+
commit a backend URL or token until the probe has confirmed the system can produce the
|
|
316
|
+
points that depend on it.
|
|
317
|
+
|
|
318
|
+
Then superpowers:writing-plans into
|
|
266
319
|
`docs/plans/round-1.md`, one task per manus point with "the manus point is green" as its
|
|
267
320
|
verification. Build: `demo/manus.spec.ts` gets one `test()` per point as it is built and
|
|
268
321
|
`test.fixme()` for the rest; independent points may go to one subagent each in its own
|
|
@@ -290,9 +343,19 @@ why.
|
|
|
290
343
|
project directory.
|
|
291
344
|
|
|
292
345
|
**PoC:** the gate is the manus: `yarn manus` (or the package manager's equivalent) with
|
|
293
|
-
every point green or `fixme`, nothing red
|
|
294
|
-
|
|
295
|
-
|
|
346
|
+
every point green or `fixme`, nothing red, and the last run before you claim anything is
|
|
347
|
+
a cold `--headed` run with the dev server stopped first. Headless wins timing races that
|
|
348
|
+
a demo-day browser loses, so a point that is green headless and red headed is red, and
|
|
349
|
+
headed is the mode the demo is actually shown in. Never put a command in the handoff
|
|
350
|
+
that you have not run yourself in exactly that form. Then: README with the start
|
|
351
|
+
command, the port and the manus command; commit `docs/MANUS.md` and
|
|
352
|
+
`docs/plans/round-1.md`. `haus doctor` shows `Profile: poc`; the CI-gate suggestion, the
|
|
353
|
+
`docs/SUMMARY.md` suggestion and the legacy `docs/adr/` migration finding are all gated
|
|
354
|
+
on the profile now, so a healthy PoC repo will not see any of the three, and seeing one
|
|
355
|
+
means the installed CLI predates this gate, not something to argue past. Whatever doctor
|
|
356
|
+
still flags here is real: read it and act on it, or, for a machine-level finding such as
|
|
357
|
+
a disabled global plugin, check it with the tool that owns it (`claude plugin list`)
|
|
358
|
+
before telling the user doctor is wrong. Then push if a remote exists (never for
|
|
296
359
|
local-only). Then stop: do NOT follow `references/init.md`
|
|
297
360
|
from step 3, because a PoC has no docs pass, no deep read and no recommend re-check. Hand off in
|
|
298
361
|
the user's language, naming the demo date, the two re-entry phrases and the decision the
|