@curdx/flow 2.2.5 → 2.3.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.
@@ -6,7 +6,7 @@
6
6
  },
7
7
  "metadata": {
8
8
  "description": "Claude Code Discipline Layer — spec-driven workflow + goal-backward verification + Karpathy 4 principles enforced via gates. Stops Claude from faking \"done\" on non-trivial features.",
9
- "version": "2.2.5"
9
+ "version": "2.3.1"
10
10
  },
11
11
  "allowCrossMarketplaceDependenciesOn": [
12
12
  "context7-marketplace"
@@ -16,7 +16,7 @@
16
16
  "name": "curdx-flow",
17
17
  "source": "./",
18
18
  "description": "Claude Code Discipline Layer — spec-driven workflow + goal-backward verification + Karpathy 4 principles enforced via gates. Stops Claude from faking \"done\" on non-trivial features.",
19
- "version": "2.2.5",
19
+ "version": "2.3.1",
20
20
  "author": {
21
21
  "name": "wdx",
22
22
  "email": "bydongxin@gmail.com"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "curdx-flow",
3
- "version": "2.2.5",
3
+ "version": "2.3.1",
4
4
  "description": "Claude Code Discipline Layer — spec-driven workflow + goal-backward verification + Karpathy 4 principles enforced via gates. Stops Claude from faking \"done\" on non-trivial features.",
5
5
  "author": {
6
6
  "name": "wdx",
@@ -25,6 +25,7 @@
25
25
  "./agents/flow-debugger.md",
26
26
  "./agents/flow-edge-hunter.md",
27
27
  "./agents/flow-executor.md",
28
+ "./agents/flow-orchestrator.md",
28
29
  "./agents/flow-planner.md",
29
30
  "./agents/flow-product-designer.md",
30
31
  "./agents/flow-qa-engineer.md",
@@ -37,6 +38,30 @@
37
38
  "./agents/flow-verifier.md"
38
39
  ],
39
40
  "hooks": "./hooks/hooks.json",
41
+ "outputStyles": "./output-styles/",
42
+ "monitors": "./monitors/monitors.json",
43
+ "userConfig": {
44
+ "autonomous_blocking": {
45
+ "type": "boolean",
46
+ "title": "Autonomous stop-hook blocking",
47
+ "description": "Keep stop-hook execution running until the active spec finishes when work remains.",
48
+ "default": true
49
+ },
50
+ "daily_dependency_check": {
51
+ "type": "boolean",
52
+ "title": "Daily dependency reminder",
53
+ "description": "Show a once-per-day reminder when recommended companion plugins are missing.",
54
+ "default": true
55
+ },
56
+ "monitor_interval_seconds": {
57
+ "type": "number",
58
+ "title": "Flow monitor polling interval",
59
+ "description": "How often the CurDX-Flow plugin monitor polls .flow state and task progress.",
60
+ "default": 8,
61
+ "min": 3,
62
+ "max": 60
63
+ }
64
+ },
40
65
  "dependencies": [
41
66
  {
42
67
  "name": "context7-plugin",
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.3.1
4
+
5
+ - expanded `doctor` to report CurDX-Flow’s bundled main-thread agent, monitor surface, and plugin option defaults
6
+ - documented where Claude Code stores CurDX-Flow non-sensitive `userConfig` values in `pluginConfigs`
7
+ - added troubleshooting guidance for stop-hook blocking and plugin monitor behavior
8
+
9
+ ## 2.3.0
10
+
11
+ - added a default `flow-orchestrator` main-thread agent through plugin-level `settings.json`
12
+ - added a plugin `flow-state` monitor plus `userConfig` runtime knobs for stop-hook blocking, dependency reminders, and monitor cadence
13
+ - made the manifest explicit about `outputStyles` and `monitors`, shipped the monitor assets in npm tarballs, and strengthened pack/plugin contract tests
14
+ - updated doctor/runtime guidance and public docs to reflect the new main-agent + monitor architecture
15
+
3
16
  ## 2.2.4
4
17
 
5
18
  - aligned the public docs surface with the current skill-first plugin layout
package/README.md CHANGED
@@ -8,7 +8,7 @@
8
8
  [![Plugin](https://img.shields.io/badge/claude--code-plugin-blue)](https://code.claude.com)
9
9
 
10
10
  CurdX-Flow is a skill-first Claude Code plugin. The public surface stays small:
11
- 11 slash commands, 5 auto-invoked skills, 16 internal agents, and a thin set of
11
+ 11 slash commands, 5 auto-invoked skills, 17 internal agents, and a thin set of
12
12
  entry docs. The heavy workflow detail lives in `skills/*/references/` and
13
13
  `knowledge/`.
14
14
 
@@ -22,6 +22,10 @@ Requires modern Claude Code and Node 18+. The install flow registers the plugin,
22
22
  required reasoning/doc tools, and recommended companion plugins. Run
23
23
  `npx @curdx/flow doctor` after install if anything looks off.
24
24
 
25
+ After restart, CurDX-Flow routes the main thread through `flow-orchestrator`
26
+ by default and starts the bundled `.flow` progress monitor in interactive
27
+ Claude Code sessions.
28
+
25
29
  ## 11 slash commands, that's it
26
30
 
27
31
  ```text
@@ -64,7 +68,9 @@ This produces a durable audit trail instead of a chat-only claim of completion.
64
68
  ## What ships
65
69
 
66
70
  - 11 slash commands and 5 auto-invoked skills
67
- - 16 internal agents
71
+ - 17 internal agents
72
+ - a default main-thread `flow-orchestrator` agent
73
+ - a `.flow` state monitor that streams spec progress changes back into Claude
68
74
  - 8 composable gates
69
75
  - 4 execution strategies for `/curdx-flow:implement`
70
76
  - thin public docs, thick supporting references
@@ -77,7 +83,7 @@ This produces a durable audit trail instead of a chat-only claim of completion.
77
83
  - [docs/headless-ci.md](./docs/headless-ci.md) for `claude --bare -p`, `system/init`, `system/plugin_install`, and CI patterns
78
84
  - [docs/troubleshoot.md](./docs/troubleshoot.md) for operator fixes
79
85
  - [docs/architecture.md](./docs/architecture.md) for the skill-first layout
80
- - [docs/agent-reference.md](./docs/agent-reference.md) for the 16 internal agents and their artifacts
86
+ - [docs/agent-reference.md](./docs/agent-reference.md) for the 17 internal agents and their artifacts
81
87
 
82
88
  ## Notes
83
89
 
@@ -0,0 +1,145 @@
1
+ ---
2
+ name: flow-orchestrator
3
+ description: "Use proactively when CurDX-Flow should own the main-thread workflow: gather context, choose fast-vs-spec path, coordinate specialist work, and enforce evidence before completion."
4
+ memory: project
5
+ model: sonnet
6
+ effort: high
7
+ maxTurns: 40
8
+ color: cyan
9
+ ---
10
+
11
+ # Flow Orchestrator — Main Thread Coordination Agent
12
+
13
+ @${CLAUDE_PLUGIN_ROOT}/agent-preamble/preamble.md
14
+ @${CLAUDE_PLUGIN_ROOT}/knowledge/execution-strategies.md
15
+ @${CLAUDE_PLUGIN_ROOT}/knowledge/planning-reviews.md
16
+ @${CLAUDE_PLUGIN_ROOT}/knowledge/claude-code-runtime-contracts.md
17
+
18
+ ## Your Role
19
+
20
+ You are the default CurDX-Flow main-thread agent. Keep the top-level Claude
21
+ session in a rigorous engineering mode:
22
+
23
+ - gather context before editing
24
+ - choose the smallest correct workflow
25
+ - delegate specialist work to `flow-*` agents
26
+ - keep artifacts on disk and summaries short
27
+ - refuse completion claims without evidence
28
+
29
+ You are not the primary artifact writer for research, requirements, design,
30
+ tasks, review, or verification. Those outputs belong to the specialist agents.
31
+
32
+ ## Operating Modes
33
+
34
+ Choose exactly one operating mode after the first context pass:
35
+
36
+ 1. **Fast path**
37
+ Use for small, well-bounded work that can be finished safely in one pass.
38
+ Preferred surfaces:
39
+ - direct execution in the main thread
40
+ - `/curdx-flow:fast`
41
+ - `flow-debugger` for surgical bug work
42
+
43
+ 2. **Spec path**
44
+ Use for multi-file features, ambiguous requests, risky refactors, new
45
+ architecture, or anything that needs durable review/verification evidence.
46
+ Preferred surfaces:
47
+ - `/curdx-flow:init` if `.flow/` does not exist yet
48
+ - `/curdx-flow:start` or existing active spec
49
+ - specialist agents for research, requirements, design, tasks, execution,
50
+ verification, and review
51
+
52
+ 3. **Advisory path**
53
+ Use for status checks, explanations, health checks, and runtime diagnostics.
54
+ Preferred surfaces:
55
+ - `/curdx-flow:status`
56
+ - `npx @curdx/flow doctor`
57
+ - `flow-brownfield-analyst` for unfamiliar codebases
58
+
59
+ State which path you chose before doing substantial work.
60
+
61
+ ## Delegation Map
62
+
63
+ - Unfamiliar or inherited repo → `flow-brownfield-analyst`
64
+ - Research or version-sensitive external docs → `flow-researcher`
65
+ - Requirements / user stories / acceptance criteria → `flow-product-designer`
66
+ - Architecture / tradeoffs / component boundaries → `flow-architect`
67
+ - Task decomposition / coverage audit → `flow-planner`
68
+ - Single task execution → `flow-executor`
69
+ - Bug root-cause work → `flow-debugger`
70
+ - Final verification → `flow-verifier`
71
+ - Review / adversarial / edge-case passes → `flow-reviewer`, `flow-adversary`, `flow-edge-hunter`
72
+ - UI QA or UI references → `flow-qa-engineer`, `flow-ui-researcher`, `flow-ux-designer`
73
+ - Security review → `flow-security-auditor`
74
+ - Epic decomposition → `flow-triage-analyst`
75
+
76
+ Delegate when the subtask will create large context, produce a durable artifact,
77
+ or benefit from a specialized prompt. Keep the main thread focused on orchestration.
78
+
79
+ ## Main-Thread Rules
80
+
81
+ ### 1. Context before edits
82
+
83
+ Before changing files:
84
+ - inspect the relevant code and runtime surface
85
+ - identify existing patterns to preserve
86
+ - decide whether the task is fast-path or spec-path
87
+
88
+ Do not jump straight from user request to writes unless the task is obviously
89
+ tiny and local.
90
+
91
+ ### 2. Use the plugin surfaces intentionally
92
+
93
+ - If the user asks for a workflow action that already exists as a CurDX-Flow
94
+ command or skill, prefer that surface instead of reinventing a parallel flow.
95
+ - If `.flow/` exists, keep work aligned with the active spec unless the user
96
+ explicitly asks to bypass it.
97
+ - If `.flow/` does not exist and the task is non-trivial, initialize or ask for
98
+ confirmation only when the distinction changes the execution model.
99
+
100
+ ### 3. Evidence-first completion
101
+
102
+ Never say complete merely because code changed.
103
+
104
+ Completion requires evidence proportional to the task:
105
+ - code read or diff for structural claims
106
+ - tests / build / lint / verify commands for behavioral claims
107
+ - browser evidence for UI claims
108
+ - written artifacts for spec/review/verification phases
109
+
110
+ ### 4. Keep summaries compact
111
+
112
+ When a specialist agent writes an artifact, your summary should point to the
113
+ artifact path, call out the decision taken, and state the next action. Do not
114
+ restate the full file content in chat.
115
+
116
+ ### 5. Prefer directness over ceremony
117
+
118
+ CurDX-Flow is disciplined, but not bureaucratic.
119
+
120
+ - Small clear task: execute directly.
121
+ - Medium ambiguous task: inspect, plan briefly, then execute.
122
+ - Large risky task: switch to the full spec path.
123
+
124
+ Do not force the user through every phase when the task does not need it.
125
+
126
+ ## Runtime Awareness
127
+
128
+ When the task depends on Claude Code runtime behavior itself
129
+ (plugins, hooks, agents, monitors, settings, output styles, commands):
130
+
131
+ - re-check the official Claude Code docs
132
+ - follow `${CLAUDE_PLUGIN_ROOT}/knowledge/claude-code-runtime-contracts.md`
133
+ - prefer `claude plugin validate .` over assumptions
134
+
135
+ ## Output Contract
136
+
137
+ Your top-level replies should be:
138
+
139
+ 1. short statement of chosen path
140
+ 2. what context you gathered or what artifact was produced
141
+ 3. what you changed or delegated
142
+ 4. concrete evidence and next action
143
+
144
+ Do not produce long architectural essays in the main thread when a specialist
145
+ artifact is the correct output.
@@ -1,5 +1,6 @@
1
1
  import fs from "node:fs/promises";
2
2
  import path from "node:path";
3
+ import { fileURLToPath } from "node:url";
3
4
 
4
5
  import { readProjectClaudeSettings } from "./lib/doctor-claude-settings.js";
5
6
  import { inspectRuntimeEnvironment } from "./lib/doctor-runtime-environment.js";
@@ -19,6 +20,8 @@ import {
19
20
  export { readProjectClaudeSettings };
20
21
  export { inspectRuntimeEnvironment };
21
22
 
23
+ const PACKAGE_ROOT = fileURLToPath(new URL("../", import.meta.url));
24
+
22
25
  export function createDoctorContext(args = []) {
23
26
  return {
24
27
  fix: args.includes("--fix"),
@@ -150,6 +153,78 @@ export async function readProjectTeamConfig(cwd = process.cwd()) {
150
153
  return state;
151
154
  }
152
155
 
156
+ export async function readBundledPluginRuntimeDefaults(packageRoot = PACKAGE_ROOT) {
157
+ const pluginSettingsPath = path.join(packageRoot, "settings.json");
158
+ const pluginManifestPath = path.join(packageRoot, ".claude-plugin", "plugin.json");
159
+ const monitorsPath = path.join(packageRoot, "monitors", "monitors.json");
160
+
161
+ const state = {
162
+ exists: false,
163
+ defaultAgent: null,
164
+ subagentStatusLineCommand: null,
165
+ monitorCount: 0,
166
+ monitors: [],
167
+ userConfig: [],
168
+ };
169
+
170
+ let pluginSettings = null;
171
+ let pluginManifest = null;
172
+ let monitors = null;
173
+
174
+ try {
175
+ pluginSettings = JSON.parse(await fs.readFile(pluginSettingsPath, "utf-8"));
176
+ } catch {
177
+ pluginSettings = null;
178
+ }
179
+
180
+ try {
181
+ pluginManifest = JSON.parse(await fs.readFile(pluginManifestPath, "utf-8"));
182
+ } catch {
183
+ pluginManifest = null;
184
+ }
185
+
186
+ try {
187
+ monitors = JSON.parse(await fs.readFile(monitorsPath, "utf-8"));
188
+ } catch {
189
+ monitors = null;
190
+ }
191
+
192
+ if (!pluginSettings && !pluginManifest && !monitors) {
193
+ return state;
194
+ }
195
+
196
+ state.exists = true;
197
+ state.defaultAgent = typeof pluginSettings?.agent === "string" ? pluginSettings.agent : null;
198
+ state.subagentStatusLineCommand =
199
+ typeof pluginSettings?.subagentStatusLine?.command === "string"
200
+ ? pluginSettings.subagentStatusLine.command
201
+ : null;
202
+
203
+ if (Array.isArray(monitors)) {
204
+ state.monitorCount = monitors.length;
205
+ state.monitors = monitors
206
+ .filter((entry) => entry && typeof entry === "object")
207
+ .map((entry) => ({
208
+ name: typeof entry.name === "string" ? entry.name : null,
209
+ when: typeof entry.when === "string" ? entry.when : "always",
210
+ }))
211
+ .filter((entry) => entry.name);
212
+ }
213
+
214
+ if (pluginManifest?.userConfig && typeof pluginManifest.userConfig === "object") {
215
+ state.userConfig = Object.entries(pluginManifest.userConfig)
216
+ .filter(([, value]) => value && typeof value === "object" && !Array.isArray(value))
217
+ .map(([key, value]) => ({
218
+ key,
219
+ type: value.type ?? null,
220
+ default: Object.prototype.hasOwnProperty.call(value, "default") ? value.default : undefined,
221
+ sensitive: value.sensitive === true,
222
+ }));
223
+ }
224
+
225
+ return state;
226
+ }
227
+
153
228
  export async function readProjectState(cwd = process.cwd()) {
154
229
  const flowDir = path.join(cwd, ".flow");
155
230
  try {
@@ -185,6 +260,7 @@ export async function collectDoctorData(
185
260
  readProjectMcpConfigImpl = readProjectMcpConfig,
186
261
  readProjectTeamConfigImpl = readProjectTeamConfig,
187
262
  readProjectClaudeSettingsImpl = readProjectClaudeSettings,
263
+ readBundledPluginRuntimeDefaultsImpl = readBundledPluginRuntimeDefaults,
188
264
  } = {}
189
265
  ) {
190
266
  const claudeVersionValue = claudeVersionImpl();
@@ -212,6 +288,7 @@ export async function collectDoctorData(
212
288
  projectMcpConfig: await readProjectMcpConfigImpl(cwd),
213
289
  projectTeamConfig: await readProjectTeamConfigImpl(cwd),
214
290
  projectClaudeSettings: await readProjectClaudeSettingsImpl(cwd),
291
+ bundledPluginRuntimeDefaults: await readBundledPluginRuntimeDefaultsImpl(),
215
292
  };
216
293
  }
217
294
 
@@ -5,10 +5,14 @@ export function printNextSteps() {
5
5
  const cliCmd = cliOnPath ? "curdx-flow" : "npx @curdx/flow";
6
6
 
7
7
  console.log(`\n${color.bold(`${color.green("✓")} Install complete`)}\n`);
8
- console.log(`${color.bold("Restart Claude Code")} so the plugin registers all its commands and hooks.\n`);
8
+ console.log(
9
+ `${color.bold("Restart Claude Code")} so the plugin registers its commands, hooks, default main-thread agent, and background monitor.\n`
10
+ );
9
11
  console.log(`${color.bold("Next steps")}:\n`);
10
12
  console.log(` ${color.dim("# Verify health")}`);
11
13
  console.log(` ${cliCmd} doctor\n`);
14
+ console.log(` ${color.dim("# Review the bundled main-agent / monitor defaults")}`);
15
+ console.log(` ${color.dim("# (doctor now prints CurDX-Flow runtime defaults and plugin option keys)")}\n`);
12
16
  console.log(` ${color.dim("# Inside any project, initialize and start a feature spec")}`);
13
17
  console.log(` ${color.cyan("cd ~/your-project")}`);
14
18
  console.log(` ${color.cyan("claude")}`);
@@ -73,6 +73,7 @@ const CURDX_FLOW_AGENT_TYPES = [
73
73
  "flow-debugger",
74
74
  "flow-edge-hunter",
75
75
  "flow-executor",
76
+ "flow-orchestrator",
76
77
  "flow-planner",
77
78
  "flow-product-designer",
78
79
  "flow-qa-engineer",
@@ -130,6 +130,7 @@ export function buildDoctorReport({
130
130
  projectMcpConfig,
131
131
  projectTeamConfig,
132
132
  projectClaudeSettings,
133
+ bundledPluginRuntimeDefaults,
133
134
  }) {
134
135
  const lines = [];
135
136
  const sections = [];
@@ -158,7 +159,7 @@ export function buildDoctorReport({
158
159
  "warn",
159
160
  `claude CLI ${claudeVersionValue} below recommended ${MIN_CLAUDE_VERSION}`,
160
161
  [
161
- "curdx-flow uses modern Claude Code plugin dependency resolution and plugin bin/ PATH support",
162
+ "curdx-flow uses modern Claude Code plugin dependency resolution, plugin bin/PATH support, plugin-level main-agent routing, and monitor surfaces",
162
163
  "run: claude update",
163
164
  ]
164
165
  );
@@ -345,6 +346,63 @@ export function buildDoctorReport({
345
346
  }
346
347
  }
347
348
 
349
+ if (bundledPluginRuntimeDefaults?.exists) {
350
+ const bundledRuntimeSection = createSection("CurDX-Flow bundled runtime:");
351
+
352
+ if (bundledPluginRuntimeDefaults.defaultAgent) {
353
+ pushSectionLine(
354
+ bundledRuntimeSection,
355
+ "ok",
356
+ `Main thread agent ${bundledPluginRuntimeDefaults.defaultAgent}`,
357
+ [
358
+ "plugin-level settings route the main Claude thread through this agent by default",
359
+ ]
360
+ );
361
+ }
362
+
363
+ if (bundledPluginRuntimeDefaults.subagentStatusLineCommand) {
364
+ pushSectionLine(
365
+ bundledRuntimeSection,
366
+ "info",
367
+ `Subagent status line configured`,
368
+ [bundledPluginRuntimeDefaults.subagentStatusLineCommand]
369
+ );
370
+ }
371
+
372
+ if (bundledPluginRuntimeDefaults.monitorCount > 0) {
373
+ const monitorSummary = bundledPluginRuntimeDefaults.monitors
374
+ .map((monitor) => `${monitor.name} (${monitor.when})`)
375
+ .join(", ");
376
+ pushSectionLine(
377
+ bundledRuntimeSection,
378
+ "ok",
379
+ `Plugin monitors ${bundledPluginRuntimeDefaults.monitorCount} configured`,
380
+ [
381
+ monitorSummary,
382
+ "official docs: plugin monitors run only in interactive Claude Code sessions where the Monitor tool is available",
383
+ ]
384
+ );
385
+ }
386
+
387
+ if ((bundledPluginRuntimeDefaults.userConfig || []).length > 0) {
388
+ const optionSummary = bundledPluginRuntimeDefaults.userConfig
389
+ .map((option) => {
390
+ const suffix = option.default === undefined ? "" : `=${String(option.default)}`;
391
+ return `${option.key}${suffix}`;
392
+ })
393
+ .join(", ");
394
+ pushSectionLine(
395
+ bundledRuntimeSection,
396
+ "info",
397
+ `Plugin options ${bundledPluginRuntimeDefaults.userConfig.length} available`,
398
+ [
399
+ optionSummary,
400
+ "non-sensitive values are stored under pluginConfigs[curdx-flow@curdx-flow-marketplace].options in Claude settings.json",
401
+ ]
402
+ );
403
+ }
404
+ }
405
+
348
406
  const localProjectSection = createSection("Local project:");
349
407
  if (projectState?.exists) {
350
408
  pushSectionLine(localProjectSection, "ok", `.flow/ ${cwd}`);
@@ -4,6 +4,13 @@ has_python3() {
4
4
  command -v python3 >/dev/null 2>&1
5
5
  }
6
6
 
7
+ env_flag_enabled() {
8
+ case "$(printf '%s' "${1:-}" | tr '[:upper:]' '[:lower:]')" in
9
+ 1|true|yes|on) return 0 ;;
10
+ *) return 1 ;;
11
+ esac
12
+ }
13
+
7
14
  json_escape() {
8
15
  local value="${1:-}"
9
16
 
@@ -26,7 +26,7 @@ mkdir -p "$DATA_DIR" 2>/dev/null || true
26
26
  LAST_CHECK=""
27
27
  [ -f "$MARKER" ] && LAST_CHECK="$(cat "$MARKER" 2>/dev/null)"
28
28
 
29
- if [ "$LAST_CHECK" != "$TODAY" ]; then
29
+ if env_flag_enabled "${CLAUDE_PLUGIN_OPTION_DAILY_DEPENDENCY_CHECK:-1}" && [ "$LAST_CHECK" != "$TODAY" ]; then
30
30
  MISSING=()
31
31
 
32
32
  # Skip if `claude` CLI is not on PATH
@@ -26,6 +26,10 @@ allow_stop() {
26
26
  exit 0
27
27
  }
28
28
 
29
+ autonomous_blocking_enabled() {
30
+ env_flag_enabled "${CLAUDE_PLUGIN_OPTION_AUTONOMOUS_BLOCKING:-1}"
31
+ }
32
+
29
33
  # ---------- helper: block and inject continuation ----------
30
34
  block_continue() {
31
35
  local reason="$1"
@@ -83,6 +87,10 @@ EOF
83
87
  [ "$STRATEGY" != "stop-hook" ] && allow_stop
84
88
  [ "$PHASE" != "execute" ] && allow_stop
85
89
 
90
+ if ! autonomous_blocking_enabled; then
91
+ allow_stop
92
+ fi
93
+
86
94
  # ---------- 5. Check hook input + completion signal in transcript ----------
87
95
  # Claude Code passes transcript path via stdin as JSON: {"transcript_path": "/path/..."}
88
96
  # We read stdin to detect ALL_TASKS_COMPLETE or TASK_FAILED
@@ -72,11 +72,23 @@ Guarded artifact targets:
72
72
  ## Plugin Settings
73
73
 
74
74
  - Claude Code plugin-root `settings.json` currently supports only `agent` and `subagentStatusLine`.
75
- - CurDX-Flow ships only `subagentStatusLine`, pointing at `${CLAUDE_PLUGIN_ROOT}/hooks/scripts/subagent-statusline.sh`.
75
+ - CurDX-Flow ships both:
76
+ - `agent: "flow-orchestrator"` to route the main thread through the CurDX-Flow coordinator by default.
77
+ - `subagentStatusLine`, pointing at `${CLAUDE_PLUGIN_ROOT}/hooks/scripts/subagent-statusline.sh`.
76
78
  - The status-line script must fail open on malformed input or missing `python3`; UI decoration must never break agent execution.
77
79
  - Plugin-root references must never traverse outside the plugin directory. Installed marketplace plugins run from Claude Code's plugin cache, so parent-directory references are invalid even if they work in a development checkout.
78
80
  - If adding plugin settings, update `schemas/plugin-settings.schema.json`, `test/plugin-structure-contract.test.js`, `test/pack-tarball-smoke.test.js`, and `scripts/validate-plugin-contracts.mjs` in the same change.
79
81
 
82
+ ## Plugin Monitors and User Config
83
+
84
+ - CurDX-Flow ships a plugin monitor at `${CLAUDE_PLUGIN_ROOT}/monitors/monitors.json` to surface `.flow` state changes back into the active Claude session.
85
+ - Monitors run only when the Claude `Monitor` tool is available, and only in interactive CLI sessions.
86
+ - CurDX-Flow `userConfig` values are exported to plugin subprocesses as `CLAUDE_PLUGIN_OPTION_<KEY>`.
87
+ - Current runtime knobs:
88
+ - `autonomous_blocking`: lets users disable stop-hook continuation without editing plugin files.
89
+ - `daily_dependency_check`: silences or enables the once-per-day recommended-plugin reminder.
90
+ - `monitor_interval_seconds`: controls plugin monitor polling cadence.
91
+
80
92
  ## Plugin Dependency Constraints
81
93
 
82
94
  - Official dependency version constraints require upstream plugin release tags in the `{plugin-name}--v{version}` format.
@@ -0,0 +1,8 @@
1
+ [
2
+ {
3
+ "name": "flow-state",
4
+ "description": "Watch CurDX-Flow .flow state changes and notify Claude when the active spec, phase, or remaining tasks change.",
5
+ "command": "${CLAUDE_PLUGIN_ROOT}/monitors/scripts/flow-state-monitor.sh",
6
+ "when": "always"
7
+ }
8
+ ]
@@ -0,0 +1,99 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -u
4
+
5
+ interval="${CLAUDE_PLUGIN_OPTION_MONITOR_INTERVAL_SECONDS:-8}"
6
+ case "$interval" in
7
+ ''|*[!0-9]*)
8
+ interval=8
9
+ ;;
10
+ esac
11
+ if [ "$interval" -lt 3 ] 2>/dev/null; then
12
+ interval=3
13
+ fi
14
+
15
+ build_snapshot() {
16
+ if [ ! -d ".flow" ]; then
17
+ return 0
18
+ fi
19
+
20
+ local active=""
21
+ active="$(cat .flow/.active-spec 2>/dev/null || true)"
22
+ [ -z "$active" ] && return 0
23
+
24
+ local spec_dir=".flow/specs/$active"
25
+ [ ! -d "$spec_dir" ] && return 0
26
+
27
+ local state_file="$spec_dir/.state.json"
28
+ local tasks_file="$spec_dir/tasks.md"
29
+
30
+ python3 - "$active" "$state_file" "$tasks_file" <<'PY' 2>/dev/null
31
+ import json
32
+ import os
33
+ import re
34
+ import sys
35
+
36
+ active, state_file, tasks_file = sys.argv[1:4]
37
+
38
+ phase = "unknown"
39
+ strategy = "unknown"
40
+ task_index = 0
41
+ total_tasks = 0
42
+ failed_attempts = 0
43
+ global_iteration = 0
44
+
45
+ if os.path.exists(state_file):
46
+ try:
47
+ state = json.load(open(state_file, "r", encoding="utf-8"))
48
+ phase = state.get("phase") or phase
49
+ strategy = state.get("strategy") or strategy
50
+ execute_state = state.get("execute_state") or {}
51
+ task_index = execute_state.get("task_index") or 0
52
+ total_tasks = execute_state.get("total_tasks") or 0
53
+ failed_attempts = execute_state.get("failed_attempts") or 0
54
+ global_iteration = execute_state.get("global_iteration") or 0
55
+ except Exception:
56
+ phase = "invalid-state"
57
+
58
+ unchecked = 0
59
+ if os.path.exists(tasks_file):
60
+ try:
61
+ text = open(tasks_file, "r", encoding="utf-8").read()
62
+ unchecked = len(re.findall(r"^- \[ \] \*\*[0-9]+(\.[0-9]+|\.VF|\.X(\+[0-9]+)?)*\*\*", text, re.M))
63
+ except Exception:
64
+ unchecked = -1
65
+
66
+ parts = [
67
+ f"CurDX-Flow monitor: spec={active}",
68
+ f"phase={phase}",
69
+ f"strategy={strategy}",
70
+ ]
71
+
72
+ if total_tasks > 0:
73
+ parts.append(f"tasks={task_index}/{total_tasks}")
74
+ parts.append(f"unchecked={unchecked}")
75
+
76
+ if failed_attempts > 0:
77
+ parts.append(f"failed_attempts={failed_attempts}")
78
+ if global_iteration > 0:
79
+ parts.append(f"loop={global_iteration}")
80
+
81
+ print(" ".join(parts))
82
+ PY
83
+ }
84
+
85
+ last_snapshot=""
86
+
87
+ while true; do
88
+ snapshot="$(build_snapshot)"
89
+ if [ -n "$snapshot" ] && [ "$snapshot" != "$last_snapshot" ]; then
90
+ printf '%s\n' "$snapshot"
91
+ last_snapshot="$snapshot"
92
+ fi
93
+
94
+ if [ "${CURDX_FLOW_MONITOR_ONCE:-0}" = "1" ]; then
95
+ exit 0
96
+ fi
97
+
98
+ sleep "$interval"
99
+ done
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@curdx/flow",
3
- "version": "2.2.5",
3
+ "version": "2.3.1",
4
4
  "description": "Skill-first discipline layer and CLI installer for Claude Code",
5
5
  "type": "module",
6
6
  "bin": {
@@ -19,6 +19,7 @@
19
19
  "gates/",
20
20
  "hooks/",
21
21
  "knowledge/",
22
+ "monitors/",
22
23
  "agent-preamble/",
23
24
  "output-styles/",
24
25
  "templates/",
package/settings.json CHANGED
@@ -1,4 +1,5 @@
1
1
  {
2
+ "agent": "flow-orchestrator",
2
3
  "subagentStatusLine": {
3
4
  "type": "command",
4
5
  "command": "${CLAUDE_PLUGIN_ROOT}/hooks/scripts/subagent-statusline.sh"