contentrain 0.13.5 → 0.14.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.
Files changed (42) hide show
  1. package/README.md +13 -0
  2. package/dist/{activity-DjSTygMo.mjs → activity-DHriVJu5.mjs} +2 -2
  3. package/dist/{branches-CzBo3c5P.mjs → branches-DZrVrweZ.mjs} +2 -2
  4. package/dist/{cdn-build-BvwW0OjV.mjs → cdn-build-ltuSzhql.mjs} +2 -2
  5. package/dist/{cdn-init-EDtGs6D6.mjs → cdn-init-CIGPuYNT.mjs} +2 -2
  6. package/dist/{connect-BK2e05he.mjs → connect-BYVRMPz9.mjs} +2 -2
  7. package/dist/delta-D6Cp9BdP.mjs +120 -0
  8. package/dist/{describe-CpQROC9y.mjs → describe-C6-AWlKx.mjs} +2 -2
  9. package/dist/{describe-format-CUAqB0C4.mjs → describe-format-CR0-NMR8.mjs} +2 -2
  10. package/dist/{diff-BUGOF3SZ.mjs → diff-6EnRgpPR.mjs} +1 -1
  11. package/dist/{doctor-MOf_LQEL.mjs → doctor-B9MJgRO5.mjs} +1 -1
  12. package/dist/{generate-BKskWYyJ.mjs → generate-fLQfw9t7.mjs} +2 -2
  13. package/dist/index.mjs +19 -18
  14. package/dist/{init-DzpPFgf2.mjs → init-_0Hp__pU.mjs} +3 -3
  15. package/dist/{login-B8P_JDLG.mjs → login-C6gv1Ec5.mjs} +2 -2
  16. package/dist/{logout-BWEtxcqT.mjs → logout-D_8LjZ2N.mjs} +1 -1
  17. package/dist/{merge-Bkx2GGET.mjs → merge-C8l80Cg-.mjs} +1 -1
  18. package/dist/{prune-RgPwvk5_.mjs → prune-CvTj9QMj.mjs} +1 -1
  19. package/dist/{reconcile-CC5xnijO.mjs → reconcile-D1clXB6h.mjs} +2 -2
  20. package/dist/{resolve-context-D1fzCGw-.mjs → resolve-context-CNBzxnlJ.mjs} +1 -1
  21. package/dist/{scaffold-C6s96dYz.mjs → scaffold-DX6eJ0n1.mjs} +2 -2
  22. package/dist/{serve-Bca9c80T.mjs → serve-Cglzhom-.mjs} +3 -3
  23. package/dist/{setup-CsgpgrlJ.mjs → setup-BRVyTOxY.mjs} +2 -2
  24. package/dist/{skills-Bst5FQ7K.mjs → skills-DZT0pbmO.mjs} +2 -2
  25. package/dist/{status-D_rC1Qln.mjs → status-5RpF1q6y.mjs} +1 -1
  26. package/dist/{status-ghQXrAtt.mjs → status-C6koCAw2.mjs} +2 -2
  27. package/dist/studio-DessrNQs.mjs +24 -0
  28. package/dist/{submissions-XXqgcE-W.mjs → submissions-C9PxDNSv.mjs} +2 -2
  29. package/dist/{usage-_kEqbIxO.mjs → usage-6pJn7APs.mjs} +2 -2
  30. package/dist/{validate-C0kK-1BC.mjs → validate-CiP3MkeV.mjs} +1 -1
  31. package/dist/{webhooks-SojN2I50.mjs → webhooks-CnGcaEQy.mjs} +2 -2
  32. package/dist/{whoami-2lHHQboY.mjs → whoami-BCuY4Zi3.mjs} +1 -1
  33. package/package.json +5 -5
  34. package/dist/studio-39PJXdw9.mjs +0 -24
  35. package/dist/{client-BeyZQEwe.mjs → client-DYn1qIPW.mjs} +1 -1
  36. package/dist/{context-OskMGy8y.mjs → context-SIGQmozp.mjs} +0 -0
  37. package/dist/{demo-937OTZSI.mjs → demo-lHnrfuW1.mjs} +1 -1
  38. package/dist/{ide-Dtw1wesv.mjs → ide-D1J4iAhK.mjs} +1 -1
  39. package/dist/{import-RezpSn3Q.mjs → import-BmS_V6le.mjs} +1 -1
  40. package/dist/{mcp-client-DVWTex2i.mjs → mcp-client-DPpPykAi.mjs} +0 -0
  41. package/dist/{oauth-server-CsI51m-2.mjs → oauth-server-Ck3RBaXD.mjs} +0 -0
  42. package/dist/{server-ftj2te6Y.mjs → server-CL18nNJ9.mjs} +2 -2
