contentrain 0.6.0 → 0.7.2

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 (31) hide show
  1. package/README.md +8 -3
  2. package/dist/{activity-B8j9gfsK.mjs → activity-DP5wjWLV.mjs} +2 -2
  3. package/dist/{branches-CvpFbyrJ.mjs → branches-D_LPptfM.mjs} +2 -2
  4. package/dist/{cdn-build-DS9FprWU.mjs → cdn-build-BuacuDbL.mjs} +2 -2
  5. package/dist/{cdn-init-Bm4dpEJn.mjs → cdn-init-CGl8-QCR.mjs} +2 -2
  6. package/dist/{connect-Bb0BrZsx.mjs → connect-BTJU6Ud3.mjs} +2 -2
  7. package/dist/{diff-ov1j9bAb.mjs → diff-DqWPyJZF.mjs} +6 -1
  8. package/dist/index.mjs +11 -10
  9. package/dist/{login-xvzL-UvR.mjs → login-yLBoeLVM.mjs} +2 -2
  10. package/dist/{logout-DzspSatR.mjs → logout-DBm34b7e.mjs} +1 -1
  11. package/dist/{merge-DdPRttF-.mjs → merge-Dm4Kl1u8.mjs} +2 -0
  12. package/dist/prune-DCcyYVcD.mjs +101 -0
  13. package/dist/{resolve-context-hKVYPniC.mjs → resolve-context-DPdtEC0i.mjs} +1 -1
  14. package/dist/{serve-iLl3Y5Bt.mjs → serve-BZVPdM0_.mjs} +2 -2
  15. package/dist/{server-B1PSjXbu.mjs → server-CPBQIj9B.mjs} +8 -4
  16. package/dist/{status-BJ6Lu3J4.mjs → status-BAQ8GFyN.mjs} +2 -2
  17. package/dist/studio-DVVkj4QL.mjs +24 -0
  18. package/dist/{submissions-zH_S7JIQ.mjs → submissions-JTtZXvcf.mjs} +2 -2
  19. package/dist/{usage-z6eyT64a.mjs → usage-CC7Chuf6.mjs} +2 -2
  20. package/dist/{webhooks-CBG2Bs9P.mjs → webhooks-C-D4zHq8.mjs} +2 -2
  21. package/dist/{whoami-CXVfvo7x.mjs → whoami-D0ZYvnWU.mjs} +1 -1
  22. package/package.json +4 -4
  23. package/dist/studio-DPVJ-2oG.mjs +0 -24
  24. /package/dist/{client-C9E9D4mb.mjs → client-CJsHr9Db.mjs} +0 -0
  25. /package/dist/{demo-DUknxn48.mjs → demo-BPbR_r4f.mjs} +0 -0
  26. /package/dist/{oauth-server-smSxDoH5.mjs → oauth-server-BSgPLV_2.mjs} +0 -0
  27. /package/dist/{scaffold-iuvrMh78.mjs → scaffold-irxW-vdX.mjs} +0 -0
  28. /package/dist/{setup-BMqKibZt.mjs → setup-ZnQXTEP-.mjs} +0 -0
  29. /package/dist/{skills-CZ54F-97.mjs → skills-DeliTaHV.mjs} +0 -0
  30. /package/dist/{status-Bmjfrk-B.mjs → status-CKHWrsUI.mjs} +0 -0
  31. /package/dist/{validate-BG0X5g09.mjs → validate-CW8FCCd4.mjs} +0 -0
package/README.md CHANGED
@@ -65,7 +65,8 @@ Example: `contentrain --debug status` or `CONTENTRAIN_DEBUG=1 contentrain valida
65
65
  | `contentrain validate` | Validate content against schemas, optionally create review-branch fixes |
66
66
  | `contentrain generate` | Generate `.contentrain/client/` and `#contentrain` package imports |
67
67
  | `contentrain diff` | Review and merge or reject pending `cr/*` branches interactively |
