@mhd-ghaith-abtah/flow 0.7.2-beta.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.
Files changed (53) hide show
  1. package/CHANGELOG.md +87 -0
  2. package/LICENSE +21 -0
  3. package/README.md +162 -0
  4. package/adapters/e2e/_interface.md +42 -0
  5. package/adapters/e2e/none.md +15 -0
  6. package/adapters/e2e/playwright-mcp.md +86 -0
  7. package/adapters/issue-tracker/_interface.md +46 -0
  8. package/adapters/issue-tracker/github-issues.md +103 -0
  9. package/adapters/issue-tracker/linear.md +65 -0
  10. package/adapters/issue-tracker/none.md +26 -0
  11. package/adapters/pr/_interface.md +29 -0
  12. package/adapters/pr/github.md +61 -0
  13. package/adapters/pr/none.md +32 -0
  14. package/adapters/verify/_interface.md +26 -0
  15. package/adapters/verify/custom.md +27 -0
  16. package/adapters/verify/make.md +30 -0
  17. package/adapters/verify/pnpm.md +27 -0
  18. package/bin/flow.js +129 -0
  19. package/catalog.yaml +364 -0
  20. package/docs/adapters.md +99 -0
  21. package/docs/migrate-from-bmad.md +95 -0
  22. package/docs/profiles.md +81 -0
  23. package/docs/quickstart.md +82 -0
  24. package/lib/catalog.js +164 -0
  25. package/lib/commands/add.js +147 -0
  26. package/lib/commands/doctor.js +392 -0
  27. package/lib/commands/init.js +86 -0
  28. package/lib/commands/install.js +181 -0
  29. package/lib/commands/plan.js +108 -0
  30. package/lib/commands/remove.js +87 -0
  31. package/lib/commands/uninstall.js +157 -0
  32. package/lib/repo-root.js +53 -0
  33. package/package.json +62 -0
  34. package/schemas/catalog.schema.json +155 -0
  35. package/schemas/flow-config.schema.json +85 -0
  36. package/schemas/install-state.schema.json +79 -0
  37. package/skills/flow-doctor/SKILL.md +15 -0
  38. package/skills/flow-doctor/workflow.md +157 -0
  39. package/skills/flow-init/SKILL.md +10 -0
  40. package/skills/flow-init/workflow.md +420 -0
  41. package/skills/flow-sprint/SKILL.md +10 -0
  42. package/skills/flow-sprint/workflow.md +394 -0
  43. package/skills/flow-story/SKILL.md +12 -0
  44. package/skills/flow-story/workflow.md +531 -0
  45. package/templates/claude-md-section.md.tmpl +55 -0
  46. package/templates/flow-readme.md.tmpl +34 -0
  47. package/templates/flow.config.yaml.tmpl +94 -0
  48. package/templates/pr.md.tmpl +40 -0
  49. package/templates/retro.md.tmpl +58 -0
  50. package/templates/sprint.yaml.tmpl +18 -0
  51. package/templates/story.md.tmpl +35 -0
  52. package/tools/fix-caveman-shrink.sh +68 -0
  53. package/tools/lint-changelog.js +98 -0
