@ryuenn3123/agentic-senior-core 2.0.26 → 2.5.3

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.
@@ -56,6 +56,10 @@ import {
56
56
  normalizeAgentName,
57
57
  writeTokenOptimizationState,
58
58
  } from '../token-optimization.mjs';
59
+ import {
60
+ createMemoryContinuityState,
61
+ writeMemoryContinuityState,
62
+ } from '../memory-continuity.mjs';
59
63
  import { evaluateSkillDomainCompatibility } from '../compatibility.mjs';
60
64
 
61
65
  export { REPO_ROOT } from '../constants.mjs';
@@ -71,6 +75,7 @@ export function parseInitArguments(commandArguments) {
71
75
  ci: undefined,
72
76
  newbie: false,
73
77
  tokenOptimize: true,
78
+ memoryContinuity: true,
74
79
  tokenAgent: 'copilot',
75
80
  includeMcpTemplate: false,
76
81
  scaffoldDocs: undefined,
@@ -166,6 +171,11 @@ export function parseInitArguments(commandArguments) {
166
171
  continue;
167
172
  }
168
173
 
174
+ if (currentArgument === '--memory-continuity') {
175
+ parsedInitOptions.memoryContinuity = true;
176
+ continue;
177
+ }
178
+
169
179
  if (currentArgument === '--token-agent') {
170
180
  parsedInitOptions.tokenAgent = commandArguments[argumentIndex + 1] || 'copilot';
171
181
  argumentIndex += 1;
@@ -182,6 +192,11 @@ export function parseInitArguments(commandArguments) {
182
192
  continue;
183
193
  }
184
194
 
195
+ if (currentArgument === '--no-memory-continuity') {
196
+ parsedInitOptions.memoryContinuity = false;
197
+ continue;
198
+ }
199
+
185
200
  if (currentArgument === '--mcp-template') {
186
201
  parsedInitOptions.includeMcpTemplate = true;
187
202
  continue;
@@ -408,6 +423,9 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
408
423
  const isTokenOptimizationEnabled = typeof initOptions.tokenOptimize === 'boolean'
409
424
  ? initOptions.tokenOptimize
410
425
  : true;
426
+ const isMemoryContinuityEnabled = typeof initOptions.memoryContinuity === 'boolean'
427
+ ? initOptions.memoryContinuity
428
+ : true;
411
429
  const shouldIncludeMcpTemplate = initOptions.includeMcpTemplate === true;
412
430
  const selectedTokenAgentName = normalizeAgentName(initOptions.tokenAgent || 'copilot');
413
431
  const isInteractiveSession = Boolean(stdin.isTTY && stdout.isTTY);
@@ -729,9 +747,20 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
729
747
  includeMcpTemplate: shouldIncludeMcpTemplate,
730
748
  });
731
749
 
750
+ let memoryContinuityState = null;
751
+ if (isMemoryContinuityEnabled) {
752
+ memoryContinuityState = createMemoryContinuityState({
753
+ isEnabled: true,
754
+ });
755
+
756
+ await writeMemoryContinuityState(resolvedTargetDirectoryPath, memoryContinuityState);
757
+ console.log(`Memory continuity policy enabled (${memoryContinuityState.hydrationMode}).`);
758
+ }
759
+
760
+ let tokenOptimizationState = null;
732
761
  if (isTokenOptimizationEnabled) {
733
762
  const detectedExternalProxy = detectRtkBinary();
734
- const tokenOptimizationState = createTokenOptimizationState({
763
+ tokenOptimizationState = createTokenOptimizationState({
735
764
  isEnabled: true,
736
765
  selectedAgentName: selectedTokenAgentName,
737
766
  rtkDetection: detectedExternalProxy,
@@ -862,6 +891,18 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
862
891
  detectionSource: detectedRuntimeEnvironment.source,
863
892
  },
864
893
  operationMode: 'init',
894
+ tokenOptimization: {
895
+ enabled: isTokenOptimizationEnabled,
896
+ selectedAgent: selectedTokenAgentName,
897
+ preferredShellProxy: tokenOptimizationState?.preferredShellProxy || null,
898
+ stateFile: isTokenOptimizationEnabled ? '.agent-context/state/token-optimization.json' : null,
899
+ },
900
+ memoryContinuity: {
901
+ enabled: isMemoryContinuityEnabled,
902
+ hydrationMode: memoryContinuityState?.hydrationMode || null,
903
+ adapters: memoryContinuityState?.adapters || [],
904
+ stateFile: isMemoryContinuityEnabled ? '.agent-context/state/memory-continuity.json' : null,
905
+ },
865
906
  });
866
907
 
867
908
  console.log('\nInitialization complete.');
@@ -892,6 +933,11 @@ export async function runInitCommand(targetDirectoryArgument, initOptions = {})
892
933
  }
893
934
  console.log(`- Repository workflows copied: no (workflows remain source-repo assets)`);
894
935
  console.log(`- MCP template file: ${shouldIncludeMcpTemplate ? 'created (.vscode/mcp.json)' : 'not created by default (use --mcp-template)'}`);
936
+ if (isMemoryContinuityEnabled) {
937
+ console.log('- Memory continuity policy: enabled (index + selective hydration)');
938
+ } else {
939
+ console.log('- Memory continuity policy: disabled (--no-memory-continuity)');
940
+ }
895
941
  if (isTokenOptimizationEnabled) {
896
942
  console.log(`- Token optimization policy: enabled for ${selectedTokenAgentName}`);
897
943
  } else {
@@ -25,6 +25,10 @@ import {
25
25
  readTokenOptimizationState,
26
26
  buildTokenOptimizationGuidanceBlock,
27
27
  } from './token-optimization.mjs';
28
+ import {
29
+ readMemoryContinuityState,
30
+ buildMemoryContinuityGuidanceBlock,
31
+ } from './memory-continuity.mjs';
28
32
 
29
33
  export async function writeSelectedPolicy(targetDirectoryPath, selectedProfileName) {
30
34
  const policyFilePath = path.join(targetDirectoryPath, '.agent-context', 'policies', POLICY_FILE_NAME);
@@ -49,8 +53,16 @@ export async function writeOnboardingReport({
49
53
  compatibilityWarnings = [],
50
54
  runtimeEnvironment = null,
51
55
  operationMode = 'init',
56
+ tokenOptimization = undefined,
57
+ memoryContinuity = undefined,
52
58
  }) {
53
59
  const onboardingReportPath = path.join(targetDirectoryPath, '.agent-context', 'state', 'onboarding-report.json');
60
+ const resolvedTokenOptimization = typeof tokenOptimization === 'undefined'
61
+ ? await readTokenOptimizationState(targetDirectoryPath)
62
+ : tokenOptimization;
63
+ const resolvedMemoryContinuity = typeof memoryContinuity === 'undefined'
64
+ ? await readMemoryContinuityState(targetDirectoryPath)
65
+ : memoryContinuity;
54
66
  const onboardingReport = {
55
67
  cliVersion: CLI_VERSION,
56
68
  generatedAt: new Date().toISOString(),
@@ -72,6 +84,8 @@ export async function writeOnboardingReport({
72
84
  selectedSkillDomains,
73
85
  compatibilityWarnings,
74
86
  runtimeEnvironment,
87
+ tokenOptimization: resolvedTokenOptimization,
88
+ memoryContinuity: resolvedMemoryContinuity,
75
89
  autoDetection: {
76
90
  recommendedStack: projectDetection.recommendedStackFileName,
77
91
  recommendedAdditionalStacks: projectDetection.secondaryStackFileNames || [],
@@ -267,6 +281,14 @@ export async function buildCompiledRulesContent({
267
281
  `## TOKEN OPTIMIZATION PROFILE\nSource: .agent-context/state/token-optimization.json\n\n${buildTokenOptimizationGuidanceBlock(tokenOptimizationState).trim()}`
268
282
  );
269
283
  }
284
+
285
+ const memoryContinuityState = await readMemoryContinuityState(resolvedTargetDirectoryPath);
286
+ if (memoryContinuityState?.enabled) {
287
+ contextBlocks.push(
288
+ `## MEMORY CONTINUITY PROFILE\nSource: .agent-context/state/memory-continuity.json\n\n${buildMemoryContinuityGuidanceBlock(memoryContinuityState).trim()}`
289
+ );
290
+ }
291
+
270
292
  contextBlocks.push(
271
293
  [
272
294
  '## LAYER 7: STATE AWARENESS (MANDATORY)',
@@ -0,0 +1,395 @@
1
+ /**
2
+ * Cross-agent memory continuity utilities.
3
+ * Provides provider-agnostic observation normalization, privacy redaction,
4
+ * lightweight indexing, and selective hydration helpers.
5
+ */
6
+
7
+ import fs from 'node:fs/promises';
8
+ import path from 'node:path';
9
+
10
+ import { pathExists } from './utils.mjs';
11
+
12
+ const PRIVATE_BLOCK_PATTERN = /<private>[\s\S]*?<\/private>/gi;
13
+
14
+ const INLINE_SENSITIVE_PATTERNS = [
15
+ {
16
+ reason: 'api-key-like-value',
17
+ pattern: /\b(api[_-]?key)\b\s*[:=]\s*[^\s,;]+/gi,
18
+ replacer: (_match, fieldName) => `${fieldName}=[REDACTED]`,
19
+ },
20
+ {
21
+ reason: 'token-like-value',
22
+ pattern: /\b(token)\b\s*[:=]\s*[^\s,;]+/gi,
23
+ replacer: (_match, fieldName) => `${fieldName}=[REDACTED]`,
24
+ },
25
+ {
26
+ reason: 'password-like-value',
27
+ pattern: /\b(password|passwd|pwd)\b\s*[:=]\s*[^\s,;]+/gi,
28
+ replacer: (_match, fieldName) => `${fieldName}=[REDACTED]`,
29
+ },
30
+ {
31
+ reason: 'bearer-token',
32
+ pattern: /\bBearer\s+[A-Za-z0-9._-]+/g,
33
+ replacer: () => 'Bearer [REDACTED]',
34
+ },
35
+ ];
36
+
37
+ export const MEMORY_SCHEMA_VERSION = '1.0.0';
38
+ export const MEMORY_CONTINUITY_STATE_FILE_NAME = 'memory-continuity.json';
39
+
40
+ const MEMORY_CONTINUITY_STATE_SCHEMA_VERSION = 'memory-continuity-v1';
41
+
42
+ export const SUPPORTED_MEMORY_ADAPTER_IDS = Object.freeze([
43
+ 'claude-code',
44
+ 'gemini-cli',
45
+ 'vscode-chat',
46
+ ]);
47
+
48
+ export const SUPPORTED_MEMORY_EVENT_TYPES = Object.freeze([
49
+ 'prompt',
50
+ 'tool-use',
51
+ 'decision',
52
+ 'summary',
53
+ 'issue',
54
+ 'context',
55
+ ]);
56
+
57
+ function toIsoTimestamp(rawValue) {
58
+ if (typeof rawValue !== 'string' || rawValue.trim().length === 0) {
59
+ return new Date().toISOString();
60
+ }
61
+
62
+ const parsedDate = new Date(rawValue);
63
+ if (Number.isNaN(parsedDate.getTime())) {
64
+ return new Date().toISOString();
65
+ }
66
+
67
+ return parsedDate.toISOString();
68
+ }
69
+
70
+ function toNonEmptyString(rawValue, fallbackValue = '') {
71
+ if (typeof rawValue !== 'string') {
72
+ return fallbackValue;
73
+ }
74
+
75
+ const normalizedValue = rawValue.trim();
76
+ return normalizedValue.length > 0 ? normalizedValue : fallbackValue;
77
+ }
78
+
79
+ function normalizeTags(rawTags) {
80
+ if (!Array.isArray(rawTags)) {
81
+ return [];
82
+ }
83
+
84
+ const tagSet = new Set();
85
+ for (const rawTag of rawTags) {
86
+ const normalizedTag = toNonEmptyString(String(rawTag || '')).toLowerCase();
87
+ if (normalizedTag) {
88
+ tagSet.add(normalizedTag);
89
+ }
90
+ }
91
+
92
+ return Array.from(tagSet);
93
+ }
94
+
95
+ function normalizeMemoryAdapterIds(rawAdapterIds) {
96
+ if (!Array.isArray(rawAdapterIds) || rawAdapterIds.length === 0) {
97
+ return [...SUPPORTED_MEMORY_ADAPTER_IDS];
98
+ }
99
+
100
+ const normalizedAdapterIdSet = new Set();
101
+ for (const rawAdapterId of rawAdapterIds) {
102
+ const normalizedAdapterId = toNonEmptyString(String(rawAdapterId || '')).toLowerCase();
103
+ if (!normalizedAdapterId) {
104
+ continue;
105
+ }
106
+
107
+ if (!SUPPORTED_MEMORY_ADAPTER_IDS.includes(normalizedAdapterId)) {
108
+ continue;
109
+ }
110
+
111
+ normalizedAdapterIdSet.add(normalizedAdapterId);
112
+ }
113
+
114
+ if (normalizedAdapterIdSet.size === 0) {
115
+ return [...SUPPORTED_MEMORY_ADAPTER_IDS];
116
+ }
117
+
118
+ return Array.from(normalizedAdapterIdSet);
119
+ }
120
+
121
+ export function estimateTokenUsage(rawText = '') {
122
+ const normalizedText = String(rawText || '');
123
+ return Math.max(1, Math.ceil(normalizedText.length / 4));
124
+ }
125
+
126
+ export function redactSensitiveMemoryText(rawText = '') {
127
+ let normalizedText = String(rawText || '');
128
+ const redactionReasons = new Set();
129
+ let privateTagRedactionCount = 0;
130
+ let inlineRedactionCount = 0;
131
+
132
+ normalizedText = normalizedText.replace(PRIVATE_BLOCK_PATTERN, () => {
133
+ privateTagRedactionCount += 1;
134
+ redactionReasons.add('private-tag');
135
+ return '[REDACTED_PRIVATE_BLOCK]';
136
+ });
137
+
138
+ for (const sensitivePattern of INLINE_SENSITIVE_PATTERNS) {
139
+ normalizedText = normalizedText.replace(sensitivePattern.pattern, (...replacerArguments) => {
140
+ inlineRedactionCount += 1;
141
+ redactionReasons.add(sensitivePattern.reason);
142
+ return sensitivePattern.replacer(...replacerArguments);
143
+ });
144
+ }
145
+
146
+ return {
147
+ redactedText: normalizedText,
148
+ wasRedacted: privateTagRedactionCount > 0 || inlineRedactionCount > 0,
149
+ privateTagRedactionCount,
150
+ inlineRedactionCount,
151
+ redactionReasons: Array.from(redactionReasons),
152
+ };
153
+ }
154
+
155
+ export function normalizeMemoryObservation(rawObservation, options = {}) {
156
+ const fallbackAdapterId = options.fallbackAdapterId || 'unknown-adapter';
157
+ const observationId = toNonEmptyString(rawObservation?.id, `${fallbackAdapterId}-${Date.now()}`);
158
+ const adapterId = toNonEmptyString(rawObservation?.adapterId, fallbackAdapterId);
159
+
160
+ const eventTypeCandidate = toNonEmptyString(rawObservation?.eventType, 'context').toLowerCase();
161
+ const eventType = SUPPORTED_MEMORY_EVENT_TYPES.includes(eventTypeCandidate)
162
+ ? eventTypeCandidate
163
+ : 'context';
164
+
165
+ const rawDetail = toNonEmptyString(rawObservation?.detail, '');
166
+ const detailRedaction = redactSensitiveMemoryText(rawDetail);
167
+
168
+ const rawSummary = toNonEmptyString(rawObservation?.summary, detailRedaction.redactedText.slice(0, 220));
169
+ const summaryRedaction = redactSensitiveMemoryText(rawSummary);
170
+
171
+ const title = toNonEmptyString(rawObservation?.title, `${eventType} from ${adapterId}`);
172
+ const tags = normalizeTags(rawObservation?.tags);
173
+
174
+ return {
175
+ id: observationId,
176
+ projectId: toNonEmptyString(rawObservation?.projectId, 'default-project'),
177
+ sessionId: toNonEmptyString(rawObservation?.sessionId, 'default-session'),
178
+ adapterId,
179
+ eventType,
180
+ timestamp: toIsoTimestamp(rawObservation?.timestamp),
181
+ title,
182
+ summary: summaryRedaction.redactedText,
183
+ detail: detailRedaction.redactedText,
184
+ tags,
185
+ privacy: {
186
+ level: toNonEmptyString(rawObservation?.privacyLevel, 'internal'),
187
+ redactionApplied: detailRedaction.wasRedacted || summaryRedaction.wasRedacted,
188
+ redactionReasons: Array.from(new Set([
189
+ ...detailRedaction.redactionReasons,
190
+ ...summaryRedaction.redactionReasons,
191
+ ])),
192
+ privateTagRedactionCount: detailRedaction.privateTagRedactionCount + summaryRedaction.privateTagRedactionCount,
193
+ inlineRedactionCount: detailRedaction.inlineRedactionCount + summaryRedaction.inlineRedactionCount,
194
+ },
195
+ };
196
+ }
197
+
198
+ export function scoreObservationRelevance(queryText, normalizedObservation) {
199
+ const normalizedQuery = toNonEmptyString(queryText, '').toLowerCase();
200
+ if (!normalizedQuery) {
201
+ return 0;
202
+ }
203
+
204
+ const queryTerms = normalizedQuery
205
+ .split(/\s+/)
206
+ .map((queryTerm) => queryTerm.trim())
207
+ .filter((queryTerm) => queryTerm.length > 2);
208
+
209
+ if (queryTerms.length === 0) {
210
+ return 0;
211
+ }
212
+
213
+ const searchableContent = [
214
+ normalizedObservation.title,
215
+ normalizedObservation.summary,
216
+ normalizedObservation.detail,
217
+ normalizedObservation.tags.join(' '),
218
+ normalizedObservation.eventType,
219
+ normalizedObservation.adapterId,
220
+ ].join(' ').toLowerCase();
221
+
222
+ let matchCount = 0;
223
+ for (const queryTerm of queryTerms) {
224
+ if (searchableContent.includes(queryTerm)) {
225
+ matchCount += 1;
226
+ }
227
+ }
228
+
229
+ return Number((matchCount / queryTerms.length).toFixed(4));
230
+ }
231
+
232
+ export function buildSessionStartIndex(normalizedObservations, options = {}) {
233
+ const queryText = toNonEmptyString(options.queryText, '');
234
+ const maxIndexEntries = Number.isFinite(Number(options.limit)) ? Math.max(1, Number(options.limit)) : 8;
235
+
236
+ const rankedEntries = normalizedObservations
237
+ .map((normalizedObservation) => {
238
+ const relevanceScore = scoreObservationRelevance(queryText, normalizedObservation);
239
+ const indexLine = `${normalizedObservation.id}|${normalizedObservation.adapterId}|${normalizedObservation.eventType}|${normalizedObservation.title}`;
240
+ const indexTokenEstimate = estimateTokenUsage(indexLine);
241
+
242
+ return {
243
+ id: normalizedObservation.id,
244
+ adapterId: normalizedObservation.adapterId,
245
+ eventType: normalizedObservation.eventType,
246
+ timestamp: normalizedObservation.timestamp,
247
+ title: normalizedObservation.title,
248
+ summarySnippet: normalizedObservation.summary.slice(0, 120),
249
+ tags: normalizedObservation.tags,
250
+ relevanceScore,
251
+ indexTokenEstimate,
252
+ };
253
+ })
254
+ .sort((leftEntry, rightEntry) => {
255
+ if (rightEntry.relevanceScore !== leftEntry.relevanceScore) {
256
+ return rightEntry.relevanceScore - leftEntry.relevanceScore;
257
+ }
258
+
259
+ return rightEntry.timestamp.localeCompare(leftEntry.timestamp);
260
+ });
261
+
262
+ const indexEntries = rankedEntries.slice(0, maxIndexEntries);
263
+ const totalTokenEstimate = indexEntries.reduce(
264
+ (tokenAccumulator, indexEntry) => tokenAccumulator + indexEntry.indexTokenEstimate,
265
+ 0
266
+ );
267
+
268
+ return {
269
+ indexEntries,
270
+ totalTokenEstimate,
271
+ totalCandidateCount: rankedEntries.length,
272
+ };
273
+ }
274
+
275
+ export function hydrateIndexedObservations(indexEntries, normalizedObservations, options = {}) {
276
+ const fullFetchLimit = Number.isFinite(Number(options.fullFetchLimit))
277
+ ? Math.max(1, Number(options.fullFetchLimit))
278
+ : 2;
279
+
280
+ const observationLookup = new Map(normalizedObservations.map((normalizedObservation) => [
281
+ normalizedObservation.id,
282
+ normalizedObservation,
283
+ ]));
284
+
285
+ const selectedIds = indexEntries.slice(0, fullFetchLimit).map((indexEntry) => indexEntry.id);
286
+ const hydratedObservations = selectedIds
287
+ .map((selectedId) => observationLookup.get(selectedId))
288
+ .filter(Boolean);
289
+
290
+ const hydrationTokenEstimate = hydratedObservations.reduce(
291
+ (tokenAccumulator, hydratedObservation) => tokenAccumulator + estimateTokenUsage(hydratedObservation.detail),
292
+ 0
293
+ );
294
+
295
+ return {
296
+ selectedIds,
297
+ hydratedObservations,
298
+ hydrationTokenEstimate,
299
+ };
300
+ }
301
+
302
+ export function createMemoryContinuityState(options = {}) {
303
+ const isEnabled = options.isEnabled !== false;
304
+ const sessionStartIndexLimit = Number.isFinite(Number(options.sessionStartIndexLimit))
305
+ ? Math.max(1, Number(options.sessionStartIndexLimit))
306
+ : 8;
307
+ const fullHydrationLimit = Number.isFinite(Number(options.fullHydrationLimit))
308
+ ? Math.max(1, Number(options.fullHydrationLimit))
309
+ : 2;
310
+
311
+ return {
312
+ schemaVersion: MEMORY_CONTINUITY_STATE_SCHEMA_VERSION,
313
+ enabled: isEnabled,
314
+ hydrationMode: 'progressive-disclosure',
315
+ adapters: normalizeMemoryAdapterIds(options.adapterIds),
316
+ retrieval: {
317
+ sessionStartIndexLimit,
318
+ fullHydrationLimit,
319
+ },
320
+ privacy: {
321
+ redactPrivateTags: true,
322
+ redactInlineSensitivePatterns: true,
323
+ },
324
+ generatedAt: new Date().toISOString(),
325
+ };
326
+ }
327
+
328
+ export async function readMemoryContinuityState(targetDirectoryPath) {
329
+ const stateFilePath = path.join(
330
+ targetDirectoryPath,
331
+ '.agent-context',
332
+ 'state',
333
+ MEMORY_CONTINUITY_STATE_FILE_NAME
334
+ );
335
+
336
+ if (!(await pathExists(stateFilePath))) {
337
+ return null;
338
+ }
339
+
340
+ try {
341
+ const stateContent = await fs.readFile(stateFilePath, 'utf8');
342
+ const parsedState = JSON.parse(stateContent);
343
+ if (typeof parsedState.enabled !== 'boolean') {
344
+ return null;
345
+ }
346
+
347
+ parsedState.adapters = normalizeMemoryAdapterIds(parsedState.adapters);
348
+ return parsedState;
349
+ } catch {
350
+ return null;
351
+ }
352
+ }
353
+
354
+ export async function writeMemoryContinuityState(targetDirectoryPath, memoryContinuityState) {
355
+ const stateDirectoryPath = path.join(targetDirectoryPath, '.agent-context', 'state');
356
+ const stateFilePath = path.join(stateDirectoryPath, MEMORY_CONTINUITY_STATE_FILE_NAME);
357
+
358
+ await fs.mkdir(stateDirectoryPath, { recursive: true });
359
+ await fs.writeFile(stateFilePath, JSON.stringify(memoryContinuityState, null, 2) + '\n', 'utf8');
360
+ }
361
+
362
+ export function buildMemoryContinuityGuidanceBlock(memoryContinuityState) {
363
+ if (!memoryContinuityState?.enabled) {
364
+ return [
365
+ 'Memory continuity mode is disabled for this repository.',
366
+ 'Use explicit session summaries when handing off context across tools.',
367
+ ].join('\n');
368
+ }
369
+
370
+ const adapterGuidanceLine = memoryContinuityState.adapters?.length
371
+ ? `Supported adapters: ${memoryContinuityState.adapters.join(', ')}.`
372
+ : `Supported adapters: ${SUPPORTED_MEMORY_ADAPTER_IDS.join(', ')}.`;
373
+
374
+ const sessionStartIndexLimit = Number.isFinite(Number(memoryContinuityState.retrieval?.sessionStartIndexLimit))
375
+ ? Number(memoryContinuityState.retrieval.sessionStartIndexLimit)
376
+ : 8;
377
+ const fullHydrationLimit = Number.isFinite(Number(memoryContinuityState.retrieval?.fullHydrationLimit))
378
+ ? Number(memoryContinuityState.retrieval.fullHydrationLimit)
379
+ : 2;
380
+
381
+ return [
382
+ 'Memory continuity mode is enabled.',
383
+ 'Hydration mode: progressive-disclosure.',
384
+ adapterGuidanceLine,
385
+ '',
386
+ 'Session-start retrieval policy:',
387
+ `- Load compact index first (limit: ${sessionStartIndexLimit} entries).`,
388
+ `- Hydrate full detail only for highest-value entries (limit: ${fullHydrationLimit}).`,
389
+ '- Always redact sensitive text before persistence (<private> blocks and inline secret-like fields).',
390
+ '',
391
+ 'Host compatibility scope:',
392
+ '- Works for local IDE, CLI, and cloud IDE chat hosts that implement the memory adapter contract or MCP retrieval path.',
393
+ '- Generic web chat sessions without repository tools cannot auto-hydrate runtime memory and should rely on manual summary export/import.',
394
+ ].join('\n');
395
+ }
package/lib/cli/utils.mjs CHANGED
@@ -28,7 +28,7 @@ export function printUsage() {
28
28
  console.log('');
29
29
  console.log('Usage:');
30
30
  console.log(' agentic-senior-core launch');
31
- console.log(' agentic-senior-core init [target-directory] [--preset <name>] [--profile <beginner|balanced|strict>] [--profile-pack <name>] [--stack <name>] [--blueprint <name>] [--ci <true|false>] [--newbie] [--token-optimize] [--no-token-optimize] [--token-agent <name>] [--scaffold-docs] [--no-scaffold-docs] [--docs-lang <en|id>] [--project-config <path>] [--runtime-env <auto|linux-wsl|linux|windows|macos>]');
31
+ console.log(' agentic-senior-core init [target-directory] [--preset <name>] [--profile <beginner|balanced|strict>] [--profile-pack <name>] [--stack <name>] [--blueprint <name>] [--ci <true|false>] [--newbie] [--token-optimize] [--no-token-optimize] [--token-agent <name>] [--memory-continuity] [--no-memory-continuity] [--scaffold-docs] [--no-scaffold-docs] [--docs-lang <en|id>] [--project-config <path>] [--runtime-env <auto|linux-wsl|linux|windows|macos>]');
32
32
  console.log(' agentic-senior-core upgrade [target-directory] [--dry-run] [--yes] [--mcp-template]');
33
33
  console.log(' agentic-senior-core optimize [target-directory] [--agent <copilot|claude|cursor|windsurf|gemini|codex|cline>] [--enable|--disable] [--show]');
34
34
  console.log(' agentic-senior-core mcp');
@@ -49,6 +49,8 @@ export function printUsage() {
49
49
  console.log(' --token-optimize Explicitly enable token optimization policy during init (default behavior)');
50
50
  console.log(' --token-agent Set token optimization agent target (copilot, claude, cursor, windsurf, gemini, codex, cline)');
51
51
  console.log(' --no-token-optimize Disable token optimization policy during init');
52
+ console.log(' --memory-continuity Explicitly enable cross-session memory continuity policy during init (default behavior)');
53
+ console.log(' --no-memory-continuity Disable memory continuity policy during init');
52
54
  console.log(' --mcp-template Create .vscode/mcp.json workspace template (MCP trust/start remains manual in IDE)');
53
55
  console.log(' --scaffold-docs Force project documentation scaffolding (architecture, database, API, flow)');
54
56
  console.log(' --no-scaffold-docs Skip project documentation scaffolding');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ryuenn3123/agentic-senior-core",
3
- "version": "2.0.26",
3
+ "version": "2.5.3",
4
4
  "type": "module",
5
5
  "description": "Force your AI Agent to code like a Staff Engineer, not a Junior.",
6
6
  "bin": {
@@ -52,6 +52,7 @@
52
52
  "benchmark:writer-judge": "node ./scripts/benchmark-writer-judge-matrix.mjs",
53
53
  "benchmark:gate": "node ./scripts/benchmark-gate.mjs",
54
54
  "benchmark:intelligence": "node ./scripts/benchmark-intelligence.mjs",
55
+ "benchmark:continuity": "node ./scripts/memory-continuity-benchmark.mjs",
55
56
  "report:quality-trend": "node ./scripts/quality-trend-report.mjs",
56
57
  "report:docs-quality-drift": "node ./scripts/docs-quality-drift-report.mjs",
57
58
  "report:governance-weekly": "node ./scripts/governance-weekly-report.mjs",