dsh-mnemon-source-runtime 0.5.8 → 0.5.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -19,6 +19,8 @@ Choose an existing data authority deliberately. Without `dataDir`, each stable S
19
19
 
20
20
  Disabling participation does not delete stored entries. Source data remains separate from the current turn's projection and access grants.
21
21
 
22
+ Model projections annotate each entry with its recorded importance and elapsed whole-day ages, for example `[importance=critical; created=14d; updated=2d]`, followed by the exact content. Future timestamps show `future`; unparseable ones show `unknown`. Ages are captured once per projection and remain fixed for that turn. Annotations count toward the Strategy's projection budget, but do not change stored JSON/Markdown, content matching or storage capacity. For replacement/removal, use only the entry content. Current instructions retain priority.
23
+
22
24
  ## Source-owned UI and tests
23
25
 
24
26
  The optional `./client` entry is an ordinary DSH Client plugin. This package owns its pages and `presentation/` resources and uses `dsh-mnemon/client` for the shared frame and scoped management client. It never receives a Host Context, credentials or another Source's controller.
package/lib/index.js CHANGED
@@ -162,6 +162,16 @@ function markdown(entries, target) {
162
162
  const content = entries.filter((entry) => entry.target === target).map((entry) => entry.content).join(RUNTIME_ENTRY_DELIMITER);
163
163
  return content === "" ? "" : `${content}\n`;
164
164
  }
165
+ function age(timestamp, projectedAt) {
166
+ const time = Date.parse(timestamp);
167
+ if (!Number.isFinite(time)) return "unknown";
168
+ if (time > projectedAt) return "future";
169
+ return `${Math.floor((projectedAt - time) / 864e5)}d`;
170
+ }
171
+ /** Prompt-only annotations; stored content, matching and capacity stay unchanged. */
172
+ function contextMarkdown(entries, target, projectedAt) {
173
+ return entries.filter((entry) => entry.target === target).map((entry) => `[importance=${entry.importance}; created=${age(entry.created_at, projectedAt)}; updated=${age(entry.updated_at, projectedAt)}]\n${entry.content}`).join(RUNTIME_ENTRY_DELIMITER);
174
+ }
165
175
  function revision(file) {
166
176
  return createHash("sha256").update(JSON.stringify(file)).digest("hex");
167
177
  }
@@ -299,7 +309,7 @@ function sleepSync(milliseconds) {
299
309
  }
300
310
  /**
301
311
  * Single authority for hot memory. JSON is the durable source of truth;
302
- * Markdown files are deterministic projections consumed by prompt assembly.
312
+ * Markdown files retain plain content; prompt projections add recorded metadata.
303
313
  */
304
314
  var RuntimeMemoryController = class RuntimeMemoryController {
305
315
  now;
@@ -352,8 +362,9 @@ var RuntimeMemoryController = class RuntimeMemoryController {
352
362
  */
353
363
  contextProjection(branch) {
354
364
  const branchScope = scopeBranch(branch);
355
- const local = this.localContextProjection(branchScope);
356
- const global = this.userController?.localContextProjection();
365
+ const projectedAt = this.now().getTime();
366
+ const local = this.localContextProjection(projectedAt, branchScope);
367
+ const global = this.userController?.localContextProjection(projectedAt);
357
368
  const user = global?.user ?? local.user;
358
369
  const memory = local.memory;
359
370
  const entries = global === void 0 ? local.snapshot.entries : [...global.snapshot.entries.filter((entry) => entry.target === "user"), ...local.snapshot.entries.filter((entry) => entry.target === "memory")];
@@ -366,7 +377,7 @@ var RuntimeMemoryController = class RuntimeMemoryController {
366
377
  version: 1,
367
378
  entries
368
379
  }),
369
- generatedAt: this.now().toISOString(),
380
+ generatedAt: new Date(projectedAt).toISOString(),
370
381
  entries,
371
382
  targets: {
372
383
  memory: {
@@ -392,6 +403,7 @@ var RuntimeMemoryController = class RuntimeMemoryController {
392
403
  totalEntries: entries.length,
393
404
  text: `MNEMON RUNTIME MEMORY SNAPSHOT
394
405
  Revision: ${snapshot.revision}${branchLine}
406
+ Metadata lines are annotations; created/updated are ages at projection in whole days (future/unknown for future/invalid timestamps). Current instructions win. For old_text/oldText, use entry content only.
395
407
 
396
408
  Contents of USER.md (user profile; entries: ${visibleUser.entryCount}; UTF-8 bytes: ${storeUser.used}/${storeUser.limit})
397
409
  <runtime-memory-file name="USER.md">
@@ -404,7 +416,7 @@ ${memory || "(empty)"}
404
416
  </runtime-memory-file>`
405
417
  };
406
418
  }
407
- localContextProjection(branch) {
419
+ localContextProjection(projectedAt, branch) {
408
420
  const branchScope = scopeBranch(branch);
409
421
  return this.withLock(() => {
410
422
  const file = this.readSource();
@@ -416,15 +428,15 @@ ${memory || "(empty)"}
416
428
  directory: this.directory,
417
429
  sourcePath: this.sourcePath,
418
430
  revision: revision(file),
419
- generatedAt: this.now().toISOString(),
431
+ generatedAt: new Date(projectedAt).toISOString(),
420
432
  entries,
421
433
  targets: {
422
434
  memory: this.targetView(visible, "memory"),
423
435
  user: this.targetView(visible, "user")
424
436
  }
425
437
  },
426
- user: readFileSync(this.localUserPath, "utf8").trimEnd(),
427
- memory: branchScope === void 0 ? readFileSync(this.memoryPath, "utf8").trimEnd() : markdown(visible, "memory").trimEnd(),
438
+ user: contextMarkdown(visible, "user", projectedAt),
439
+ memory: contextMarkdown(visible, "memory", projectedAt),
428
440
  hidden: branchScope === void 0 ? 0 : entries.length - visible.length
429
441
  };
430
442
  });
@@ -737,7 +749,7 @@ function createRuntimeMemorySource(config = {}) {
737
749
  content: { type: "string" },
738
750
  oldText: {
739
751
  type: "string",
740
- description: "Full content of the existing entry, or a unique substring. A unique full-content match takes precedence within the selected target. Required for replace and remove."
752
+ description: "Full content of the existing entry, or a unique substring, excluding the generated metadata line. A unique full-content match takes precedence within the selected target. Required for replace and remove."
741
753
  },
742
754
  importance: {
743
755
  type: "string",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-mnemon-source-runtime",
3
- "version": "0.5.8",
3
+ "version": "0.5.9",
4
4
  "description": "Self-contained runtime Source for Composable View Memory.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -61,7 +61,7 @@
61
61
  "@types/node": "^22.0.0",
62
62
  "@types/react": "^18.3.0",
63
63
  "@types/react-dom": "^18.3.0",
64
- "dsh-mnemon": "^0.5.11",
64
+ "dsh-mnemon": "^0.5.15",
65
65
  "jsdom": "^26.0.0",
66
66
  "react": "^18.2.0",
67
67
  "react-dom": "^18.2.0",