@pcircle/memesh 4.10.1 → 4.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/AGENTS.md +44 -13
- package/README.de.md +3 -3
- package/README.md +3 -3
- package/README.zh-TW.md +3 -3
- package/dashboard/dist/index.html +1 -1
- package/dist/core/agent-message-inbox.d.ts +6 -0
- package/dist/core/agent-message-inbox.d.ts.map +1 -1
- package/dist/core/agent-message-inbox.js +28 -1
- package/dist/core/agent-message-inbox.js.map +1 -1
- package/dist/core/briefing-level.d.ts +22 -0
- package/dist/core/briefing-level.d.ts.map +1 -0
- package/dist/core/briefing-level.js +75 -0
- package/dist/core/briefing-level.js.map +1 -0
- package/dist/core/briefing.d.ts +3 -0
- package/dist/core/briefing.d.ts.map +1 -1
- package/dist/core/briefing.js +33 -11
- package/dist/core/briefing.js.map +1 -1
- package/dist/core/capture-liveness.d.ts +1 -0
- package/dist/core/capture-liveness.d.ts.map +1 -1
- package/dist/core/capture-liveness.js +1 -0
- package/dist/core/capture-liveness.js.map +1 -1
- package/dist/core/config.d.ts +1 -0
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +3 -1
- package/dist/core/config.js.map +1 -1
- package/dist/core/paths.d.ts +1 -0
- package/dist/core/paths.d.ts.map +1 -1
- package/dist/core/paths.js +4 -0
- package/dist/core/paths.js.map +1 -1
- package/dist/core/schema-export.d.ts.map +1 -1
- package/dist/core/schema-export.js +5 -1
- package/dist/core/schema-export.js.map +1 -1
- package/dist/core/serializer.d.ts +2 -0
- package/dist/core/serializer.d.ts.map +1 -1
- package/dist/core/serializer.js +119 -6
- package/dist/core/serializer.js.map +1 -1
- package/dist/core/task-state.d.ts +5 -0
- package/dist/core/task-state.d.ts.map +1 -1
- package/dist/core/task-state.js +70 -0
- package/dist/core/task-state.js.map +1 -1
- package/dist/core/types.d.ts +2 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/work-topology.d.ts +1 -0
- package/dist/core/work-topology.d.ts.map +1 -1
- package/dist/core/work-topology.js +3 -0
- package/dist/core/work-topology.js.map +1 -1
- package/dist/mcp/THIRD_PARTY_NOTICES.txt +2 -2
- package/dist/mcp/server.js +448 -121
- package/dist/mcp/server.js.map +3 -3
- package/dist/skills-manifest.json +29 -24
- package/dist/storage/fts-index.d.ts +1 -0
- package/dist/storage/fts-index.d.ts.map +1 -1
- package/dist/storage/fts-index.js +5 -0
- package/dist/storage/fts-index.js.map +1 -1
- package/dist/transports/cli/cli.d.ts.map +1 -1
- package/dist/transports/cli/cli.js +348 -53
- package/dist/transports/cli/cli.js.map +3 -3
- package/dist/transports/http/server.d.ts.map +1 -1
- package/dist/transports/http/server.js +10 -1
- package/dist/transports/http/server.js.map +1 -1
- package/dist/transports/mcp/handlers.d.ts +7 -3
- package/dist/transports/mcp/handlers.d.ts.map +1 -1
- package/dist/transports/mcp/handlers.js +7 -3
- package/dist/transports/mcp/handlers.js.map +1 -1
- package/dist/transports/schemas.d.ts +1 -0
- package/dist/transports/schemas.d.ts.map +1 -1
- package/dist/transports/schemas.js +1 -0
- package/dist/transports/schemas.js.map +1 -1
- package/docs/platforms/agent-messaging.md +17 -3
- package/package.json +4 -9
- package/scripts/hooks/_generated/agent-message-inbox.js +28 -1
- package/scripts/hooks/_generated/briefing-level.js +82 -0
- package/scripts/hooks/_generated/capture-liveness.js +1 -0
- package/scripts/hooks/_generated/core-paths.js +4 -0
- package/scripts/hooks/_generated/fts-index.js +5 -0
- package/scripts/hooks/_generated/task-state.js +70 -0
- package/scripts/hooks/_generated/work-topology.js +3 -0
- package/scripts/hooks/_shared.js +623 -15
- package/scripts/hooks/pre-edit-recall.js +386 -65
- package/scripts/hooks/session-start.js +261 -77
- package/scripts/hooks/user-prompt-intent.js +38 -6
- package/scripts/upgrade-plugin.sh +3 -4
- package/skills/memesh/SKILL.md +26 -16
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// AUTO-GENERATED from src/core/briefing-level.ts — DO NOT EDIT BY HAND.
|
|
3
|
+
// Regenerate with: npm run build (scripts/generate-hook-core.mjs)
|
|
4
|
+
//
|
|
5
|
+
// Claude Code hooks import this committed copy instead of dist/, so the
|
|
6
|
+
// always-on capture path survives a missing or stale dist/ while staying
|
|
7
|
+
// byte-locked to core — eliminating the hand-mirror drift behind the P0 FTS bug.
|
|
8
|
+
// ============================================================================
|
|
9
|
+
export const BRIEFING_LEVELS = ['minimal', 'standard', 'full'];
|
|
10
|
+
export const DEFAULT_BRIEFING_LEVEL = 'standard';
|
|
11
|
+
export function isBriefingLevel(value) {
|
|
12
|
+
return typeof value === 'string' && BRIEFING_LEVELS.includes(value);
|
|
13
|
+
}
|
|
14
|
+
const INVALID_VALUE_SERIALIZED_MAX = 100;
|
|
15
|
+
const PRE_SLICE_RAW_MAX = 256;
|
|
16
|
+
function safeRawPreSlice(value, maxUnits) {
|
|
17
|
+
if (value.length <= maxUnits)
|
|
18
|
+
return value;
|
|
19
|
+
let end = maxUnits;
|
|
20
|
+
const lastKept = value.charCodeAt(end - 1);
|
|
21
|
+
const nextUnit = value.charCodeAt(end);
|
|
22
|
+
const lastKeptIsHighSurrogate = lastKept >= 0xd800 && lastKept <= 0xdbff;
|
|
23
|
+
const nextUnitIsLowSurrogate = nextUnit >= 0xdc00 && nextUnit <= 0xdfff;
|
|
24
|
+
if (lastKeptIsHighSurrogate && nextUnitIsLowSurrogate)
|
|
25
|
+
end -= 1;
|
|
26
|
+
return value.slice(0, end);
|
|
27
|
+
}
|
|
28
|
+
function truncateToSerializedBound(codePoints) {
|
|
29
|
+
let kept = 0;
|
|
30
|
+
for (; kept < codePoints.length; kept++) {
|
|
31
|
+
const candidate = JSON.stringify(`${codePoints.slice(0, kept + 1).join('')}…`);
|
|
32
|
+
if (candidate.length > INVALID_VALUE_SERIALIZED_MAX)
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
return JSON.stringify(`${codePoints.slice(0, kept).join('')}…`);
|
|
36
|
+
}
|
|
37
|
+
function describeInvalidValue(value) {
|
|
38
|
+
if (typeof value === 'string') {
|
|
39
|
+
if (value.length <= INVALID_VALUE_SERIALIZED_MAX) {
|
|
40
|
+
const whole = JSON.stringify(value);
|
|
41
|
+
if (whole.length <= INVALID_VALUE_SERIALIZED_MAX)
|
|
42
|
+
return whole;
|
|
43
|
+
return truncateToSerializedBound(Array.from(value));
|
|
44
|
+
}
|
|
45
|
+
return truncateToSerializedBound(Array.from(safeRawPreSlice(value, PRE_SLICE_RAW_MAX)));
|
|
46
|
+
}
|
|
47
|
+
if (Array.isArray(value))
|
|
48
|
+
return '[array]';
|
|
49
|
+
if (value !== null && typeof value === 'object')
|
|
50
|
+
return '[object]';
|
|
51
|
+
if (typeof value === 'bigint')
|
|
52
|
+
return '[bigint]';
|
|
53
|
+
if (typeof value === 'symbol')
|
|
54
|
+
return '[symbol]';
|
|
55
|
+
if (typeof value === 'function')
|
|
56
|
+
return '[function]';
|
|
57
|
+
return JSON.stringify(value) ?? String(value);
|
|
58
|
+
}
|
|
59
|
+
export function resolveBriefingLevel(envValue, configValue) {
|
|
60
|
+
if (envValue !== undefined) {
|
|
61
|
+
if (isBriefingLevel(envValue))
|
|
62
|
+
return { level: envValue, invalid: null };
|
|
63
|
+
return { level: DEFAULT_BRIEFING_LEVEL, invalid: { source: 'env', value: describeInvalidValue(envValue) } };
|
|
64
|
+
}
|
|
65
|
+
if (configValue !== undefined) {
|
|
66
|
+
if (isBriefingLevel(configValue))
|
|
67
|
+
return { level: configValue, invalid: null };
|
|
68
|
+
return { level: DEFAULT_BRIEFING_LEVEL, invalid: { source: 'config', value: describeInvalidValue(configValue) } };
|
|
69
|
+
}
|
|
70
|
+
return { level: DEFAULT_BRIEFING_LEVEL, invalid: null };
|
|
71
|
+
}
|
|
72
|
+
const POLICIES = {
|
|
73
|
+
minimal: { global: false, foreign: false, taskState: false, index: false, workPackageNotice: false },
|
|
74
|
+
standard: { global: false, foreign: false, taskState: true, index: true, workPackageNotice: false },
|
|
75
|
+
full: { global: true, foreign: true, taskState: true, index: true, workPackageNotice: true },
|
|
76
|
+
};
|
|
77
|
+
export function briefingLevelPolicy(level) {
|
|
78
|
+
return POLICIES[level];
|
|
79
|
+
}
|
|
80
|
+
export function sessionStartAppendsWorkPackageNotice(level) {
|
|
81
|
+
return briefingLevelPolicy(level).workPackageNotice;
|
|
82
|
+
}
|
|
@@ -130,6 +130,7 @@ export const SKIP_REASONS = {
|
|
|
130
130
|
noFilePath: 'no file_path in the tool input',
|
|
131
131
|
noDatabaseForRecall: 'no database yet — nothing to recall',
|
|
132
132
|
nothingToRecall: 'no guard matched and nothing to recall for this file',
|
|
133
|
+
candidateWindowTruncated: 'more candidates may exist than the search window examined',
|
|
133
134
|
noPromptIntent: 'the prompt carried no remember intent and no update decision',
|
|
134
135
|
noMemoryDir: 'no Claude Code memory directory for this project',
|
|
135
136
|
noNoteChanged: 'no note file changed since the last ingestion',
|
|
@@ -100,6 +100,10 @@ function tryGit(cwd, args) {
|
|
|
100
100
|
return null;
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
|
+
export function gitRepoRoot(cwdInput) {
|
|
104
|
+
const cwd = cwdInput && cwdInput.length > 0 ? cwdInput : process.cwd();
|
|
105
|
+
return tryGit(cwd, ['rev-parse', '--show-toplevel']);
|
|
106
|
+
}
|
|
103
107
|
export function canonicalRemoteLocator(remote) {
|
|
104
108
|
const value = remote.trim();
|
|
105
109
|
if (!value)
|
|
@@ -62,6 +62,11 @@ const LONE_UNSPACED_CHAR = new RegExp(`[${UNSPACED_SCRIPT_CLASS}]`, 'u');
|
|
|
62
62
|
export function isLoneUnspacedChar(term) {
|
|
63
63
|
return [...term].length === 1 && LONE_UNSPACED_CHAR.test(term);
|
|
64
64
|
}
|
|
65
|
+
export function renderPhraseExpression(terms) {
|
|
66
|
+
if (terms.length === 0)
|
|
67
|
+
return null;
|
|
68
|
+
return `"${terms.map((term) => term.replace(/"/g, '""')).join(' ')}"`;
|
|
69
|
+
}
|
|
65
70
|
function foldTitleIntoObservations(title, observationsText) {
|
|
66
71
|
return title ? `${title} ${observationsText}` : observationsText;
|
|
67
72
|
}
|
|
@@ -96,3 +96,73 @@ export function taskStateLines(state, project, now = new Date()) {
|
|
|
96
96
|
}
|
|
97
97
|
return lines;
|
|
98
98
|
}
|
|
99
|
+
export const STALE_TASK_STATE_HOURS = 72;
|
|
100
|
+
export const CLOCK_SKEW_ALLOWANCE_MINUTES = 5;
|
|
101
|
+
const ZONED_INSTANT = /^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})[Tt](?<hour>\d{2}):(?<minute>\d{2})(?::(?<second>\d{2})(?:\.\d+)?)?(?:(?<zulu>[Zz])|(?<offSign>[+-])(?<offHour>\d{2}):?(?<offMinute>\d{2}))$/;
|
|
102
|
+
function isLeapYear(year) {
|
|
103
|
+
return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
|
|
104
|
+
}
|
|
105
|
+
const DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
106
|
+
function daysInMonth(year, month) {
|
|
107
|
+
return month === 2 && isLeapYear(year) ? 29 : DAYS_IN_MONTH[month - 1];
|
|
108
|
+
}
|
|
109
|
+
function isRealInstant(groups) {
|
|
110
|
+
const year = Number(groups.year);
|
|
111
|
+
const month = Number(groups.month);
|
|
112
|
+
const day = Number(groups.day);
|
|
113
|
+
const hour = Number(groups.hour);
|
|
114
|
+
const minute = Number(groups.minute);
|
|
115
|
+
const second = groups.second === undefined ? 0 : Number(groups.second);
|
|
116
|
+
if (month < 1 || month > 12)
|
|
117
|
+
return false;
|
|
118
|
+
if (day < 1 || day > daysInMonth(year, month))
|
|
119
|
+
return false;
|
|
120
|
+
if (hour > 23)
|
|
121
|
+
return false;
|
|
122
|
+
if (minute > 59)
|
|
123
|
+
return false;
|
|
124
|
+
if (second > 59)
|
|
125
|
+
return false;
|
|
126
|
+
if (groups.zulu === undefined) {
|
|
127
|
+
const offHour = Number(groups.offHour);
|
|
128
|
+
const offMinute = Number(groups.offMinute);
|
|
129
|
+
if (offHour > 23 || offMinute > 59)
|
|
130
|
+
return false;
|
|
131
|
+
if (groups.offSign === '-' && offHour === 0 && offMinute === 0)
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
136
|
+
function resolveTaskStateAge(updatedAt, now) {
|
|
137
|
+
if (!updatedAt)
|
|
138
|
+
return { known: false };
|
|
139
|
+
const match = ZONED_INSTANT.exec(updatedAt);
|
|
140
|
+
if (!match?.groups || !isRealInstant(match.groups))
|
|
141
|
+
return { known: false };
|
|
142
|
+
const then = Date.parse(updatedAt);
|
|
143
|
+
if (Number.isNaN(then))
|
|
144
|
+
return { known: false };
|
|
145
|
+
const hours = (now.getTime() - then) / 3_600_000;
|
|
146
|
+
if (hours < -(CLOCK_SKEW_ALLOWANCE_MINUTES / 60))
|
|
147
|
+
return { known: false };
|
|
148
|
+
return { known: true, hours: Math.max(0, hours) };
|
|
149
|
+
}
|
|
150
|
+
function staleTaskStateLine(project, hours) {
|
|
151
|
+
const days = Math.floor(hours / 24);
|
|
152
|
+
const age = days >= 1 ? `${days} day${days === 1 ? '' : 's'} ago` : `${Math.floor(hours)} hour${Math.floor(hours) === 1 ? '' : 's'} ago`;
|
|
153
|
+
return `Task state for "${project}" was last stated ${age} — older than ${STALE_TASK_STATE_HOURS}h, so it is not shown as current. Run \`memesh task\` to see or update it.`;
|
|
154
|
+
}
|
|
155
|
+
function taskStateAgeUnknownLine(project) {
|
|
156
|
+
return `Task state for "${project}" has a missing, unreadable, or future-dated timestamp, so its age could not be established — not shown as current. Run \`memesh task\` to see or update it.`;
|
|
157
|
+
}
|
|
158
|
+
export function briefingTaskStateLines(state, project, now = new Date(), { includeFresh = true } = {}) {
|
|
159
|
+
if (isEmptyTaskState(state))
|
|
160
|
+
return [];
|
|
161
|
+
const age = resolveTaskStateAge(state.updated_at, now);
|
|
162
|
+
if (!age.known)
|
|
163
|
+
return [taskStateAgeUnknownLine(project)];
|
|
164
|
+
if (age.hours > STALE_TASK_STATE_HOURS) {
|
|
165
|
+
return [staleTaskStateLine(project, age.hours)];
|
|
166
|
+
}
|
|
167
|
+
return includeFresh ? taskStateLines(state, project, now) : [];
|
|
168
|
+
}
|
|
@@ -200,6 +200,9 @@ export function assembleTopologyBlock(stateLines, pools, projectName, budget = D
|
|
|
200
200
|
lines.push(...globalLines);
|
|
201
201
|
return lines;
|
|
202
202
|
}
|
|
203
|
+
export function hasBriefingContent(lines) {
|
|
204
|
+
return lines.length > 0;
|
|
205
|
+
}
|
|
203
206
|
export function buildReferenceContext(memoryLines) {
|
|
204
207
|
const safeLines = memoryLines.map((line) => String(line ?? '')
|
|
205
208
|
.replace(/[\s\u0085\u001c-\u001e]+/g, ' ')
|