@@ -0,0 +1,85 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://github.com/mhd-ghaith-abtah/flow/schemas/flow-config.schema.json",
4
+ "title": "Flow project config",
5
+ "description": "Per-project configuration written by /flow-init. Intended to be committed (team-share). Per-developer overrides go in flow.config.local.yaml (gitignored, deep-merged on top).",
6
+ "type": "object",
7
+ "required": ["version", "mode", "adapters"],
8
+ "properties": {
9
+ "version": { "type": "integer", "minimum": 1 },
10
+ "generated": { "type": "string" },
11
+ "flow_version": { "type": "string" },
12
+ "mode": { "type": "string", "enum": ["minimal", "mini", "standard", "team"] },
13
+
14
+ "sprint_file": { "type": "string" },
15
+ "stories_dir": { "type": "string" },
16
+ "journeys_dir": { "type": "string" },
17
+ "retros_dir": { "type": "string" },
18
+ "archive_dir": { "type": "string" },
19
+ "deferred_file": { "type": "string" },
20
+ "artifacts_dir": { "type": "string" },
21
+
22
+ "adapters": {
23
+ "type": "object",
24
+ "required": ["issue_tracker", "pr", "e2e", "verify"],
25
+ "properties": {
26
+ "issue_tracker": { "type": "string" },
27
+ "pr": { "type": "string" },
28
+ "e2e": { "type": "string" },
29
+ "verify": { "type": "string" }
30
+ },
31
+ "additionalProperties": false
32
+ },
33
+
34
+ "integrations": {
35
+ "type": "object",
36
+ "additionalProperties": true
37
+ },
38
+
39
+ "review": {
40
+ "type": "object",
41
+ "properties": {
42
+ "use_separate_model": { "type": "boolean" },
43
+ "auto_hard_review_tags": { "type": "array", "items": { "type": "string" } },
44
+ "language_reviewer": { "type": ["string", "null"] },
45
+ "barrier_timeout_seconds": { "type": "integer", "minimum": 60, "maximum": 7200 }
46
+ },
47
+ "additionalProperties": false
48
+ },
49
+
50
+ "implement": {
51
+ "type": "object",
52
+ "properties": {
53
+ "default": { "type": "string" },
54
+ "use_tdd": { "type": "boolean" },
55
+ "e2e_auto_trigger_tags": { "type": "array", "items": { "type": "string" } },
56
+ "docs_auto_trigger": { "type": "boolean" }
57
+ },
58
+ "additionalProperties": true
59
+ },
60
+
61
+ "pr": {
62
+ "type": "object",
63
+ "properties": {
64
+ "auto_merge_wait_seconds": { "type": "integer", "minimum": 5, "maximum": 600 }
65
+ },
66
+ "additionalProperties": true
67
+ },
68
+
69
+ "secrets": {
70
+ "type": "object",
71
+ "properties": {
72
+ "store": { "type": "string", "enum": ["env_file", "shell", "onepassword"] }
73
+ },
74
+ "additionalProperties": true
75
+ },
76
+
77
+ "reference_docs": { "type": "array", "items": { "type": "string" } },
78
+
79
+ "upstreams": {
80
+ "type": "object",
81
+ "additionalProperties": true
82
+ }
83
+ },
84
+ "additionalProperties": true
85
+ }
@@ -0,0 +1,79 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://github.com/mhd-ghaith-abtah/flow/schemas/install-state.schema.json",
4
+ "title": "Flow install state",
5
+ "description": "Records what Flow installed at a given scope (home or project). Used for diffing on /flow-init --update and for /flow-doctor checks.",
6
+ "type": "object",
7
+ "required": ["schema_version"],
8
+ "properties": {
9
+ "schema_version": {
10
+ "type": "string",
11
+ "pattern": "^flow\\.install\\.v[0-9]+$"
12
+ },
13
+ "scope": { "type": "string", "enum": ["home", "project"] },
14
+ "installed_at": { "type": "string", "format": "date-time" },
15
+ "updated_at": { "type": "string", "format": "date-time" },
16
+ "flow_version": { "type": "string" },
17
+ "profile": { "type": "string" },
18
+ "components": {
19
+ "type": "array",
20
+ "items": {
21
+ "type": "object",
22
+ "required": ["id"],
23
+ "properties": {
24
+ "id": { "type": "string" },
25
+ "installed_at": { "type": "string", "format": "date-time" },
26
+ "paths": { "type": "array", "items": { "type": "string" } }
27
+ },
28
+ "additionalProperties": true
29
+ }
30
+ },
31
+ "adapters": {
32
+ "type": "object",
33
+ "additionalProperties": {
34
+ "type": "object",
35
+ "properties": {
36
+ "id": { "type": "string" },
37
+ "installed_at": { "type": "string", "format": "date-time" }
38
+ }
39
+ }
40
+ },
41
+ "mcps": {
42
+ "type": "array",
43
+ "items": {
44
+ "type": "object",
45
+ "required": ["id"],
46
+ "properties": {
47
+ "id": { "type": "string" },
48
+ "registered_at": { "type": "string", "format": "date-time" },
49
+ "scope": { "type": "string", "enum": ["home", "project"] },
50
+ "auth_pending": { "type": "boolean" }
51
+ },
52
+ "additionalProperties": true
53
+ }
54
+ },
55
+ "upstreams": {
56
+ "type": "object",
57
+ "properties": {
58
+ "bmad": { "$ref": "#/definitions/upstream_record" },
59
+ "ecc": { "$ref": "#/definitions/upstream_record" },
60
+ "caveman": { "$ref": "#/definitions/upstream_record" }
61
+ },
62
+ "additionalProperties": true
63
+ }
64
+ },
65
+ "additionalProperties": true,
66
+
67
+ "definitions": {
68
+ "upstream_record": {
69
+ "type": "object",
70
+ "properties": {
71
+ "installed": { "type": "boolean" },
72
+ "subset": { "type": "string" },
73
+ "version": { "type": "string" },
74
+ "installed_at": { "type": "string", "format": "date-time" }
75
+ },
76
+ "additionalProperties": true
77
+ }
78
+ }
79
+ }
@@ -0,0 +1,15 @@
1
+ ---
2
+ name: flow-doctor
3
+ description: 'Health check for a Flow installation. Verifies catalog, install-state, flow.config.yaml, adapters, MCPs, required CLIs, upstream installers (BMad / ECC / Caveman), and known-bug probes (e.g., caveman-shrink standalone-vs-wrapper). Use when the user runs `/flow-doctor` or `flow doctor`. Read-only by default. With `--fix`, attempts safe auto-repairs (re-register caveman-shrink wrapper, regenerate adapter symlinks, recreate missing state files).'
4
+ argument-hint: '[--mcp <id>] [--fix] [--json] [--verbose]'
5
+ version: 0.0.1
6
+ ---
7
+
8
+ Follow the instructions in ./workflow.md.
9
+
10
+ Resolves `{repo-root}` the same way `flow-init` does (`$FLOW_REPO_ROOT` env, then walk up from `~/.claude/skills/flow-doctor/`, then CWD). Runs the doctor checklist from `flow-init` step 13 as a standalone, plus extra probes for known bugs (e.g., caveman-shrink mis-registered as standalone instead of wrapping context7).
11
+
12
+ Exit codes (when invoked from `bin/flow.js doctor`):
13
+ - `0` — all checks pass or only ℹ findings
14
+ - `1` — at least one ⚠ warning
15
+ - `2` — at least one ✗ failure
@@ -0,0 +1,157 @@
1
+ # flow-doctor — health check
2
+
3
+ <workflow>
4
+
5
+ <step n="1" goal="Locate the catalog and existing state">
6
+ <action>Resolve `{{repo_root}}`:
7
+ - If env `FLOW_REPO_ROOT` is set, use it.
8
+ - Else if running from `~/.claude/skills/flow-doctor/`, walk up to find a directory containing `catalog.yaml`.
9
+ - Else if the CWD contains `catalog.yaml`, use the CWD (dev mode).
10
+ - Else record `catalog: ✗ not found` and continue with reduced checks.
11
+ </action>
12
+
13
+ <action>Read `{{home_state}}` from `$HOME/.claude/flow/install-state.json` if it exists.</action>
14
+ <action>Read `{{project_state}}` from `$CWD/.claude/flow/install-state.json` if it exists.</action>
15
+ <action>Read `{{flow_config}}` from `$CWD/flow.config.yaml` if it exists.</action>
16
+ <action>Parse `--fix`, `--mcp <id>`, `--json`, `--verbose` from args.</action>
17
+ </step>
18
+
19
+ <step n="2" goal="Catalog + schema integrity">
20
+ <action>Probe:
21
+ - `{{repo_root}}/catalog.yaml` exists and parses as YAML → `catalog.parse`
22
+ - `{{repo_root}}/schemas/catalog.schema.json` exists → `catalog.schema_present`
23
+ - If schema present, validate catalog against it → `catalog.schema_valid`
24
+ </action>
25
+ </step>
26
+
27
+ <step n="3" goal="State integrity">
28
+ <action>Probe:
29
+ - `home_state` JSON parses, schema version starts with `flow.install.v` → `state.home_parse`
30
+ - `project_state` JSON parses, schema version starts with `flow.install.v` → `state.project_parse`
31
+ - `flow.config.yaml` parses, has at least `profile` + `adapters` keys → `state.config_parse`
32
+ </action>
33
+ </step>
34
+
35
+ <step n="4" goal="Adapter wiring">
36
+ <action>For each adapter referenced in `flow.config.yaml.adapters` (one per family: issue-tracker, pr, e2e, verify):
37
+ - Verify the adapter file exists at `{{repo_root}}/adapters/<family>/<adapter-id>.md` → `adapter.<family>.file`
38
+ - Probe `.claude/flow/adapters/<family>.md` or `.claude/flow/adapters/<family>/<adapter-id>.md` (depending on layout):
39
+ - If it's a symlink → resolve target. Record `adapter.<family>.kind: symlink → <target>`. If target doesn't exist, record `⚠ broken symlink`.
40
+ - If it's a regular file → record `adapter.<family>.kind: regular_file`. Issue #28: this is the **mixed state** — Flow expects symlinks (so updating the upstream `adapters/<family>/*.md` propagates automatically), but a regular file means someone edited the project-side copy directly. Record `bug.adapter_symlink_drift: ⚠ <family> is a regular file, will not pick up upstream adapter updates` and suggest `flow adapter swap <family> <id>` (forces re-symlink) or accept the divergence intentionally.
41
+ - If neither exists → record `⚠ adapter file missing` (suggest `flow-init --repair`).
42
+ </action>
43
+ </step>
44
+
45
+ <step n="5" goal="MCP reachability">
46
+ <action>Run `claude mcp list` (capture output; if `claude` CLI missing, record `mcp.cli_present: ✗` and skip).</action>
47
+ <action>For each MCP recorded in `home_state.mcps` (or `project_state.mcps`), verify it appears in `claude mcp list` output → `mcp.<id>.registered`.</action>
48
+ <action>If `--mcp <id>` passed, deep-probe only that MCP (attempt a no-op tool call) → `mcp.<id>.responding`.</action>
49
+ </step>
50
+
51
+ <step n="6" goal="Required CLIs">
52
+ <action>For each adapter, check its declared CLI deps (from `catalog.yaml.adapters.<family>.<id>.requires_cli`):
53
+ - `which <cli>` → record presence
54
+ - If missing, record `cli.<name>: ✗ not in $PATH`
55
+ </action>
56
+ </step>
57
+
58
+ <step n="7" goal="Upstream installers">
59
+ <action>Probe each declared upstream:
60
+ - **BMad:** `test -d _bmad` OR `test -d docs/_bmad-output` → `upstream.bmad.present`. If present, parse `_bmad/_config/manifest.yaml` for version.
61
+ - **ECC:** check for `~/.claude/rules/common/` and `~/.claude/skills/<known-ecc-skill>` presence → `upstream.ecc.present`. Read recorded ECC profile from `home_state.upstreams.ecc.profile`.
62
+ - **Caveman:** check `~/.claude/skills/caveman/` and `~/.claude/skills/caveman-shrink/` → `upstream.caveman.present`.
63
+ </action>
64
+ </step>
65
+
66
+ <step n="8" goal="Known-bug probes">
67
+ <action>**caveman-shrink standalone-vs-wrapper probe** (issue #5): caveman-shrink is an MCP **proxy** — it must be invoked with an upstream command to wrap (e.g., `npx caveman-shrink npx @upstash/context7-mcp@latest`). Registering it standalone (no upstream args) crashes immediately with `-32000` because `index.js` exits at "missing upstream command".
68
+ - Run `claude mcp get caveman-shrink 2>/dev/null` to fetch the registration. If absent, record `caveman_shrink.registered: ℹ not registered` and skip.
69
+ - Parse the command line. A correctly-wrapped registration has at least 3 tokens **after** the `caveman-shrink` invocation (e.g., `npx caveman-shrink npx <pkg>` → 2+ tokens after `caveman-shrink`).
70
+ - A standalone (broken) registration has 0 tokens after `caveman-shrink` and will return `-32000` on first call. Record `bug.caveman_shrink_standalone: ⚠ caveman-shrink registered without upstream — will fail with -32000`.
71
+ - With `--fix`, re-register by running `{{repo_root}}/tools/fix-caveman-shrink.sh <upstream-name>` (default upstream: `context7`). Script prints the exact `claude mcp remove` + `claude mcp add` commands; user runs them.
72
+ </action>
73
+
74
+ <action>**Severity-label preservation probe** (issue #6):
75
+ - If `caveman:caveman-review` skill is installed, check whether the most-recent `## Review Notes` blocks in `docs/flow/stories/*.md` retain `CRITICAL` / `HIGH` / `MEDIUM` / `LOW` literal labels.
76
+ - If recent compressed review notes are missing any severity label, record `bug.severity_labels_stripped: ⚠`.
77
+ </action>
78
+
79
+ <action>**Plan/Verified/Review-Notes loose-match probe** (issue #10):
80
+ - For each story in `docs/flow/stories/*.md`, run `grep -c '^## Plan$'` (anchored, exact). Compare to `grep -c '^## Plan'` (loose). If counts differ, record `bug.plan_marker_loose: ⚠ <story-id>`.
81
+ </action>
82
+
83
+ <action>**Upstream version-drift probe** (issue #12):
84
+ - For each upstream (bmad, ecc, caveman): read recorded `version` from `home_state.upstreams.<name>.version`. If absent, record `drift.<name>: ℹ not pinned (install pre-dates pinning)`.
85
+ - Read currently-installed version (same resolution chain as `/flow-init`: BMad → `_bmad/_config/manifest.yaml`; ECC → `~/.claude/rules/VERSION`; Caveman → `~/.claude/plugins/cache/caveman/caveman/*/package.json`).
86
+ - If recorded ≠ current AND neither is `unknown@*`, record `drift.<name>: ⚠ pinned <recorded>, installed <current>`. Suggest: `flow-init --update --pin-upstream <name>` to re-pin, or `flow-init --repair --upstream <name>` to reinstall the pinned version.
87
+ </action>
88
+
89
+ <action>**Caveman global-scope probe** (issue #9 + #25):
90
+ - Caveman's `SessionStart` hook (`~/.claude/hooks/caveman-activate.js`) runs in every Claude Code session, including non-Flow projects. This is by design upstream but can surprise users who only wanted Caveman in Flow projects.
91
+ - Probe: detect whether the current CWD has `flow.config.yaml`. If NOT (we're outside a Flow project) AND `test -f ~/.claude/.caveman-active` (Caveman is active here), record `info.caveman_global_scope: ℹ Caveman active outside a Flow project (this is upstream default)`.
92
+ - Suggest in the report: to gate Caveman per-project, either (a) set Caveman's default mode to `off` via `~/.claude/.caveman-mode = off`, then add a per-project `~/.claude/hooks/caveman-config.local.js` that flips it to `full` when `flow.config.yaml` is detected, or (b) file an upstream request with the Caveman project for native project-scope detection. Don't auto-fix — modifying Caveman's hooks affects every session.
93
+ </action>
94
+ </step>
95
+
96
+ <step n="9" goal="Render report">
97
+ <output>━━━ flow doctor ━━━
98
+
99
+ Catalog: {{catalog.parse ? ✓ : ✗}} ({{catalog.path}})
100
+ Schemas: {{catalog.schema_valid ? ✓ : (catalog.schema_present ? ⚠ invalid : ℹ not present)}}
101
+
102
+ State:
103
+ Home: {{state.home_parse ? ✓ : ✗}} ({{home_state.path}})
104
+ Project: {{state.project_parse ? ✓ : ✗}} ({{project_state.path}})
105
+ Config: {{state.config_parse ? ✓ : ✗}}
106
+
107
+ Adapters:
108
+ {{ for each family: "<family>: <adapter-id> <✓|⚠|✗>" }}
109
+
110
+ MCPs:
111
+ {{ for each mcp: "<id>: <✓ registered|⚠ not responding|✗ missing>" }}
112
+
113
+ CLIs:
114
+ {{ for each cli: "<name>: <✓|✗ not in $PATH>" }}
115
+
116
+ Upstreams:
117
+ BMad: {{upstream.bmad.present ? ✓ : ℹ not installed}} {{version}}
118
+ ECC: {{upstream.ecc.present ? ✓ : ℹ not installed}} {{profile}}
119
+ Caveman: {{upstream.caveman.present ? ✓ : ℹ not installed}}
120
+
121
+ Known-bug probes:
122
+ {{ for each probe: "<name>: <✓ clean|⚠ flagged: <fix-hint>>" }}
123
+
124
+ Summary: {{n_ok}} ✓ · {{n_warn}} ⚠ · {{n_fail}} ✗
125
+ </output>
126
+ </step>
127
+
128
+ <step n="10" goal="Auto-repair (only if --fix)">
129
+ <check if="--fix AND bug.caveman_shrink_standalone == ⚠">
130
+ <output>🔧 Re-registering caveman-shrink as a wrapper…</output>
131
+ <action>Invoke `{{repo_root}}/tools/fix-caveman-shrink.sh ${args.shrink_upstream || 'context7'}`. Script prints the `claude mcp remove caveman-shrink` and `claude mcp add ...` commands. Print the exact commands; do NOT auto-run them (modifying MCP registration without user consent is a side-effect on every Claude Code session).</action>
132
+ </check>
133
+
134
+ <check if="--fix AND any adapter.<family>.symlink == ✗">
135
+ <action>Re-create the missing symlink(s) from `{{repo_root}}/adapters/<family>/<id>.md` → `$CWD/.claude/flow/adapters/<family>.md`.</action>
136
+ </check>
137
+
138
+ <check if="--fix AND state.home_parse == ✗ AND home_state file exists but invalid">
139
+ <action>Move the broken file to `<path>.broken.<timestamp>`, write a fresh empty state with current schema version, print "Re-run /flow-init to re-populate."</action>
140
+ </check>
141
+ </step>
142
+
143
+ </workflow>
144
+
145
+ ---
146
+
147
+ ## Handling failures
148
+
149
+ - **catalog.yaml missing entirely:** Doctor still runs reduced checks (state + config + MCPs + CLIs) and prints `Run /flow-init` at the bottom.
150
+ - **`claude` CLI missing:** All MCP checks skip with `mcp.cli_present: ✗`. Doctor itself still completes.
151
+ - **`--fix` makes things worse:** Every fix logs to `~/.claude/flow/doctor.log` with a timestamp + before/after. The user can restore the pre-fix state manually from `<path>.broken.<timestamp>` snapshots.
152
+
153
+ ## Exit codes (when invoked via `bin/flow.js doctor`)
154
+
155
+ - `0` — all ✓ or only ℹ
156
+ - `1` — at least one ⚠
157
+ - `2` — at least one ✗
@@ -0,0 +1,10 @@
1
+ ---
2
+ name: flow-init
3
+ description: 'Interactive first-time installer for Flow. Detects project shape, asks for profile + adapters + upstream choices, delegates to BMad / ECC installers, configures MCP servers, scaffolds docs/flow/, and writes install-state.json. Use when the user runs `/flow-init`. Idempotent — safe to re-run with --update.'
4
+ argument-hint: '[--profile mini|standard|team] [--update] [--repair] [--dry-run] [--yes] [--catalog-source <path|url>]'
5
+ version: 0.0.1
6
+ ---
7
+
8
+ Follow the instructions in ./workflow.md.
9
+
10
+ Loads the catalog from `{repo-root}/catalog.yaml` (resolved via `$FLOW_REPO_ROOT` env or by walking up from `~/.claude/skills/flow-init/`). When invoked with `--update` or `--repair`, reads the existing install-state.json and runs in delta mode. Otherwise runs the full first-install flow.