package/README.md CHANGED
@@ -69,6 +69,7 @@ Example: `contentrain --debug status` or `CONTENTRAIN_DEBUG=1 contentrain valida
69
69
  | `contentrain reconcile` | Content-aware three-way merge of a diverged contentrain ↔ base pair (dry-run plan, interactive decisions) |
70
70
  | `contentrain prune` | Delete merged `cr/*` branches locally and on the remote (backlog drain) |
71
71
  | `contentrain describe <model>` | Inspect a model's schema, stats, and import snippet |
72
+ | `contentrain delta <delta.json> --dry-run` | Plan a WordPress source delta against the store: placement, field changes, conflicts, tombstones, redirects (plan only) |
72
73
  | `contentrain describe-format` | Print the Contentrain content-format specification |
73
74
  | `contentrain scaffold --template` | Apply a template (`blog`, `landing`, `docs`, `ecommerce`, `saas`, `i18n`, `mobile`) |
74
75
  | `contentrain setup <agent\|--all>` | Configure MCP server + AI rules for IDE (Claude Code, Cursor, Windsurf, VSCode, Copilot) |
@@ -101,6 +102,7 @@ Every read command supports `--json` for CI use; write commands surface `--watch
101
102
  | `merge` | `--yes` (skip confirm) |
102
103
  | `reconcile` | `--yes` (execute a clean plan without prompting), `--json` (dry-run plan) |
103
104
  | `prune` | `--dry-run`, `--yes`, `--json` (mutates only with `--yes`) |
105
+ | `delta` | `--dry-run` (required; there is no apply mode), `--incoming <dir>`, `--store <dir>`, `--taxonomy <csv>`, `--json` |
104
106
  | `describe` | `--sample`, `--locale`, `--json` |
105
107
  | `scaffold` | `--template <id>`, `--locales <csv>`, `--no-sample`, `--json` |
106
108
  | `serve` | `--port`, `--host`, `--open`, `--demo`, `--stdio`, `--mcpHttp`, `--authToken` |
@@ -335,6 +337,17 @@ contentrain import https://site.example --auth user:app-password # authenticate
335
337
 
336
338
  Writes the canonical store plus `import-report.json`, `entry-source-map.json` (WP id → entry address), and — when the source has comments — `comments-export.json` (`contentrain-comments@1`, ready for a comments-service intake). An existing `.contentrain` is only overwritten with `--force`. Powered by `@contentrain/wp-import`.
337
339
 
340
+ ### `contentrain delta`
341
+
342
+ Plan what a later WordPress change means for a store that was already delivered:
343
+
344
+ ```bash
345
+ contentrain delta bridge-delta.json --incoming ./next-export --dry-run # report
346
+ contentrain delta bridge-delta.json --incoming ./next-export --dry-run --json # the planned SourceDeltaPlan
347
+ ```
348
+
349
+ The command reads the store (`--store`, default: the current directory) and its `entry-source-map.json`, from the store root or from `bridge/`. It reads the new export the same way. For each record it reports where it lives in the store, which fields differ, and which addresses moved (each becomes a 301). Trashed and purged deletions are kept apart. A record that was also edited in the repository is a conflict, and it is not overwritten. There is no apply mode: without `--dry-run` the command refuses, because applying a plan goes through review. Taxonomies come from the bridge's `inventory.json` when it is beside the export; name others with `--taxonomy`.
350
+
338
351
  ### Public static builds
339
352
 
340
353
  `contentrain generate --published` excludes drafts and content outside its
@@ -1,6 +1,6 @@
1
1
  import { i as pc } from "./ui-B8l_LC36.mjs";
2
- import { n as resolveStudioClient } from "./client-BeyZQEwe.mjs";
3
- import { t as resolveStudioContext } from "./resolve-context-D1fzCGw-.mjs";
2
+ import { n as resolveStudioClient } from "./client-DYn1qIPW.mjs";
3
+ import { t as resolveStudioContext } from "./resolve-context-CNBzxnlJ.mjs";
4
4
  import { defineCommand } from "citty";
5
5
  import { intro, log, outro, spinner } from "@clack/prompts";
6
6
  //#region src/studio/commands/activity.ts
@@ -1,6 +1,6 @@
1
1
  import { i as pc, r as formatTable, t as formatCount } from "./ui-B8l_LC36.mjs";
2
- import { n as resolveStudioClient } from "./client-BeyZQEwe.mjs";
3
- import { t as resolveStudioContext } from "./resolve-context-D1fzCGw-.mjs";
2
+ import { n as resolveStudioClient } from "./client-DYn1qIPW.mjs";
3
+ import { t as resolveStudioContext } from "./resolve-context-CNBzxnlJ.mjs";
4
4
  import { defineCommand } from "citty";
5
5
  import { confirm, intro, isCancel, log, outro, select, spinner } from "@clack/prompts";
6
6
  //#region src/studio/commands/branches.ts
@@ -1,6 +1,6 @@
1
1
  import { i as pc, t as formatCount } from "./ui-B8l_LC36.mjs";
2
- import { n as resolveStudioClient } from "./client-BeyZQEwe.mjs";
3
- import { t as resolveStudioContext } from "./resolve-context-D1fzCGw-.mjs";
2
+ import { n as resolveStudioClient } from "./client-DYn1qIPW.mjs";
3
+ import { t as resolveStudioContext } from "./resolve-context-CNBzxnlJ.mjs";
4
4
  import { defineCommand } from "citty";
5
5
  import { intro, log, outro, spinner } from "@clack/prompts";
6
6
  //#region src/studio/commands/cdn-build.ts
@@ -1,6 +1,6 @@
1
1
  import { i as pc } from "./ui-B8l_LC36.mjs";
2
- import { n as resolveStudioClient } from "./client-BeyZQEwe.mjs";
3
- import { t as resolveStudioContext } from "./resolve-context-D1fzCGw-.mjs";
2
+ import { n as resolveStudioClient } from "./client-DYn1qIPW.mjs";
3
+ import { t as resolveStudioContext } from "./resolve-context-CNBzxnlJ.mjs";
4
4
  import { defineCommand } from "citty";
5
5
  import { confirm, intro, isCancel, log, outro, spinner } from "@clack/prompts";
6
6
  //#region src/studio/commands/cdn-init.ts
@@ -1,6 +1,6 @@
1
1
  import { i as pc } from "./ui-B8l_LC36.mjs";
2
- import { c as saveDefaults, n as resolveStudioClient } from "./client-BeyZQEwe.mjs";
3
- import { n as openBrowser, t as startOAuthServer } from "./oauth-server-CsI51m-2.mjs";
2
+ import { c as saveDefaults, n as resolveStudioClient } from "./client-DYn1qIPW.mjs";
3
+ import { n as openBrowser, t as startOAuthServer } from "./oauth-server-Ck3RBaXD.mjs";
4
4
  import { defineCommand } from "citty";
5
5
  import { confirm, intro, isCancel, log, outro, select, spinner, text } from "@clack/prompts";
6
6
  import { createGit } from "@contentrain/mcp/git/identity";
@@ -0,0 +1,120 @@
1
+ import { i as pc } from "./ui-B8l_LC36.mjs";
2
+ import { defineCommand } from "citty";
3
+ import { intro, log, outro } from "@clack/prompts";
4
+ import { existsSync } from "node:fs";
5
+ import { readFile, readdir } from "node:fs/promises";
6
+ import { join, relative, resolve } from "node:path";
7
+ //#region src/commands/delta.ts
8
+ /** Every file under `<dir>/.contentrain`, keyed repo-relative. */
9
+ async function readStoreFiles(dir) {
10
+ const paths = (await readdir(join(dir, ".contentrain"), {
11
+ recursive: true,
12
+ withFileTypes: true
13
+ })).filter((entry) => entry.isFile()).map((entry) => join(entry.parentPath, entry.name));
14
+ const texts = await Promise.all(paths.map((path) => readFile(path, "utf8")));
15
+ return Object.fromEntries(paths.map((path, i) => [relative(dir, path), texts[i]]));
16
+ }
17
+ /** The source map the store was built from: the bridge's, or the one `contentrain import` writes. */
18
+ async function readSourceMap(dir) {
19
+ for (const path of [join(dir, "bridge/entry-source-map.json"), join(dir, "entry-source-map.json")]) if (existsSync(path)) return JSON.parse(await readFile(path, "utf8"));
20
+ }
21
+ /** Taxonomies the bridge inventoried, when its inventory is beside the export. */
22
+ async function readTaxonomies(dir) {
23
+ const path = join(dir, "bridge/inventory.json");
24
+ if (!existsSync(path)) return [];
25
+ return JSON.parse(await readFile(path, "utf8")).scope?.taxonomies ?? [];
26
+ }
27
+ var delta_default = defineCommand({
28
+ meta: {
29
+ name: "delta",
30
+ description: "Plan a WordPress source delta against the store (dry run only; applying goes through review)"
31
+ },
32
+ args: {
33
+ delta: {
34
+ type: "positional",
35
+ description: "Path to the SourceDeltaPlan JSON a bridge wrote",
36
+ required: true
37
+ },
38
+ incoming: {
39
+ type: "string",
40
+ description: "Directory of the new export (its .contentrain/ and entry-source-map.json)",
41
+ required: false
42
+ },
43
+ store: {
44
+ type: "string",
45
+ description: "Directory of the repository store (default: current directory)",
46
+ required: false
47
+ },
48
+ taxonomy: {
49
+ type: "string",
50
+ description: "Comma-separated custom taxonomies (term ids, never looked up in the post map)",
51
+ required: false
52
+ },
53
+ "dry-run": {
54
+ type: "boolean",
55
+ description: "Required: report the plan without writing anything",
56
+ required: false
57
+ },
58
+ json: {
59
+ type: "boolean",
60
+ description: "Print the planned SourceDeltaPlan as JSON",
61
+ required: false
62
+ }
63
+ },
64
+ async run({ args }) {
65
+ if (!args["dry-run"]) {
66
+ log.error("contentrain delta only plans. Pass --dry-run; applying a plan goes through review, not this command.");
67
+ process.exitCode = 1;
68
+ return;
69
+ }
70
+ const deltaPath = resolve(args.delta);
71
+ const storeDir = resolve(args.store ?? ".");
72
+ const incomingDir = args.incoming ? resolve(args.incoming) : void 0;
73
+ for (const [label, path] of [
74
+ ["Delta", deltaPath],
75
+ ["Store", join(storeDir, ".contentrain")],
76
+ ...incomingDir ? [["Incoming export", join(incomingDir, ".contentrain")]] : []
77
+ ]) if (!existsSync(path)) {
78
+ log.error(`${label} not found: ${path}`);
79
+ process.exitCode = 1;
80
+ return;
81
+ }
82
+ const storeMap = await readSourceMap(storeDir);
83
+ if (!storeMap) {
84
+ log.error(`No entry-source-map.json in ${storeDir} (or its bridge/) — without it no post can be placed.`);
85
+ process.exitCode = 1;
86
+ return;
87
+ }
88
+ const { DEFAULT_TAXONOMIES, formatSourceDeltaReport, planSourceDelta } = await import("@contentrain/wp-import");
89
+ const delta = JSON.parse(await readFile(deltaPath, "utf8"));
90
+ const store = {
91
+ files: await readStoreFiles(storeDir),
92
+ entry_source_map: storeMap
93
+ };
94
+ const incoming = incomingDir ? {
95
+ files: await readStoreFiles(incomingDir),
96
+ entry_source_map: await readSourceMap(incomingDir) ?? {}
97
+ } : void 0;
98
+ const custom = (args.taxonomy ?? "").split(",").map((name) => name.trim()).filter(Boolean);
99
+ const plan = planSourceDelta({
100
+ delta,
101
+ store,
102
+ incoming,
103
+ taxonomies: [...new Set([
104
+ ...DEFAULT_TAXONOMIES,
105
+ ...incomingDir ? await readTaxonomies(incomingDir) : [],
106
+ ...custom
107
+ ])]
108
+ });
109
+ if (args.json) {
110
+ console.log(JSON.stringify(plan, null, 2));
111
+ return;
112
+ }
113
+ intro(pc.bold("contentrain delta --dry-run"));
114
+ log.message(formatSourceDeltaReport(plan).trimEnd());
115
+ const conflicts = plan.entries.filter((entry) => entry.conflict).length;
116
+ outro(conflicts ? `${conflicts} conflict(s) need a decision before this plan is applied.` : "Plan ready for review.");
117
+ }
118
+ });
119
+ //#endregion
120
+ export { delta_default as default };
@@ -1,6 +1,6 @@
1
1
  import { i as pc } from "./ui-B8l_LC36.mjs";
