@co-engram/core 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/dist/i18n/en.d.ts.map +1 -1
  2. package/dist/i18n/en.js +1 -0
  3. package/dist/i18n/en.js.map +1 -1
  4. package/dist/i18n/zh.d.ts +1 -0
  5. package/dist/i18n/zh.d.ts.map +1 -1
  6. package/dist/i18n/zh.js +1 -0
  7. package/dist/i18n/zh.js.map +1 -1
  8. package/dist/index.d.ts +1 -0
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +1 -0
  11. package/dist/index.js.map +1 -1
  12. package/dist/merge/anomaly-detector.d.ts +63 -0
  13. package/dist/merge/anomaly-detector.d.ts.map +1 -0
  14. package/dist/merge/anomaly-detector.js +128 -0
  15. package/dist/merge/anomaly-detector.js.map +1 -0
  16. package/dist/merge/arbitration.d.ts +18 -0
  17. package/dist/merge/arbitration.d.ts.map +1 -0
  18. package/dist/merge/arbitration.js +27 -0
  19. package/dist/merge/arbitration.js.map +1 -0
  20. package/dist/merge/auto-onboard.d.ts +56 -0
  21. package/dist/merge/auto-onboard.d.ts.map +1 -0
  22. package/dist/merge/auto-onboard.js +81 -0
  23. package/dist/merge/auto-onboard.js.map +1 -0
  24. package/dist/merge/backup.d.ts +27 -0
  25. package/dist/merge/backup.d.ts.map +1 -0
  26. package/dist/merge/backup.js +49 -0
  27. package/dist/merge/backup.js.map +1 -0
  28. package/dist/merge/content.d.ts +50 -0
  29. package/dist/merge/content.d.ts.map +1 -0
  30. package/dist/merge/content.js +137 -0
  31. package/dist/merge/content.js.map +1 -0
  32. package/dist/merge/cross-file-coordinator.d.ts +52 -0
  33. package/dist/merge/cross-file-coordinator.d.ts.map +1 -0
  34. package/dist/merge/cross-file-coordinator.js +222 -0
  35. package/dist/merge/cross-file-coordinator.js.map +1 -0
  36. package/dist/merge/data-root.d.ts +9 -0
  37. package/dist/merge/data-root.d.ts.map +1 -0
  38. package/dist/merge/data-root.js +42 -0
  39. package/dist/merge/data-root.js.map +1 -0
  40. package/dist/merge/driver-llm.d.ts +92 -0
  41. package/dist/merge/driver-llm.d.ts.map +1 -0
  42. package/dist/merge/driver-llm.js +174 -0
  43. package/dist/merge/driver-llm.js.map +1 -0
  44. package/dist/merge/driver-main.d.ts +29 -0
  45. package/dist/merge/driver-main.d.ts.map +1 -0
  46. package/dist/merge/driver-main.js +220 -0
  47. package/dist/merge/driver-main.js.map +1 -0
  48. package/dist/merge/evidence-union.d.ts +35 -0
  49. package/dist/merge/evidence-union.d.ts.map +1 -0
  50. package/dist/merge/evidence-union.js +88 -0
  51. package/dist/merge/evidence-union.js.map +1 -0
  52. package/dist/merge/frontmatter-rules.d.ts +38 -0
  53. package/dist/merge/frontmatter-rules.d.ts.map +1 -0
  54. package/dist/merge/frontmatter-rules.js +77 -0
  55. package/dist/merge/frontmatter-rules.js.map +1 -0
  56. package/dist/merge/frontmatter.d.ts +52 -0
  57. package/dist/merge/frontmatter.d.ts.map +1 -0
  58. package/dist/merge/frontmatter.js +211 -0
  59. package/dist/merge/frontmatter.js.map +1 -0
  60. package/dist/merge/index.d.ts +31 -0
  61. package/dist/merge/index.d.ts.map +1 -0
  62. package/dist/merge/index.js +31 -0
  63. package/dist/merge/index.js.map +1 -0
  64. package/dist/merge/llm-arbiter.d.ts +85 -0
  65. package/dist/merge/llm-arbiter.d.ts.map +1 -0
  66. package/dist/merge/llm-arbiter.js +177 -0
  67. package/dist/merge/llm-arbiter.js.map +1 -0
  68. package/dist/merge/llm-contract.d.ts +86 -0
  69. package/dist/merge/llm-contract.d.ts.map +1 -0
  70. package/dist/merge/llm-contract.js +134 -0
  71. package/dist/merge/llm-contract.js.map +1 -0
  72. package/dist/merge/llm-prompt.d.ts +25 -0
  73. package/dist/merge/llm-prompt.d.ts.map +1 -0
  74. package/dist/merge/llm-prompt.js +73 -0
  75. package/dist/merge/llm-prompt.js.map +1 -0
  76. package/dist/merge/merge-engram.d.ts +33 -0
  77. package/dist/merge/merge-engram.d.ts.map +1 -0
  78. package/dist/merge/merge-engram.js +164 -0
  79. package/dist/merge/merge-engram.js.map +1 -0
  80. package/dist/merge/merge-stats.d.ts +68 -0
  81. package/dist/merge/merge-stats.d.ts.map +1 -0
  82. package/dist/merge/merge-stats.js +152 -0
  83. package/dist/merge/merge-stats.js.map +1 -0
  84. package/dist/merge/onboard.d.ts +72 -0
  85. package/dist/merge/onboard.d.ts.map +1 -0
  86. package/dist/merge/onboard.js +146 -0
  87. package/dist/merge/onboard.js.map +1 -0
  88. package/dist/merge/post-merge-hook.d.ts +77 -0
  89. package/dist/merge/post-merge-hook.d.ts.map +1 -0
  90. package/dist/merge/post-merge-hook.js +211 -0
  91. package/dist/merge/post-merge-hook.js.map +1 -0
  92. package/dist/merge/resolution-state.d.ts +41 -0
  93. package/dist/merge/resolution-state.d.ts.map +1 -0
  94. package/dist/merge/resolution-state.js +100 -0
  95. package/dist/merge/resolution-state.js.map +1 -0
  96. package/dist/merge/synapse-merger.d.ts +63 -0
  97. package/dist/merge/synapse-merger.d.ts.map +1 -0
  98. package/dist/merge/synapse-merger.js +277 -0
  99. package/dist/merge/synapse-merger.js.map +1 -0
  100. package/dist/merge/synapse-rules.d.ts +66 -0
  101. package/dist/merge/synapse-rules.d.ts.map +1 -0
  102. package/dist/merge/synapse-rules.js +112 -0
  103. package/dist/merge/synapse-rules.js.map +1 -0
  104. package/dist/merge/version.d.ts +10 -0
  105. package/dist/merge/version.d.ts.map +1 -0
  106. package/dist/merge/version.js +10 -0
  107. package/dist/merge/version.js.map +1 -0
  108. package/dist/merge-driver.cjs +9371 -0
  109. package/dist/observability/audit-log.d.ts +4 -1
  110. package/dist/observability/audit-log.d.ts.map +1 -1
  111. package/dist/observability/audit-log.js +3 -0
  112. package/dist/observability/audit-log.js.map +1 -1
  113. package/package.json +6 -2
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Post-merge git hook installer + runner (spec §7.5).
3
+ *
4
+ * Git 在 `git pull` / `git merge` 完成后会触发 `.git/hooks/post-merge`。
5
+ * 我们利用它跑一次跨文件一致性 check,捕捉 merge driver 看不到的
6
+ * 跨文件状态不一致(spec §7.3)。
7
+ *
8
+ * 设计要点:
9
+ * 1. installer 写一个**幂等**的 shell 脚本,不依赖具体路径
10
+ * 2. 脚本调用 `node <co-engram-cli>` 跑 runCrossFileConsistency
11
+ * 3. 失败/缺失不影响 git 操作(exit 0);不一致通过 audit log + stderr 提示
12
+ * 4. CLI 找不到时静默跳过(zero-friction:不影响普通 git pull)
13
+ *
14
+ * @module @co-engram/core/merge
15
+ */
16
+ /** Marker 让我们识别已安装的 hook(避免覆盖用户自定义 hook)。 */
17
+ export declare const HOOK_MARKER = "# co-engram-post-merge-hook";
18
+ /** Hook 在仓库中的相对路径(相对于 repoRoot)。 */
19
+ export declare const HOOK_RELATIVE_PATH = ".git/hooks/post-merge";
20
+ export interface InstallPostMergeHookResult {
21
+ /** Hook 写入的绝对路径。 */
22
+ readonly hookPath: string;
23
+ /** True = 本次新建;False = 已存在且被覆盖(用户上次手改过或重装)。 */
24
+ readonly overwritten: boolean;
25
+ }
26
+ /**
27
+ * 在 repoRoot 中安装 `.git/hooks/post-merge` 钩子。
28
+ *
29
+ * 行为:
30
+ * - .git/hooks 目录不存在 → 创建
31
+ * - hook 不存在 → 写入
32
+ * - hook 存在且包含 HOOK_MARKER → 覆盖(平滑升级)
33
+ * - hook 存在但不含 HOOK_MARKER → **不覆盖**,把新内容写到 `.post-merge.co-engram`,
34
+ * 并提示用户手动合并(保护用户的自定义 hook)
35
+ */
36
+ export declare function installPostMergeHook(params: {
37
+ repoRoot: string;
38
+ }): InstallPostMergeHookResult;
39
+ /**
40
+ * 卸载 post-merge hook(仅当我们安装的)。
41
+ *
42
+ * 如果 hook 不含 HOOK_MARKER,不操作(用户自定义)。
43
+ */
44
+ export declare function uninstallPostMergeHook(params: {
45
+ repoRoot: string;
46
+ }): {
47
+ removed: boolean;
48
+ };
49
+ export interface PostMergeHookStatus {
50
+ readonly installed: boolean;
51
+ /** True = 主 hook 是我们的;False = 主 hook 是用户的,但有 sidecar。 */
52
+ readonly atPrimaryPath: boolean;
53
+ readonly hookPath: string;
54
+ }
55
+ /** 检查 post-merge hook 是否已安装。 */
56
+ export declare function getPostMergeHookStatus(params: {
57
+ repoRoot: string;
58
+ }): PostMergeHookStatus;
59
+ export interface PostMergeRunResult {
60
+ readonly dataRoot: string | null;
61
+ readonly inconsistencies: number;
62
+ readonly autoFixed: number;
63
+ readonly escalated: number;
64
+ readonly durationMs: number;
65
+ /** 数据根未找到 / repository 构建失败等错误。 */
66
+ readonly error?: string;
67
+ }
68
+ /**
69
+ * Post-merge runner:发现数据根 → 构建 repository → 跑 cross-file check。
70
+ *
71
+ * 设计为 CLI 友好:失败不抛(写 error 字段),返回值有结构化结果。
72
+ * 调用方(CLI)负责把它格式化成 stdout/stderr 文本。
73
+ */
74
+ export declare function runPostMergeCheck(params: {
75
+ cwd: string;
76
+ }): Promise<PostMergeRunResult>;
77
+ //# sourceMappingURL=post-merge-hook.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"post-merge-hook.d.ts","sourceRoot":"","sources":["../../src/merge/post-merge-hook.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAaH,6CAA6C;AAC7C,eAAO,MAAM,WAAW,gCAAgC,CAAC;AAEzD,oCAAoC;AACpC,eAAO,MAAM,kBAAkB,0BAA0B,CAAC;AAmC1D,MAAM,WAAW,0BAA0B;IACzC,oBAAoB;IACpB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,+CAA+C;IAC/C,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;CAC/B;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE;IAC3C,QAAQ,EAAE,MAAM,CAAC;CAClB,GAAG,0BAA0B,CAoB7B;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG;IACpE,OAAO,EAAE,OAAO,CAAC;CAClB,CAYA;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,yDAAyD;IACzD,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,gCAAgC;AAChC,wBAAgB,sBAAsB,CAAC,MAAM,EAAE;IAC7C,QAAQ,EAAE,MAAM,CAAC;CAClB,GAAG,mBAAmB,CActB;AAMD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,mCAAmC;IACnC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,EAAE;IAC9C,GAAG,EAAE,MAAM,CAAC;CACb,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAkE9B"}
@@ -0,0 +1,211 @@
1
+ /**
2
+ * Post-merge git hook installer + runner (spec §7.5).
3
+ *
4
+ * Git 在 `git pull` / `git merge` 完成后会触发 `.git/hooks/post-merge`。
5
+ * 我们利用它跑一次跨文件一致性 check,捕捉 merge driver 看不到的
6
+ * 跨文件状态不一致(spec §7.3)。
7
+ *
8
+ * 设计要点:
9
+ * 1. installer 写一个**幂等**的 shell 脚本,不依赖具体路径
10
+ * 2. 脚本调用 `node <co-engram-cli>` 跑 runCrossFileConsistency
11
+ * 3. 失败/缺失不影响 git 操作(exit 0);不一致通过 audit log + stderr 提示
12
+ * 4. CLI 找不到时静默跳过(zero-friction:不影响普通 git pull)
13
+ *
14
+ * @module @co-engram/core/merge
15
+ */
16
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
17
+ import { execSync } from "node:child_process";
18
+ import { dirname, join, resolve } from "node:path";
19
+ import { findDataRoot } from "./data-root.js";
20
+ import { runCrossFileConsistency } from "./cross-file-coordinator.js";
21
+ import { EngramRepository } from "../storage/repository.js";
22
+ import { AuditLog } from "../observability/audit-log.js";
23
+ import { createDriverLlmClient } from "./driver-llm.js";
24
+ import { LlmArbiter } from "./llm-arbiter.js";
25
+ /** Marker 让我们识别已安装的 hook(避免覆盖用户自定义 hook)。 */
26
+ export const HOOK_MARKER = "# co-engram-post-merge-hook";
27
+ /** Hook 在仓库中的相对路径(相对于 repoRoot)。 */
28
+ export const HOOK_RELATIVE_PATH = ".git/hooks/post-merge";
29
+ /**
30
+ * 模板 shell 脚本。
31
+ *
32
+ * 策略:
33
+ * 1. 找到 co-engram CLI(尝试 PATH 中的 `co-engram`,然后 `npx co-engram`)
34
+ * 2. 跑 `co-engram post-merge --cwd <cwd>`
35
+ * 3. 任何错误都 exit 0(绝不阻塞 git)
36
+ *
37
+ * 注:模板里用 `${CO_ENGRAM_CLI}` 占位,installer 写入时替换。
38
+ */
39
+ const HOOK_TEMPLATE = `#!/bin/sh
40
+ ${HOOK_MARKER}
41
+ # Auto-installed by @co-engram/core. Runs cross-file consistency check.
42
+ # Safe to remove. Will NOT be re-installed unless you run install again.
43
+
44
+ # 找 co-engram CLI:PATH 优先,fallback 到 npx
45
+ CO_ENGRAM_CLI=""
46
+ if command -v co-engram >/dev/null 2>&1; then
47
+ CO_ENGRAM_CLI="co-engram"
48
+ elif command -v npx >/dev/null 2>&1; then
49
+ CO_ENGRAM_CLI="npx --no-install co-engram"
50
+ fi
51
+
52
+ # CLI 不可用 → 静默退出(不阻塞 git,不刷屏)
53
+ if [ -z "$CO_ENGRAM_CLI" ]; then
54
+ exit 0
55
+ fi
56
+
57
+ # 跑 post-merge check(任何错误都吞掉,只 stderr 提示)
58
+ "$CO_ENGRAM_CLI" post-merge --cwd "$(pwd)" 2>&1 | sed 's/^/[co-engram] /' >&2 || true
59
+ exit 0
60
+ `;
61
+ /**
62
+ * 在 repoRoot 中安装 `.git/hooks/post-merge` 钩子。
63
+ *
64
+ * 行为:
65
+ * - .git/hooks 目录不存在 → 创建
66
+ * - hook 不存在 → 写入
67
+ * - hook 存在且包含 HOOK_MARKER → 覆盖(平滑升级)
68
+ * - hook 存在但不含 HOOK_MARKER → **不覆盖**,把新内容写到 `.post-merge.co-engram`,
69
+ * 并提示用户手动合并(保护用户的自定义 hook)
70
+ */
71
+ export function installPostMergeHook(params) {
72
+ const { repoRoot } = params;
73
+ const hookPath = join(repoRoot, HOOK_RELATIVE_PATH);
74
+ const hookDir = dirname(hookPath);
75
+ if (!existsSync(hookDir)) {
76
+ mkdirSync(hookDir, { recursive: true });
77
+ }
78
+ const existing = existsSync(hookPath) ? readFileSync(hookPath, "utf8") : null;
79
+ if (existing !== null && !existing.includes(HOOK_MARKER)) {
80
+ // 用户已有自定义 hook — 旁挂一份,不动原 hook
81
+ const sidecarPath = join(hookDir, "post-merge.co-engram");
82
+ writeFileSync(sidecarPath, HOOK_TEMPLATE, { mode: 0o755 });
83
+ return { hookPath: sidecarPath, overwritten: false };
84
+ }
85
+ writeFileSync(hookPath, HOOK_TEMPLATE, { mode: 0o755 });
86
+ return { hookPath, overwritten: existing !== null };
87
+ }
88
+ /**
89
+ * 卸载 post-merge hook(仅当我们安装的)。
90
+ *
91
+ * 如果 hook 不含 HOOK_MARKER,不操作(用户自定义)。
92
+ */
93
+ export function uninstallPostMergeHook(params) {
94
+ const { repoRoot } = params;
95
+ const hookPath = join(repoRoot, HOOK_RELATIVE_PATH);
96
+ if (!existsSync(hookPath))
97
+ return { removed: false };
98
+ const content = readFileSync(hookPath, "utf8");
99
+ if (!content.includes(HOOK_MARKER))
100
+ return { removed: false };
101
+ try {
102
+ execSync(`rm -f ${JSON.stringify(hookPath)}`);
103
+ return { removed: true };
104
+ }
105
+ catch {
106
+ return { removed: false };
107
+ }
108
+ }
109
+ /** 检查 post-merge hook 是否已安装。 */
110
+ export function getPostMergeHookStatus(params) {
111
+ const { repoRoot } = params;
112
+ const hookPath = join(repoRoot, HOOK_RELATIVE_PATH);
113
+ if (existsSync(hookPath)) {
114
+ const content = readFileSync(hookPath, "utf8");
115
+ if (content.includes(HOOK_MARKER)) {
116
+ return { installed: true, atPrimaryPath: true, hookPath };
117
+ }
118
+ }
119
+ const sidecar = join(dirname(hookPath), "post-merge.co-engram");
120
+ if (existsSync(sidecar)) {
121
+ return { installed: true, atPrimaryPath: false, hookPath: sidecar };
122
+ }
123
+ return { installed: false, atPrimaryPath: false, hookPath };
124
+ }
125
+ /**
126
+ * Post-merge runner:发现数据根 → 构建 repository → 跑 cross-file check。
127
+ *
128
+ * 设计为 CLI 友好:失败不抛(写 error 字段),返回值有结构化结果。
129
+ * 调用方(CLI)负责把它格式化成 stdout/stderr 文本。
130
+ */
131
+ export async function runPostMergeCheck(params) {
132
+ const { cwd } = params;
133
+ const dataRoot = findDataRoot(resolve(cwd));
134
+ if (!dataRoot) {
135
+ return {
136
+ dataRoot: null,
137
+ inconsistencies: 0,
138
+ autoFixed: 0,
139
+ escalated: 0,
140
+ durationMs: 0,
141
+ };
142
+ }
143
+ const startedAt = Date.now();
144
+ let repo;
145
+ try {
146
+ repo = new EngramRepository({
147
+ rootPath: dataRoot,
148
+ language: detectLanguage(dataRoot),
149
+ });
150
+ }
151
+ catch (e) {
152
+ return {
153
+ dataRoot,
154
+ inconsistencies: 0,
155
+ autoFixed: 0,
156
+ escalated: 0,
157
+ durationMs: Date.now() - startedAt,
158
+ error: e instanceof Error ? e.message : String(e),
159
+ };
160
+ }
161
+ const auditLog = new AuditLog(dataRoot);
162
+ // 复用 driver 的 LLM bootstrap(可选)
163
+ const llmBootstrap = createDriverLlmClient();
164
+ const llmArbiter = llmBootstrap
165
+ ? new LlmArbiter({
166
+ client: llmBootstrap.client,
167
+ auditLog,
168
+ providerName: llmBootstrap.config.model,
169
+ })
170
+ : undefined;
171
+ try {
172
+ const report = await runCrossFileConsistency({
173
+ repository: repo,
174
+ auditLog,
175
+ llmArbiter,
176
+ });
177
+ return {
178
+ dataRoot,
179
+ inconsistencies: report.inconsistencies.length,
180
+ autoFixed: report.autoFixedCount,
181
+ escalated: report.llmEscalatedCount,
182
+ durationMs: Date.now() - startedAt,
183
+ };
184
+ }
185
+ catch (e) {
186
+ return {
187
+ dataRoot,
188
+ inconsistencies: 0,
189
+ autoFixed: 0,
190
+ escalated: 0,
191
+ durationMs: Date.now() - startedAt,
192
+ error: e instanceof Error ? e.message : String(e),
193
+ };
194
+ }
195
+ }
196
+ /**
197
+ * 从数据根探测语言。读 `.co-engram/config.json`,失败默认 'en'。
198
+ */
199
+ function detectLanguage(dataRoot) {
200
+ try {
201
+ const configPath = join(dataRoot, ".co-engram", "config.json");
202
+ if (!existsSync(configPath))
203
+ return "en";
204
+ const config = JSON.parse(readFileSync(configPath, "utf8"));
205
+ return config.language ?? "en";
206
+ }
207
+ catch {
208
+ return "en";
209
+ }
210
+ }
211
+ //# sourceMappingURL=post-merge-hook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"post-merge-hook.js","sourceRoot":"","sources":["../../src/merge/post-merge-hook.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * resolutionState state-machine merge (spec §6.3).
3
+ *
4
+ * Contradicts synapse three-phase lifecycle:
5
+ * pending → auto_resolved / escalated → contested → resolved
6
+ *
7
+ * Merge rules:
8
+ * 1. ours == theirs → use either
9
+ * 2. one side absent → use the one present
10
+ * 3. phases differ → higher phase wins (closer to resolution)
11
+ * 4. phases equal → higher priority status wins
12
+ * priority = { resolved: 4, escalated: 3, auto_resolved: 2, contested: 2, pending: 1 }
13
+ * 5. on override: append loser's rationale as evidence for the winner
14
+ *
15
+ * @module @co-engram/core/merge
16
+ */
17
+ import type { SynapseResolutionState, SynapseResolutionStatus } from "../types/synapse.js";
18
+ export declare const RESOLUTION_STATUS_PRIORITY: Record<SynapseResolutionStatus, number>;
19
+ export type ResolutionMergeStrategy = "all-absent" | "one-side-absent" | "same-status" | "higher-phase" | "higher-priority-status" | "tie-keep-ours";
20
+ export interface LoserRationale {
21
+ readonly fromStatus: SynapseResolutionStatus;
22
+ readonly fromPhase: 1 | 2 | 3;
23
+ readonly rationale: string;
24
+ }
25
+ export interface ResolutionMergeResult {
26
+ readonly merged: SynapseResolutionState | undefined;
27
+ readonly strategy: ResolutionMergeStrategy;
28
+ /** Loser's rationale, surfaced so caller can append it as evidence. */
29
+ readonly loserRationale: LoserRationale | null;
30
+ }
31
+ /**
32
+ * Merge three resolutionState values per spec §6.3 state machine.
33
+ *
34
+ * `base`, `ours`, `theirs` may all be undefined (synapse may not have one).
35
+ */
36
+ export declare function mergeResolutionState(params: {
37
+ base?: SynapseResolutionState;
38
+ ours?: SynapseResolutionState;
39
+ theirs?: SynapseResolutionState;
40
+ }): ResolutionMergeResult;
41
+ //# sourceMappingURL=resolution-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolution-state.d.ts","sourceRoot":"","sources":["../../src/merge/resolution-state.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EACV,sBAAsB,EACtB,uBAAuB,EACxB,MAAM,qBAAqB,CAAC;AAE7B,eAAO,MAAM,0BAA0B,EAAE,MAAM,CAC7C,uBAAuB,EACvB,MAAM,CAOP,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAC/B,YAAY,GACZ,iBAAiB,GACjB,aAAa,GACb,cAAc,GACd,wBAAwB,GACxB,eAAe,CAAC;AAEpB,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,UAAU,EAAE,uBAAuB,CAAC;IAC7C,QAAQ,CAAC,SAAS,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,MAAM,EAAE,sBAAsB,GAAG,SAAS,CAAC;IACpD,QAAQ,CAAC,QAAQ,EAAE,uBAAuB,CAAC;IAC3C,uEAAuE;IACvE,QAAQ,CAAC,cAAc,EAAE,cAAc,GAAG,IAAI,CAAC;CAChD;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE;IAC3C,IAAI,CAAC,EAAE,sBAAsB,CAAC;IAC9B,IAAI,CAAC,EAAE,sBAAsB,CAAC;IAC9B,MAAM,CAAC,EAAE,sBAAsB,CAAC;CACjC,GAAG,qBAAqB,CAsExB"}
@@ -0,0 +1,100 @@
1
+ /**
2
+ * resolutionState state-machine merge (spec §6.3).
3
+ *
4
+ * Contradicts synapse three-phase lifecycle:
5
+ * pending → auto_resolved / escalated → contested → resolved
6
+ *
7
+ * Merge rules:
8
+ * 1. ours == theirs → use either
9
+ * 2. one side absent → use the one present
10
+ * 3. phases differ → higher phase wins (closer to resolution)
11
+ * 4. phases equal → higher priority status wins
12
+ * priority = { resolved: 4, escalated: 3, auto_resolved: 2, contested: 2, pending: 1 }
13
+ * 5. on override: append loser's rationale as evidence for the winner
14
+ *
15
+ * @module @co-engram/core/merge
16
+ */
17
+ export const RESOLUTION_STATUS_PRIORITY = {
18
+ pending: 1,
19
+ auto_resolved: 2,
20
+ contested: 2,
21
+ escalated: 3,
22
+ resolved: 4,
23
+ };
24
+ /**
25
+ * Merge three resolutionState values per spec §6.3 state machine.
26
+ *
27
+ * `base`, `ours`, `theirs` may all be undefined (synapse may not have one).
28
+ */
29
+ export function mergeResolutionState(params) {
30
+ const { base, ours, theirs } = params;
31
+ if (!ours && !theirs) {
32
+ return {
33
+ merged: base,
34
+ strategy: "all-absent",
35
+ loserRationale: null,
36
+ };
37
+ }
38
+ if (ours && !theirs) {
39
+ return { merged: ours, strategy: "one-side-absent", loserRationale: null };
40
+ }
41
+ if (theirs && !ours) {
42
+ return {
43
+ merged: theirs,
44
+ strategy: "one-side-absent",
45
+ loserRationale: null,
46
+ };
47
+ }
48
+ // Both sides present — guaranteed by guards above
49
+ const oursState = ours;
50
+ const theirsState = theirs;
51
+ if (oursState.status === theirsState.status &&
52
+ oursState.phase === theirsState.phase) {
53
+ return {
54
+ merged: oursState,
55
+ strategy: "same-status",
56
+ loserRationale: null,
57
+ };
58
+ }
59
+ // Phases differ → higher phase wins
60
+ if (oursState.phase !== theirsState.phase) {
61
+ const oursWins = oursState.phase > theirsState.phase;
62
+ const winner = oursWins ? oursState : theirsState;
63
+ const loser = oursWins ? theirsState : oursState;
64
+ return {
65
+ merged: winner,
66
+ strategy: "higher-phase",
67
+ loserRationale: extractLoserRationale(loser),
68
+ };
69
+ }
70
+ // Same phase → higher priority status wins
71
+ const oursPriority = RESOLUTION_STATUS_PRIORITY[oursState.status];
72
+ const theirsPriority = RESOLUTION_STATUS_PRIORITY[theirsState.status];
73
+ if (oursPriority !== theirsPriority) {
74
+ const oursWins = oursPriority > theirsPriority;
75
+ const winner = oursWins ? oursState : theirsState;
76
+ const loser = oursWins ? theirsState : oursState;
77
+ return {
78
+ merged: winner,
79
+ strategy: "higher-priority-status",
80
+ loserRationale: extractLoserRationale(loser),
81
+ };
82
+ }
83
+ // Same phase + same priority (e.g. both 'contested' phase 3) → tie.
84
+ // Deterministically keep ours; caller may escalate if they detect the tie.
85
+ return {
86
+ merged: oursState,
87
+ strategy: "tie-keep-ours",
88
+ loserRationale: extractLoserRationale(theirsState),
89
+ };
90
+ }
91
+ function extractLoserRationale(loser) {
92
+ if (!loser.rationale || loser.rationale.trim() === "")
93
+ return null;
94
+ return {
95
+ fromStatus: loser.status,
96
+ fromPhase: loser.phase,
97
+ rationale: loser.rationale,
98
+ };
99
+ }
100
+ //# sourceMappingURL=resolution-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolution-state.js","sourceRoot":"","sources":["../../src/merge/resolution-state.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * SynapseMerger — orchestrator for synapse file 3-way merge (spec §6).
3
+ *
4
+ * Composes:
5
+ * - synapse-rules: immutable / updatedAt_arbitration / max_updatedAt
6
+ * - evidence-union: array_union
7
+ * - resolution-state: state_machine
8
+ * - passthrough: unknown fields kept from ours
9
+ *
10
+ * Identity fields (id/from/to/kind/createdBy/createdAt) — divergent edits
11
+ * escalate per spec §6.4 "kind 改变 → driver 不介入". Note that since
12
+ * kind is part of the file path (`synapses/{kind}/syn-{id}.yaml`), kind
13
+ * changes show up as rename/add in git itself, not as content conflict.
14
+ *
15
+ * `mergeSynapseFile` 是 sync 版本,只走 Layer A(机械规则)。
16
+ * `mergeSynapseFileAsync` 在 updatedAt_arbitration 字段 escalate 时追加
17
+ * Layer B(LLM)兜底;immutable 字段保持 escalate(spec §6.4)。
18
+ *
19
+ * @module @co-engram-core/merge
20
+ */
21
+ import type { Synapse } from "../types/synapse.js";
22
+ import type { LlmArbiter } from "./llm-arbiter.js";
23
+ export interface SynapseMergeResult {
24
+ /** Parsed merged synapse (only valid when escalated=false). */
25
+ readonly merged: Synapse;
26
+ /** Serialized merged YAML (with frontmatter delimiters). */
27
+ readonly mergedContent: string;
28
+ /** True when conflict could not be auto-resolved; markers in mergedContent. */
29
+ readonly escalated: boolean;
30
+ /** Human-readable summary of the strategy used. */
31
+ readonly strategy: string;
32
+ /** Winner side for updatedAt arbitrated fields, when applicable. */
33
+ readonly arbitratedWinner: "ours" | "theirs" | null;
34
+ }
35
+ export declare function mergeSynapseFile(params: {
36
+ baseRaw: string;
37
+ oursRaw: string;
38
+ theirsRaw: string;
39
+ /**
40
+ * 预解析的字段解决方案(用于 async 版注入 LLM 结果)。
41
+ * sync 调用方不传;key=字段名,value=替代 escalate 的最终值。
42
+ */
43
+ preResolvedFields?: Record<string, unknown>;
44
+ }): SynapseMergeResult;
45
+ /**
46
+ * Async 版 synapse 合并,在 Layer A escalate 后追加 Layer B(LLM)兜底。
47
+ *
48
+ * 触发条件(spec §5.7):
49
+ * - updatedAt_arbitration 字段(weight/direction/sourceSemantic/targetSemantic)
50
+ * 双方都改 + updatedAt 一致 → LLM 决定
51
+ *
52
+ * 不触发:
53
+ * - immutable 字段 escalate(spec §6.4: identity 字段冲突必须人工)
54
+ * - Layer A 已解决
55
+ */
56
+ export declare function mergeSynapseFileAsync(params: {
57
+ baseRaw: string;
58
+ oursRaw: string;
59
+ theirsRaw: string;
60
+ arbiter: LlmArbiter;
61
+ path: string;
62
+ }): Promise<SynapseMergeResult>;
63
+ //# sourceMappingURL=synapse-merger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"synapse-merger.d.ts","sourceRoot":"","sources":["../../src/merge/synapse-merger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAaH,OAAO,KAAK,EAAE,OAAO,EAAmB,MAAM,qBAAqB,CAAC;AACpE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGnD,MAAM,WAAW,kBAAkB;IACjC,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,4DAA4D;IAC5D,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,+EAA+E;IAC/E,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,mDAAmD;IACnD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,oEAAoE;IACpE,QAAQ,CAAC,gBAAgB,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAAC;CACrD;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC7C,GAAG,kBAAkB,CAyJrB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,qBAAqB,CAAC,MAAM,EAAE;IAClD,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,UAAU,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;CACd,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAyF9B"}