68
- | `contentrain merge <branch>` | Merge one pending `cr/*` branch non-interactively (CI/agents) |
68
+ | `contentrain merge <branch>` | Merge one pending `cr/*` branch non-interactively (CI/agents); deletes its remote copy |
69
+ | `contentrain prune` | Delete merged `cr/*` branches locally and on the remote (backlog drain) |
69
70
  | `contentrain describe <model>` | Inspect a model's schema, stats, and import snippet |
70
71
  | `contentrain describe-format` | Print the Contentrain content-format specification |
71
72
  | `contentrain scaffold --template` | Apply a template (`blog`, `landing`, `docs`, `ecommerce`, `saas`, `i18n`, `mobile`) |
@@ -92,11 +93,12 @@ Every read command supports `--json` for CI use; write commands surface `--watch
92
93
  | Command | Notable flags |
93
94
  | --- | --- |
94
95
  | `status` | `--json` |
95
- | `doctor` | `--json`, `--usage` — non-zero exit on failure |
96
+ | `doctor` | `--json`, `--usage` — non-zero exit on failure; includes a remote `cr/*` branch check |
96
97
  | `validate` | `--json`, `--fix`, `--interactive`, `--watch`, `--model <id>` |
97
98
  | `generate` | `--json`, `--watch` |
98
99
  | `diff` | `--json` |
99
100
  | `merge` | `--yes` (skip confirm) |
101
+ | `prune` | `--dry-run`, `--yes`, `--json` (mutates only with `--yes`) |
100
102
  | `describe` | `--sample`, `--locale`, `--json` |
101
103
  | `scaffold` | `--template <id>`, `--locales <csv>`, `--no-sample`, `--json` |
102
104
  | `serve` | `--port`, `--host`, `--open`, `--demo`, `--stdio`, `--mcpHttp`, `--authToken` |
@@ -240,16 +242,19 @@ This installs:
240
242
 
241
243
  Most write operations create feature branches from the dedicated `contentrain` branch. In review mode, these branches are pushed to remote for team review. In auto-merge mode, they are merged into the `contentrain` branch and baseBranch is advanced via update-ref.
242
244
 
245
+ Merging a review branch (via `contentrain merge`, `contentrain diff`, the Serve UI, or the MCP tools) also deletes its remote copy, so merged branches never pile up as phantom pending reviews. The same applies to rejected/deleted drafts. This is best-effort — an offline or permission failure only produces a warning — and can be disabled with `remoteBranchCleanup: false` in `config.json`. Note that deleting a pushed branch closes any open PR/MR on it.
246
+
243
247
  Use:
244
248
 
245
249
  ```bash
246
250
  contentrain status
247
251
  contentrain diff
252
+ contentrain prune --dry-run # preview merged local/remote leftovers, then run with --yes
248
253
  ```
249
254
 
250
255
  to understand:
251
256
 
252
- - how many active `cr/*` review branches exist on the `contentrain` branch
257
+ - how many active `cr/*` review branches exist on the `contentrain` branch (and on the remote — `contentrain doctor`)
253
258
  - whether branch health is blocking new writes (warning at 50, blocked at 80)
254
259
  - what changed before merging or deleting a branch
255
260
 
@@ -1,6 +1,6 @@
1
1
  import { i as pc } from "./ui-B8l_LC36.mjs";
2
- import { n as resolveStudioClient } from "./client-C9E9D4mb.mjs";
3
- import { t as resolveStudioContext } from "./resolve-context-hKVYPniC.mjs";
2
+ import { n as resolveStudioClient } from "./client-CJsHr9Db.mjs";
3
+ import { t as resolveStudioContext } from "./resolve-context-DPdtEC0i.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-C9E9D4mb.mjs";
3
- import { t as resolveStudioContext } from "./resolve-context-hKVYPniC.mjs";
2
+ import { n as resolveStudioClient } from "./client-CJsHr9Db.mjs";
3
+ import { t as resolveStudioContext } from "./resolve-context-DPdtEC0i.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-C9E9D4mb.mjs";
3
- import { t as resolveStudioContext } from "./resolve-context-hKVYPniC.mjs";
2
+ import { n as resolveStudioClient } from "./client-CJsHr9Db.mjs";
3
+ import { t as resolveStudioContext } from "./resolve-context-DPdtEC0i.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-C9E9D4mb.mjs";
3
- import { t as resolveStudioContext } from "./resolve-context-hKVYPniC.mjs";
2
+ import { n as resolveStudioClient } from "./client-CJsHr9Db.mjs";
3
+ import { t as resolveStudioContext } from "./resolve-context-DPdtEC0i.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-C9E9D4mb.mjs";
3
- import { n as openBrowser, t as startOAuthServer } from "./oauth-server-smSxDoH5.mjs";
2
+ import { c as saveDefaults, n as resolveStudioClient } from "./client-CJsHr9Db.mjs";
3
+ import { n as openBrowser, t as startOAuthServer } from "./oauth-server-BSgPLV_2.mjs";
4
4
  import { defineCommand } from "citty";
5
5
  import { confirm, intro, isCancel, log, outro, select, spinner, text } from "@clack/prompts";
6
6
  import { simpleGit } from "simple-git";
@@ -5,7 +5,7 @@ import { confirm, intro, isCancel, log, outro, select } from "@clack/prompts";
5
5
  import { simpleGit } from "simple-git";
6
6
  import { CONTENTRAIN_BRANCH } from "@contentrain/types";
7
7
  import { mergeBranch } from "@contentrain/mcp/git/transaction";
8
- import { branchDiff } from "@contentrain/mcp/git/branch-lifecycle";
8
+ import { branchDiff, deleteRemoteBranch } from "@contentrain/mcp/git/branch-lifecycle";
9
9
  //#region src/commands/diff.ts
10
10
  var diff_default = defineCommand({
11
11
  meta: {
@@ -132,6 +132,8 @@ var diff_default = defineCommand({
132
132
  if (!isCancel(confirmMerge) && confirmMerge) try {
133
133
  const result = await mergeBranch(projectRoot, selectedBranch);
134
134
  log.success(`Merged ${selectedBranch} (commit ${result.commit.slice(0, 8)})`);
135
+ if (result.remote?.deleted) log.message(pc.dim(" Deleted remote copy."));
136
+ if (result.remote?.warning) log.warning(`Remote copy not deleted: ${result.remote.warning}`);
135
137
  if (result.sync?.skipped?.length) {
136
138
  log.warning(`${result.sync.skipped.length} file(s) skipped during sync — you have uncommitted changes:`);
137
139
  for (const f of result.sync.skipped) log.message(pc.dim(` ${f}`));
@@ -144,7 +146,10 @@ var diff_default = defineCommand({
144
146
  const confirmDelete = await confirm({ message: `Delete ${selectedBranch}? This cannot be undone.` });
145
147
  if (!isCancel(confirmDelete) && confirmDelete) try {
146
148
  await git.deleteLocalBranch(selectedBranch, true);
149
+ const remote = await deleteRemoteBranch(projectRoot, selectedBranch);
147
150
  log.success(`Deleted ${selectedBranch}`);
151
+ if (remote.deleted) log.message(pc.dim(" Deleted remote copy."));
152
+ if (remote.warning) log.warning(`Remote copy not deleted: ${remote.warning}`);
148
153
  } catch (error) {
149
154
  log.error(`Delete failed: ${error instanceof Error ? error.message : String(error)}`);
150
155
  }
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.6.0";
5
+ var version = "0.7.2";
6
6
  //#endregion
7
7
  //#region src/utils/debug.ts
8
8
  /**
@@ -44,19 +44,20 @@ runMain(defineCommand({
44
44
  },
45
45
  subCommands: {
46
46
  init: () => import("./init-1fl35oaD.mjs").then((m) => m.default),
47
- status: () => import("./status-Bmjfrk-B.mjs").then((m) => m.default),
47
+ status: () => import("./status-CKHWrsUI.mjs").then((m) => m.default),
48
48
  doctor: () => import("./doctor-MOf_LQEL.mjs").then((m) => m.default),
49
- validate: () => import("./validate-BG0X5g09.mjs").then((m) => m.default),
50
- serve: () => import("./serve-iLl3Y5Bt.mjs").then((m) => m.default),
49
+ validate: () => import("./validate-CW8FCCd4.mjs").then((m) => m.default),
50
+ serve: () => import("./serve-BZVPdM0_.mjs").then((m) => m.default),
51
51
  generate: () => import("./generate-VI3xEA3Q.mjs").then((m) => m.default),
52
- diff: () => import("./diff-ov1j9bAb.mjs").then((m) => m.default),
53
- merge: () => import("./merge-DdPRttF-.mjs").then((m) => m.default),
52
+ diff: () => import("./diff-DqWPyJZF.mjs").then((m) => m.default),
53
+ merge: () => import("./merge-Dm4Kl1u8.mjs").then((m) => m.default),
54
+ prune: () => import("./prune-DCcyYVcD.mjs").then((m) => m.default),
54
55
  describe: () => import("./describe-DJ5H9Cxm.mjs").then((m) => m.default),
55
56
  "describe-format": () => import("./describe-format-CUAqB0C4.mjs").then((m) => m.default),
56
- scaffold: () => import("./scaffold-iuvrMh78.mjs").then((m) => m.default),
57
- setup: () => import("./setup-BMqKibZt.mjs").then((m) => m.default),
58
- skills: () => import("./skills-CZ54F-97.mjs").then((m) => m.default),
59
- studio: () => import("./studio-DPVJ-2oG.mjs").then((m) => m.default)
57
+ scaffold: () => import("./scaffold-irxW-vdX.mjs").then((m) => m.default),
58
+ setup: () => import("./setup-ZnQXTEP-.mjs").then((m) => m.default),
59
+ skills: () => import("./skills-DeliTaHV.mjs").then((m) => m.default),
60
+ studio: () => import("./studio-DVVkj4QL.mjs").then((m) => m.default)
60
61
  }
61
62
  }));
62
63
  //#endregion
@@ -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-C9E9D4mb.mjs";
3
- import { n as openBrowser, t as startOAuthServer } from "./oauth-server-smSxDoH5.mjs";
2
+ import { i as checkPermissions, o as loadCredentials, s as saveCredentials, t as StudioApiClient } from "./client-CJsHr9Db.mjs";
3
+ import { n as openBrowser, t as startOAuthServer } from "./oauth-server-BSgPLV_2.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-C9E9D4mb.mjs";
2
+ import { a as clearCredentials, o as loadCredentials, t as StudioApiClient } from "./client-CJsHr9Db.mjs";
3
3
  import { defineCommand } from "citty";
4
4
  import { intro, log, outro } from "@clack/prompts";
5
5
  //#region src/studio/commands/logout.ts
@@ -64,6 +64,8 @@ var merge_default = defineCommand({
64
64
  try {
65
65
  const result = await mergeBranch(projectRoot, branch);
66
66
  log.success(`Merged ${branch} (commit ${result.commit.slice(0, 8)})`);
67
+ if (result.remote?.deleted) log.message(pc.dim(" Deleted remote copy."));
68
+ if (result.remote?.warning) log.warning(`Remote copy not deleted: ${result.remote.warning}`);
67
69
  if (result.sync?.synced?.length) log.message(pc.dim(` Synced ${result.sync.synced.length} file(s) to working tree.`));
68
70
  if (result.sync?.skipped?.length) {
69
71
  log.warning(`${result.sync.skipped.length} file(s) skipped during sync — you have uncommitted changes:`);
@@ -0,0 +1,101 @@
1
+ import { i as pc } from "./ui-B8l_LC36.mjs";
2
+ import { r as resolveProjectRoot } from "./context-OskMGy8y.mjs";
3
+ import { defineCommand } from "citty";
4
+ import { confirm, intro, isCancel, log, outro } from "@clack/prompts";
5
+ import { cleanupMergedBranches, pruneMergedRemoteBranches } from "@contentrain/mcp/git/branch-lifecycle";
6
+ //#region src/commands/prune.ts
7
+ /**
8
+ * Batch cleanup of merged cr/* branches: local refs past their retention
9
+ * period plus every merged copy left on the remote. The remote sweep is the
10
+ * operator-facing drain for backlogs the per-merge cleanup could not remove
11
+ * (e.g. branches merged before remote cleanup shipped, or after auth/offline
12
+ * failures). Merged-state uses the same ancestry + patch-id classification
13
+ * as the rest of the toolchain, so branches orphaned by a base-history
14
+ * rewrite are still recognised.
15
+ */
16
+ var prune_default = defineCommand({
17
+ meta: {
18
+ name: "prune",
19
+ description: "Delete merged cr/* branches locally and on the remote"
20
+ },
21
+ args: {
22
+ root: {
23
+ type: "string",
24
+ description: "Project root path",
25
+ required: false
26
+ },
27
+ "dry-run": {
28
+ type: "boolean",
29
+ description: "Show what would be deleted without deleting anything",
30
+ required: false
31
+ },
32
+ yes: {
33
+ type: "boolean",
34
+ description: "Skip confirmation prompt",
35
+ required: false
36
+ },
37
+ json: {
38
+ type: "boolean",
39
+ description: "Machine-readable JSON output (mutates only with --yes)",
40
+ required: false
41
+ }
42
+ },
43
+ async run({ args }) {
44
+ const projectRoot = await resolveProjectRoot(args.root);
45
+ const dryRun = Boolean(args["dry-run"]);
46
+ const json = Boolean(args.json);
47
+ const preview = await pruneMergedRemoteBranches(projectRoot, { dryRun: true });
48
+ if (json) {
49
+ if (dryRun || !args.yes) {
50
+ console.log(JSON.stringify({
51
+ dry_run: true,
52
+ remote: preview
53
+ }, null, 2));
54
+ return;
55
+ }
56
+ const local = await cleanupMergedBranches(projectRoot);
57
+ const remote = await pruneMergedRemoteBranches(projectRoot);
58
+ console.log(JSON.stringify({
59
+ dry_run: false,
60
+ local,
61
+ remote
62
+ }, null, 2));
63
+ if (remote.errors.length > 0) process.exitCode = 1;
64
+ return;
65
+ }
66
+ intro(pc.bold("contentrain prune"));
67
+ if (preview.skipped === "disabled") log.info("Remote branch cleanup is disabled (remoteBranchCleanup: false in config.json).");
68
+ else if (preview.skipped === "no-remote") log.info("No git remote configured — only local merged branches will be pruned.");
69
+ else if (preview.skipped === "offline") log.warning(`Could not reach the remote: ${preview.errors[0] ?? "unknown error"}`);
70
+ else if (preview.deleted.length === 0) log.info("No merged cr/* branches on the remote.");
71
+ else {
72
+ log.info(`${preview.deleted.length} merged cr/* branch(es) on the remote:`);
73
+ for (const branch of preview.deleted) log.message(pc.dim(` ${branch}`));
74
+ if (preview.kept.length > 0) log.message(pc.dim(` (${preview.kept.length} unmerged branch(es) kept)`));
75
+ }
76
+ if (dryRun) {
77
+ log.message(pc.dim("Dry run — nothing deleted."));
78
+ outro("");
79
+ return;
80
+ }
81
+ if (!args.yes) {
82
+ const ok = await confirm({ message: "Prune merged branches (local past retention + the remote list above)?" });
83
+ if (isCancel(ok) || !ok) {
84
+ outro("");
85
+ return;
86
+ }
87
+ }
88
+ const local = await cleanupMergedBranches(projectRoot);
89
+ if (local.deleted > 0) log.success(`Deleted ${local.deleted} local merged branch(es).`);
90
+ else log.message(pc.dim("No local merged branches past retention."));
91
+ if (!preview.skipped && preview.deleted.length > 0) {
92
+ const remote = await pruneMergedRemoteBranches(projectRoot);
93
+ if (remote.deleted.length > 0) log.success(`Deleted ${remote.deleted.length} remote branch(es).`);
94
+ for (const err of remote.errors) log.warning(err);
95
+ if (remote.errors.length > 0) process.exitCode = 1;
96
+ }
97
+ outro("");
98
+ }
99
+ });
100
+ //#endregion
101
+ export { prune_default as default };
@@ -1,4 +1,4 @@
1
- import { c as saveDefaults, o as loadCredentials } from "./client-C9E9D4mb.mjs";
1
+ import { c as saveDefaults, o as loadCredentials } from "./client-CJsHr9Db.mjs";
2
2
  import { confirm, isCancel, select } from "@clack/prompts";
