mirror of
https://github.com/PR0M3TH3AN/TORCH.git
synced 2026-10-27 07:51:52 +00:00
Harden memory workflow to reduce merge conflicts
This commit is contained in:
1 parent
561bc9b4bd
commit
811f45b3af
8 files changed
+84
-10
No files matched your search
@@ -1,2 +1,7 @@
|
|||||||
# Auto detect text files and perform LF normalization
|
# Auto detect text files and perform LF normalization
|
||||||
* text=auto
|
* text=auto
|
||||||
|
|
||||||
|
# Reduce merge conflicts for append-style memory artifacts.
|
||||||
|
memory-updates/*.md merge=union
|
||||||
|
.scheduler-memory/latest/daily/memories.md merge=union
|
||||||
|
.scheduler-memory/latest/weekly/memories.md merge=union
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
# Memory Architecture Report - 2026-02-26
|
||||||
|
|
||||||
|
## Problem
|
||||||
|
Recurring merge conflicts come from shared write-hotspot files (`memory-update.md`, aggregate `memories.md`) being edited by many branches/runs.
|
||||||
|
|
||||||
|
## Goals
|
||||||
|
- Preserve reliable short-term and long-term memory for agents.
|
||||||
|
- Keep memory artifacts traceable in git.
|
||||||
|
- Minimize manual merge work and conflict risk.
|
||||||
|
|
||||||
|
## Core Learnings
|
||||||
|
1. Shared mutable files are conflict magnets.
|
||||||
|
2. Per-run immutable files are merge-friendly and auditable.
|
||||||
|
3. Aggregate views should be generated artifacts, not canonical sources of truth.
|
||||||
|
4. Reliable memory quality comes from deterministic ingestion and stable schema, not from one giant markdown file.
|
||||||
|
|
||||||
|
## Recommended Structure
|
||||||
|
- Source of truth (tracked): `memory-updates/<timestamp>__<agent>.md`
|
||||||
|
- Optional index/metadata (tracked): machine-readable pointers (run id, agent, cadence, tags, embedding/version).
|
||||||
|
- Generated read model (tracked or regenerated): `.scheduler-memory/latest/<cadence>/memories.md`
|
||||||
|
|
||||||
|
Canonical rule:
|
||||||
|
- Write path: only per-run file (`$SCHEDULER_MEMORY_FILE`).
|
||||||
|
- Read path: generated latest aggregate and/or retrieval service.
|
||||||
|
- Never write directly to shared aggregate files from agents.
|
||||||
|
|
||||||
|
## Merge Policy
|
||||||
|
- Keep `memory-updates/*.md` append-style and use `merge=union` to reduce non-overlapping merge collisions.
|
||||||
|
- For generated aggregates (`.scheduler-memory/latest/*/memories.md`):
|
||||||
|
- Prefer keeping one side during merge, then regenerate from source files.
|
||||||
|
- Treat as a cache/read model, not primary truth.
|
||||||
|
|
||||||
|
## Determinism and Reliability Controls
|
||||||
|
- Stable timestamp format (`YYYY-MM-DDTHH-MM-SSZ`) and agent-id naming.
|
||||||
|
- Ingestion writes structured metadata (agent, cadence, run id, tags, source path).
|
||||||
|
- Retrieval/storage must emit verifiable markers/artifacts (`MEMORY_RETRIEVED`, `MEMORY_STORED`, JSON evidence).
|
||||||
|
- Avoid retries/sleeps as correctness fixes; remove nondeterminism at source.
|
||||||
|
|
||||||
|
## Short-Term Memory Design
|
||||||
|
- Scope by cadence and recent window in retrieval queries.
|
||||||
|
- Prioritize high-signal recent memories by recency + importance + semantic match.
|
||||||
|
- Keep run-local context in artifacts (`context/`, `todo/`, `decisions/`, `test_logs/`) and link memory entries to those artifacts.
|
||||||
|
|
||||||
|
## Long-Term Memory Design
|
||||||
|
- Periodic consolidation jobs should summarize repeated findings into durable patterns.
|
||||||
|
- Promote stable insights to a curated long-term layer (policy/decision docs or pinned memory records).
|
||||||
|
- Keep provenance: every promoted insight references original run files.
|
||||||
|
|
||||||
|
## Suggested Evolution Path
|
||||||
|
1. Enforce write contract: only `$SCHEDULER_MEMORY_FILE` in `memory-updates/`.
|
||||||
|
2. Regenerate aggregates from `memory-updates/` in scheduler cycle.
|
||||||
|
3. Add lightweight memory manifest for faster deterministic rebuilds.
|
||||||
|
4. Add pruning/compaction rules that preserve high-value long-term insights.
|
||||||
|
5. Add integrity checks: fail if agents write to deprecated shared files.
|
||||||
|
|
||||||
|
## Operational Playbook for Conflicts
|
||||||
|
When conflicts involve memory files:
|
||||||
|
1. Resolve source files (`memory-updates/*`) by keeping both sides when possible.
|
||||||
|
2. Resolve aggregate files (`.scheduler-memory/latest/*/memories.md`) by choosing one side.
|
||||||
|
3. Regenerate aggregates from source files.
|
||||||
|
4. Run memory policy tests before merge completion.
|
||||||
|
|
||||||
|
## Success Criteria
|
||||||
|
- Significant drop in memory-related merge conflicts.
|
||||||
|
- No loss in retrieval quality for recent and historical tasks.
|
||||||
|
- Rebuild of aggregate memory is deterministic from tracked source files.
|
||||||
@@ -8,10 +8,14 @@ const ROOT_DIR = path.resolve(__dirname, '../../');
|
|||||||
const DAILY_DIR = path.join(ROOT_DIR, 'src/prompts/daily');
|
const DAILY_DIR = path.join(ROOT_DIR, 'src/prompts/daily');
|
||||||
const WEEKLY_DIR = path.join(ROOT_DIR, 'src/prompts/weekly');
|
const WEEKLY_DIR = path.join(ROOT_DIR, 'src/prompts/weekly');
|
||||||
const REPORT_DIR = path.join(ROOT_DIR, 'reports/prompt-safety');
|
const REPORT_DIR = path.join(ROOT_DIR, 'reports/prompt-safety');
|
||||||
|
const MEMORY_DIR = path.join(ROOT_DIR, 'memory-updates');
|
||||||
|
|
||||||
if (!fs.existsSync(REPORT_DIR)) {
|
if (!fs.existsSync(REPORT_DIR)) {
|
||||||
fs.mkdirSync(REPORT_DIR, { recursive: true });
|
fs.mkdirSync(REPORT_DIR, { recursive: true });
|
||||||
}
|
}
|
||||||
|
if (!fs.existsSync(MEMORY_DIR)) {
|
||||||
|
fs.mkdirSync(MEMORY_DIR, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
const SAFETY_KEYWORDS = [
|
const SAFETY_KEYWORDS = [
|
||||||
'FAILURE MODES',
|
'FAILURE MODES',
|
||||||
@@ -96,8 +100,9 @@ function runAudit() {
|
|||||||
memoryContent += `Flagged prompts: ${results.filter(r => r.status === 'NEEDS_REVIEW').map(r => r.filename).join(', ')}\n`;
|
memoryContent += `Flagged prompts: ${results.filter(r => r.status === 'NEEDS_REVIEW').map(r => r.filename).join(', ')}\n`;
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.writeFileSync(path.join(ROOT_DIR, 'memory-update.md'), memoryContent);
|
const memoryFile = path.join(MEMORY_DIR, `${timestamp}__prompt-safety-audit-agent.md`);
|
||||||
console.log('Memory update written to memory-update.md');
|
fs.writeFileSync(memoryFile, memoryContent);
|
||||||
|
console.log(`Memory update written to ${memoryFile}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
runAudit();
|
runAudit();
|
||||||
@@ -69,7 +69,7 @@ async function main() {
|
|||||||
const runner = resolveRunner(promptMarkdown);
|
const runner = resolveRunner(promptMarkdown);
|
||||||
|
|
||||||
// Compute a stable, per-run memory output file path so agents know where to write learnings.
|
// Compute a stable, per-run memory output file path so agents know where to write learnings.
|
||||||
// store.mjs reads this env var; if absent it falls back to the root memory-update.md placeholder.
|
// store.mjs reads this env var and ingests this file.
|
||||||
const agentName = process.env.SCHEDULER_AGENT || 'unknown-agent';
|
const agentName = process.env.SCHEDULER_AGENT || 'unknown-agent';
|
||||||
const runTs = new Date().toISOString().replace(/:/g, '-').replace(/\.\d+Z$/, 'Z');
|
const runTs = new Date().toISOString().replace(/:/g, '-').replace(/\.\d+Z$/, 'Z');
|
||||||
const memoryFile = `memory-updates/${runTs}__${agentName}.md`;
|
const memoryFile = `memory-updates/${runTs}__${agentName}.md`;
|
||||||
|
|||||||
@@ -35,9 +35,7 @@ const cliArgs = process.argv.slice(2);
|
|||||||
const fileArgIndex = cliArgs.indexOf('--file');
|
const fileArgIndex = cliArgs.indexOf('--file');
|
||||||
const explicitFile = fileArgIndex !== -1 ? cliArgs[fileArgIndex + 1] : null;
|
const explicitFile = fileArgIndex !== -1 ? cliArgs[fileArgIndex + 1] : null;
|
||||||
const envFile = process.env.SCHEDULER_MEMORY_FILE;
|
const envFile = process.env.SCHEDULER_MEMORY_FILE;
|
||||||
const defaultFile = 'memory-update.md';
|
const targetFile = explicitFile || (envFile && existsSync(envFile) ? envFile : null);
|
||||||
|
|
||||||
const targetFile = explicitFile || (envFile && existsSync(envFile) ? envFile : (existsSync(defaultFile) ? defaultFile : null));
|
|
||||||
|
|
||||||
if (targetFile) {
|
if (targetFile) {
|
||||||
try {
|
try {
|
||||||
@@ -71,7 +69,7 @@ if (memoryContent) {
|
|||||||
} else {
|
} else {
|
||||||
// No memory file found — skip ingest rather than storing meaningless placeholder events.
|
// No memory file found — skip ingest rather than storing meaningless placeholder events.
|
||||||
// Placeholder events pollute the store and degrade retrieval quality on future runs.
|
// Placeholder events pollute the store and degrade retrieval quality on future runs.
|
||||||
console.warn(`No memory input found (checked --file, env SCHEDULER_MEMORY_FILE=${envFile}, and default ${defaultFile}). Skipping ingest.`);
|
console.warn(`No memory input found (checked --file and env SCHEDULER_MEMORY_FILE=${envFile}). Skipping ingest.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ import { detectTorchInstallDir } from './cmd-remove.mjs';
|
|||||||
|
|
||||||
const MEMORY_HEADING = '## TORCH Memory Integration';
|
const MEMORY_HEADING = '## TORCH Memory Integration';
|
||||||
const MEMORY_READ_LINE = '`.scheduler-memory/latest/${cadence}/memories.md`';
|
const MEMORY_READ_LINE = '`.scheduler-memory/latest/${cadence}/memories.md`';
|
||||||
const MEMORY_WRITE_LINE = '`memory-update.md`';
|
const MEMORY_WRITE_LINE = '`$SCHEDULER_MEMORY_FILE`';
|
||||||
|
|
||||||
function parseMajorNodeVersion(version) {
|
function parseMajorNodeVersion(version) {
|
||||||
const major = Number.parseInt(String(version).split('.')[0], 10);
|
const major = Number.parseInt(String(version).split('.')[0], 10);
|
||||||
|
|||||||
+1
-1
@@ -59,7 +59,7 @@ const MEMORY_INTEGRATION_HEADING = '## TORCH Memory Integration';
|
|||||||
const MEMORY_INTEGRATION_BLOCK = `${MEMORY_INTEGRATION_HEADING}
|
const MEMORY_INTEGRATION_BLOCK = `${MEMORY_INTEGRATION_HEADING}
|
||||||
You have access to the TORCH memory system.
|
You have access to the TORCH memory system.
|
||||||
1. READ: Check \`.scheduler-memory/latest/\${cadence}/memories.md\` for past learnings.
|
1. READ: Check \`.scheduler-memory/latest/\${cadence}/memories.md\` for past learnings.
|
||||||
2. WRITE: Before exiting, save new insights to \`memory-update.md\` so future runs can learn from this session.`;
|
2. WRITE: Before exiting, save new insights to \`$SCHEDULER_MEMORY_FILE\` (for example \`memory-updates/<timestamp>__<agent>.md\`) so future runs can learn from this session.`;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolves the absolute paths for the installation.
|
* Resolves the absolute paths for the installation.
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ Every agent prompt invoked by the schedulers (daily/weekly) MUST enforce this co
|
|||||||
- Write only facts that will help the **same agent** on its **next run**. Skip meta-commentary about the task structure.
|
- Write only facts that will help the **same agent** on its **next run**. Skip meta-commentary about the task structure.
|
||||||
- Run configured memory storage workflow after prompt execution (for example via `scheduler.memoryPolicyByCadence.<cadence>.storeCommand`)
|
- Run configured memory storage workflow after prompt execution (for example via `scheduler.memoryPolicyByCadence.<cadence>.storeCommand`)
|
||||||
- Storage command MUST call real memory services (`src/services/memory/index.js#ingestEvents`, which uses ingestor/summarizer pipeline) and MUST emit deterministic marker `MEMORY_STORED`.
|
- Storage command MUST call real memory services (`src/services/memory/index.js#ingestEvents`, which uses ingestor/summarizer pipeline) and MUST emit deterministic marker `MEMORY_STORED`.
|
||||||
- Storage command MUST ingest content from the file at `$SCHEDULER_MEMORY_FILE` (or fallback to `memory-update.md` if present).
|
- Storage command MUST ingest content from the file at `$SCHEDULER_MEMORY_FILE`.
|
||||||
- Storage command MUST write cadence-scoped evidence artifacts:
|
- Storage command MUST write cadence-scoped evidence artifacts:
|
||||||
- `.scheduler-memory/store-<cadence>.ok`
|
- `.scheduler-memory/store-<cadence>.ok`
|
||||||
- `.scheduler-memory/store-<cadence>.json` containing operation inputs/outputs (`agentId`, input event count, stored count, generated summaries).
|
- `.scheduler-memory/store-<cadence>.json` containing operation inputs/outputs (`agentId`, input event count, stored count, generated summaries).
|
||||||
|
|||||||
Reference in new issue
Block a user