2
- import { r as resolveProjectRoot } from "./context-OskMGy8y.mjs";
3
- import { t as openMcpSession } from "./mcp-client-DVWTex2i.mjs";
2
+ import { r as resolveProjectRoot } from "./context-SIGQmozp.mjs";
3
+ import { t as openMcpSession } from "./mcp-client-DPpPykAi.mjs";
4
4
  import { defineCommand } from "citty";
5
5
  import { intro, log, outro } from "@clack/prompts";
6
6
  //#region src/commands/describe.ts
@@ -1,6 +1,6 @@
1
1
  import { i as pc } from "./ui-B8l_LC36.mjs";
2
- import { r as resolveProjectRoot } from "./context-OskMGy8y.mjs";
3
- import { t as openMcpSession } from "./mcp-client-DVWTex2i.mjs";
2
+ import { r as resolveProjectRoot } from "./context-SIGQmozp.mjs";
3
+ import { t as openMcpSession } from "./mcp-client-DPpPykAi.mjs";
4
4
  import { defineCommand } from "citty";
5
5
  import { intro, log, outro } from "@clack/prompts";
6
6
  //#region src/commands/describe-format.ts
@@ -1,5 +1,5 @@
1
1
  import { i as pc } from "./ui-B8l_LC36.mjs";
