@danielmarbach/mnemonic-mcp 0.5.1 → 0.6.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/CHANGELOG.md +12 -0
- package/README.md +11 -3
- package/build/config.d.ts +1 -1
- package/build/config.d.ts.map +1 -1
- package/build/config.js +42 -1
- package/build/config.js.map +1 -1
- package/build/index.js +129 -27
- package/build/index.js.map +1 -1
- package/build/project-memory-policy.d.ts +11 -0
- package/build/project-memory-policy.d.ts.map +1 -1
- package/build/project-memory-policy.js +25 -0
- package/build/project-memory-policy.js.map +1 -1
- package/build/project.d.ts +1 -0
- package/build/project.d.ts.map +1 -1
- package/build/project.js +10 -0
- package/build/project.js.map +1 -1
- package/build/structured-content.d.ts +4 -0
- package/build/structured-content.d.ts.map +1 -1
- package/build/structured-content.js +2 -0
- package/build/structured-content.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,18 @@ All notable changes to `mnemonic` will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is loosely based on Keep a Changelog and uses semver-style version headings.
|
|
6
6
|
|
|
7
|
+
## [0.6.0] - 2026-03-13
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Protected-branch policy support for automatic `remember` project-vault commits. `ProjectMemoryPolicy` now supports `protectedBranchBehavior` (`ask` | `block` | `allow`) and `protectedBranchPatterns` (glob-like patterns). Built-in patterns are `main`, `master`, and `release*`.
|
|
12
|
+
- `remember` now accepts `allowProtectedBranch` as a one-time override when a protected-branch policy would otherwise ask or block.
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- `set_project_memory_policy` and `get_project_memory_policy` now manage and display protected-branch settings in addition to write-scope and consolidation defaults.
|
|
17
|
+
- `remember` now checks the current local git branch before automatic project-vault commits (scope omitted) and follows protected-branch policy with actionable guidance.
|
|
18
|
+
|
|
7
19
|
## [0.5.1] - 2026-03-12
|
|
8
20
|
|
|
9
21
|
### Fixed
|
package/README.md
CHANGED
|
@@ -208,6 +208,7 @@ User-tunable fields:
|
|
|
208
208
|
| `mutationPushMode` | `"main-only"` | When to auto-push after a write: `"all"`, `"main-only"`, or `"none"` |
|
|
209
209
|
|
|
210
210
|
`projectMemoryPolicies` and `projectIdentityOverrides` are written automatically by `set_project_memory_policy` and `set_project_identity` — no need to edit them by hand.
|
|
211
|
+
Project memory policies can include protected-branch settings (`protectedBranchBehavior`, `protectedBranchPatterns`) used by `remember` when writing to project vaults.
|
|
211
212
|
|
|
212
213
|
Example — raise concurrency on a fast machine and disable auto-push everywhere:
|
|
213
214
|
|
|
@@ -255,7 +256,14 @@ Two vault types store notes:
|
|
|
255
256
|
- `cwd` + `scope: "global"` → main vault, with project association in frontmatter
|
|
256
257
|
- no `cwd` → main vault as a plain global memory
|
|
257
258
|
|
|
258
|
-
Use `set_project_memory_policy` to save
|
|
259
|
+
Use `set_project_memory_policy` to save per-project defaults:
|
|
260
|
+
|
|
261
|
+
- write scope (`project`, `global`, `ask`)
|
|
262
|
+
- consolidation mode (`supersedes`, `delete`)
|
|
263
|
+
- protected-branch behavior for project-vault writes (`ask`, `block`, `allow`)
|
|
264
|
+
- protected-branch patterns (glob strings; defaults are `main`, `master`, `release*`)
|
|
265
|
+
|
|
266
|
+
When write scope policy is `ask`, `remember` returns a clear storage choice instead of guessing. When protected-branch behavior is `ask`, `remember` returns a one-time override option plus instructions to persist `block`/`allow`.
|
|
259
267
|
|
|
260
268
|
### Project identity
|
|
261
269
|
|
|
@@ -370,7 +378,7 @@ Imported notes are written to the main vault with `lifecycle: permanent` and `sc
|
|
|
370
378
|
| `forget` | Delete note + embedding, git commit + push, cleanup relationships |
|
|
371
379
|
| `get` | Fetch one or more notes by exact id |
|
|
372
380
|
| `get_project_identity` | Show effective project identity and remote override |
|
|
373
|
-
| `get_project_memory_policy` | Show saved
|
|
381
|
+
| `get_project_memory_policy` | Show saved write scope, consolidation mode, and protected-branch settings |
|
|
374
382
|
| `list` | List notes filtered by scope/tags/storage |
|
|
375
383
|
| `list_migrations` | List available migrations and pending count |
|
|
376
384
|
| `memory_graph` | Show compact adjacency list of relationships |
|
|
@@ -381,7 +389,7 @@ Imported notes are written to the main vault with `lifecycle: permanent` and `sc
|
|
|
381
389
|
| `remember` | Write note + embedding; `cwd` sets context, `scope` picks storage, `lifecycle` picks temporary vs permanent |
|
|
382
390
|
| `relate` | Create typed relationship between notes (bidirectional) |
|
|
383
391
|
| `set_project_identity` | Save which git remote defines project identity |
|
|
384
|
-
| `set_project_memory_policy` | Save
|
|
392
|
+
| `set_project_memory_policy` | Save project policy defaults (scope, consolidation mode, protected-branch behavior/patterns) |
|
|
385
393
|
| `sync` | Git sync when remote exists plus embedding backfill always; `force=true` rebuilds all embeddings |
|
|
386
394
|
| `unrelate` | Remove relationship between notes |
|
|
387
395
|
| `update` | Update note content/title/tags/lifecycle, re-embeds always |
|
package/build/config.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type ProjectMemoryPolicy } from "./project-memory-policy.js";
|
|
2
2
|
import type { ProjectIdentityOverride } from "./project.js";
|
|
3
3
|
export type MutationPushMode = "all" | "main-only" | "none";
|
|
4
4
|
export interface MnemonicConfig {
|
package/build/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,OAAO,EAIL,KAAK,mBAAmB,EACzB,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAE5D,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,WAAW,GAAG,MAAM,CAAC;AAE5D,MAAM,WAAW,cAAc;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,uBAAuB,EAAE,MAAM,CAAC;IAChC,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IAC3D,wBAAwB,EAAE,MAAM,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAAC;CACnE;AAkID;;;;GAIG;AACH,wBAAsB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAS/E;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,CAAC,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAWrG;AAED,qBAAa,mBAAmB;IAC9B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAEd,aAAa,EAAE,MAAM;IAI3B,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC;IAI/B,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,GAAG,SAAS,CAAC;IAK7E,0BAA0B,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,GAAG,SAAS,CAAC;IAK3F,gBAAgB,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAM5D,0BAA0B,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC;IAM/F,gBAAgB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAM9C,OAAO;YAgBP,QAAQ;CAGvB"}
|
package/build/config.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import fs from "fs/promises";
|
|
2
2
|
import path from "path";
|
|
3
|
+
import { CONSOLIDATION_MODES, PROJECT_POLICY_SCOPES, PROTECTED_BRANCH_BEHAVIORS, } from "./project-memory-policy.js";
|
|
3
4
|
const defaultConfig = {
|
|
4
5
|
// Keep this at the latest schema version. When adding a new latest-schema
|
|
5
6
|
// migration, bump this value in the same change so fresh installs start at
|
|
@@ -54,6 +55,46 @@ function normalizeProjectIdentityOverrides(value) {
|
|
|
54
55
|
}
|
|
55
56
|
return normalized;
|
|
56
57
|
}
|
|
58
|
+
function normalizeProjectMemoryPolicies(value) {
|
|
59
|
+
if (!value || typeof value !== "object") {
|
|
60
|
+
return {};
|
|
61
|
+
}
|
|
62
|
+
const normalized = {};
|
|
63
|
+
for (const [projectId, policy] of Object.entries(value)) {
|
|
64
|
+
if (!policy || typeof policy !== "object") {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
const policyRecord = policy;
|
|
68
|
+
const normalizedProjectId = typeof policyRecord.projectId === "string" && policyRecord.projectId.trim().length > 0
|
|
69
|
+
? policyRecord.projectId.trim()
|
|
70
|
+
: projectId;
|
|
71
|
+
const defaultScope = PROJECT_POLICY_SCOPES.includes(policyRecord.defaultScope)
|
|
72
|
+
? policyRecord.defaultScope
|
|
73
|
+
: "project";
|
|
74
|
+
const consolidationMode = CONSOLIDATION_MODES.includes(policyRecord.consolidationMode)
|
|
75
|
+
? policyRecord.consolidationMode
|
|
76
|
+
: undefined;
|
|
77
|
+
const protectedBranchBehavior = PROTECTED_BRANCH_BEHAVIORS.includes(policyRecord.protectedBranchBehavior)
|
|
78
|
+
? policyRecord.protectedBranchBehavior
|
|
79
|
+
: undefined;
|
|
80
|
+
const protectedBranchPatterns = Array.isArray(policyRecord.protectedBranchPatterns)
|
|
81
|
+
? policyRecord.protectedBranchPatterns
|
|
82
|
+
.filter((pattern) => typeof pattern === "string")
|
|
83
|
+
.map((pattern) => pattern.trim())
|
|
84
|
+
.filter((pattern) => pattern.length > 0)
|
|
85
|
+
: undefined;
|
|
86
|
+
normalized[projectId] = {
|
|
87
|
+
projectId: normalizedProjectId,
|
|
88
|
+
projectName: typeof policyRecord.projectName === "string" ? policyRecord.projectName : undefined,
|
|
89
|
+
defaultScope,
|
|
90
|
+
consolidationMode,
|
|
91
|
+
protectedBranchPatterns,
|
|
92
|
+
protectedBranchBehavior,
|
|
93
|
+
updatedAt: typeof policyRecord.updatedAt === "string" ? policyRecord.updatedAt : "",
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
return normalized;
|
|
97
|
+
}
|
|
57
98
|
/**
|
|
58
99
|
* Read the schema version from a vault's config.json.
|
|
59
100
|
* Works for both main vault and project vaults.
|
|
@@ -126,7 +167,7 @@ export class MnemonicConfigStore {
|
|
|
126
167
|
schemaVersion: normalizeSchemaVersion(parsed.schemaVersion),
|
|
127
168
|
reindexEmbedConcurrency: normalizeConcurrency(parsed.reindexEmbedConcurrency),
|
|
128
169
|
mutationPushMode: normalizeMutationPushMode(parsed.mutationPushMode),
|
|
129
|
-
projectMemoryPolicies: parsed.projectMemoryPolicies
|
|
170
|
+
projectMemoryPolicies: normalizeProjectMemoryPolicies(parsed.projectMemoryPolicies),
|
|
130
171
|
projectIdentityOverrides: normalizeProjectIdentityOverrides(parsed.projectIdentityOverrides),
|
|
131
172
|
};
|
|
132
173
|
}
|
package/build/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,aAAa,CAAC;AAC7B,OAAO,IAAI,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/build/index.js
CHANGED
|
@@ -11,9 +11,9 @@ import { filterRelationships, mergeRelationshipsFromNotes, normalizeMergePlanSou
|
|
|
11
11
|
import { selectRecallResults } from "./recall.js";
|
|
12
12
|
import { cleanMarkdown } from "./markdown.js";
|
|
13
13
|
import { MnemonicConfigStore, readVaultSchemaVersion } from "./config.js";
|
|
14
|
-
import { CONSOLIDATION_MODES, PROJECT_POLICY_SCOPES, WRITE_SCOPES, resolveConsolidationMode, resolveWriteScope, } from "./project-memory-policy.js";
|
|
14
|
+
import { CONSOLIDATION_MODES, PROTECTED_BRANCH_BEHAVIORS, PROJECT_POLICY_SCOPES, WRITE_SCOPES, isProtectedBranch, resolveProtectedBranchBehavior, resolveProtectedBranchPatterns, resolveConsolidationMode, resolveWriteScope, } from "./project-memory-policy.js";
|
|
15
15
|
import { classifyTheme, summarizePreview, titleCaseTheme } from "./project-introspection.js";
|
|
16
|
-
import { detectProject, resolveProjectIdentity } from "./project.js";
|
|
16
|
+
import { detectProject, getCurrentGitBranch, resolveProjectIdentity } from "./project.js";
|
|
17
17
|
import { VaultManager } from "./vault.js";
|
|
18
18
|
import { Migrator } from "./migration.js";
|
|
19
19
|
import { parseMemorySections } from "./import.js";
|
|
@@ -352,14 +352,6 @@ function formatProjectIdentityText(identity) {
|
|
|
352
352
|
}
|
|
353
353
|
return lines.join("\n");
|
|
354
354
|
}
|
|
355
|
-
async function getProjectPolicyScope(cwd) {
|
|
356
|
-
const project = await resolveProject(cwd);
|
|
357
|
-
if (!project) {
|
|
358
|
-
return undefined;
|
|
359
|
-
}
|
|
360
|
-
const policy = await configStore.getProjectPolicy(project.id);
|
|
361
|
-
return policy?.defaultScope;
|
|
362
|
-
}
|
|
363
355
|
function describeLifecycle(lifecycle) {
|
|
364
356
|
return `lifecycle: ${lifecycle}`;
|
|
365
357
|
}
|
|
@@ -454,6 +446,49 @@ function formatAskForWriteScope(project, unadopted = false) {
|
|
|
454
446
|
"To avoid being asked again: call `set_project_memory_policy` with your preferred scope.",
|
|
455
447
|
].join("\n");
|
|
456
448
|
}
|
|
449
|
+
function formatAskForProtectedBranch(project, branch, patterns) {
|
|
450
|
+
const projectLabel = project ? `${project.name} (${project.id})` : "this context";
|
|
451
|
+
return [
|
|
452
|
+
`Protected branch check for ${projectLabel}: current branch \`${branch}\` matches ${patterns.join(", ")}.`,
|
|
453
|
+
"Choose how to proceed:",
|
|
454
|
+
"- One-time override: call `remember` again with `allowProtectedBranch: true`",
|
|
455
|
+
"- Persist policy: call `set_project_memory_policy` with `protectedBranchBehavior: \"block\"`",
|
|
456
|
+
"- Persist policy: call `set_project_memory_policy` with `protectedBranchBehavior: \"allow\"`",
|
|
457
|
+
"",
|
|
458
|
+
"Optional: set `protectedBranchPatterns` to customize which branches are protected.",
|
|
459
|
+
].join("\n");
|
|
460
|
+
}
|
|
461
|
+
function formatProtectedBranchBlocked(project, branch, patterns) {
|
|
462
|
+
const projectLabel = project ? `${project.name} (${project.id})` : "this context";
|
|
463
|
+
return [
|
|
464
|
+
`Auto-commit blocked for ${projectLabel}: current branch \`${branch}\` matches protected patterns ${patterns.join(", ")}.`,
|
|
465
|
+
"Policy is set to `protectedBranchBehavior: \"block\"`.",
|
|
466
|
+
"To proceed once, call `remember` again with `allowProtectedBranch: true`.",
|
|
467
|
+
"To change the default, call `set_project_memory_policy` with `protectedBranchBehavior: \"allow\"`.",
|
|
468
|
+
].join("\n");
|
|
469
|
+
}
|
|
470
|
+
async function shouldBlockProtectedBranchCommit(options) {
|
|
471
|
+
const { cwd, writeScope, automaticCommit, project, policy, allowProtectedBranch } = options;
|
|
472
|
+
if (!cwd || writeScope !== "project" || !automaticCommit) {
|
|
473
|
+
return { blocked: false };
|
|
474
|
+
}
|
|
475
|
+
const branch = await getCurrentGitBranch(cwd);
|
|
476
|
+
if (!branch) {
|
|
477
|
+
return { blocked: false };
|
|
478
|
+
}
|
|
479
|
+
const patterns = resolveProtectedBranchPatterns(policy);
|
|
480
|
+
if (!isProtectedBranch(branch, patterns) || allowProtectedBranch) {
|
|
481
|
+
return { blocked: false };
|
|
482
|
+
}
|
|
483
|
+
const behavior = resolveProtectedBranchBehavior(policy);
|
|
484
|
+
if (behavior === "allow") {
|
|
485
|
+
return { blocked: false };
|
|
486
|
+
}
|
|
487
|
+
const message = behavior === "block"
|
|
488
|
+
? formatProtectedBranchBlocked(project, branch, patterns)
|
|
489
|
+
: formatAskForProtectedBranch(project, branch, patterns);
|
|
490
|
+
return { blocked: true, message };
|
|
491
|
+
}
|
|
457
492
|
async function embedMissingNotes(storage, noteIds, force = false) {
|
|
458
493
|
const notes = noteIds
|
|
459
494
|
? (await Promise.all(noteIds.map((id) => storage.readNote(id)))).filter(Boolean)
|
|
@@ -1056,7 +1091,9 @@ server.registerTool("remember", {
|
|
|
1056
1091
|
"- Multiple related notes have accumulated — use `consolidate` to merge them\n\n" +
|
|
1057
1092
|
"After storing: consider whether this note relates to any note you recalled earlier in this session. " +
|
|
1058
1093
|
"If so, call `relate` to link them while you still have context.\n\n" +
|
|
1059
|
-
"Side effects: writes note + embedding files, git commits.
|
|
1094
|
+
"Side effects: writes note + embedding files, git commits. " +
|
|
1095
|
+
"When project-vault writes target protected branches, policy may ask or block before writing. " +
|
|
1096
|
+
"Returns persistence status.",
|
|
1060
1097
|
annotations: {
|
|
1061
1098
|
readOnlyHint: false,
|
|
1062
1099
|
destructiveHint: false,
|
|
@@ -1081,18 +1118,35 @@ server.registerTool("remember", {
|
|
|
1081
1118
|
.optional()
|
|
1082
1119
|
.describe("Where to store: 'project' = shared project vault (.mnemonic/), " +
|
|
1083
1120
|
"'global' = private main vault. When omitted, uses the project's saved policy or defaults to 'project'."),
|
|
1121
|
+
allowProtectedBranch: z
|
|
1122
|
+
.boolean()
|
|
1123
|
+
.optional()
|
|
1124
|
+
.describe("One-time override for protected branch checks. " +
|
|
1125
|
+
"When true, remember can commit on a protected branch without changing project policy."),
|
|
1084
1126
|
}),
|
|
1085
1127
|
outputSchema: RememberResultSchema,
|
|
1086
|
-
}, async ({ title, content, tags, lifecycle, summary, cwd, scope }) => {
|
|
1128
|
+
}, async ({ title, content, tags, lifecycle, summary, cwd, scope, allowProtectedBranch = false }) => {
|
|
1087
1129
|
const project = await resolveProject(cwd);
|
|
1088
1130
|
const cleanedContent = await cleanMarkdown(content);
|
|
1089
|
-
const
|
|
1131
|
+
const policy = project ? await configStore.getProjectPolicy(project.id) : undefined;
|
|
1132
|
+
const policyScope = policy?.defaultScope;
|
|
1090
1133
|
const projectVaultExists = cwd ? Boolean(await vaultManager.getProjectVaultIfExists(cwd)) : true;
|
|
1091
1134
|
const writeScope = resolveWriteScope(scope, policyScope, Boolean(project), projectVaultExists);
|
|
1092
1135
|
if (writeScope === "ask") {
|
|
1093
1136
|
const unadopted = !projectVaultExists && !policyScope;
|
|
1094
1137
|
return { content: [{ type: "text", text: formatAskForWriteScope(project, unadopted) }], isError: true };
|
|
1095
1138
|
}
|
|
1139
|
+
const protectedBranchCheck = await shouldBlockProtectedBranchCommit({
|
|
1140
|
+
cwd,
|
|
1141
|
+
writeScope,
|
|
1142
|
+
automaticCommit: scope === undefined,
|
|
1143
|
+
project,
|
|
1144
|
+
policy,
|
|
1145
|
+
allowProtectedBranch,
|
|
1146
|
+
});
|
|
1147
|
+
if (protectedBranchCheck.blocked) {
|
|
1148
|
+
return { content: [{ type: "text", text: protectedBranchCheck.message ?? "Protected branch policy blocked this commit." }], isError: true };
|
|
1149
|
+
}
|
|
1096
1150
|
const vault = await resolveWriteVault(cwd, writeScope);
|
|
1097
1151
|
const id = makeId(title);
|
|
1098
1152
|
const now = new Date().toISOString();
|
|
@@ -1158,10 +1212,11 @@ server.registerTool("remember", {
|
|
|
1158
1212
|
// ── set_project_memory_policy ─────────────────────────────────────────────────
|
|
1159
1213
|
server.registerTool("set_project_memory_policy", {
|
|
1160
1214
|
title: "Set Project Memory Policy",
|
|
1161
|
-
description: "Set the default write scope
|
|
1215
|
+
description: "Set the default write scope, consolidation mode, and protected-branch behavior for a project.\n\n" +
|
|
1162
1216
|
"Use this when:\n" +
|
|
1163
1217
|
"- The user wants all memories for a project to go to a specific vault by default\n" +
|
|
1164
|
-
"- The current 'ask' behavior is inconvenient and should be automated\n
|
|
1218
|
+
"- The current 'ask' behavior is inconvenient and should be automated\n" +
|
|
1219
|
+
"- Protected branches should prompt, block, or allow project-vault commits by default\n\n" +
|
|
1165
1220
|
"Do not use this when:\n" +
|
|
1166
1221
|
"- You just need to store a single memory with a specific scope — pass `scope` to `remember` instead\n\n" +
|
|
1167
1222
|
"Side effects: writes to main vault config.json, git commits and pushes.",
|
|
@@ -1173,42 +1228,79 @@ server.registerTool("set_project_memory_policy", {
|
|
|
1173
1228
|
},
|
|
1174
1229
|
inputSchema: z.object({
|
|
1175
1230
|
cwd: z.string().describe("Absolute path to the project working directory"),
|
|
1176
|
-
defaultScope: z.enum(PROJECT_POLICY_SCOPES).describe("Default storage: 'project' = shared .mnemonic/ vault, 'global' = private main vault, 'ask' = prompt each time"),
|
|
1231
|
+
defaultScope: z.enum(PROJECT_POLICY_SCOPES).optional().describe("Default storage: 'project' = shared .mnemonic/ vault, 'global' = private main vault, 'ask' = prompt each time"),
|
|
1177
1232
|
consolidationMode: z.enum(CONSOLIDATION_MODES).optional().describe("Default consolidation mode: 'supersedes' preserves history (default), 'delete' removes sources immediately"),
|
|
1233
|
+
protectedBranchBehavior: z.enum(PROTECTED_BRANCH_BEHAVIORS).optional().describe("Behavior for protected-branch matches during project-vault remember writes: 'ask', 'block', or 'allow'"),
|
|
1234
|
+
protectedBranchPatterns: z.array(z.string()).optional().describe("Protected branch glob patterns. Defaults to [\"main\", \"master\", \"release*\"] when not set"),
|
|
1178
1235
|
}),
|
|
1179
1236
|
outputSchema: PolicyResultSchema,
|
|
1180
|
-
}, async ({ cwd, defaultScope, consolidationMode }) => {
|
|
1237
|
+
}, async ({ cwd, defaultScope, consolidationMode, protectedBranchBehavior, protectedBranchPatterns }) => {
|
|
1181
1238
|
const project = await resolveProject(cwd);
|
|
1182
1239
|
if (!project) {
|
|
1183
1240
|
return { content: [{ type: "text", text: `Could not detect a project for: ${cwd}` }], isError: true };
|
|
1184
1241
|
}
|
|
1242
|
+
if (defaultScope === undefined
|
|
1243
|
+
&& consolidationMode === undefined
|
|
1244
|
+
&& protectedBranchBehavior === undefined
|
|
1245
|
+
&& protectedBranchPatterns === undefined) {
|
|
1246
|
+
return {
|
|
1247
|
+
content: [{
|
|
1248
|
+
type: "text",
|
|
1249
|
+
text: "No policy fields provided. Set at least one of: defaultScope, consolidationMode, protectedBranchBehavior, protectedBranchPatterns.",
|
|
1250
|
+
}],
|
|
1251
|
+
isError: true,
|
|
1252
|
+
};
|
|
1253
|
+
}
|
|
1254
|
+
const existing = await configStore.getProjectPolicy(project.id);
|
|
1255
|
+
const effectiveDefaultScope = defaultScope ?? existing?.defaultScope ?? "project";
|
|
1256
|
+
const effectiveConsolidationMode = consolidationMode ?? existing?.consolidationMode;
|
|
1257
|
+
const effectiveProtectedBranchBehavior = protectedBranchBehavior ?? existing?.protectedBranchBehavior;
|
|
1258
|
+
const effectiveProtectedBranchPatterns = protectedBranchPatterns
|
|
1259
|
+
? protectedBranchPatterns.map((pattern) => pattern.trim()).filter((pattern) => pattern.length > 0)
|
|
1260
|
+
: existing?.protectedBranchPatterns;
|
|
1185
1261
|
const now = new Date().toISOString();
|
|
1186
1262
|
const policy = {
|
|
1187
1263
|
projectId: project.id,
|
|
1188
1264
|
projectName: project.name,
|
|
1189
|
-
defaultScope,
|
|
1190
|
-
consolidationMode,
|
|
1265
|
+
defaultScope: effectiveDefaultScope,
|
|
1266
|
+
consolidationMode: effectiveConsolidationMode,
|
|
1267
|
+
protectedBranchBehavior: effectiveProtectedBranchBehavior,
|
|
1268
|
+
protectedBranchPatterns: effectiveProtectedBranchPatterns,
|
|
1191
1269
|
updatedAt: now,
|
|
1192
1270
|
};
|
|
1193
1271
|
await configStore.setProjectPolicy(policy);
|
|
1194
|
-
const modeStr =
|
|
1272
|
+
const modeStr = effectiveConsolidationMode ? `, consolidationMode=${effectiveConsolidationMode}` : "";
|
|
1273
|
+
const branchBehaviorStr = effectiveProtectedBranchBehavior
|
|
1274
|
+
? `, protectedBranchBehavior=${effectiveProtectedBranchBehavior}`
|
|
1275
|
+
: "";
|
|
1276
|
+
const branchPatternsStr = effectiveProtectedBranchPatterns && effectiveProtectedBranchPatterns.length > 0
|
|
1277
|
+
? `, protectedBranchPatterns=${effectiveProtectedBranchPatterns.join("|")}`
|
|
1278
|
+
: "";
|
|
1195
1279
|
const commitBody = formatCommitBody({
|
|
1196
1280
|
projectName: project.name,
|
|
1197
|
-
description: `Default scope: ${
|
|
1281
|
+
description: `Default scope: ${effectiveDefaultScope}` +
|
|
1282
|
+
`${effectiveConsolidationMode ? `\nConsolidation mode: ${effectiveConsolidationMode}` : ""}` +
|
|
1283
|
+
`${effectiveProtectedBranchBehavior ? `\nProtected branch behavior: ${effectiveProtectedBranchBehavior}` : ""}` +
|
|
1284
|
+
`${effectiveProtectedBranchPatterns && effectiveProtectedBranchPatterns.length > 0
|
|
1285
|
+
? `\nProtected branch patterns: ${effectiveProtectedBranchPatterns.join(", ")}`
|
|
1286
|
+
: ""}`,
|
|
1198
1287
|
});
|
|
1199
|
-
await vaultManager.main.git.commit(`policy: ${project.name} default scope ${
|
|
1288
|
+
await vaultManager.main.git.commit(`policy: ${project.name} default scope ${effectiveDefaultScope}`, ["config.json"], commitBody);
|
|
1200
1289
|
await pushAfterMutation(vaultManager.main);
|
|
1201
1290
|
const structuredContent = {
|
|
1202
1291
|
action: "policy_set",
|
|
1203
1292
|
project: { id: project.id, name: project.name },
|
|
1204
|
-
defaultScope,
|
|
1205
|
-
consolidationMode,
|
|
1293
|
+
defaultScope: effectiveDefaultScope,
|
|
1294
|
+
consolidationMode: effectiveConsolidationMode,
|
|
1295
|
+
protectedBranchBehavior: effectiveProtectedBranchBehavior,
|
|
1296
|
+
protectedBranchPatterns: effectiveProtectedBranchPatterns,
|
|
1206
1297
|
timestamp: now,
|
|
1207
1298
|
};
|
|
1208
1299
|
return {
|
|
1209
1300
|
content: [{
|
|
1210
1301
|
type: "text",
|
|
1211
|
-
text: `Project memory policy set for ${project.name}: defaultScope=${
|
|
1302
|
+
text: `Project memory policy set for ${project.name}: defaultScope=${effectiveDefaultScope}` +
|
|
1303
|
+
`${modeStr}${branchBehaviorStr}${branchPatternsStr}`,
|
|
1212
1304
|
}],
|
|
1213
1305
|
structuredContent,
|
|
1214
1306
|
};
|
|
@@ -1216,7 +1308,7 @@ server.registerTool("set_project_memory_policy", {
|
|
|
1216
1308
|
// ── get_project_memory_policy ─────────────────────────────────────────────────
|
|
1217
1309
|
server.registerTool("get_project_memory_policy", {
|
|
1218
1310
|
title: "Get Project Memory Policy",
|
|
1219
|
-
description: "Show the saved default write scope
|
|
1311
|
+
description: "Show the saved default write scope, consolidation mode, and protected-branch settings for a project.\n\n" +
|
|
1220
1312
|
"Use this when:\n" +
|
|
1221
1313
|
"- Checking what the current storage default is before changing it\n" +
|
|
1222
1314
|
"- Debugging why memories are landing in an unexpected vault\n\n" +
|
|
@@ -1254,12 +1346,22 @@ server.registerTool("get_project_memory_policy", {
|
|
|
1254
1346
|
project: { id: project.id, name: project.name },
|
|
1255
1347
|
defaultScope: policy.defaultScope,
|
|
1256
1348
|
consolidationMode: policy.consolidationMode,
|
|
1349
|
+
protectedBranchBehavior: policy.protectedBranchBehavior,
|
|
1350
|
+
protectedBranchPatterns: policy.protectedBranchPatterns,
|
|
1257
1351
|
updatedAt: policy.updatedAt,
|
|
1258
1352
|
};
|
|
1353
|
+
const details = [
|
|
1354
|
+
`defaultScope=${policy.defaultScope}`,
|
|
1355
|
+
policy.consolidationMode ? `consolidationMode=${policy.consolidationMode}` : undefined,
|
|
1356
|
+
policy.protectedBranchBehavior ? `protectedBranchBehavior=${policy.protectedBranchBehavior}` : undefined,
|
|
1357
|
+
policy.protectedBranchPatterns && policy.protectedBranchPatterns.length > 0
|
|
1358
|
+
? `protectedBranchPatterns=${policy.protectedBranchPatterns.join("|")}`
|
|
1359
|
+
: undefined,
|
|
1360
|
+
].filter(Boolean).join(", ");
|
|
1259
1361
|
return {
|
|
1260
1362
|
content: [{
|
|
1261
1363
|
type: "text",
|
|
1262
|
-
text: `Project memory policy for ${project.name}:
|
|
1364
|
+
text: `Project memory policy for ${project.name}: ${details} (updated ${policy.updatedAt})`,
|
|
1263
1365
|
}],
|
|
1264
1366
|
structuredContent,
|
|
1265
1367
|
};
|