@curdx/flow 2.3.6 → 2.3.8
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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +12 -0
- package/cli/README.md +4 -0
- package/cli/doctor-workflow.js +43 -0
- package/cli/lib/doctor-report.js +57 -0
- package/cli/lib/process.js +7 -2
- package/package.json +1 -1
|
@@ -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.3.
|
|
9
|
+
"version": "2.3.8"
|
|
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.3.
|
|
19
|
+
"version": "2.3.8",
|
|
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.3.
|
|
3
|
+
"version": "2.3.8",
|
|
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",
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.3.8
|
|
4
|
+
|
|
5
|
+
- taught `doctor` to detect dirty CurDX-Flow source checkouts, so plugin developers immediately see when Claude cannot possibly be running their latest local edits yet
|
|
6
|
+
- surfaced bundled source repo metadata (`branch`, `shortSha`, `exactTag`, `dirty`) alongside bundled plugin body version in diagnostics and JSON output
|
|
7
|
+
- documented the reinstall workflow for “same version, but local source changed” plugin-development scenarios
|
|
8
|
+
|
|
9
|
+
## 2.3.7
|
|
10
|
+
|
|
11
|
+
- taught `doctor` to detect source/package-vs-installed plugin version drift so local plugin development and release validation no longer silently run against stale Claude plugin cache state
|
|
12
|
+
- exposed bundled plugin body version in the runtime report and machine-readable doctor payload for automation consumers
|
|
13
|
+
- documented the reinstall/restart recovery path when Claude is still loading an older CurDX-Flow build
|
|
14
|
+
|
|
3
15
|
## 2.3.6
|
|
4
16
|
|
|
5
17
|
- taught `doctor` to inspect file-based Claude Code managed settings and apply them at the correct highest-precedence layer for CurDX-Flow plugin options
|
package/cli/README.md
CHANGED
|
@@ -44,6 +44,10 @@ External diagnostics: claude CLI / curdx-flow / required MCPs / recommended plug
|
|
|
44
44
|
|
|
45
45
|
`--json` emits the full health result as machine-readable JSON for CI, wrappers, or external diagnostics. It includes `contractVersion`, `metadata.appliedFixes`, settings inspection scope metadata, the rendered report structure, and raw `doctorData`, including CurDX-Flow plugin option precedence, file-based managed settings, and runtime env projection.
|
|
46
46
|
|
|
47
|
+
`doctor` also compares the plugin body shipped with the current CLI/package against the `curdx-flow` version Claude actually has installed, so local development and release validation do not silently run against stale plugin cache state.
|
|
48
|
+
|
|
49
|
+
When the CLI is running from a git checkout, `doctor` also reports whether that source repo is dirty. This catches the common plugin-development trap where Claude is still running the previously installed cache while your local checkout has uninstalled edits.
|
|
50
|
+
|
|
47
51
|
### Project initialization (not a CLI command)
|
|
48
52
|
|
|
49
53
|
Project initialization is a Claude Code slash command, not a CLI one. After `install`, open your project in Claude Code and run:
|
package/cli/doctor-workflow.js
CHANGED
|
@@ -163,9 +163,19 @@ export async function readBundledPluginRuntimeDefaults(packageRoot = PACKAGE_ROO
|
|
|
163
163
|
const pluginSettingsPath = path.join(packageRoot, "settings.json");
|
|
164
164
|
const pluginManifestPath = path.join(packageRoot, ".claude-plugin", "plugin.json");
|
|
165
165
|
const monitorsPath = path.join(packageRoot, "monitors", "monitors.json");
|
|
166
|
+
const packageJsonPath = path.join(packageRoot, "package.json");
|
|
166
167
|
|
|
167
168
|
const state = {
|
|
168
169
|
exists: false,
|
|
170
|
+
packageVersion: null,
|
|
171
|
+
pluginVersion: null,
|
|
172
|
+
sourceRepo: {
|
|
173
|
+
isGitRepo: false,
|
|
174
|
+
branch: null,
|
|
175
|
+
shortSha: null,
|
|
176
|
+
exactTag: null,
|
|
177
|
+
dirty: false,
|
|
178
|
+
},
|
|
169
179
|
defaultAgent: null,
|
|
170
180
|
subagentStatusLineCommand: null,
|
|
171
181
|
monitorCount: 0,
|
|
@@ -189,6 +199,38 @@ export async function readBundledPluginRuntimeDefaults(packageRoot = PACKAGE_ROO
|
|
|
189
199
|
pluginManifest = null;
|
|
190
200
|
}
|
|
191
201
|
|
|
202
|
+
try {
|
|
203
|
+
const pkg = JSON.parse(await fs.readFile(packageJsonPath, "utf-8"));
|
|
204
|
+
state.packageVersion = typeof pkg?.version === "string" ? pkg.version : null;
|
|
205
|
+
} catch {
|
|
206
|
+
state.packageVersion = null;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const gitRepoCheck = runSync("git", ["rev-parse", "--is-inside-work-tree"], { cwd: packageRoot });
|
|
210
|
+
if (gitRepoCheck.code === 0 && gitRepoCheck.stdout.trim() === "true") {
|
|
211
|
+
state.sourceRepo.isGitRepo = true;
|
|
212
|
+
|
|
213
|
+
const branch = runSync("git", ["rev-parse", "--abbrev-ref", "HEAD"], { cwd: packageRoot });
|
|
214
|
+
if (branch.code === 0) {
|
|
215
|
+
state.sourceRepo.branch = branch.stdout.trim() || null;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const shortSha = runSync("git", ["rev-parse", "--short", "HEAD"], { cwd: packageRoot });
|
|
219
|
+
if (shortSha.code === 0) {
|
|
220
|
+
state.sourceRepo.shortSha = shortSha.stdout.trim() || null;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const exactTag = runSync("git", ["describe", "--tags", "--exact-match", "HEAD"], { cwd: packageRoot });
|
|
224
|
+
if (exactTag.code === 0) {
|
|
225
|
+
state.sourceRepo.exactTag = exactTag.stdout.trim() || null;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const status = runSync("git", ["status", "--short"], { cwd: packageRoot });
|
|
229
|
+
if (status.code === 0) {
|
|
230
|
+
state.sourceRepo.dirty = status.stdout.trim().length > 0;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
192
234
|
try {
|
|
193
235
|
monitors = JSON.parse(await fs.readFile(monitorsPath, "utf-8"));
|
|
194
236
|
} catch {
|
|
@@ -200,6 +242,7 @@ export async function readBundledPluginRuntimeDefaults(packageRoot = PACKAGE_ROO
|
|
|
200
242
|
}
|
|
201
243
|
|
|
202
244
|
state.exists = true;
|
|
245
|
+
state.pluginVersion = typeof pluginManifest?.version === "string" ? pluginManifest.version : null;
|
|
203
246
|
state.defaultAgent = typeof pluginSettings?.agent === "string" ? pluginSettings.agent : null;
|
|
204
247
|
state.subagentStatusLineCommand =
|
|
205
248
|
typeof pluginSettings?.subagentStatusLine?.command === "string"
|
package/cli/lib/doctor-report.js
CHANGED
|
@@ -263,9 +263,36 @@ export function buildDoctorReport({
|
|
|
263
263
|
pushLine(lines, "ok", `Node ${nodeVersion}`);
|
|
264
264
|
|
|
265
265
|
const curdx = plugins.find((plugin) => plugin.name === "curdx-flow");
|
|
266
|
+
const bundledVersion =
|
|
267
|
+
bundledPluginRuntimeDefaults?.pluginVersion || bundledPluginRuntimeDefaults?.packageVersion || null;
|
|
268
|
+
const bundledSourceRepo = bundledPluginRuntimeDefaults?.sourceRepo || {};
|
|
266
269
|
if (curdx) {
|
|
267
270
|
if (curdx.status === "enabled") {
|
|
268
271
|
pushLine(lines, "ok", `curdx-flow v${curdx.version} (enabled)`);
|
|
272
|
+
if (bundledVersion && curdx.version && curdx.version !== bundledVersion) {
|
|
273
|
+
pushLine(
|
|
274
|
+
lines,
|
|
275
|
+
"warn",
|
|
276
|
+
`curdx-flow source/body v${bundledVersion} differs from installed v${curdx.version}`,
|
|
277
|
+
[
|
|
278
|
+
"you are not validating the same CurDX-Flow build that Claude currently loads",
|
|
279
|
+
"reinstall the plugin from the current source/package, then restart Claude Code",
|
|
280
|
+
"run: npx @curdx/flow install --all",
|
|
281
|
+
]
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
if (bundledSourceRepo.isGitRepo && bundledSourceRepo.dirty) {
|
|
285
|
+
pushLine(
|
|
286
|
+
lines,
|
|
287
|
+
"warn",
|
|
288
|
+
"curdx-flow source repo has uninstalled local changes",
|
|
289
|
+
[
|
|
290
|
+
"the current CLI/source checkout has git modifications that Claude's installed plugin cannot see until you reinstall it",
|
|
291
|
+
"re-run: npx @curdx/flow install --all",
|
|
292
|
+
"then fully restart Claude Code before validating plugin behavior",
|
|
293
|
+
]
|
|
294
|
+
);
|
|
295
|
+
}
|
|
269
296
|
} else {
|
|
270
297
|
pushLine(
|
|
271
298
|
lines,
|
|
@@ -442,6 +469,36 @@ export function buildDoctorReport({
|
|
|
442
469
|
if (bundledPluginRuntimeDefaults?.exists) {
|
|
443
470
|
const bundledRuntimeSection = createSection("CurDX-Flow bundled runtime:");
|
|
444
471
|
|
|
472
|
+
if (bundledVersion) {
|
|
473
|
+
pushSectionLine(
|
|
474
|
+
bundledRuntimeSection,
|
|
475
|
+
"info",
|
|
476
|
+
`Bundled plugin body v${bundledVersion}`
|
|
477
|
+
);
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
if (bundledSourceRepo.isGitRepo) {
|
|
481
|
+
const sourceSummary = [
|
|
482
|
+
bundledSourceRepo.branch,
|
|
483
|
+
bundledSourceRepo.shortSha,
|
|
484
|
+
].filter(Boolean).join(" @ ");
|
|
485
|
+
const sourceDetails = [];
|
|
486
|
+
if (bundledSourceRepo.exactTag) {
|
|
487
|
+
sourceDetails.push(`exact tag: ${bundledSourceRepo.exactTag}`);
|
|
488
|
+
}
|
|
489
|
+
sourceDetails.push(
|
|
490
|
+
bundledSourceRepo.dirty
|
|
491
|
+
? "git worktree dirty: local source changes are not reflected in Claude until reinstall"
|
|
492
|
+
: "git worktree clean"
|
|
493
|
+
);
|
|
494
|
+
pushSectionLine(
|
|
495
|
+
bundledRuntimeSection,
|
|
496
|
+
bundledSourceRepo.dirty ? "warn" : "info",
|
|
497
|
+
`Bundled source repo ${sourceSummary || "git checkout detected"}`,
|
|
498
|
+
sourceDetails
|
|
499
|
+
);
|
|
500
|
+
}
|
|
501
|
+
|
|
445
502
|
if (bundledPluginRuntimeDefaults.defaultAgent) {
|
|
446
503
|
pushSectionLine(
|
|
447
504
|
bundledRuntimeSection,
|
package/cli/lib/process.js
CHANGED
|
@@ -29,8 +29,13 @@ export function run(cmd, args = [], opts = {}) {
|
|
|
29
29
|
/**
|
|
30
30
|
* Sync run — for quick checks (e.g. "which claude").
|
|
31
31
|
*/
|
|
32
|
-
export function runSync(cmd, args = []) {
|
|
33
|
-
const res = spawnSync(cmd, args, {
|
|
32
|
+
export function runSync(cmd, args = [], opts = {}) {
|
|
33
|
+
const res = spawnSync(cmd, args, {
|
|
34
|
+
encoding: "utf-8",
|
|
35
|
+
shell: false,
|
|
36
|
+
cwd: opts.cwd,
|
|
37
|
+
env: opts.env ? { ...process.env, ...opts.env } : process.env,
|
|
38
|
+
});
|
|
34
39
|
return {
|
|
35
40
|
code: res.status ?? -1,
|
|
36
41
|
stdout: res.stdout ?? "",
|