@contentrain/mcp 3.4.2 → 3.5.0
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/README.md +24 -0
- package/dist/core/ops/index.mjs +2 -2
- package/dist/core/validator/index.d.mts.map +1 -1
- package/dist/core/validator/index.mjs +1 -1
- package/dist/git/reconcile.mjs +3 -3
- package/dist/index.mjs +5 -5
- package/dist/{local-DbPlR0Br.mjs → local-DgjDad1x.mjs} +2 -2
- package/dist/{local-DbPlR0Br.mjs.map → local-DgjDad1x.mjs.map} +1 -1
- package/dist/providers/local/index.mjs +3 -3
- package/dist/{reconcile-TyPQKjme.mjs → reconcile-B55dZqhg.mjs} +2 -2
- package/dist/{reconcile-TyPQKjme.mjs.map → reconcile-B55dZqhg.mjs.map} +1 -1
- package/dist/{reconcile-EANDIp_T.mjs → reconcile-CwS4LUbo.mjs} +2 -2
- package/dist/{reconcile-EANDIp_T.mjs.map → reconcile-CwS4LUbo.mjs.map} +1 -1
- package/dist/server/http/index.mjs +5 -5
- package/dist/{server-CPRan_R2.mjs → server-CaVOG4yI.mjs} +10 -6
- package/dist/server-CaVOG4yI.mjs.map +1 -0
- package/dist/server.mjs +5 -5
- package/dist/{validator-CLugFhHw.mjs → validator-BD0Z0O0_.mjs} +39 -17
- package/dist/validator-BD0Z0O0_.mjs.map +1 -0
- package/package.json +2 -2
- package/dist/server-CPRan_R2.mjs.map +0 -1
- package/dist/validator-CLugFhHw.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -357,6 +357,30 @@ Full documentation at **[ai.contentrain.io/packages/mcp](https://ai.contentrain.
|
|
|
357
357
|
|
|
358
358
|
MIT
|
|
359
359
|
|
|
360
|
+
### Locale coverage (`model.locales`)
|
|
361
|
+
|
|
362
|
+
`contentrain_validate` checks an `i18n: true` model's parity against every locale
|
|
363
|
+
in `config.locales.supported`. A model that declares `locales` — a subset of that
|
|
364
|
+
list — is checked against the subset instead, which is how a partially-translated
|
|
365
|
+
site states the truth rather than failing on translations it never had. Absent, as
|
|
366
|
+
on every model that predates the field, means the whole project list.
|
|
367
|
+
|
|
368
|
+
Severity is unchanged and still follows the kind: a missing translation is a
|
|
369
|
+
**warning** on a `document` model and an **error** on a `collection`. Every message
|
|
370
|
+
names the list it was evaluated against, so the two cases read apart:
|
|
371
|
+
|
|
372
|
+
```
|
|
373
|
+
Locale file missing: tr.json (checked against the model's own locales [en, tr])
|
|
374
|
+
Entry parity: entry "a1b2c3" exists in en but missing in tr (checked against the project's supported locales [en, tr, da])
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
`contentrain_model_save` accepts `locales` and rejects a locale outside
|
|
378
|
+
`config.locales.supported`. `contentrain_validate fix:true` reports a broken
|
|
379
|
+
declaration but never invents one: narrowing a model's coverage is a content
|
|
380
|
+
decision, and the only value the tool could derive — the locales that happen to
|
|
381
|
+
have files today — would write the current gaps into the schema and silence the
|
|
382
|
+
errors that reveal them.
|
|
383
|
+
|
|
360
384
|
### Runtime model configuration
|
|
361
385
|
|
|
362
386
|
Structural `contentrain_model_save` edits preserve existing top-level `form` and
|
package/dist/core/ops/index.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { n as applyChangesToWorktree, t as planReconcile } from "../../reconcile-
|
|
1
|
+
import { n as applyChangesToWorktree, t as planReconcile } from "../../reconcile-B55dZqhg.mjs";
|
|
2
2
|
import "../../context-BHfO4WBv.mjs";
|
|
3
3
|
import { A as contentDirPath, M as documentFilePath, N as metaFilePath, j as contentFilePath } from "../../model-manager-CfwJWvz7.mjs";
|
|
4
4
|
import { a as planModelDelete, i as planModelSave, n as planVocabularySave, o as planContentSave, r as bindRef, s as planContentDelete, t as planVocabularyDelete } from "../../ops-B2P11b8v.mjs";
|
|
5
5
|
import "../../fs-DJv5G8uL.mjs";
|
|
6
6
|
import "../../meta-manager-Cd6AfuGS.mjs";
|
|
7
7
|
import "../../config-B8a4JBT1.mjs";
|
|
8
|
-
import "../../validator-
|
|
8
|
+
import "../../validator-BD0Z0O0_.mjs";
|
|
9
9
|
export { applyChangesToWorktree, bindRef, contentDirPath, contentFilePath, documentFilePath, metaFilePath, planContentDelete, planContentSave, planModelDelete, planModelSave, planReconcile, planVocabularyDelete, planVocabularySave };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../../../src/core/validator/entry.ts","../../../src/core/validator/relation-integrity.ts","../../../src/core/validator/project.ts","../../../src/core/validator/schedule.ts"],"mappings":";;;;;;;AAUA;;;;UAAiB,iBAAA;EAMN;EAJT,UAAA,GAAa,MAAA,SAAe,MAAA;EAIJ;EAFxB,cAAA;EAFa;EAIb,MAAA,GAAS,eAAA;AAAA;;;;;AAgBX;;;;;;;;;iBAAgB,eAAA,CACd,IAAA,EAAM,MAAA,mBACN,MAAA,EAAQ,MAAA,SAAe,QAAA,GACvB,OAAA,UACA,MAAA,UACA,OAAA,WACA,GAAA,GAAM,iBAAA,GACL,gBAAA;;;;;;AA7BH;;;;;;;;;UCIiB,cAAA;EACf,MAAA;EACA,OAAA,GAAU,MAAA;AAAA;;KAIA,iBAAA,IACV,aAAA,UACA,YAAA,aACG,OAAA,CAAQ,MAAA;AAAA,UAEI,6BAAA;EDOD;ECLd,QAAA;;;;;;EAMA,aAAA,IACE,aAAA,UACA,YAAA,aACG,OAAA,CAAQ,cAAA;AAAA;;;;;;;;;;;;iBAcO,sBAAA,CACpB,IAAA,EAAM,MAAA,mBACN,MAAA,EAAQ,MAAA,SAAe,QAAA,GACvB,OAAA,UACA,MAAA,UACA,OAAA,sBACA,WAAA,EAAa,iBAAA,EACb,IAAA,GAAM,6BAAA,GACL,OAAA,CAAQ,eAAA;;;UCxCM,eAAA;EACf,KAAA;EACA,GAAA;AAAA;AAAA,UAGe,cAAA;EACf,KAAA;EACA,OAAA;IACE,MAAA;IACA,QAAA;IACA,OAAA;IACA,cAAA;IACA,eAAA;EAAA;EAEF,MAAA,EAAQ,eAAA;EACR,KAAA;AAAA;;;AFDF;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../../src/core/validator/entry.ts","../../../src/core/validator/relation-integrity.ts","../../../src/core/validator/project.ts","../../../src/core/validator/schedule.ts"],"mappings":";;;;;;;AAUA;;;;UAAiB,iBAAA;EAMN;EAJT,UAAA,GAAa,MAAA,SAAe,MAAA;EAIJ;EAFxB,cAAA;EAFa;EAIb,MAAA,GAAS,eAAA;AAAA;;;;;AAgBX;;;;;;;;;iBAAgB,eAAA,CACd,IAAA,EAAM,MAAA,mBACN,MAAA,EAAQ,MAAA,SAAe,QAAA,GACvB,OAAA,UACA,MAAA,UACA,OAAA,WACA,GAAA,GAAM,iBAAA,GACL,gBAAA;;;;;;AA7BH;;;;;;;;;UCIiB,cAAA;EACf,MAAA;EACA,OAAA,GAAU,MAAA;AAAA;;KAIA,iBAAA,IACV,aAAA,UACA,YAAA,aACG,OAAA,CAAQ,MAAA;AAAA,UAEI,6BAAA;EDOD;ECLd,QAAA;;;;;;EAMA,aAAA,IACE,aAAA,UACA,YAAA,aACG,OAAA,CAAQ,cAAA;AAAA;;;;;;;;;;;;iBAcO,sBAAA,CACpB,IAAA,EAAM,MAAA,mBACN,MAAA,EAAQ,MAAA,SAAe,QAAA,GACvB,OAAA,UACA,MAAA,UACA,OAAA,sBACA,WAAA,EAAa,iBAAA,EACb,IAAA,GAAM,6BAAA,GACL,OAAA,CAAQ,eAAA;;;UCxCM,eAAA;EACf,KAAA;EACA,GAAA;AAAA;AAAA,UAGe,cAAA;EACf,KAAA;EACA,OAAA;IACE,MAAA;IACA,QAAA;IACA,OAAA;IACA,cAAA;IACA,eAAA;EAAA;EAEF,MAAA,EAAQ,eAAA;EACR,KAAA;AAAA;;;AFDF;;;;;;;;;;;;;iBE+/BsB,eAAA,CAAgB,WAAA,UAAqB,OAAA,GAAU,eAAA,GAAkB,OAAA,CAAQ,cAAA;AAAA,iBACzE,eAAA,CAAgB,MAAA,EAAQ,UAAA,EAAY,OAAA,GAAU,eAAA,GAAkB,OAAA,CAAQ,cAAA;;;;;;AFthC9F;;;;;iBGAgB,sBAAA,CACd,IAAA,EAAM,SAAA,EACN,GAAA;EAAO,KAAA;EAAe,MAAA;EAAgB,KAAA;EAAgB,IAAA;AAAA,GACtD,MAAA,EAAQ,eAAA"}
|
|
@@ -2,5 +2,5 @@ import "../../model-manager-CfwJWvz7.mjs";
|
|
|
2
2
|
import "../../fs-DJv5G8uL.mjs";
|
|
3
3
|
import "../../meta-manager-Cd6AfuGS.mjs";
|
|
4
4
|
import "../../config-B8a4JBT1.mjs";
|
|
5
|
-
import { i as validateContent, n as validateScheduleFields, r as checkRelationIntegrity, t as validateProject } from "../../validator-
|
|
5
|
+
import { i as validateContent, n as validateScheduleFields, r as checkRelationIntegrity, t as validateProject } from "../../validator-BD0Z0O0_.mjs";
|
|
6
6
|
export { checkRelationIntegrity, validateContent, validateProject, validateScheduleFields };
|
package/dist/git/reconcile.mjs
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import "../reconcile-
|
|
1
|
+
import "../reconcile-B55dZqhg.mjs";
|
|
2
2
|
import "../context-BHfO4WBv.mjs";
|
|
3
3
|
import "../model-manager-CfwJWvz7.mjs";
|
|
4
4
|
import "../fs-DJv5G8uL.mjs";
|
|
5
5
|
import "../meta-manager-Cd6AfuGS.mjs";
|
|
6
6
|
import "../config-B8a4JBT1.mjs";
|
|
7
|
-
import "../validator-
|
|
7
|
+
import "../validator-BD0Z0O0_.mjs";
|
|
8
8
|
import "../identity-CxAB9Qb8.mjs";
|
|
9
9
|
import "../branch-lifecycle-DUOoyNWn.mjs";
|
|
10
10
|
import "../id-CjGMPP1k.mjs";
|
|
11
11
|
import "../transaction-BR2jg4uj.mjs";
|
|
12
|
-
import { t as reconcileBranches } from "../reconcile-
|
|
12
|
+
import { t as reconcileBranches } from "../reconcile-CwS4LUbo.mjs";
|
|
13
13
|
export { reconcileBranches };
|
package/dist/index.mjs
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import "./contracts-DfL0BfrD.mjs";
|
|
3
|
-
import "./reconcile-
|
|
3
|
+
import "./reconcile-B55dZqhg.mjs";
|
|
4
4
|
import "./context-BHfO4WBv.mjs";
|
|
5
5
|
import "./model-manager-CfwJWvz7.mjs";
|
|
6
6
|
import "./ops-B2P11b8v.mjs";
|
|
7
7
|
import "./fs-DJv5G8uL.mjs";
|
|
8
8
|
import "./meta-manager-Cd6AfuGS.mjs";
|
|
9
9
|
import "./config-B8a4JBT1.mjs";
|
|
10
|
-
import "./validator-
|
|
10
|
+
import "./validator-BD0Z0O0_.mjs";
|
|
11
11
|
import "./identity-CxAB9Qb8.mjs";
|
|
12
12
|
import "./branch-lifecycle-DUOoyNWn.mjs";
|
|
13
13
|
import "./id-CjGMPP1k.mjs";
|
|
14
14
|
import "./transaction-BR2jg4uj.mjs";
|
|
15
|
-
import "./local-
|
|
15
|
+
import "./local-DgjDad1x.mjs";
|
|
16
16
|
import "./detect-CI32ynpq.mjs";
|
|
17
17
|
import "./annotations-CXHPnS-M.mjs";
|
|
18
|
-
import { n as createServer } from "./server-
|
|
18
|
+
import { n as createServer } from "./server-CaVOG4yI.mjs";
|
|
19
19
|
import "./errors-BmLE-JSC.mjs";
|
|
20
|
-
import "./reconcile-
|
|
20
|
+
import "./reconcile-CwS4LUbo.mjs";
|
|
21
21
|
import "./scan-config-C5zzygeH.mjs";
|
|
22
22
|
import "./graph-builder-C9NS7y-a.mjs";
|
|
23
23
|
import "./scanner-CEiT8Tgx.mjs";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as LOCAL_CAPABILITIES } from "./contracts-DfL0BfrD.mjs";
|
|
2
|
-
import { n as applyChangesToWorktree } from "./reconcile-
|
|
2
|
+
import { n as applyChangesToWorktree } from "./reconcile-B55dZqhg.mjs";
|
|
3
3
|
import { k as LocalReader } from "./model-manager-CfwJWvz7.mjs";
|
|
4
4
|
import { t as readConfig } from "./config-B8a4JBT1.mjs";
|
|
5
5
|
import { r as createGit } from "./identity-CxAB9Qb8.mjs";
|
|
@@ -263,4 +263,4 @@ var LocalProvider = class {
|
|
|
263
263
|
//#endregion
|
|
264
264
|
export { isMerged as n, LocalProvider as t };
|
|
265
265
|
|
|
266
|
-
//# sourceMappingURL=local-
|
|
266
|
+
//# sourceMappingURL=local-DgjDad1x.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local-DbPlR0Br.mjs","names":["mergeBranchOp","listBranchesOp","createBranchOp","deleteBranchOp","getBranchDiffOp","mergeBranchOp","isMergedOp","getDefaultBranchOp"],"sources":["../src/providers/local/branch-ops.ts","../src/providers/local/provider.ts"],"sourcesContent":["import { CONTENTRAIN_BRANCH } from '@contentrain/types'\nimport { createGit } from '../../git/identity.js'\nimport type { Branch, FileDiff, MergeResult } from '../../core/contracts/index.js'\nimport { readConfig } from '../../core/config.js'\nimport { classifyMergedBranches, deleteRemoteBranch } from '../../git/branch-lifecycle.js'\nimport { mergeBranch as mergeBranchOp } from '../../git/transaction.js'\n\n/**\n * Branch/merge/diff helpers backed by the local simple-git worktree flow.\n *\n * Pure functions composed into `LocalProvider` — mirroring the shape of\n * `providers/github/branch-ops.ts` so the two providers share the same\n * surface at the `RepoProvider` boundary.\n */\n\nexport async function getDefaultBranch(projectRoot: string): Promise<string> {\n const config = await readConfig(projectRoot)\n if (config?.repository?.default_branch) return config.repository.default_branch\n const envBranch = process.env['CONTENTRAIN_BRANCH']\n if (envBranch) return envBranch\n const git = createGit(projectRoot)\n const current = (await git.raw(['branch', '--show-current'])).trim()\n return current || 'main'\n}\n\nexport async function listBranches(\n projectRoot: string,\n prefix?: string,\n): Promise<Branch[]> {\n const git = createGit(projectRoot)\n const summary = await git.branchLocal()\n const names = prefix\n ? summary.all.filter(n => n.startsWith(prefix))\n : summary.all\n const branches: Branch[] = []\n for (const name of names) {\n const info = summary.branches[name]\n branches.push({ name, sha: info?.commit ?? '' })\n }\n return branches\n}\n\nexport async function createBranch(\n projectRoot: string,\n name: string,\n fromRef: string,\n): Promise<void> {\n const git = createGit(projectRoot)\n await git.raw(['branch', name, fromRef])\n}\n\nexport async function deleteBranch(\n projectRoot: string,\n name: string,\n): Promise<void> {\n const git = createGit(projectRoot)\n await git.deleteLocalBranch(name, true)\n // Parity with the remote-API providers, whose deleteBranch removes the\n // remote ref: best-effort, config-gated inside the helper, never throws.\n await deleteRemoteBranch(projectRoot, name)\n}\n\nexport async function getBranchDiff(\n projectRoot: string,\n branch: string,\n base: string,\n): Promise<FileDiff[]> {\n const git = createGit(projectRoot)\n const raw = await git.raw(['diff', '--name-status', `${base}...${branch}`])\n const diffs: FileDiff[] = []\n for (const line of raw.split('\\n')) {\n if (!line.trim()) continue\n const [code, ...pathParts] = line.split('\\t')\n const path = pathParts[pathParts.length - 1]\n if (!code || !path) continue\n const status: FileDiff['status'] = code.startsWith('A')\n ? 'added'\n : code.startsWith('D')\n ? 'removed'\n : 'modified'\n diffs.push({ path, status, before: null, after: null })\n }\n return diffs\n}\n\nexport async function mergeBranch(\n projectRoot: string,\n branch: string,\n into: string,\n): Promise<MergeResult> {\n if (into !== CONTENTRAIN_BRANCH) {\n throw Object.assign(new Error(\n `LocalProvider.mergeBranch only supports merging into \"${CONTENTRAIN_BRANCH}\" (got \"${into}\"). `\n + `The local flow merges feature branches into the content-tracking branch and fast-forwards the base branch via update-ref.`,\n ), {\n code: 'UNSUPPORTED_MERGE_TARGET',\n agent_hint: `Pass \"${CONTENTRAIN_BRANCH}\" as the merge target, or use a non-local provider that supports arbitrary targets.`,\n developer_action: `Merge \"${branch}\" into \"${CONTENTRAIN_BRANCH}\" instead.`,\n })\n }\n const result = await mergeBranchOp(projectRoot, branch)\n return {\n merged: true,\n sha: result.commit,\n pullRequestUrl: null,\n sync: result.sync,\n ...(result.remote ? { remote: result.remote } : {}),\n }\n}\n\nexport async function isMerged(\n projectRoot: string,\n branch: string,\n into: string,\n): Promise<boolean> {\n try {\n const merged = await classifyMergedBranches(projectRoot, [branch], into)\n return merged.has(branch)\n } catch {\n return false\n }\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 {\n Branch,\n Commit,\n CommitAuthor,\n FileChange,\n FileDiff,\n MergeResult,\n ProviderCapabilities,\n RepoProvider,\n WriteReadiness,\n} from '../../core/contracts/index.js'\nimport { LOCAL_CAPABILITIES } from '../../core/contracts/index.js'\nimport { applyChangesToWorktree } from '../../core/ops/index.js'\nimport { checkBranchHealth } from '../../git/branch-lifecycle.js'\nimport { createGit } from '../../git/identity.js'\nimport { createTransaction } from '../../git/transaction.js'\nimport {\n createBranch as createBranchOp,\n deleteBranch as deleteBranchOp,\n getBranchDiff as getBranchDiffOp,\n getDefaultBranch as getDefaultBranchOp,\n isMerged as isMergedOp,\n listBranches as listBranchesOp,\n mergeBranch as mergeBranchOp,\n} from './branch-ops.js'\nimport { LocalReader } from './reader.js'\nimport type { LocalApplyPlanInput, LocalApplyResult } from './types.js'\n\nconst DEFAULT_AUTHOR_NAME = 'Contentrain'\nconst DEFAULT_AUTHOR_EMAIL = 'ai@contentrain.io'\n\n/**\n * LocalProvider — the local-filesystem, worktree-backed content provider.\n *\n * Implements the full `RepoProvider` surface:\n * - Reader methods delegate to `LocalReader`.\n * - `applyPlan` wraps `createTransaction` and returns `LocalApplyResult`\n * (a superset of `Commit` carrying workflow action + selective sync).\n * - Branch ops mirror `GitHubProvider` — thin wrappers over the local\n * simple-git helpers in `./branch-ops.ts`.\n *\n * `mergeBranch` only supports merging into the singleton\n * `CONTENTRAIN_BRANCH`; the local flow advances the base branch via\n * `update-ref` in `transaction.mergeBranch`, so arbitrary merge targets\n * would bypass that invariant.\n */\nexport class LocalProvider implements RepoProvider {\n readonly capabilities: ProviderCapabilities = LOCAL_CAPABILITIES\n private readonly reader: LocalReader\n\n constructor(public readonly projectRoot: string) {\n this.reader = new LocalReader(projectRoot)\n }\n\n readFile(path: string, ref?: string): Promise<string> {\n return this.reader.readFile(path, ref)\n }\n\n listDirectory(path: string, ref?: string): Promise<string[]> {\n return this.reader.listDirectory(path, ref)\n }\n\n fileExists(path: string, ref?: string): Promise<boolean> {\n return this.reader.fileExists(path, ref)\n }\n\n /**\n * Branch pressure gate. Unmerged `cr/*` branches accumulate in a local repo\n * and eventually have to stop new writes; hosted providers have no such\n * limit, so they omit this method entirely.\n */\n async checkWriteReadiness(): Promise<WriteReadiness> {\n const health = await checkBranchHealth(this.projectRoot)\n return health.blocked\n ? { blocked: true, message: health.message ?? 'Too many active contentrain branches.' }\n : { blocked: false }\n }\n\n async applyPlan(input: LocalApplyPlanInput): Promise<LocalApplyResult> {\n const tx = await createTransaction(this.projectRoot, input.branch, {\n workflowOverride: input.workflowOverride,\n })\n try {\n await tx.write(async (wt) => {\n await applyChangesToWorktree(wt, input.changes)\n })\n await tx.commit(input.message, input.context)\n const gitResult = await tx.complete()\n return {\n sha: gitResult.commit,\n message: input.message,\n author: input.author ?? {\n name: process.env['CONTENTRAIN_AUTHOR_NAME'] ?? DEFAULT_AUTHOR_NAME,\n email: process.env['CONTENTRAIN_AUTHOR_EMAIL'] ?? DEFAULT_AUTHOR_EMAIL,\n },\n timestamp: new Date().toISOString(),\n workflowAction: gitResult.action,\n sync: gitResult.sync,\n warning: gitResult.warning,\n base_advance: gitResult.base_advance,\n remote_push: gitResult.remote_push,\n }\n } finally {\n await tx.cleanup()\n }\n }\n\n listBranches(prefix?: string): Promise<Branch[]> {\n return listBranchesOp(this.projectRoot, prefix)\n }\n\n async createBranch(name: string, fromRef?: string): Promise<void> {\n const resolved = fromRef ?? CONTENTRAIN_BRANCH\n await createBranchOp(this.projectRoot, name, resolved)\n }\n\n deleteBranch(name: string): Promise<void> {\n return deleteBranchOp(this.projectRoot, name)\n }\n\n getBranchDiff(branch: string, base?: string): Promise<FileDiff[]> {\n const resolved = base ?? CONTENTRAIN_BRANCH\n return getBranchDiffOp(this.projectRoot, branch, resolved)\n }\n\n mergeBranch(branch: string, into: string): Promise<MergeResult> {\n return mergeBranchOp(this.projectRoot, branch, into)\n }\n\n isMerged(branch: string, into?: string): Promise<boolean> {\n const resolved = into ?? CONTENTRAIN_BRANCH\n return isMergedOp(this.projectRoot, branch, resolved)\n }\n\n getDefaultBranch(): Promise<string> {\n return getDefaultBranchOp(this.projectRoot)\n }\n\n async getMergeBase(refA: string, refB: string): Promise<string | null> {\n const git = createGit(this.projectRoot)\n try {\n return (await git.raw(['merge-base', refA, refB])).trim() || null\n } catch {\n return null\n }\n }\n\n /**\n * Two-parent merge commit in a temp worktree. The real `git merge`\n * resolves everything outside the plan; the plan's changes then\n * overwrite every content-owned path (planner output is authoritative,\n * never git's textual auto-merge). Leftover unmerged paths abort — they\n * are outside the content planner's scope by construction.\n */\n async createMergeCommit(input: {\n branch: string\n ours: string\n theirs: string\n changes: FileChange[]\n message: string\n author: CommitAuthor\n }): Promise<Commit> {\n const git = createGit(this.projectRoot)\n const tip = (await git.raw(['rev-parse', input.branch])).trim()\n if (tip !== input.ours) {\n throw Object.assign(new Error(\n `createMergeCommit: \"${input.branch}\" is at ${tip.slice(0, 8)}, not the expected ${input.ours.slice(0, 8)} — the branch moved since planning.`,\n ), {\n code: 'RECONCILE_STALE_OURS',\n agent_hint: 'Re-run the reconcile plan against the current tip.',\n })\n }\n\n const worktreePath = join(tmpdir(), `cr-merge-commit-${randomUUID()}`)\n await git.raw(['worktree', 'add', worktreePath, input.branch])\n const wtGit = createGit(worktreePath, {\n config: [\n `user.name=${input.author.name}`,\n `user.email=${input.author.email}`,\n ],\n })\n try {\n try {\n await wtGit.merge([input.theirs, '--no-commit', '--no-ff'])\n } catch {\n // Conflicts are expected — the plan overwrites content paths next.\n }\n await applyChangesToWorktree(worktreePath, input.changes)\n await wtGit.raw(['add', '-A'])\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 `createMergeCommit: ${paths.length} non-content file(s) conflict: ${paths.join(', ')}.`,\n ), { code: 'RECONCILE_SOURCE_CONFLICT' })\n }\n await wtGit.commit(input.message, { '--no-verify': null })\n const sha = (await wtGit.raw(['rev-parse', 'HEAD'])).trim()\n return {\n sha,\n message: input.message,\n author: input.author,\n timestamp: new Date().toISOString(),\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}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"local-DgjDad1x.mjs","names":["mergeBranchOp","listBranchesOp","createBranchOp","deleteBranchOp","getBranchDiffOp","mergeBranchOp","isMergedOp","getDefaultBranchOp"],"sources":["../src/providers/local/branch-ops.ts","../src/providers/local/provider.ts"],"sourcesContent":["import { CONTENTRAIN_BRANCH } from '@contentrain/types'\nimport { createGit } from '../../git/identity.js'\nimport type { Branch, FileDiff, MergeResult } from '../../core/contracts/index.js'\nimport { readConfig } from '../../core/config.js'\nimport { classifyMergedBranches, deleteRemoteBranch } from '../../git/branch-lifecycle.js'\nimport { mergeBranch as mergeBranchOp } from '../../git/transaction.js'\n\n/**\n * Branch/merge/diff helpers backed by the local simple-git worktree flow.\n *\n * Pure functions composed into `LocalProvider` — mirroring the shape of\n * `providers/github/branch-ops.ts` so the two providers share the same\n * surface at the `RepoProvider` boundary.\n */\n\nexport async function getDefaultBranch(projectRoot: string): Promise<string> {\n const config = await readConfig(projectRoot)\n if (config?.repository?.default_branch) return config.repository.default_branch\n const envBranch = process.env['CONTENTRAIN_BRANCH']\n if (envBranch) return envBranch\n const git = createGit(projectRoot)\n const current = (await git.raw(['branch', '--show-current'])).trim()\n return current || 'main'\n}\n\nexport async function listBranches(\n projectRoot: string,\n prefix?: string,\n): Promise<Branch[]> {\n const git = createGit(projectRoot)\n const summary = await git.branchLocal()\n const names = prefix\n ? summary.all.filter(n => n.startsWith(prefix))\n : summary.all\n const branches: Branch[] = []\n for (const name of names) {\n const info = summary.branches[name]\n branches.push({ name, sha: info?.commit ?? '' })\n }\n return branches\n}\n\nexport async function createBranch(\n projectRoot: string,\n name: string,\n fromRef: string,\n): Promise<void> {\n const git = createGit(projectRoot)\n await git.raw(['branch', name, fromRef])\n}\n\nexport async function deleteBranch(\n projectRoot: string,\n name: string,\n): Promise<void> {\n const git = createGit(projectRoot)\n await git.deleteLocalBranch(name, true)\n // Parity with the remote-API providers, whose deleteBranch removes the\n // remote ref: best-effort, config-gated inside the helper, never throws.\n await deleteRemoteBranch(projectRoot, name)\n}\n\nexport async function getBranchDiff(\n projectRoot: string,\n branch: string,\n base: string,\n): Promise<FileDiff[]> {\n const git = createGit(projectRoot)\n const raw = await git.raw(['diff', '--name-status', `${base}...${branch}`])\n const diffs: FileDiff[] = []\n for (const line of raw.split('\\n')) {\n if (!line.trim()) continue\n const [code, ...pathParts] = line.split('\\t')\n const path = pathParts[pathParts.length - 1]\n if (!code || !path) continue\n const status: FileDiff['status'] = code.startsWith('A')\n ? 'added'\n : code.startsWith('D')\n ? 'removed'\n : 'modified'\n diffs.push({ path, status, before: null, after: null })\n }\n return diffs\n}\n\nexport async function mergeBranch(\n projectRoot: string,\n branch: string,\n into: string,\n): Promise<MergeResult> {\n if (into !== CONTENTRAIN_BRANCH) {\n throw Object.assign(new Error(\n `LocalProvider.mergeBranch only supports merging into \"${CONTENTRAIN_BRANCH}\" (got \"${into}\"). `\n + `The local flow merges feature branches into the content-tracking branch and fast-forwards the base branch via update-ref.`,\n ), {\n code: 'UNSUPPORTED_MERGE_TARGET',\n agent_hint: `Pass \"${CONTENTRAIN_BRANCH}\" as the merge target, or use a non-local provider that supports arbitrary targets.`,\n developer_action: `Merge \"${branch}\" into \"${CONTENTRAIN_BRANCH}\" instead.`,\n })\n }\n const result = await mergeBranchOp(projectRoot, branch)\n return {\n merged: true,\n sha: result.commit,\n pullRequestUrl: null,\n sync: result.sync,\n ...(result.remote ? { remote: result.remote } : {}),\n }\n}\n\nexport async function isMerged(\n projectRoot: string,\n branch: string,\n into: string,\n): Promise<boolean> {\n try {\n const merged = await classifyMergedBranches(projectRoot, [branch], into)\n return merged.has(branch)\n } catch {\n return false\n }\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 {\n Branch,\n Commit,\n CommitAuthor,\n FileChange,\n FileDiff,\n MergeResult,\n ProviderCapabilities,\n RepoProvider,\n WriteReadiness,\n} from '../../core/contracts/index.js'\nimport { LOCAL_CAPABILITIES } from '../../core/contracts/index.js'\nimport { applyChangesToWorktree } from '../../core/ops/index.js'\nimport { checkBranchHealth } from '../../git/branch-lifecycle.js'\nimport { createGit } from '../../git/identity.js'\nimport { createTransaction } from '../../git/transaction.js'\nimport {\n createBranch as createBranchOp,\n deleteBranch as deleteBranchOp,\n getBranchDiff as getBranchDiffOp,\n getDefaultBranch as getDefaultBranchOp,\n isMerged as isMergedOp,\n listBranches as listBranchesOp,\n mergeBranch as mergeBranchOp,\n} from './branch-ops.js'\nimport { LocalReader } from './reader.js'\nimport type { LocalApplyPlanInput, LocalApplyResult } from './types.js'\n\nconst DEFAULT_AUTHOR_NAME = 'Contentrain'\nconst DEFAULT_AUTHOR_EMAIL = 'ai@contentrain.io'\n\n/**\n * LocalProvider — the local-filesystem, worktree-backed content provider.\n *\n * Implements the full `RepoProvider` surface:\n * - Reader methods delegate to `LocalReader`.\n * - `applyPlan` wraps `createTransaction` and returns `LocalApplyResult`\n * (a superset of `Commit` carrying workflow action + selective sync).\n * - Branch ops mirror `GitHubProvider` — thin wrappers over the local\n * simple-git helpers in `./branch-ops.ts`.\n *\n * `mergeBranch` only supports merging into the singleton\n * `CONTENTRAIN_BRANCH`; the local flow advances the base branch via\n * `update-ref` in `transaction.mergeBranch`, so arbitrary merge targets\n * would bypass that invariant.\n */\nexport class LocalProvider implements RepoProvider {\n readonly capabilities: ProviderCapabilities = LOCAL_CAPABILITIES\n private readonly reader: LocalReader\n\n constructor(public readonly projectRoot: string) {\n this.reader = new LocalReader(projectRoot)\n }\n\n readFile(path: string, ref?: string): Promise<string> {\n return this.reader.readFile(path, ref)\n }\n\n listDirectory(path: string, ref?: string): Promise<string[]> {\n return this.reader.listDirectory(path, ref)\n }\n\n fileExists(path: string, ref?: string): Promise<boolean> {\n return this.reader.fileExists(path, ref)\n }\n\n /**\n * Branch pressure gate. Unmerged `cr/*` branches accumulate in a local repo\n * and eventually have to stop new writes; hosted providers have no such\n * limit, so they omit this method entirely.\n */\n async checkWriteReadiness(): Promise<WriteReadiness> {\n const health = await checkBranchHealth(this.projectRoot)\n return health.blocked\n ? { blocked: true, message: health.message ?? 'Too many active contentrain branches.' }\n : { blocked: false }\n }\n\n async applyPlan(input: LocalApplyPlanInput): Promise<LocalApplyResult> {\n const tx = await createTransaction(this.projectRoot, input.branch, {\n workflowOverride: input.workflowOverride,\n })\n try {\n await tx.write(async (wt) => {\n await applyChangesToWorktree(wt, input.changes)\n })\n await tx.commit(input.message, input.context)\n const gitResult = await tx.complete()\n return {\n sha: gitResult.commit,\n message: input.message,\n author: input.author ?? {\n name: process.env['CONTENTRAIN_AUTHOR_NAME'] ?? DEFAULT_AUTHOR_NAME,\n email: process.env['CONTENTRAIN_AUTHOR_EMAIL'] ?? DEFAULT_AUTHOR_EMAIL,\n },\n timestamp: new Date().toISOString(),\n workflowAction: gitResult.action,\n sync: gitResult.sync,\n warning: gitResult.warning,\n base_advance: gitResult.base_advance,\n remote_push: gitResult.remote_push,\n }\n } finally {\n await tx.cleanup()\n }\n }\n\n listBranches(prefix?: string): Promise<Branch[]> {\n return listBranchesOp(this.projectRoot, prefix)\n }\n\n async createBranch(name: string, fromRef?: string): Promise<void> {\n const resolved = fromRef ?? CONTENTRAIN_BRANCH\n await createBranchOp(this.projectRoot, name, resolved)\n }\n\n deleteBranch(name: string): Promise<void> {\n return deleteBranchOp(this.projectRoot, name)\n }\n\n getBranchDiff(branch: string, base?: string): Promise<FileDiff[]> {\n const resolved = base ?? CONTENTRAIN_BRANCH\n return getBranchDiffOp(this.projectRoot, branch, resolved)\n }\n\n mergeBranch(branch: string, into: string): Promise<MergeResult> {\n return mergeBranchOp(this.projectRoot, branch, into)\n }\n\n isMerged(branch: string, into?: string): Promise<boolean> {\n const resolved = into ?? CONTENTRAIN_BRANCH\n return isMergedOp(this.projectRoot, branch, resolved)\n }\n\n getDefaultBranch(): Promise<string> {\n return getDefaultBranchOp(this.projectRoot)\n }\n\n async getMergeBase(refA: string, refB: string): Promise<string | null> {\n const git = createGit(this.projectRoot)\n try {\n return (await git.raw(['merge-base', refA, refB])).trim() || null\n } catch {\n return null\n }\n }\n\n /**\n * Two-parent merge commit in a temp worktree. The real `git merge`\n * resolves everything outside the plan; the plan's changes then\n * overwrite every content-owned path (planner output is authoritative,\n * never git's textual auto-merge). Leftover unmerged paths abort — they\n * are outside the content planner's scope by construction.\n */\n async createMergeCommit(input: {\n branch: string\n ours: string\n theirs: string\n changes: FileChange[]\n message: string\n author: CommitAuthor\n }): Promise<Commit> {\n const git = createGit(this.projectRoot)\n const tip = (await git.raw(['rev-parse', input.branch])).trim()\n if (tip !== input.ours) {\n throw Object.assign(new Error(\n `createMergeCommit: \"${input.branch}\" is at ${tip.slice(0, 8)}, not the expected ${input.ours.slice(0, 8)} — the branch moved since planning.`,\n ), {\n code: 'RECONCILE_STALE_OURS',\n agent_hint: 'Re-run the reconcile plan against the current tip.',\n })\n }\n\n const worktreePath = join(tmpdir(), `cr-merge-commit-${randomUUID()}`)\n await git.raw(['worktree', 'add', worktreePath, input.branch])\n const wtGit = createGit(worktreePath, {\n config: [\n `user.name=${input.author.name}`,\n `user.email=${input.author.email}`,\n ],\n })\n try {\n try {\n await wtGit.merge([input.theirs, '--no-commit', '--no-ff'])\n } catch {\n // Conflicts are expected — the plan overwrites content paths next.\n }\n await applyChangesToWorktree(worktreePath, input.changes)\n await wtGit.raw(['add', '-A'])\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 `createMergeCommit: ${paths.length} non-content file(s) conflict: ${paths.join(', ')}.`,\n ), { code: 'RECONCILE_SOURCE_CONFLICT' })\n }\n await wtGit.commit(input.message, { '--no-verify': null })\n const sha = (await wtGit.raw(['rev-parse', 'HEAD'])).trim()\n return {\n sha,\n message: input.message,\n author: input.author,\n timestamp: new Date().toISOString(),\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}\n"],"mappings":"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"}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import "../../contracts-DfL0BfrD.mjs";
|
|
2
|
-
import "../../reconcile-
|
|
2
|
+
import "../../reconcile-B55dZqhg.mjs";
|
|
3
3
|
import "../../context-BHfO4WBv.mjs";
|
|
4
4
|
import { k as LocalReader } from "../../model-manager-CfwJWvz7.mjs";
|
|
5
5
|
import "../../ops-B2P11b8v.mjs";
|
|
6
6
|
import "../../fs-DJv5G8uL.mjs";
|
|
7
7
|
import "../../meta-manager-Cd6AfuGS.mjs";
|
|
8
8
|
import "../../config-B8a4JBT1.mjs";
|
|
9
|
-
import "../../validator-
|
|
9
|
+
import "../../validator-BD0Z0O0_.mjs";
|
|
10
10
|
import "../../identity-CxAB9Qb8.mjs";
|
|
11
11
|
import "../../branch-lifecycle-DUOoyNWn.mjs";
|
|
12
12
|
import "../../id-CjGMPP1k.mjs";
|
|
13
13
|
import "../../transaction-BR2jg4uj.mjs";
|
|
14
|
-
import { t as LocalProvider } from "../../local-
|
|
14
|
+
import { t as LocalProvider } from "../../local-DgjDad1x.mjs";
|
|
15
15
|
export { LocalProvider, LocalReader };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { t as buildContextChange } from "./context-BHfO4WBv.mjs";
|
|
2
2
|
import { A as contentDirPath, M as documentFilePath, j as contentFilePath } from "./model-manager-CfwJWvz7.mjs";
|
|
3
3
|
import { t as OverlayReader } from "./overlay-reader-Bx1YxGXq.mjs";
|
|
4
|
-
import { t as validateProject } from "./validator-
|
|
4
|
+
import { t as validateProject } from "./validator-BD0Z0O0_.mjs";
|
|
5
5
|
import { dirname, join } from "node:path";
|
|
6
6
|
import { MODEL_FIELD_ORDER, canonicalStringify, conflictId, parseMarkdownFrontmatter, serializeMarkdownFrontmatter, sortKeys, stableHash } from "@contentrain/types";
|
|
7
7
|
import { mkdir, rm, writeFile } from "node:fs/promises";
|
|
@@ -1724,4 +1724,4 @@ function parseJson(raw) {
|
|
|
1724
1724
|
//#endregion
|
|
1725
1725
|
export { applyChangesToWorktree as n, planReconcile as t };
|
|
1726
1726
|
|
|
1727
|
-
//# sourceMappingURL=reconcile-
|
|
1727
|
+
//# sourceMappingURL=reconcile-B55dZqhg.mjs.map
|