2
- import { r as resolveProjectRoot } from "./context-OskMGy8y.mjs";
2
+ import { r as resolveProjectRoot } from "./context-SIGQmozp.mjs";
3
3
  import { defineCommand } from "citty";
4
4
  import { confirm, intro, isCancel, log, outro, select } from "@clack/prompts";
5
5
  import { createGit } from "@contentrain/mcp/git/identity";
@@ -1,5 +1,5 @@
1
1
  import { i as pc, o as statusIcon } from "./ui-B8l_LC36.mjs";
2
- import { r as resolveProjectRoot } from "./context-OskMGy8y.mjs";
2
+ import { r as resolveProjectRoot } from "./context-SIGQmozp.mjs";
3
3
  import { defineCommand } from "citty";
4
4
  import { intro, log, outro, spinner } from "@clack/prompts";
5
5
  import { runDoctor } from "@contentrain/mcp/core/doctor";
@@ -1,10 +1,10 @@
1
1
  import { i as pc } from "./ui-B8l_LC36.mjs";
2
- import { n as requireInitialized, r as resolveProjectRoot, t as loadProjectContext } from "./context-OskMGy8y.mjs";
2
+ import { n as requireInitialized, r as resolveProjectRoot, t as loadProjectContext } from "./context-SIGQmozp.mjs";
3
3
  import { defineCommand } from "citty";
4
4
  import { intro, log, outro, spinner } from "@clack/prompts";
5
+ import { watch } from "node:fs";
5
6
  import { join } from "node:path";
6
7
  import { contentrainDir } from "@contentrain/mcp/util/fs";
7
- import { watch } from "node:fs";
8
8
  //#region src/utils/watch.ts
9
9
  const watchPath = watch;
10
10
  //#endregion
package/dist/index.mjs CHANGED
@@ -2,7 +2,7 @@
2
2
  import { i as pc } from "./ui-B8l_LC36.mjs";
3
3
  import { defineCommand, runMain } from "citty";
4
4
  //#region package.json
5
- var version = "0.13.5";
5
+ var version = "0.14.1";
6
6
  //#endregion
7
7
  //#region src/utils/debug.ts
