@curdx/flow 2.0.0-beta.8 → 2.0.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.
@@ -40,17 +40,20 @@ ACTIVE=$(cat .flow/.active-spec 2>/dev/null)
40
40
  STATE_FILE=".flow/specs/$ACTIVE/.state.json"
41
41
  [ ! -f "$STATE_FILE" ] && exit 0
42
42
 
43
- # Read quickMode + mode
44
- QUICK_MODE=$(python3 -c "
45
- import json
43
+ # Read quickMode + mode. Pass STATE_FILE via env (NOT shell interpolation
44
+ # into the python source) so an active-spec name containing quotes/$ cannot
45
+ # inject python code.
46
+ export STATE_FILE
47
+ QUICK_MODE=$(python3 -c '
48
+ import json, os
46
49
  try:
47
- s = json.load(open('$STATE_FILE'))
48
- qm = s.get('quickMode', False)
49
- mode = s.get('mode', '')
50
- print('true' if (qm or mode == 'autonomous') else 'false')
50
+ s = json.load(open(os.environ["STATE_FILE"]))
51
+ qm = s.get("quickMode", False)
52
+ mode = s.get("mode", "")
53
+ print("true" if (qm or mode == "autonomous") else "false")
51
54
  except Exception:
52
- print('false')
53
- " 2>/dev/null)
55
+ print("false")
56
+ ' 2>/dev/null)
54
57
 
55
58
  if [ "$QUICK_MODE" = "true" ]; then
56
59
  # Block and inject guidance
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env bash
2
2
  # CurDX-Flow SessionStart Hook
3
3
  # Duties:
4
- # 1. Daily dependency check — nudge user to /flow-install-deps if recommended plugins missing
4
+ # 1. Daily dependency check — nudge user to `npx @curdx/flow install --all` if recommended plugins missing
5
5
  # 2. Load active spec progress into session context
6
6
  #
7
7
  # Design notes:
@@ -56,6 +56,12 @@ if ! command -v python3 >/dev/null 2>&1; then
56
56
  allow_stop
57
57
  fi
58
58
 
59
+ # Export STATE_FILE BEFORE invoking python3 — the heredoc-based parser reads
60
+ # os.environ["STATE_FILE"]. Previously the export was placed after the
61
+ # heredoc, so python3 always got None, json.load(None) silently failed, and
62
+ # the stop-hook strategy never activated.
63
+ export STATE_FILE
64
+
59
65
  read STRATEGY PHASE TASK_INDEX TOTAL_TASKS FAILED ROUNDS <<EOF
60
66
  $(python3 <<'PY'
61
67
  import json, os, sys
@@ -75,7 +81,6 @@ print(strategy, phase, ti, tt, failed, rounds)
75
81
  PY
76
82
  )
77
83
  EOF
78
- export STATE_FILE
79
84
 
80
85
  # Only activate for stop-hook strategy + execute phase
81
86
  [ "$STRATEGY" != "stop-hook" ] && allow_stop
@@ -95,12 +100,17 @@ if [ -n "$TRANSCRIPT_PATH" ] && [ -f "$TRANSCRIPT_PATH" ]; then
95
100
  TRANSCRIPT_TAIL=$(tail -c 51200 "$TRANSCRIPT_PATH" 2>/dev/null || echo "")
96
101
  fi
97
102
 
103
+ # Python state-file updates: use quoted heredocs (<<'PY') + os.environ so
104
+ # the spec-name-derived STATE_FILE path is NEVER interpolated into the
105
+ # python source text. Previously a spec name containing single quotes or
106
+ # $-signs could break the script or inject arbitrary code.
107
+
98
108
  # Check for explicit completion signals
99
109
  if echo "$TRANSCRIPT_TAIL" | grep -q "ALL_TASKS_COMPLETE"; then
100
110
  # Cleanup: mark phase completed
101
- python3 <<PY 2>/dev/null
102
- import json
103
- p = "$STATE_FILE"
111
+ python3 <<'PY' 2>/dev/null
112
+ import json, os
113
+ p = os.environ["STATE_FILE"]
104
114
  s = json.load(open(p))
105
115
  s.setdefault("phase_status", {})["execute"] = "completed"
106
116
  s["phase"] = "verify" # move to verify phase
@@ -112,16 +122,16 @@ fi
112
122
  # Check for fail signal (accumulate; actual stop decision below)
113
123
  if echo "$TRANSCRIPT_TAIL" | grep -q "TASK_FAILED"; then
114
124
  # Increment failed_attempts
115
- python3 <<PY 2>/dev/null
116
- import json
117
- p = "$STATE_FILE"
125
+ python3 <<'PY' 2>/dev/null
126
+ import json, os
127
+ p = os.environ["STATE_FILE"]
118
128
  s = json.load(open(p))
119
129
  s.setdefault("execute_state", {})
120
130
  s["execute_state"]["failed_attempts"] = s["execute_state"].get("failed_attempts", 0) + 1
121
131
  json.dump(s, open(p, "w"), indent=2, ensure_ascii=False)
122
132
  PY
123
- # Re-read
124
- FAILED=$(python3 -c "import json; print(json.load(open('$STATE_FILE'))['execute_state']['failed_attempts'])" 2>/dev/null || echo 0)
133
+ # Re-read — again via os.environ, no shell interpolation into python.
134
+ FAILED=$(python3 -c 'import json, os; print(json.load(open(os.environ["STATE_FILE"]))["execute_state"]["failed_attempts"])' 2>/dev/null || echo 0)
125
135
  fi
126
136
 
127
137
  # ---------- 6. Safety brakes ----------
@@ -138,9 +148,9 @@ fi
138
148
  # Check if all tasks done
139
149
  if [ "$TASK_INDEX" -ge "$TOTAL_TASKS" ] && [ "$TOTAL_TASKS" -gt 0 ]; then
140
150
  # Mark complete
141
- python3 <<PY 2>/dev/null
142
- import json
143
- p = "$STATE_FILE"
151
+ python3 <<'PY' 2>/dev/null
152
+ import json, os
153
+ p = os.environ["STATE_FILE"]
144
154
  s = json.load(open(p))
145
155
  s.setdefault("phase_status", {})["execute"] = "completed"
146
156
  s["phase"] = "verify"
@@ -151,9 +161,9 @@ fi
151
161
 
152
162
  # ---------- 7. Block and continue ----------
153
163
  # Increment round counter
154
- python3 <<PY 2>/dev/null
155
- import json
156
- p = "$STATE_FILE"
164
+ python3 <<'PY' 2>/dev/null
165
+ import json, os
166
+ p = os.environ["STATE_FILE"]
157
167
  s = json.load(open(p))
158
168
  s.setdefault("execute_state", {})
159
169
  s["execute_state"]["global_iteration"] = s["execute_state"].get("global_iteration", 0) + 1
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@curdx/flow",
3
- "version": "2.0.0-beta.8",
3
+ "version": "2.0.0",
4
4
  "description": "CLI installer for CurDX-Flow — AI engineering workflow meta-framework for Claude Code",
5
5
  "type": "module",
6
6
  "bin": {
7
- "flow": "bin/curdx-flow.js",
8
7
  "curdx-flow": "bin/curdx-flow.js"
9
8
  },
10
9
  "scripts": {
11
- "prepublishOnly": "node bin/curdx-flow.js --version"
10
+ "test": "node --test test/*.test.js",
11
+ "prepublishOnly": "node --test test/*.test.js && node bin/curdx-flow.js --version"
12
12
  },
13
13
  "files": [
14
14
  "bin/",
@@ -22,6 +22,7 @@
22
22
  "agent-preamble/",
23
23
  "templates/",
24
24
  "schemas/",
25
+ "skills/",
25
26
  "README.md",
26
27
  "CHANGELOG.md",
27
28
  "LICENSE"
@@ -43,5 +44,9 @@
43
44
  "installer",
44
45
  "ai-engineering",
45
46
  "curdx-flow"
46
- ]
47
+ ],
48
+ "dependencies": {
49
+ "@clack/prompts": "^0.8.2",
50
+ "picocolors": "^1.1.1"
51
+ }
47
52
  }
