@contentrain/mcp 3.8.2 → 3.9.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.
- package/dist/{apply-manager-B-VMXKiW.mjs → apply-manager-BenQNb_b.mjs} +4 -4
- package/dist/{apply-manager-B-VMXKiW.mjs.map → apply-manager-BenQNb_b.mjs.map} +1 -1
- package/dist/{context-fJCKH_qv.mjs → context-Cp8b8Nxm.mjs} +2 -2
- package/dist/{context-fJCKH_qv.mjs.map → context-Cp8b8Nxm.mjs.map} +1 -1
- package/dist/core/apply-manager.mjs +4 -4
- package/dist/core/content-manager.mjs +1 -1
- package/dist/core/context.mjs +2 -2
- package/dist/core/doctor.mjs +2 -2
- package/dist/core/model-manager.d.mts.map +1 -1
- package/dist/core/model-manager.mjs +1 -1
- package/dist/core/ops/index.mjs +5 -5
- package/dist/core/validator/index.mjs +2 -2
- package/dist/{doctor-Du4MVG5w.mjs → doctor-Qabcb-Z1.mjs} +2 -2
- package/dist/{doctor-Du4MVG5w.mjs.map → doctor-Qabcb-Z1.mjs.map} +1 -1
- package/dist/git/reconcile.mjs +6 -6
- package/dist/git/transaction.mjs +3 -3
- package/dist/index.mjs +11 -11
- package/dist/{local-BXTVAAr-.mjs → local-DaITA8Ye.mjs} +5 -5
- package/dist/{local-BXTVAAr-.mjs.map → local-DaITA8Ye.mjs.map} +1 -1
- package/dist/{model-manager-DPXulg7z.mjs → model-manager-BYF2z7qC.mjs} +18 -8
- package/dist/model-manager-BYF2z7qC.mjs.map +1 -0
- package/dist/{ops-DxhCCs_Z.mjs → ops-CQ_IIedh.mjs} +3 -3
- package/dist/{ops-DxhCCs_Z.mjs.map → ops-CQ_IIedh.mjs.map} +1 -1
- package/dist/providers/local/index.mjs +7 -7
- package/dist/{reconcile-CPDGFQ8H.mjs → reconcile-8pEO4mBC.mjs} +4 -4
- package/dist/{reconcile-CPDGFQ8H.mjs.map → reconcile-8pEO4mBC.mjs.map} +1 -1
- package/dist/{reconcile-BWbckvbv.mjs → reconcile-Do8OJDAo.mjs} +3 -3
- package/dist/{reconcile-BWbckvbv.mjs.map → reconcile-Do8OJDAo.mjs.map} +1 -1
- package/dist/server/http/index.mjs +11 -11
- package/dist/{server-UojGbAaw.mjs → server-rEFicTHs.mjs} +12 -12
- package/dist/server-rEFicTHs.mjs.map +1 -0
- package/dist/server.mjs +11 -11
- package/dist/{transaction-DfrvGIfk.mjs → transaction-CcjGiVYg.mjs} +2 -2
- package/dist/{transaction-DfrvGIfk.mjs.map → transaction-CcjGiVYg.mjs.map} +1 -1
- package/dist/{validator-C08p1OpM.mjs → validator-eUdQqQGc.mjs} +3 -3
- package/dist/validator-eUdQqQGc.mjs.map +1 -0
- package/package.json +2 -2
- package/dist/model-manager-DPXulg7z.mjs.map +0 -1
- package/dist/server-UojGbAaw.mjs.map +0 -1
- package/dist/validator-C08p1OpM.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reconcile-BWbckvbv.mjs","names":[],"sources":["../src/git/ref-reader.ts","../src/git/reconcile.ts"],"sourcesContent":["import { type SimpleGit } from 'simple-git'\nimport { createGit } from './identity.js'\nimport type { RepoReader } from '../core/contracts/index.js'\n\n/**\n * GitRefReader — `RepoReader` over an arbitrary local git ref, without a\n * checkout. `git show <ref>:<path>` reads blobs, `ls-tree` lists a tree\n * level, `cat-file -e` answers existence. This is what lets a reconcile\n * planner read three trees (merge-base, contentrain, base branch) side by\n * side while the developer's working tree stays untouched.\n *\n * The ref is fixed at construction; the per-call `ref?` parameter of the\n * `RepoReader` contract is ignored — a bound reader answering for a\n * different ref than it was built for would be a lie. Bind another instance\n * instead.\n */\nexport class GitRefReader implements RepoReader {\n private readonly git: SimpleGit\n\n constructor(\n public readonly projectRoot: string,\n public readonly ref: string,\n ) {\n this.git = createGit(projectRoot)\n }\n\n async readFile(path: string, _ref?: string): Promise<string> {\n return this.git.show([`${this.ref}:${normalize(path)}`])\n }\n\n async listDirectory(path: string, _ref?: string): Promise<string[]> {\n try {\n // Trailing slash = \"list the tree at this path\", bare names via\n // --name-only; ls-tree is non-recursive by default, matching the\n // contract's \"does not recurse\".\n const dir = normalize(path)\n const args = dir && dir !== '.'\n ? ['ls-tree', '--name-only', this.ref, `${dir}/`]\n : ['ls-tree', '--name-only', this.ref]\n const raw = await this.git.raw(args)\n return raw\n .split('\\n')\n .map(line => line.trim())\n .filter(Boolean)\n .map(entry => entry.slice(entry.lastIndexOf('/') + 1))\n } catch {\n return []\n }\n }\n\n async fileExists(path: string, _ref?: string): Promise<boolean> {\n try {\n await this.git.raw(['cat-file', '-e', `${this.ref}:${normalize(path)}`])\n return true\n } catch {\n return false\n }\n }\n}\n\n/** Strip a trailing slash — `<ref>:dir/` and `<ref>:dir` name different things to git. */\nfunction normalize(path: string): string {\n return path.endsWith('/') ? path.slice(0, -1) : path\n}\n","import { join } from 'node:path'\nimport { tmpdir } from 'node:os'\nimport { randomUUID } from 'node:crypto'\nimport { CONTENTRAIN_BRANCH } from '@contentrain/types'\nimport type { BaseAdvance, ConflictResolution, ContextSource, RemotePush, SyncResult } from '@contentrain/types'\nimport { createGit, authorConfig } from './identity.js'\nimport { networkGit } from './branch-lifecycle.js'\nimport { GitRefReader } from './ref-reader.js'\nimport { resolveBaseBranch } from './base-branch.js'\nimport {\n NETWORK_TIMEOUT_MS,\n ensureContentBranch,\n isAncestor,\n pushContentBranches,\n selectiveSync,\n} from './transaction.js'\nimport { readConfig } from '../core/config.js'\nimport { planReconcile } from '../core/ops/reconcile/index.js'\nimport type { ReconcilePlan } from '../core/ops/reconcile/index.js'\nimport { applyChangesToWorktree } from '../core/ops/apply-to-worktree.js'\n\nexport interface ReconcileBranchesOptions {\n /** Preview only — plan, never touch a ref. Default true. */\n dryRun?: boolean\n /** Decisions for previously reported conflicts, matched by id. */\n resolutions?: ConflictResolution[]\n /** Stamped into the regenerated context.json. */\n source?: ContextSource\n}\n\nexport interface ReconcileBranchesResult {\n /**\n * `in_sync` — nothing to reconcile (base already contained in contentrain\n * and no content differences; a base merely behind was fast-forwarded).\n * `preview` — dry-run: the plan says what WOULD happen.\n * `conflicts` — unresolved conflicts remain; nothing was written.\n * `reconciled` — the merge commit landed and the base branch advanced.\n */\n action: 'in_sync' | 'preview' | 'conflicts' | 'reconciled'\n plan: ReconcilePlan\n base: string\n merge_base: string | null\n commit?: string\n base_advance?: BaseAdvance\n sync?: SyncResult\n remote_push?: RemotePush\n}\n\n/**\n * Content-aware reconcile of a diverged `contentrain` ↔ base pair, local\n * executor. Plans with three `GitRefReader`s (no checkout, developer tree\n * untouched), then — when clean or fully resolved — performs a REAL\n * `git merge --no-commit` in a temp worktree and writes the ENTIRE plan\n * output over it before committing: for content-owned paths the planner is\n * authoritative, never git's textual auto-merge (its line-level result can\n * be non-canonical or wrong without ever surfacing as a conflict). Git\n * still resolves everything the planner does not own — source files, lock\n * files — exactly as a manual merge would. The commit joins both parents,\n * so afterwards the base branch is an ancestor again and the ordinary\n * fast-forward advance works.\n *\n * Reconcile never runs inside a write path: it is an explicit, separate\n * step (tool, CLI, or Studio background job).\n */\nexport async function reconcileBranches(\n projectRoot: string,\n options: ReconcileBranchesOptions = {},\n): Promise<ReconcileBranchesResult> {\n const dryRun = options.dryRun ?? true\n const git = createGit(projectRoot)\n const config = await readConfig(projectRoot)\n const remoteName = process.env['CONTENTRAIN_REMOTE'] ?? 'origin'\n\n const currentBranch = (await git.raw(['branch', '--show-current']).catch(() => '')).trim()\n const baseBranch = await resolveBaseBranch(git, config, { remoteName, currentBranch })\n if (currentBranch === CONTENTRAIN_BRANCH) {\n throw Object.assign(new Error(\n `The '${CONTENTRAIN_BRANCH}' branch is checked out in your working directory. `\n + `Switch to your working branch and retry.`,\n ), {\n code: 'CONTENT_BRANCH_CHECKED_OUT',\n agent_hint: 'Ask the developer to switch to their working branch, then retry.',\n developer_action: `git checkout ${baseBranch}`,\n })\n }\n\n await ensureContentBranch(projectRoot)\n\n let hasRemote = false\n try {\n const remotes = await git.getRemotes()\n hasRemote = remotes.some(r => r.name === remoteName)\n } catch {\n hasRemote = false\n }\n if (hasRemote) {\n const net = networkGit(projectRoot, NETWORK_TIMEOUT_MS)\n await Promise.all([\n net.fetch(remoteName, baseBranch).catch(() => {}),\n net.fetch(remoteName, CONTENTRAIN_BRANCH).catch(() => {}),\n ])\n }\n\n const [contentrainTip, baseTip] = await Promise.all([\n git.raw(['rev-parse', CONTENTRAIN_BRANCH]).then(s => s.trim()),\n git.raw(['rev-parse', baseBranch]).then(s => s.trim()),\n ])\n\n let mergeBase: string | null = null\n try {\n mergeBase = (await git.raw(['merge-base', CONTENTRAIN_BRANCH, baseBranch])).trim() || null\n } catch {\n mergeBase = null\n }\n if (!mergeBase) {\n throw Object.assign(new Error(\n `\"${CONTENTRAIN_BRANCH}\" and \"${baseBranch}\" share no history — reconcile needs a common ancestor.`,\n ), {\n code: 'RECONCILE_NO_MERGE_BASE',\n agent_hint: 'The branches are unrelated. This needs a human decision about which history is canonical.',\n })\n }\n\n const plan = await planReconcile({\n base: new GitRefReader(projectRoot, mergeBase),\n ours: new GitRefReader(projectRoot, CONTENTRAIN_BRANCH),\n theirs: new GitRefReader(projectRoot, baseBranch),\n resolutions: options.resolutions,\n source: options.source ?? 'mcp-local',\n })\n\n // Base already contained in contentrain: there is no divergence. A base\n // merely BEHIND is fast-forwarded on the spot (that is what the ordinary\n // write path would do next anyway).\n if (await isAncestor(git, baseTip, contentrainTip)) {\n if (!dryRun && baseTip !== contentrainTip) {\n await git.raw(['update-ref', `refs/heads/${baseBranch}`, contentrainTip])\n try {\n await git.raw(['read-tree', 'HEAD'])\n } catch {\n try { await git.raw(['reset', 'HEAD']) } catch { /* ignore */ }\n }\n return { action: 'reconciled', plan, base: baseBranch, merge_base: mergeBase, commit: contentrainTip, base_advance: 'advanced' }\n }\n return { action: 'in_sync', plan, base: baseBranch, merge_base: mergeBase }\n }\n\n if (dryRun) {\n return { action: 'preview', plan, base: baseBranch, merge_base: mergeBase }\n }\n if (plan.conflicts.length > 0) {\n return { action: 'conflicts', plan, base: baseBranch, merge_base: mergeBase }\n }\n\n // Execute: real merge in a temp worktree, planner output written on top.\n const worktreePath = join(tmpdir(), `cr-reconcile-${randomUUID()}`)\n await git.raw(['worktree', 'add', worktreePath, CONTENTRAIN_BRANCH])\n const wtGit = createGit(worktreePath, { config: authorConfig() })\n\n try {\n try {\n await wtGit.merge([baseBranch, '--no-commit', '--no-ff'])\n } catch {\n // Conflicts inside the worktree are expected — the planner's output\n // overwrites every content-owned path next. Anything left unmerged\n // after that is genuinely outside the planner's scope.\n }\n\n await applyChangesToWorktree(worktreePath, plan.changes)\n await wtGit.raw(['add', '-A'])\n\n const unmerged = (await wtGit.raw(['ls-files', '-u'])).trim()\n if (unmerged) {\n const paths = [...new Set(unmerged.split('\\n').map(l => l.split('\\t')[1]).filter(Boolean))]\n try { await wtGit.merge(['--abort']) } catch { /* not in merge state */ }\n throw Object.assign(new Error(\n `Reconcile stopped: ${paths.length} non-content file(s) conflict between \"${CONTENTRAIN_BRANCH}\" and \"${baseBranch}\": ${paths.join(', ')}. `\n + `These are outside the content planner's scope and need a manual merge.`,\n ), {\n code: 'RECONCILE_SOURCE_CONFLICT',\n agent_hint: 'Non-content files conflict. Ask the developer to merge the branches manually for those paths.',\n developer_action: `git checkout ${CONTENTRAIN_BRANCH} && git merge ${baseBranch}`,\n })\n }\n\n await wtGit.commit(\n `[contentrain] reconcile: merge ${baseBranch} into ${CONTENTRAIN_BRANCH}`,\n { '--no-verify': null },\n )\n\n const [newTip, previousBaseRef, statusBeforeUpdate] = await Promise.all([\n wtGit.raw(['rev-parse', 'HEAD']).then(s => s.trim()),\n git.raw(['rev-parse', baseBranch]).then(s => s.trim()),\n git.status(),\n ])\n const dirtyFilesBeforeUpdate = new Set(statusBeforeUpdate.files.map(f => f.path))\n\n // The merge commit has baseBranch as a parent, so this is a true\n // fast-forward again — the whole point of the exercise.\n await git.raw(['update-ref', `refs/heads/${baseBranch}`, newTip])\n try {\n await git.raw(['read-tree', 'HEAD'])\n } catch {\n try { await git.raw(['reset', 'HEAD']) } catch { /* ignore */ }\n }\n const sync = await selectiveSync(projectRoot, worktreePath, newTip, previousBaseRef, dirtyFilesBeforeUpdate)\n\n let remotePush: RemotePush = 'no-remote'\n if (hasRemote) {\n remotePush = await pushContentBranches(projectRoot, worktreePath, wtGit, remoteName, baseBranch, true)\n }\n\n return {\n action: 'reconciled',\n plan,\n base: baseBranch,\n merge_base: mergeBase,\n commit: newTip,\n base_advance: 'advanced',\n sync,\n remote_push: remotePush,\n }\n } finally {\n try {\n await git.raw(['worktree', 'remove', worktreePath, '--force'])\n } catch {\n // worktree may already be cleaned up\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"reconcile-Do8OJDAo.mjs","names":[],"sources":["../src/git/ref-reader.ts","../src/git/reconcile.ts"],"sourcesContent":["import { type SimpleGit } from 'simple-git'\nimport { createGit } from './identity.js'\nimport type { RepoReader } from '../core/contracts/index.js'\n\n/**\n * GitRefReader — `RepoReader` over an arbitrary local git ref, without a\n * checkout. `git show <ref>:<path>` reads blobs, `ls-tree` lists a tree\n * level, `cat-file -e` answers existence. This is what lets a reconcile\n * planner read three trees (merge-base, contentrain, base branch) side by\n * side while the developer's working tree stays untouched.\n *\n * The ref is fixed at construction; the per-call `ref?` parameter of the\n * `RepoReader` contract is ignored — a bound reader answering for a\n * different ref than it was built for would be a lie. Bind another instance\n * instead.\n */\nexport class GitRefReader implements RepoReader {\n private readonly git: SimpleGit\n\n constructor(\n public readonly projectRoot: string,\n public readonly ref: string,\n ) {\n this.git = createGit(projectRoot)\n }\n\n async readFile(path: string, _ref?: string): Promise<string> {\n return this.git.show([`${this.ref}:${normalize(path)}`])\n }\n\n async listDirectory(path: string, _ref?: string): Promise<string[]> {\n try {\n // Trailing slash = \"list the tree at this path\", bare names via\n // --name-only; ls-tree is non-recursive by default, matching the\n // contract's \"does not recurse\".\n const dir = normalize(path)\n const args = dir && dir !== '.'\n ? ['ls-tree', '--name-only', this.ref, `${dir}/`]\n : ['ls-tree', '--name-only', this.ref]\n const raw = await this.git.raw(args)\n return raw\n .split('\\n')\n .map(line => line.trim())\n .filter(Boolean)\n .map(entry => entry.slice(entry.lastIndexOf('/') + 1))\n } catch {\n return []\n }\n }\n\n async fileExists(path: string, _ref?: string): Promise<boolean> {\n try {\n await this.git.raw(['cat-file', '-e', `${this.ref}:${normalize(path)}`])\n return true\n } catch {\n return false\n }\n }\n}\n\n/** Strip a trailing slash — `<ref>:dir/` and `<ref>:dir` name different things to git. */\nfunction normalize(path: string): string {\n return path.endsWith('/') ? path.slice(0, -1) : path\n}\n","import { join } from 'node:path'\nimport { tmpdir } from 'node:os'\nimport { randomUUID } from 'node:crypto'\nimport { CONTENTRAIN_BRANCH } from '@contentrain/types'\nimport type { BaseAdvance, ConflictResolution, ContextSource, RemotePush, SyncResult } from '@contentrain/types'\nimport { createGit, authorConfig } from './identity.js'\nimport { networkGit } from './branch-lifecycle.js'\nimport { GitRefReader } from './ref-reader.js'\nimport { resolveBaseBranch } from './base-branch.js'\nimport {\n NETWORK_TIMEOUT_MS,\n ensureContentBranch,\n isAncestor,\n pushContentBranches,\n selectiveSync,\n} from './transaction.js'\nimport { readConfig } from '../core/config.js'\nimport { planReconcile } from '../core/ops/reconcile/index.js'\nimport type { ReconcilePlan } from '../core/ops/reconcile/index.js'\nimport { applyChangesToWorktree } from '../core/ops/apply-to-worktree.js'\n\nexport interface ReconcileBranchesOptions {\n /** Preview only — plan, never touch a ref. Default true. */\n dryRun?: boolean\n /** Decisions for previously reported conflicts, matched by id. */\n resolutions?: ConflictResolution[]\n /** Stamped into the regenerated context.json. */\n source?: ContextSource\n}\n\nexport interface ReconcileBranchesResult {\n /**\n * `in_sync` — nothing to reconcile (base already contained in contentrain\n * and no content differences; a base merely behind was fast-forwarded).\n * `preview` — dry-run: the plan says what WOULD happen.\n * `conflicts` — unresolved conflicts remain; nothing was written.\n * `reconciled` — the merge commit landed and the base branch advanced.\n */\n action: 'in_sync' | 'preview' | 'conflicts' | 'reconciled'\n plan: ReconcilePlan\n base: string\n merge_base: string | null\n commit?: string\n base_advance?: BaseAdvance\n sync?: SyncResult\n remote_push?: RemotePush\n}\n\n/**\n * Content-aware reconcile of a diverged `contentrain` ↔ base pair, local\n * executor. Plans with three `GitRefReader`s (no checkout, developer tree\n * untouched), then — when clean or fully resolved — performs a REAL\n * `git merge --no-commit` in a temp worktree and writes the ENTIRE plan\n * output over it before committing: for content-owned paths the planner is\n * authoritative, never git's textual auto-merge (its line-level result can\n * be non-canonical or wrong without ever surfacing as a conflict). Git\n * still resolves everything the planner does not own — source files, lock\n * files — exactly as a manual merge would. The commit joins both parents,\n * so afterwards the base branch is an ancestor again and the ordinary\n * fast-forward advance works.\n *\n * Reconcile never runs inside a write path: it is an explicit, separate\n * step (tool, CLI, or Studio background job).\n */\nexport async function reconcileBranches(\n projectRoot: string,\n options: ReconcileBranchesOptions = {},\n): Promise<ReconcileBranchesResult> {\n const dryRun = options.dryRun ?? true\n const git = createGit(projectRoot)\n const config = await readConfig(projectRoot)\n const remoteName = process.env['CONTENTRAIN_REMOTE'] ?? 'origin'\n\n const currentBranch = (await git.raw(['branch', '--show-current']).catch(() => '')).trim()\n const baseBranch = await resolveBaseBranch(git, config, { remoteName, currentBranch })\n if (currentBranch === CONTENTRAIN_BRANCH) {\n throw Object.assign(new Error(\n `The '${CONTENTRAIN_BRANCH}' branch is checked out in your working directory. `\n + `Switch to your working branch and retry.`,\n ), {\n code: 'CONTENT_BRANCH_CHECKED_OUT',\n agent_hint: 'Ask the developer to switch to their working branch, then retry.',\n developer_action: `git checkout ${baseBranch}`,\n })\n }\n\n await ensureContentBranch(projectRoot)\n\n let hasRemote = false\n try {\n const remotes = await git.getRemotes()\n hasRemote = remotes.some(r => r.name === remoteName)\n } catch {\n hasRemote = false\n }\n if (hasRemote) {\n const net = networkGit(projectRoot, NETWORK_TIMEOUT_MS)\n await Promise.all([\n net.fetch(remoteName, baseBranch).catch(() => {}),\n net.fetch(remoteName, CONTENTRAIN_BRANCH).catch(() => {}),\n ])\n }\n\n const [contentrainTip, baseTip] = await Promise.all([\n git.raw(['rev-parse', CONTENTRAIN_BRANCH]).then(s => s.trim()),\n git.raw(['rev-parse', baseBranch]).then(s => s.trim()),\n ])\n\n let mergeBase: string | null = null\n try {\n mergeBase = (await git.raw(['merge-base', CONTENTRAIN_BRANCH, baseBranch])).trim() || null\n } catch {\n mergeBase = null\n }\n if (!mergeBase) {\n throw Object.assign(new Error(\n `\"${CONTENTRAIN_BRANCH}\" and \"${baseBranch}\" share no history — reconcile needs a common ancestor.`,\n ), {\n code: 'RECONCILE_NO_MERGE_BASE',\n agent_hint: 'The branches are unrelated. This needs a human decision about which history is canonical.',\n })\n }\n\n const plan = await planReconcile({\n base: new GitRefReader(projectRoot, mergeBase),\n ours: new GitRefReader(projectRoot, CONTENTRAIN_BRANCH),\n theirs: new GitRefReader(projectRoot, baseBranch),\n resolutions: options.resolutions,\n source: options.source ?? 'mcp-local',\n })\n\n // Base already contained in contentrain: there is no divergence. A base\n // merely BEHIND is fast-forwarded on the spot (that is what the ordinary\n // write path would do next anyway).\n if (await isAncestor(git, baseTip, contentrainTip)) {\n if (!dryRun && baseTip !== contentrainTip) {\n await git.raw(['update-ref', `refs/heads/${baseBranch}`, contentrainTip])\n try {\n await git.raw(['read-tree', 'HEAD'])\n } catch {\n try { await git.raw(['reset', 'HEAD']) } catch { /* ignore */ }\n }\n return { action: 'reconciled', plan, base: baseBranch, merge_base: mergeBase, commit: contentrainTip, base_advance: 'advanced' }\n }\n return { action: 'in_sync', plan, base: baseBranch, merge_base: mergeBase }\n }\n\n if (dryRun) {\n return { action: 'preview', plan, base: baseBranch, merge_base: mergeBase }\n }\n if (plan.conflicts.length > 0) {\n return { action: 'conflicts', plan, base: baseBranch, merge_base: mergeBase }\n }\n\n // Execute: real merge in a temp worktree, planner output written on top.\n const worktreePath = join(tmpdir(), `cr-reconcile-${randomUUID()}`)\n await git.raw(['worktree', 'add', worktreePath, CONTENTRAIN_BRANCH])\n const wtGit = createGit(worktreePath, { config: authorConfig() })\n\n try {\n try {\n await wtGit.merge([baseBranch, '--no-commit', '--no-ff'])\n } catch {\n // Conflicts inside the worktree are expected — the planner's output\n // overwrites every content-owned path next. Anything left unmerged\n // after that is genuinely outside the planner's scope.\n }\n\n await applyChangesToWorktree(worktreePath, plan.changes)\n await wtGit.raw(['add', '-A'])\n\n const unmerged = (await wtGit.raw(['ls-files', '-u'])).trim()\n if (unmerged) {\n const paths = [...new Set(unmerged.split('\\n').map(l => l.split('\\t')[1]).filter(Boolean))]\n try { await wtGit.merge(['--abort']) } catch { /* not in merge state */ }\n throw Object.assign(new Error(\n `Reconcile stopped: ${paths.length} non-content file(s) conflict between \"${CONTENTRAIN_BRANCH}\" and \"${baseBranch}\": ${paths.join(', ')}. `\n + `These are outside the content planner's scope and need a manual merge.`,\n ), {\n code: 'RECONCILE_SOURCE_CONFLICT',\n agent_hint: 'Non-content files conflict. Ask the developer to merge the branches manually for those paths.',\n developer_action: `git checkout ${CONTENTRAIN_BRANCH} && git merge ${baseBranch}`,\n })\n }\n\n await wtGit.commit(\n `[contentrain] reconcile: merge ${baseBranch} into ${CONTENTRAIN_BRANCH}`,\n { '--no-verify': null },\n )\n\n const [newTip, previousBaseRef, statusBeforeUpdate] = await Promise.all([\n wtGit.raw(['rev-parse', 'HEAD']).then(s => s.trim()),\n git.raw(['rev-parse', baseBranch]).then(s => s.trim()),\n git.status(),\n ])\n const dirtyFilesBeforeUpdate = new Set(statusBeforeUpdate.files.map(f => f.path))\n\n // The merge commit has baseBranch as a parent, so this is a true\n // fast-forward again — the whole point of the exercise.\n await git.raw(['update-ref', `refs/heads/${baseBranch}`, newTip])\n try {\n await git.raw(['read-tree', 'HEAD'])\n } catch {\n try { await git.raw(['reset', 'HEAD']) } catch { /* ignore */ }\n }\n const sync = await selectiveSync(projectRoot, worktreePath, newTip, previousBaseRef, dirtyFilesBeforeUpdate)\n\n let remotePush: RemotePush = 'no-remote'\n if (hasRemote) {\n remotePush = await pushContentBranches(projectRoot, worktreePath, wtGit, remoteName, baseBranch, true)\n }\n\n return {\n action: 'reconciled',\n plan,\n base: baseBranch,\n merge_base: mergeBase,\n commit: newTip,\n base_advance: 'advanced',\n sync,\n remote_push: remotePush,\n }\n } finally {\n try {\n await git.raw(['worktree', 'remove', worktreePath, '--force'])\n } catch {\n // worktree may already be cleaned up\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
import "../../contracts-DfL0BfrD.mjs";
|
|
2
|
-
import "../../reconcile-
|
|
3
|
-
import "../../context-
|
|
4
|
-
import "../../model-manager-
|
|
5
|
-
import "../../ops-
|
|
2
|
+
import "../../reconcile-8pEO4mBC.mjs";
|
|
3
|
+
import "../../context-Cp8b8Nxm.mjs";
|
|
4
|
+
import "../../model-manager-BYF2z7qC.mjs";
|
|
5
|
+
import "../../ops-CQ_IIedh.mjs";
|
|
6
6
|
import "../../fs-BFTuXbbw.mjs";
|
|
7
7
|
import "../../meta-manager-CSpKtjnP.mjs";
|
|
8
8
|
import "../../config-BLwZtwlI.mjs";
|
|
9
|
-
import "../../validator-
|
|
9
|
+
import "../../validator-eUdQqQGc.mjs";
|
|
10
10
|
import "../../identity-CxAB9Qb8.mjs";
|
|
11
11
|
import "../../base-branch-Cw9DWvCC.mjs";
|
|
12
12
|
import "../../branch-lifecycle-CcsSyfSw.mjs";
|
|
13
13
|
import "../../id-jrHWdtqn.mjs";
|
|
14
|
-
import "../../transaction-
|
|
15
|
-
import "../../local-
|
|
14
|
+
import "../../transaction-CcjGiVYg.mjs";
|
|
15
|
+
import "../../local-DaITA8Ye.mjs";
|
|
16
16
|
import "../../detect-B1QHYA0u.mjs";
|
|
17
17
|
import "../../annotations-BYkjoj2d.mjs";
|
|
18
|
-
import { n as createServer } from "../../server-
|
|
18
|
+
import { n as createServer } from "../../server-rEFicTHs.mjs";
|
|
19
19
|
import "../../errors-De8Noahk.mjs";
|
|
20
|
-
import "../../reconcile-
|
|
20
|
+
import "../../reconcile-Do8OJDAo.mjs";
|
|
21
21
|
import "../../scan-config-S5fkzNhL.mjs";
|
|
22
22
|
import "../../graph-builder-BPhi-1KH.mjs";
|
|
23
23
|
import "../../scanner-0sc_pARB.mjs";
|
|
24
24
|
import "../../tsx-parser-DgFdpsea.mjs";
|
|
25
|
-
import "../../apply-manager-
|
|
26
|
-
import "../../doctor-
|
|
25
|
+
import "../../apply-manager-BenQNb_b.mjs";
|
|
26
|
+
import "../../doctor-Qabcb-Z1.mjs";
|
|
27
27
|
import { randomUUID } from "node:crypto";
|
|
28
28
|
import http from "node:http";
|
|
29
29
|
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
import { n as readContext } from "./context-
|
|
2
|
-
import { A as contentDirPath, C as resolveMdFilePath, O as writeContent, S as resolveLocaleStrategy, _ as listContent, a as countEntries, b as resolveContentDir, d as readModel, g as deleteContent, h as writeModel, i as collectFieldPaths, j as contentFilePath, m as validateModelDefinition, r as checkReferences, s as fieldDefZodSchema, u as listModels, x as resolveJsonFilePath } from "./model-manager-
|
|
3
|
-
import { a as planModelDelete, i as planModelSave, n as planVocabularySave, o as planContentSave, s as planContentDelete, t as planVocabularyDelete } from "./ops-
|
|
1
|
+
import { n as readContext } from "./context-Cp8b8Nxm.mjs";
|
|
2
|
+
import { A as contentDirPath, C as resolveMdFilePath, O as writeContent, S as resolveLocaleStrategy, _ as listContent, a as countEntries, b as resolveContentDir, d as readModel, g as deleteContent, h as writeModel, i as collectFieldPaths, j as contentFilePath, m as validateModelDefinition, r as checkReferences, s as fieldDefZodSchema, u as listModels, x as resolveJsonFilePath } from "./model-manager-BYF2z7qC.mjs";
|
|
3
|
+
import { a as planModelDelete, i as planModelSave, n as planVocabularySave, o as planContentSave, s as planContentDelete, t as planVocabularyDelete } from "./ops-CQ_IIedh.mjs";
|
|
4
4
|
import { a as readJson, n as ensureDir, r as pathExists, s as writeJson, t as contentrainDir } from "./fs-BFTuXbbw.mjs";
|
|
5
5
|
import { a as writeMeta, i as readMeta, o as writeMetaEntries, r as mergeEntryMeta, t as applyStatusChange } from "./meta-manager-CSpKtjnP.mjs";
|
|
6
6
|
import { t as OverlayReader } from "./overlay-reader-Bx1YxGXq.mjs";
|
|
7
7
|
import { n as readVocabulary, t as readConfig } from "./config-BLwZtwlI.mjs";
|
|
8
|
-
import { t as validateProject } from "./validator-
|
|
8
|
+
import { t as validateProject } from "./validator-eUdQqQGc.mjs";
|
|
9
9
|
import { r as createGit } from "./identity-CxAB9Qb8.mjs";
|
|
10
10
|
import { r as resolveInitDefaultBranch, t as resolveBaseBranch } from "./base-branch-Cw9DWvCC.mjs";
|
|
11
11
|
import { a as contentBranchRelation, c as listRemoteCrBranches, i as cleanupMergedBranches, n as checkBranchHealth, o as deleteRemoteBranch, u as pruneMergedRemoteBranches } from "./branch-lifecycle-CcsSyfSw.mjs";
|
|
12
|
-
import { i as ensureContentBranch, n as buildBranchName, o as mergeBranch, r as createTransaction } from "./transaction-
|
|
13
|
-
import { n as withReadScope, r as isMerged, t as LocalProvider } from "./local-
|
|
12
|
+
import { i as ensureContentBranch, n as buildBranchName, o as mergeBranch, r as createTransaction } from "./transaction-CcjGiVYg.mjs";
|
|
13
|
+
import { n as withReadScope, r as isMerged, t as LocalProvider } from "./local-DaITA8Ye.mjs";
|
|
14
14
|
import { n as isToolAvailable, t as TOOL_REQUIREMENTS } from "./availability-CO8Xfx3w.mjs";
|
|
15
15
|
import { t as detectStack } from "./detect-B1QHYA0u.mjs";
|
|
16
16
|
import { t as TOOL_ANNOTATIONS } from "./annotations-BYkjoj2d.mjs";
|
|
17
17
|
import { n as listTemplates, t as getTemplate } from "./templates-Dn-iZyzp.mjs";
|
|
18
18
|
import { t as normalizeOperationError } from "./errors-De8Noahk.mjs";
|
|
19
|
-
import { t as reconcileBranches } from "./reconcile-
|
|
19
|
+
import { t as reconcileBranches } from "./reconcile-Do8OJDAo.mjs";
|
|
20
20
|
import { t as buildGraph } from "./graph-builder-BPhi-1KH.mjs";
|
|
21
21
|
import { n as scanSummary, t as scanCandidates } from "./scanner-0sc_pARB.mjs";
|
|
22
|
-
import { n as applyExtract, r as applyReuse } from "./apply-manager-
|
|
23
|
-
import { t as runDoctor } from "./doctor-
|
|
22
|
+
import { n as applyExtract, r as applyReuse } from "./apply-manager-BenQNb_b.mjs";
|
|
23
|
+
import { t as runDoctor } from "./doctor-Qabcb-Z1.mjs";
|
|
24
24
|
import { join } from "node:path";
|
|
25
25
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
26
26
|
import { appendFile, readFile, writeFile } from "node:fs/promises";
|
|
@@ -232,7 +232,7 @@ function registerContextTools(server, provider, projectRoot) {
|
|
|
232
232
|
kind: "One of: singleton, collection, document, dictionary.",
|
|
233
233
|
domain: "Organizational group; maps to the content subdirectory.",
|
|
234
234
|
i18n: "Whether the model stores content per locale.",
|
|
235
|
-
title_field: "Name of the field shown as an entry title in listings, pickers and relation references. Must name a field declared on this model whose type is one of: string, text, slug, email, url, code, markdown, richtext. Dictionary models have no fields — they use the reserved value \"key\", meaning the entry key is the title."
|
|
235
|
+
title_field: "Name of the field shown as an entry title in listings, pickers and relation references. Must name a field declared on this model whose type is one of: string, text, slug, email, url, code, markdown, richtext — or a dotted path one level into an object field (\"hero.heading\"), for a page singleton whose top level holds only section objects. Never through an array, never deeper than one level. Dictionary models have no fields — they use the reserved value \"key\", meaning the entry key is the title."
|
|
236
236
|
},
|
|
237
237
|
optional: {
|
|
238
238
|
description: "Model description for documentation and agent context.",
|
|
@@ -3051,7 +3051,7 @@ function registerMediaTools(server, provider, _projectRoot) {
|
|
|
3051
3051
|
}
|
|
3052
3052
|
//#endregion
|
|
3053
3053
|
//#region package.json
|
|
3054
|
-
var version = "3.
|
|
3054
|
+
var version = "3.9.1";
|
|
3055
3055
|
//#endregion
|
|
3056
3056
|
//#region src/server.ts
|
|
3057
3057
|
/**
|
|
@@ -3128,4 +3128,4 @@ function resolveServerContext(input) {
|
|
|
3128
3128
|
//#endregion
|
|
3129
3129
|
export { createServer as n, DEFAULT_INSTRUCTIONS as t };
|
|
3130
3130
|
|
|
3131
|
-
//# sourceMappingURL=server-
|
|
3131
|
+
//# sourceMappingURL=server-rEFicTHs.mjs.map
|