8
8
  /**
@@ -43,23 +43,24 @@ runMain(defineCommand({
43
43
  description: "Contentrain CLI — AI content governance infrastructure"
44
44
  },
45
45
  subCommands: {
46
- init: () => import("./init-DzpPFgf2.mjs").then((m) => m.default),
47
- import: () => import("./import-RezpSn3Q.mjs").then((m) => m.default),
48
- status: () => import("./status-D_rC1Qln.mjs").then((m) => m.default),
49
- doctor: () => import("./doctor-MOf_LQEL.mjs").then((m) => m.default),
50
- validate: () => import("./validate-C0kK-1BC.mjs").then((m) => m.default),
51
- serve: () => import("./serve-Bca9c80T.mjs").then((m) => m.default),
52
- generate: () => import("./generate-BKskWYyJ.mjs").then((m) => m.default),
53
- diff: () => import("./diff-BUGOF3SZ.mjs").then((m) => m.default),
54
- merge: () => import("./merge-Bkx2GGET.mjs").then((m) => m.default),
55
- reconcile: () => import("./reconcile-CC5xnijO.mjs").then((m) => m.default),
56
- prune: () => import("./prune-RgPwvk5_.mjs").then((m) => m.default),
57
- describe: () => import("./describe-CpQROC9y.mjs").then((m) => m.default),
58
- "describe-format": () => import("./describe-format-CUAqB0C4.mjs").then((m) => m.default),
59
- scaffold: () => import("./scaffold-C6s96dYz.mjs").then((m) => m.default),
60
- setup: () => import("./setup-CsgpgrlJ.mjs").then((m) => m.default),
61
- skills: () => import("./skills-Bst5FQ7K.mjs").then((m) => m.default),
62
- studio: () => import("./studio-39PJXdw9.mjs").then((m) => m.default)
46
+ init: () => import("./init-_0Hp__pU.mjs").then((m) => m.default),
47
+ import: () => import("./import-BmS_V6le.mjs").then((m) => m.default),
48
+ delta: () => import("./delta-D6Cp9BdP.mjs").then((m) => m.default),
49
+ status: () => import("./status-5RpF1q6y.mjs").then((m) => m.default),
50
+ doctor: () => import("./doctor-B9MJgRO5.mjs").then((m) => m.default),
51
+ validate: () => import("./validate-CiP3MkeV.mjs").then((m) => m.default),
52
+ serve: () => import("./serve-Cglzhom-.mjs").then((m) => m.default),
53
+ generate: () => import("./generate-fLQfw9t7.mjs").then((m) => m.default),
54
+ diff: () => import("./diff-6EnRgpPR.mjs").then((m) => m.default),
55
+ merge: () => import("./merge-C8l80Cg-.mjs").then((m) => m.default),
56
+ reconcile: () => import("./reconcile-D1clXB6h.mjs").then((m) => m.default),
57
+ prune: () => import("./prune-CvTj9QMj.mjs").then((m) => m.default),
58
+ describe: () => import("./describe-C6-AWlKx.mjs").then((m) => m.default),
59
+ "describe-format": () => import("./describe-format-CR0-NMR8.mjs").then((m) => m.default),
60
+ scaffold: () => import("./scaffold-DX6eJ0n1.mjs").then((m) => m.default),
61
+ setup: () => import("./setup-BRVyTOxY.mjs").then((m) => m.default),
62
+ skills: () => import("./skills-DZT0pbmO.mjs").then((m) => m.default),
63
+ studio: () => import("./studio-DessrNQs.mjs").then((m) => m.default)
63
64
  }
64
65
  }));
65
66
  //#endregion
@@ -1,14 +1,14 @@
1
1
  import { i as pc } from "./ui-B8l_LC36.mjs";
2
- import { r as resolveProjectRoot, t as loadProjectContext } from "./context-OskMGy8y.mjs";
3
- import { a as createPackageResolver, c as writeMcpConfig, i as addClaudeMdReference, n as IDE_CONFIGS, o as detectIdes, s as installIdeRulesAndSkills } from "./ide-Dtw1wesv.mjs";
2
+ import { r as resolveProjectRoot, t as loadProjectContext } from "./context-SIGQmozp.mjs";
3
+ import { a as createPackageResolver, c as writeMcpConfig, i as addClaudeMdReference, n as IDE_CONFIGS, o as detectIdes, s as installIdeRulesAndSkills } from "./ide-D1J4iAhK.mjs";
4
4
  import { defineCommand } from "citty";
5
5
  import { confirm, intro, isCancel, log, multiselect, outro, select, spinner } from "@clack/prompts";
6
+ import { appendFile, readFile, writeFile } from "node:fs/promises";
6
7
  import { join } from "node:path";
7
8
  import { writeModel } from "@contentrain/mcp/core/model-manager";
8
9
  import { ensureDir, pathExists, writeJson } from "@contentrain/mcp/util/fs";
9
10
  import { createGit } from "@contentrain/mcp/git/identity";
10
11
  import { buildBranchName, createTransaction } from "@contentrain/mcp/git/transaction";
11
- import { appendFile, readFile, writeFile } from "node:fs/promises";
12
12
  import { detectStackInfo } from "@contentrain/mcp/util/detect";
13
13
  import { getTemplate, listTemplates } from "@contentrain/mcp/templates";
14
14
  import { scanSummary } from "@contentrain/mcp/core/scanner";
@@ -1,6 +1,6 @@
1
1
  import { i as pc } from "./ui-B8l_LC36.mjs";
2
- import { i as checkPermissions, o as loadCredentials, s as saveCredentials, t as StudioApiClient } from "./client-BeyZQEwe.mjs";
3
- import { n as openBrowser, t as startOAuthServer } from "./oauth-server-CsI51m-2.mjs";
2
+ import { i as checkPermissions, o as loadCredentials, s as saveCredentials, t as StudioApiClient } from "./client-DYn1qIPW.mjs";
3
+ import { n as openBrowser, t as startOAuthServer } from "./oauth-server-Ck3RBaXD.mjs";
4
4
  import { defineCommand } from "citty";
5
5
  import { confirm, intro, isCancel, log, outro, select, spinner } from "@clack/prompts";
6
6
  //#region src/studio/commands/login.ts
@@ -1,5 +1,5 @@
1
1
  import { i as pc } from "./ui-B8l_LC36.mjs";
2
- import { a as clearCredentials, o as loadCredentials, t as StudioApiClient } from "./client-BeyZQEwe.mjs";
2
+ import { a as clearCredentials, o as loadCredentials, t as StudioApiClient } from "./client-DYn1qIPW.mjs";
3
3
  import { defineCommand } from "citty";
4
4
  import { intro, log, outro } from "@clack/prompts";
5
5
  //#region src/studio/commands/logout.ts
@@ -1,5 +1,5 @@
1
1
  import { i as pc } from "./ui-B8l_LC36.mjs";
2
- import { r as resolveProjectRoot } from "./context-OskMGy8y.mjs";
2
+ import { r as resolveProjectRoot } from "./context-SIGQmozp.mjs";
3
3
  import { defineCommand } from "citty";
4
4
  import { confirm, intro, isCancel, log, outro } from "@clack/prompts";
5
5
  import { createGit } from "@contentrain/mcp/git/identity";
@@ -1,5 +1,5 @@
1
1
  import { i as pc } from "./ui-B8l_LC36.mjs";
2
- import { r as resolveProjectRoot } from "./context-OskMGy8y.mjs";
2
+ import { r as resolveProjectRoot } from "./context-SIGQmozp.mjs";
3
3
  import { defineCommand } from "citty";
4
4
  import { confirm, intro, isCancel, log, outro } from "@clack/prompts";
5
5
  import { cleanupMergedBranches, pruneMergedRemoteBranches } from "@contentrain/mcp/git/branch-lifecycle";
@@ -1,6 +1,6 @@
1
1
  import { i as pc } from "./ui-B8l_LC36.mjs";
2
- import { r as resolveProjectRoot } from "./context-OskMGy8y.mjs";
3
- import { t as openMcpSession } from "./mcp-client-DVWTex2i.mjs";
2
+ import { r as resolveProjectRoot } from "./context-SIGQmozp.mjs";
3
+ import { t as openMcpSession } from "./mcp-client-DPpPykAi.mjs";
4
4
  import { defineCommand } from "citty";
5
5
  import { intro, isCancel, log, outro, select } from "@clack/prompts";
6
6
  //#region src/commands/reconcile.ts
@@ -1,4 +1,4 @@
1
- import { c as saveDefaults, o as loadCredentials } from "./client-BeyZQEwe.mjs";
1
+ import { c as saveDefaults, o as loadCredentials } from "./client-DYn1qIPW.mjs";
2
2
  import { confirm, isCancel, select } from "@clack/prompts";
3
3
  //#region src/studio/resolve-context.ts
4
4
  /**
@@ -1,6 +1,6 @@
1
1
  import { i as pc } from "./ui-B8l_LC36.mjs";
2
- import { r as resolveProjectRoot } from "./context-OskMGy8y.mjs";
3
- import { t as openMcpSession } from "./mcp-client-DVWTex2i.mjs";
2
+ import { r as resolveProjectRoot } from "./context-SIGQmozp.mjs";
3
+ import { t as openMcpSession } from "./mcp-client-DPpPykAi.mjs";
4
4
  import { defineCommand } from "citty";
5
5
  import { intro, isCancel, log, outro, select, spinner } from "@clack/prompts";
6
6
  //#region src/commands/scaffold.ts
@@ -1,4 +1,4 @@
1
- import { r as resolveProjectRoot } from "./context-OskMGy8y.mjs";
1
+ import { r as resolveProjectRoot } from "./context-SIGQmozp.mjs";
2
2
  import { defineCommand } from "citty";
3
3
  import { createServer } from "@contentrain/mcp/server";
4
4
  import { createGit } from "@contentrain/mcp/git/identity";
@@ -55,7 +55,7 @@ var serve_default = defineCommand({
55
55
  let projectRoot = await resolveProjectRoot(args.root);
56
56
  let demoDir;
57
57
  if (args.demo) {
58
- const { createDemoProject, cleanupDemoProject } = await import("./demo-937OTZSI.mjs");
58
+ const { createDemoProject, cleanupDemoProject } = await import("./demo-lHnrfuW1.mjs");
59
59
  demoDir = await createDemoProject();
60
60
  projectRoot = demoDir;
61
61
  consola.info(`Demo project created at ${demoDir}`);
@@ -139,7 +139,7 @@ var serve_default = defineCommand({
139
139
  consola.warn("Serve UI not found. Running in API-only mode.");
140
140
  consola.info("UI will be available after building: cd packages/cli/src/serve-ui && pnpm build");
141
141
  }
142
- const { createServeApp } = await import("./server-ftj2te6Y.mjs");
142
+ const { createServeApp } = await import("./server-CL18nNJ9.mjs");
143
143
  const { app, handleUpgrade } = await createServeApp({
144
144
  projectRoot,
145
145
  port,
@@ -1,6 +1,6 @@
1
1
  import { i as pc } from "./ui-B8l_LC36.mjs";
2
- import { r as resolveProjectRoot, t as loadProjectContext } from "./context-OskMGy8y.mjs";
3
- import { a as createPackageResolver, c as writeMcpConfig, n as IDE_CONFIGS, o as detectIdes, r as MCP_CONFIGS, s as installIdeRulesAndSkills } from "./ide-Dtw1wesv.mjs";
2
+ import { r as resolveProjectRoot, t as loadProjectContext } from "./context-SIGQmozp.mjs";
3
+ import { a as createPackageResolver, c as writeMcpConfig, n as IDE_CONFIGS, o as detectIdes, r as MCP_CONFIGS, s as installIdeRulesAndSkills } from "./ide-D1J4iAhK.mjs";
4
4
  import { defineCommand } from "citty";
5
5
  import { intro, log, outro, spinner } from "@clack/prompts";
6
6
  //#region src/commands/setup.ts
@@ -1,6 +1,6 @@
1
1
  import { i as pc } from "./ui-B8l_LC36.mjs";
2
- import { r as resolveProjectRoot } from "./context-OskMGy8y.mjs";
3
- import { a as createPackageResolver, n as IDE_CONFIGS, o as detectIdes, s as installIdeRulesAndSkills, t as AGENT_SKILL_NAMES } from "./ide-Dtw1wesv.mjs";
2
+ import { r as resolveProjectRoot } from "./context-SIGQmozp.mjs";
3
+ import { a as createPackageResolver, n as IDE_CONFIGS, o as detectIdes, s as installIdeRulesAndSkills, t as AGENT_SKILL_NAMES } from "./ide-D1J4iAhK.mjs";
4
4
  import { defineCommand } from "citty";
5
5
  import { intro, log, outro, spinner } from "@clack/prompts";
6
6
  import { join } from "node:path";
@@ -1,5 +1,5 @@
1
1
  import { i as pc, n as formatPercent, r as formatTable, t as formatCount } from "./ui-B8l_LC36.mjs";
2
- import { n as requireInitialized, r as resolveProjectRoot, t as loadProjectContext } from "./context-OskMGy8y.mjs";
2
+ import { n as requireInitialized, r as resolveProjectRoot, t as loadProjectContext } from "./context-SIGQmozp.mjs";
3
3
  import { defineCommand } from "citty";
4
4
  import { intro, log, outro } from "@clack/prompts";
5
5
  import { countEntries, readModel } from "@contentrain/mcp/core/model-manager";
@@ -1,6 +1,6 @@
1
1
  import { i as pc, r as formatTable, t as formatCount } from "./ui-B8l_LC36.mjs";
2
- import { n as resolveStudioClient } from "./client-BeyZQEwe.mjs";
3
- import { t as resolveStudioContext } from "./resolve-context-D1fzCGw-.mjs";
2
+ import { n as resolveStudioClient } from "./client-DYn1qIPW.mjs";
3
+ import { t as resolveStudioContext } from "./resolve-context-CNBzxnlJ.mjs";
4
4
  import { defineCommand } from "citty";
5
5
  import { intro, log, outro, spinner } from "@clack/prompts";
6
6
  //#region src/studio/commands/status.ts
@@ -0,0 +1,24 @@
1
+ import { defineCommand } from "citty";
2
+ //#region src/studio/index.ts
3
+ var studio_default = defineCommand({
4
+ meta: {
5
+ name: "studio",
6
+ description: "Interact with Contentrain Studio"
7
+ },
8
+ subCommands: {
9
+ login: () => import("./login-C6gv1Ec5.mjs").then((m) => m.default),
10
+ logout: () => import("./logout-D_8LjZ2N.mjs").then((m) => m.default),
11
+ whoami: () => import("./whoami-BCuY4Zi3.mjs").then((m) => m.default),
12
+ connect: () => import("./connect-BYVRMPz9.mjs").then((m) => m.default),
13
+ status: () => import("./status-C6koCAw2.mjs").then((m) => m.default),
14
+ activity: () => import("./activity-DHriVJu5.mjs").then((m) => m.default),
15
+ usage: () => import("./usage-6pJn7APs.mjs").then((m) => m.default),
16
+ branches: () => import("./branches-DZrVrweZ.mjs").then((m) => m.default),
17
+ "cdn-init": () => import("./cdn-init-CIGPuYNT.mjs").then((m) => m.default),
18
+ "cdn-build": () => import("./cdn-build-ltuSzhql.mjs").then((m) => m.default),
19
+ webhooks: () => import("./webhooks-CnGcaEQy.mjs").then((m) => m.default),
20
+ submissions: () => import("./submissions-C9PxDNSv.mjs").then((m) => m.default)
21
+ }
22
+ });
23
+ //#endregion
24
+ export { studio_default as default };
@@ -1,6 +1,6 @@
1
1
  import { i as pc, r as formatTable, t as formatCount } from "./ui-B8l_LC36.mjs";
2
- import { n as resolveStudioClient } from "./client-BeyZQEwe.mjs";
3
- import { t as resolveStudioContext } from "./resolve-context-D1fzCGw-.mjs";
2
+ import { n as resolveStudioClient } from "./client-DYn1qIPW.mjs";
3
+ import { t as resolveStudioContext } from "./resolve-context-CNBzxnlJ.mjs";
4
4
  import { defineCommand } from "citty";
5
5
  import { confirm, intro, isCancel, log, outro, select, spinner } from "@clack/prompts";
6
6
  //#region src/studio/commands/submissions.ts
@@ -1,6 +1,6 @@
1
1
  import { i as pc, n as formatPercent, r as formatTable } from "./ui-B8l_LC36.mjs";
2
- import { n as resolveStudioClient } from "./client-BeyZQEwe.mjs";
3
- import { t as resolveStudioContext } from "./resolve-context-D1fzCGw-.mjs";
2
+ import { n as resolveStudioClient } from "./client-DYn1qIPW.mjs";
3
+ import { t as resolveStudioContext } from "./resolve-context-CNBzxnlJ.mjs";
4
4
  import { defineCommand } from "citty";
5
5
  import { intro, log, outro, spinner } from "@clack/prompts";
6
6
  //#region src/studio/commands/usage.ts
@@ -1,6 +1,6 @@
1
1
  import { a as severityColor, i as pc, t as formatCount } from "./ui-B8l_LC36.mjs";
2
2
  import { t as debug } from "./index.mjs";
3
- import { n as requireInitialized, r as resolveProjectRoot, t as loadProjectContext } from "./context-OskMGy8y.mjs";
3
+ import { n as requireInitialized, r as resolveProjectRoot, t as loadProjectContext } from "./context-SIGQmozp.mjs";
4
4
  import { defineCommand } from "citty";
5
5
  import { intro, isCancel, log, outro, select, spinner } from "@clack/prompts";
6
6
  import { join } from "node:path";
@@ -1,6 +1,6 @@
1
1
  import { i as pc, o as statusIcon, r as formatTable } from "./ui-B8l_LC36.mjs";
2
- import { n as resolveStudioClient } from "./client-BeyZQEwe.mjs";
3
- import { t as resolveStudioContext } from "./resolve-context-D1fzCGw-.mjs";
2
+ import { n as resolveStudioClient } from "./client-DYn1qIPW.mjs";
3
+ import { t as resolveStudioContext } from "./resolve-context-CNBzxnlJ.mjs";
4
4
  import { defineCommand } from "citty";
5
5
  import { confirm, intro, isCancel, log, multiselect, outro, select, spinner, text } from "@clack/prompts";
6
6
  //#region src/studio/commands/webhooks.ts
@@ -1,5 +1,5 @@
1
1
  import { i as pc } from "./ui-B8l_LC36.mjs";
2
- import { i as checkPermissions, n as resolveStudioClient, r as AuthExpiredError } from "./client-BeyZQEwe.mjs";
2
+ import { i as checkPermissions, n as resolveStudioClient, r as AuthExpiredError } from "./client-DYn1qIPW.mjs";
3
3
  import { defineCommand } from "citty";
4
4
  import { intro, log, outro } from "@clack/prompts";
5
5
  //#region src/studio/commands/whoami.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "contentrain",
3
- "version": "0.13.5",
3
+ "version": "0.14.1",
4
4
  "license": "MIT",
5
5
  "description": "CLI for Contentrain — AI content governance infrastructure",
6
6
  "type": "module",
@@ -47,12 +47,12 @@
47
47
  "simple-git": "^3.27.0",
48
48
  "ws": "^8.18.0",
49
49
  "zod": "^3.24.0",
50
- "@contentrain/mcp": "3.4.3",
51
- "@contentrain/query": "7.3.5",
50
+ "@contentrain/mcp": "3.6.0",
51
+ "@contentrain/query": "7.3.7",
52
52
  "@contentrain/rules": "0.7.2",
53
53
  "@contentrain/skills": "0.9.4",
54
- "@contentrain/types": "1.17.0",
55
- "@contentrain/wp-import": "0.4.6"
54
+ "@contentrain/types": "1.18.1",
55
+ "@contentrain/wp-import": "0.5.1"
56
56
  },
57
57
  "devDependencies": {
58
58
  "@types/ws": "^8.5.0",
@@ -1,24 +0,0 @@
1
- import { defineCommand } from "citty";
2
- //#region src/studio/index.ts
3
- var studio_default = defineCommand({
4
- meta: {
5
- name: "studio",
6
- description: "Interact with Contentrain Studio"
7
- },
8
- subCommands: {
9
- login: () => import("./login-B8P_JDLG.mjs").then((m) => m.default),
10
- logout: () => import("./logout-BWEtxcqT.mjs").then((m) => m.default),
11
- whoami: () => import("./whoami-2lHHQboY.mjs").then((m) => m.default),
12
- connect: () => import("./connect-BK2e05he.mjs").then((m) => m.default),
13
- status: () => import("./status-ghQXrAtt.mjs").then((m) => m.default),
14
- activity: () => import("./activity-DjSTygMo.mjs").then((m) => m.default),
15
- usage: () => import("./usage-_kEqbIxO.mjs").then((m) => m.default),
16
- branches: () => import("./branches-CzBo3c5P.mjs").then((m) => m.default),
17
- "cdn-init": () => import("./cdn-init-EDtGs6D6.mjs").then((m) => m.default),
18
- "cdn-build": () => import("./cdn-build-BvwW0OjV.mjs").then((m) => m.default),
19
- webhooks: () => import("./webhooks-SojN2I50.mjs").then((m) => m.default),
20
- submissions: () => import("./submissions-XXqgcE-W.mjs").then((m) => m.default)
21
- }
22
- });
23
- //#endregion
24
- export { studio_default as default };
@@ -1,5 +1,5 @@
1
- import { join } from "node:path";
2
1
  import { chmod, mkdir, readFile, stat, unlink, writeFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
3
  import { homedir } from "node:os";
4
4
  //#region src/studio/auth/credential-store.ts
5
5
  const DIR_NAME = ".contentrain";
@@ -1,8 +1,8 @@
1
+ import { mkdtemp, rm, writeFile } from "node:fs/promises";
1
2
  import { join } from "node:path";
2
3
  import { writeModel } from "@contentrain/mcp/core/model-manager";
3
4
  import { ensureDir, writeJson } from "@contentrain/mcp/util/fs";
4
5
  import { createGit } from "@contentrain/mcp/git/identity";
5
- import { mkdtemp, rm, writeFile } from "node:fs/promises";
6
6
  import { getTemplate } from "@contentrain/mcp/templates";
7
7
  import { tmpdir } from "node:os";
8
8
  //#region src/utils/demo.ts
@@ -1,7 +1,7 @@
1
+ import { appendFile, readFile, writeFile } from "node:fs/promises";
1
2
  import { join } from "node:path";
2
3
  import { ensureDir, pathExists } from "@contentrain/mcp/util/fs";
3
4
  import { createGit } from "@contentrain/mcp/git/identity";
4
- import { appendFile, readFile, writeFile } from "node:fs/promises";
5
5
  //#region src/utils/ide.ts
6
6
  const AGENT_SKILL_NAMES = [
7
7
  "contentrain",
@@ -1,9 +1,9 @@
1
1
  import { i as pc } from "./ui-B8l_LC36.mjs";
2
2
  import { defineCommand } from "citty";
3
3
  import { intro, log, outro, spinner } from "@clack/prompts";
4
- import { dirname, join, resolve } from "node:path";
5
4
  import { createReadStream, existsSync } from "node:fs";
6
5
  import { access, mkdir, writeFile } from "node:fs/promises";
6
+ import { dirname, join, resolve } from "node:path";
7
7
  //#region src/commands/import.ts
8
8
  var import_default = defineCommand({
9
9
  meta: {
@@ -1,3 +1,5 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { readFile, unlink, writeFile } from "node:fs/promises";
1
3
  import { join } from "node:path";
2
4
  import { readConfig } from "@contentrain/mcp/core/config";
3
5
  import { createServer } from "@contentrain/mcp/server";
@@ -7,8 +9,6 @@ import { createGit } from "@contentrain/mcp/git/identity";
7
9
  import { CONTENTRAIN_BRANCH, LOCAL_CAPABILITIES } from "@contentrain/types";
8
10
  import { mergeBranch } from "@contentrain/mcp/git/transaction";
9
11
  import { branchDiff, checkBranchHealth, deleteRemoteBranch } from "@contentrain/mcp/git/branch-lifecycle";
10
- import { existsSync, readFileSync } from "node:fs";
11
- import { readFile, unlink, writeFile } from "node:fs/promises";
12
12
  import { normalizeOperationError } from "@contentrain/mcp/git/errors";
13
13
  import { createApp, createError, createRouter, defineEventHandler, getQuery, getRouterParam, readBody, toNodeListener } from "h3";
14
14
  import { WebSocketServer } from "ws";