@@ -0,0 +1,62 @@
1
+ ---
2
+ name: brownfield-index
3
+ description: Invoke when the user is new to an unfamiliar / legacy / brownfield codebase and wants a structural understanding — module map, component inventory, API surface, data flow. Triggers on "legacy code", "brownfield", "unfamiliar", "new to this code", "new to this project", "just joined", "inherited codebase", "explore codebase", "understand structure", "index code", "map modules", "tour", "onboard", "what is this project".
4
+ allowed-tools: [Read, Grep, Glob, Bash]
5
+ ---
6
+
7
+ # Brownfield Index
8
+
9
+ You are invoked when the user needs a structural map of an existing codebase they are not yet familiar with.
10
+
11
+ ## Preconditions
12
+
13
+ 1. The repository root is the current working directory (or a path the user specifies).
14
+ 2. The project is not a new `/curdx-flow:init`-ed greenfield project (if it is, direct the user to `/curdx-flow:start` instead).
15
+
16
+ ## Workflow
17
+
18
+ ### Step 1: Detect project type
19
+
20
+ Read `package.json` / `Cargo.toml` / `pyproject.toml` / `go.mod` / `pom.xml` to classify the ecosystem and build tool. This determines which directory conventions to apply.
21
+
22
+ ### Step 2: Scan directory structure
23
+
24
+ Produce a top-level inventory:
25
+ - **Entry points** (main / index / bin scripts)
26
+ - **Module directories** (src/, lib/, internal/, pkg/ …)
27
+ - **Test directories**
28
+ - **Config files**
29
+ - **Tooling** (CI, lint, format configs)
30
+
31
+ ### Step 3: Component inventory
32
+
33
+ For each module directory, list:
34
+ - Files and their apparent role (inferred from names + top-of-file comments)
35
+ - Public exports / exported symbols
36
+ - Third-party dependencies imported
37
+
38
+ ### Step 4: API surface
39
+
40
+ If HTTP / RPC endpoints exist, index them: route → handler → middleware. For CLI tools, index commands → handlers.
41
+
42
+ ### Step 5: Write index document
43
+
44
+ Output `.flow/codebase-index.md` containing:
45
+ - **Overview** (project purpose, build tool, runtime)
46
+ - **Directory tree** (with per-directory one-liner descriptions)
47
+ - **Entry points** (where execution starts)
48
+ - **Key abstractions** (core types, interfaces, classes that everything else hangs off)
49
+ - **External dependencies** (grouped: prod runtime / dev tooling / transitive)
50
+ - **Known gaps / red flags** (missing tests, TODOs, suspicious patterns)
51
+
52
+ ### Step 6: Hand off
53
+
54
+ Point the user at the next useful action:
55
+ - "Looking to add a feature here? Run `/curdx-flow:start <name>` to begin a spec."
56
+ - "Debugging something specific? Run `/curdx-flow:debug '<symptom>'`."
57
+
58
+ ## Notes
59
+
60
+ This skill uses Read + Grep + Glob + Bash with no specialized agent — general tools are enough for structural discovery. The index is meant to be quick (5–10 minutes), not exhaustive.
61
+
62
+ For deep research into a specific library or framework, use `context7` MCP directly.
@@ -0,0 +1,50 @@
1
+ ---
2
+ name: browser-qa
3
+ description: Invoke when the user wants to test a UI/frontend in a real browser — accessibility, performance, console errors, network traffic, visual regression. Triggers on "browser test", "test in browser", "UI test", "e2e test", "frontend test", "accessibility", "a11y", "WCAG", "lighthouse", "performance audit", "console error", "network request", "cross-browser", "responsive", "mobile test", "visual regression", "screenshot".
4
+ allowed-tools: [Read, Write, Bash, Grep, Glob, WebFetch]
5
+ ---
6
+
7
+ # Browser QA
8
+
9
+ You are invoked when the user wants real-browser QA of a UI flow.
10
+
11
+ ## Preconditions
12
+
13
+ 1. `chrome-devtools` MCP is available (`mcp__chrome-devtools__*`). If missing, fall back to a manual checklist.
14
+ 2. A URL (dev server or deployed) is available. Prompt for it if not provided.
15
+
16
+ ## Workflow
17
+
18
+ ### Step 1: Clarify scope
19
+
20
+ Confirm with the user:
21
+ - **URL under test** (local `http://localhost:3000` or remote)
22
+ - **Flow to test** (e.g., "sign up → dashboard → logout")
23
+ - **What success looks like** (accessibility / performance / zero console errors / visual match)
24
+
25
+ ### Step 2: Dispatch `flow-qa-engineer`
26
+
27
+ Delegate to the `flow-qa-engineer` agent. It will:
28
+ 1. Open the target URL via `mcp__chrome-devtools__new_page`
29
+ 2. Drive the flow with `mcp__chrome-devtools__click` / `fill` / `navigate`
30
+ 3. Capture `list_console_messages`, `list_network_requests`, `take_screenshot`, optionally `lighthouse_audit`
31
+ 4. Compare against expected behavior
32
+
33
+ ### Step 3: Report findings
34
+
35
+ Produce `.flow/specs/<active>/qa-report.md` with:
36
+ - **Bugs** (reproducible, severity P1/P2/P3)
37
+ - **Performance** (LCP / INP / CLS from Lighthouse)
38
+ - **Accessibility** (axe violations with WCAG references)
39
+ - **Console errors** (full stack traces)
40
+ - **Screenshots** (attached)
41
+
42
+ ### Step 4: Hand off
43
+
44
+ If bugs found: suggest `/curdx-flow:debug "<bug title>"` for systematic root-cause analysis.
45
+ If accessibility violations: suggest fixes inline with WCAG refs.
46
+
47
+ ## References
48
+
49
+ - `flow-qa-engineer` agent: `@${CLAUDE_PLUGIN_ROOT}/agents/flow-qa-engineer.md`
50
+ - chrome-devtools MCP docs: https://github.com/ChromeDevTools/chrome-devtools-mcp
@@ -0,0 +1,68 @@
1
+ ---
2
+ name: epic
3
+ description: Invoke when user wants to break a large feature into multiple smaller specs with a dependency graph. Triggers on "epic", "big feature", "too big", "decompose", "break down", "break into", "split into", "multi-spec", "multiple features", "sub-features", "vertical slice", "parent feature", "large scope", "won't fit in one sprint", "needs splitting".
4
+ allowed-tools: [Read, Write, Grep, Glob, Bash]
5
+ ---
6
+
7
+ # Epic Decomposition
8
+
9
+ You are invoked when the user wants to break a large feature into multiple vertical-slice specs.
10
+
11
+ ## Preconditions
12
+
13
+ 1. A `.flow/` project must exist (run `/curdx-flow:init` first if missing).
14
+ 2. The user has stated a feature scope that is too large for a single spec.
15
+
16
+ ## Workflow
17
+
18
+ ### Step 1: Clarify the epic scope
19
+
20
+ Ask the user (or infer from context) for:
21
+ - **Epic name** (short identifier, kebab-case)
22
+ - **One-sentence goal** of the whole epic
23
+ - **Hard boundary**: what is explicitly out of scope for this epic
24
+
25
+ ### Step 2: Dispatch `flow-triage-analyst`
26
+
27
+ Delegate to the `flow-triage-analyst` agent with the epic name + goal + boundary. The agent returns:
28
+ - A vertical-slice decomposition (not horizontal by layer)
29
+ - Dependency graph between slices
30
+ - Shared interfaces that must be frozen before parallel work begins
31
+ - Suggested slice ordering (MVP → iteration → polish)
32
+
33
+ ### Step 3: Write epic manifest
34
+
35
+ Create `.flow/_epics/<epic-name>/epic.md` with:
36
+
37
+ ```markdown
38
+ # Epic: <name>
39
+
40
+ ## Goal
41
+ <one sentence>
42
+
43
+ ## Slices (vertical)
44
+ | ID | Slice | Depends on | Shared interface |
45
+ |----|-------|-----------|------------------|
46
+ | S1 | ... | — | — |
47
+ | S2 | ... | S1 | `types/auth.ts` |
48
+ | S3 | ... | S1 | — |
49
+
50
+ ## Frozen Interfaces
51
+ (contracts that must not change once slices start)
52
+
53
+ ## Out of Scope
54
+ - ...
55
+ ```
56
+
57
+ ### Step 4: Scaffold sub-spec skeletons
58
+
59
+ For each slice, create `.flow/specs/<epic-name>-<slice-id>/` with a minimal `.state.json` linking back to the epic manifest.
60
+
61
+ ### Step 5: Report to user
62
+
63
+ Summarize: "Epic `<name>` decomposed into N vertical slices. Start any slice with `/curdx-flow:start <epic-name>-<slice-id>`. Suggested order: S1 → S2 → S3."
64
+
65
+ ## References
66
+
67
+ - Vertical-slice methodology: `@${CLAUDE_PLUGIN_ROOT}/knowledge/epic-decomposition.md`
68
+ - Spec skeleton: `@${CLAUDE_PLUGIN_ROOT}/templates/`
@@ -0,0 +1,50 @@
1
+ ---
2
+ name: security-audit
3
+ description: Invoke when the user wants a security review — OWASP Top 10, STRIDE threat modeling, credential handling, injection, secrets, sensitive data handling. Triggers on "security", "auth", "authentication", "credential", "password", "secret", "API key", "token", "OWASP", "STRIDE", "CVE", "vulnerability", "injection", "XSS", "CSRF", "SSRF", "SQL injection", "hardcoded secret", "sensitive data", "leak", "will my API key leak", "is this safe".
4
+ allowed-tools: [Read, Grep, Glob, Bash, WebSearch]
5
+ ---
6
+
7
+ # Security Audit
8
+
9
+ You are invoked when the user wants a systematic security review of the current spec or codebase.
10
+
11
+ ## Preconditions
12
+
13
+ 1. The code or spec under review is reachable from the current working directory.
14
+ 2. The user has identified the scope (current spec, specific module, or whole repo).
15
+
16
+ ## Workflow
17
+
18
+ ### Step 1: Clarify audit scope
19
+
20
+ Confirm:
21
+ - **Scope** (current spec / specific paths / whole repo)
22
+ - **Depth** (OWASP-only / OWASP + STRIDE / + dependency CVE scan)
23
+ - **Risk tolerance** (block on any SR / only block on SR with POC / advisory only)
24
+
25
+ ### Step 2: Dispatch `flow-security-auditor`
26
+
27
+ Delegate to the `flow-security-auditor` agent. It will:
28
+ 1. Scan for hardcoded secrets, weak crypto, unsanitized inputs
29
+ 2. Apply OWASP Top 10 (A01 Broken Access Control → A10 SSRF)
30
+ 3. Apply STRIDE threat modeling (Spoofing, Tampering, Repudiation, Information disclosure, DoS, Elevation)
31
+ 4. Run dependency CVE scan (`npm audit` / equivalent)
32
+ 5. Produce a findings report with severity labels (SR = Blocking Red line, SW = Warning, SM = Mandatory-to-address)
33
+
34
+ ### Step 3: Write security report
35
+
36
+ Output `.flow/specs/<active>/security-audit.md` containing:
37
+ - **SR (blocking)** — must fix before ship
38
+ - **SW (warning)** — should fix, won't block
39
+ - **SM (mandatory)** — baseline items that must be present
40
+ - **CVE hits** — direct / transitive dependencies with known vulns
41
+ - **Recommended fixes** — concrete patches, not generic advice
42
+
43
+ ### Step 4: Enforce gate
44
+
45
+ Apply the `security-gate` (`@${CLAUDE_PLUGIN_ROOT}/gates/security-gate.md`) — if any SR findings exist, block completion until remediated or explicitly waived with a D-NN decision in STATE.md.
46
+
47
+ ## References
48
+
49
+ - `flow-security-auditor` agent: `@${CLAUDE_PLUGIN_ROOT}/agents/flow-security-auditor.md`
50
+ - security-gate: `@${CLAUDE_PLUGIN_ROOT}/gates/security-gate.md`
@@ -0,0 +1,49 @@
1
+ ---
2
+ name: ui-sketch
3
+ description: Invoke when the user wants UI design drafts — components, layouts, variants, mockups, CSS/theme/styling decisions. Triggers on "design UI", "UI design", "component layout", "variants", "wireframe", "mockup", "prototype", "sketch", "draft layout", "visual design", "styling", "CSS", "theming", "dark mode", "responsive design", "color scheme", "build me a UI", "show several variants", "try different colors".
4
+ allowed-tools: [Read, Write, Bash, WebSearch]
5
+ ---
6
+
7
+ # UI Sketch
8
+
9
+ You are invoked when the user wants fresh UI design drafts — typically 2–4 variants for comparison, or a single iterative refinement.
10
+
11
+ ## Preconditions
12
+
13
+ 1. The `frontend-design` skill (Anthropic official) should be installed. Without it, fall back to Tailwind + shadcn/ui defaults.
14
+ 2. The user provides a description of the UI goal (component, page, or flow).
15
+
16
+ ## Workflow
17
+
18
+ ### Step 1: Clarify design brief
19
+
20
+ Confirm with the user:
21
+ - **What is being designed** (component / page / full screen)
22
+ - **Context** (consumer product / enterprise tool / marketing site / internal dashboard)
23
+ - **Must-haves** (brand colors / existing design system / responsive breakpoints)
24
+ - **Variant count** (default: 3 variants with distinct design directions)
25
+
26
+ ### Step 2: Dispatch `flow-ux-designer`
27
+
28
+ Delegate to the `flow-ux-designer` agent with the brief. It will:
29
+ 1. Invoke the `frontend-design` skill with the brief
30
+ 2. Generate N variant HTML/JSX files under `.flow/specs/<active>/sketches/`
31
+ 3. For each variant, produce a rationale: typography, color, layout decisions
32
+ 4. Open the variants for user preview if a dev server is running
33
+
34
+ ### Step 3: Present variants
35
+
36
+ Show the user:
37
+ - **Variant preview URLs** or file paths
38
+ - **Design rationale** per variant (what's different, why)
39
+ - **Accessibility notes** (contrast ratios, focus states)
40
+
41
+ ### Step 4: Iterate or finalize
42
+
43
+ - If user picks a variant: move the chosen file into the spec's `design.md` asset section.
44
+ - If user wants a hybrid: dispatch `flow-ux-designer` again with "merge variant A layout + variant B color scheme".
45
+
46
+ ## References
47
+
48
+ - `flow-ux-designer` agent: `@${CLAUDE_PLUGIN_ROOT}/agents/flow-ux-designer.md`
49
+ - `flow-ui-researcher` agent (for competitive reference scraping): `@${CLAUDE_PLUGIN_ROOT}/agents/flow-ui-researcher.md`
@@ -1,31 +0,0 @@
1
- #!/usr/bin/env bash
2
- # CurDX-Flow PostToolUseFailure Hook
3
- # Tracks consecutive tool failures to enable pua integration (Phase 4+).
4
- # For now, just maintains a counter in plugin data directory.
5
- #
6
- # Future: when pua is installed and fail_count >= threshold, auto-invoke /pua:pua.
7
-
8
- set -u
9
-
10
- DATA_DIR="${CLAUDE_PLUGIN_DATA:-$HOME/.claude/plugins/data/curdx-flow}"
11
- COUNTER="$DATA_DIR/fail-count"
12
-
13
- mkdir -p "$DATA_DIR" 2>/dev/null || true
14
-
15
- # Read current count
16
- CURRENT=0
17
- [ -f "$COUNTER" ] && CURRENT="$(cat "$COUNTER" 2>/dev/null || echo 0)"
18
-
19
- # Increment
20
- NEXT=$((CURRENT + 1))
21
- echo "$NEXT" > "$COUNTER" 2>/dev/null || true
22
-
23
- # Placeholder for future pua escalation (Phase 4+):
24
- # if [ "$NEXT" -ge 2 ] && command -v claude >/dev/null 2>&1; then
25
- # if claude plugin list 2>/dev/null | grep -q 'pua'; then
26
- # # Inject escalation suggestion via hook output
27
- # ...
28
- # fi
29
- # fi
30
-
31
- exit 0