3
3
  //#region src/studio/resolve-context.ts
4
4
  /**
@@ -54,7 +54,7 @@ var serve_default = defineCommand({
54
54
  let projectRoot = await resolveProjectRoot(args.root);
55
55
  let demoDir;
56
56
  if (args.demo) {
57
- const { createDemoProject, cleanupDemoProject } = await import("./demo-DUknxn48.mjs");
57
+ const { createDemoProject, cleanupDemoProject } = await import("./demo-BPbR_r4f.mjs");
58
58
  demoDir = await createDemoProject();
59
59
  projectRoot = demoDir;
60
60
  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-B1PSjXbu.mjs");
142
+ const { createServeApp } = await import("./server-CPBQIj9B.mjs");
143
143
  const { app, handleUpgrade } = await createServeApp({
144
144
  projectRoot,
145
145
  port,
@@ -6,7 +6,7 @@ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
6
6
  import { simpleGit } from "simple-git";
7
7
  import { CONTENTRAIN_BRANCH, LOCAL_CAPABILITIES } from "@contentrain/types";
8
8
  import { mergeBranch } from "@contentrain/mcp/git/transaction";
9
- import { branchDiff, checkBranchHealth } from "@contentrain/mcp/git/branch-lifecycle";
9
+ import { branchDiff, checkBranchHealth, deleteRemoteBranch } from "@contentrain/mcp/git/branch-lifecycle";
10
10
  import { existsSync, readFileSync } from "node:fs";
11
11
  import { readFile, unlink, writeFile } from "node:fs/promises";
12
12
  import { createApp, createError, createRouter, defineEventHandler, getQuery, getRouterParam, readBody, toNodeListener } from "h3";
@@ -467,7 +467,8 @@ async function createServeApp(options) {
467
467
  branch: branchName,
468
468
  commit: result.commit,
469
469
  action: result.action,
470
- sync: result.sync
470
+ sync: result.sync,
471
+ remote: result.remote
471
472
  };
472
473
  } catch (error) {
473
474
  const message = error instanceof Error ? error.message : String(error);
@@ -489,6 +490,7 @@ async function createServeApp(options) {
489
490
  });
490
491
  const { branch: branchName } = parseOrThrow(BranchActionBodySchema, await readBody(event));
491
492
  await simpleGit(projectRoot).deleteLocalBranch(branchName, true);
493
+ const remote = await deleteRemoteBranch(projectRoot, branchName);
492
494
  syncWarnings.delete(branchName);
493
495
  broadcast({
494
496
  type: "branch:rejected",
@@ -496,7 +498,8 @@ async function createServeApp(options) {
496
498
  });
497
499
  return {
498
500
  status: "deleted",
499
- branch: branchName
501
+ branch: branchName,
502
+ remote
500
503
  };
501
504
  }));
502
505
  router.add("/api/history", defineEventHandler(async (event) => {
@@ -773,7 +776,8 @@ async function createServeApp(options) {
773
776
  branch: branchName,
774
777
  commit: result.commit,
775
778
  action: result.action,
776
- sync: result.sync
779
+ sync: result.sync,
780
+ remote: result.remote
777
781
  };
778
782
  } catch (error) {
779
783
  const message = error instanceof Error ? error.message : String(error);
@@ -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-C9E9D4mb.mjs";
3
- import { t as resolveStudioContext } from "./resolve-context-hKVYPniC.mjs";
2
+ import { n as resolveStudioClient } from "./client-CJsHr9Db.mjs";
3
+ import { t as resolveStudioContext } from "./resolve-context-DPdtEC0i.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-yLBoeLVM.mjs").then((m) => m.default),
10
+ logout: () => import("./logout-DBm34b7e.mjs").then((m) => m.default),
11
+ whoami: () => import("./whoami-D0ZYvnWU.mjs").then((m) => m.default),
12
+ connect: () => import("./connect-BTJU6Ud3.mjs").then((m) => m.default),
13
+ status: () => import("./status-BAQ8GFyN.mjs").then((m) => m.default),
14
+ activity: () => import("./activity-DP5wjWLV.mjs").then((m) => m.default),
15
+ usage: () => import("./usage-CC7Chuf6.mjs").then((m) => m.default),
16
+ branches: () => import("./branches-D_LPptfM.mjs").then((m) => m.default),
17
+ "cdn-init": () => import("./cdn-init-CGl8-QCR.mjs").then((m) => m.default),
18
+ "cdn-build": () => import("./cdn-build-BuacuDbL.mjs").then((m) => m.default),
19
+ webhooks: () => import("./webhooks-C-D4zHq8.mjs").then((m) => m.default),
20
+ submissions: () => import("./submissions-JTtZXvcf.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-C9E9D4mb.mjs";
3
- import { t as resolveStudioContext } from "./resolve-context-hKVYPniC.mjs";
2
+ import { n as resolveStudioClient } from "./client-CJsHr9Db.mjs";
3
+ import { t as resolveStudioContext } from "./resolve-context-DPdtEC0i.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-C9E9D4mb.mjs";
3
- import { t as resolveStudioContext } from "./resolve-context-hKVYPniC.mjs";
2
+ import { n as resolveStudioClient } from "./client-CJsHr9Db.mjs";
3
+ import { t as resolveStudioContext } from "./resolve-context-DPdtEC0i.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 { i as pc, o as statusIcon, r as formatTable } from "./ui-B8l_LC36.mjs";
2
- import { n as resolveStudioClient } from "./client-C9E9D4mb.mjs";
3
- import { t as resolveStudioContext } from "./resolve-context-hKVYPniC.mjs";
2
+ import { n as resolveStudioClient } from "./client-CJsHr9Db.mjs";
3
+ import { t as resolveStudioContext } from "./resolve-context-DPdtEC0i.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-C9E9D4mb.mjs";
2
+ import { i as checkPermissions, n as resolveStudioClient, r as AuthExpiredError } from "./client-CJsHr9Db.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.6.0",
3
+ "version": "0.7.2",
4
4
  "license": "MIT",
5
5
  "description": "CLI for Contentrain — AI content governance infrastructure",
6
6
  "type": "module",
@@ -47,11 +47,11 @@
47
47
  "simple-git": "^3.27.0",
48
48
  "ws": "^8.18.0",
49
49
  "zod": "^3.24.0",
50
+ "@contentrain/mcp": "1.8.1",
51
+ "@contentrain/query": "6.1.1",
50
52
  "@contentrain/rules": "0.5.3",
51
53
  "@contentrain/skills": "0.5.3",
52
- "@contentrain/mcp": "1.6.0",
53
- "@contentrain/query": "6.1.0",
54
- "@contentrain/types": "0.6.0"
54
+ "@contentrain/types": "0.7.0"
55
55
  },
56
56
  "devDependencies": {
57
57
  "@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-xvzL-UvR.mjs").then((m) => m.default),
10
- logout: () => import("./logout-DzspSatR.mjs").then((m) => m.default),
11
- whoami: () => import("./whoami-CXVfvo7x.mjs").then((m) => m.default),
12
- connect: () => import("./connect-Bb0BrZsx.mjs").then((m) => m.default),
13
- status: () => import("./status-BJ6Lu3J4.mjs").then((m) => m.default),
14
- activity: () => import("./activity-B8j9gfsK.mjs").then((m) => m.default),
15
- usage: () => import("./usage-z6eyT64a.mjs").then((m) => m.default),
16
- branches: () => import("./branches-CvpFbyrJ.mjs").then((m) => m.default),
17
- "cdn-init": () => import("./cdn-init-Bm4dpEJn.mjs").then((m) => m.default),
18
- "cdn-build": () => import("./cdn-build-DS9FprWU.mjs").then((m) => m.default),
19
- webhooks: () => import("./webhooks-CBG2Bs9P.mjs").then((m) => m.default),
20
- submissions: () => import("./submissions-zH_S7JIQ.mjs").then((m) => m.default)
21
- }
22
- });
23
- //#endregion
24
- export { studio_default as default };
File without changes
File without changes