From 22198a6c6fcbc749e546f94420932a2a219eb820 Mon Sep 17 00:00:00 2001 From: "david.delagneau" Date: Thu, 9 Apr 2026 15:11:43 -0600 Subject: [PATCH] feat: Enhance memory management and promotion rules for Mattermost context and user prompts --- .opencode/agents/fidelity.md | 4 + .opencode/commands/mattermost-sync.md | 21 ++-- .opencode/commands/promote-project-context.md | 1 + .opencode/commands/sync-context.md | 6 +- .opencode/plugins/mattermost-inbox.js | 12 +- AGENTS.md | 10 +- ai/AGENTS.md | 12 +- knowledge/agent-memory-rules.md | 116 ++++++++++++++++++ knowledge/memory-promotion-rules.md | 106 ++++++++++++++++ opencode.json | 4 +- workflows/opencode-entry.md | 1 + 11 files changed, 277 insertions(+), 16 deletions(-) create mode 100644 knowledge/agent-memory-rules.md create mode 100644 knowledge/memory-promotion-rules.md diff --git a/.opencode/agents/fidelity.md b/.opencode/agents/fidelity.md index 1ec310d..78aee52 100644 --- a/.opencode/agents/fidelity.md +++ b/.opencode/agents/fidelity.md @@ -12,6 +12,7 @@ Behavior rules: - Treat `README.md`, `ai/context/`, `ai/state/`, `knowledge/`, and `ai/logs/` as the persistent memory of the project. - Before answering a prompt that depends on current state, verify the latest relevant files instead of relying only on conversation history. +- For any meaningful prompt, decide whether the interaction adds, corrects, or sharpens project memory. - When the user provides new durable information, update the right workspace files before or while answering. - If existing context is stale, correct it directly instead of leaving conflicting versions. - Promote information carefully: @@ -20,5 +21,8 @@ Behavior rules: - durable project knowledge goes to `ai/context/project.md` - confirmed team or manager communication preferences go to `ai/context/people/jeff.md` - confirmed decisions go to `ai/context/decisions/` +- Default to writing new same-day information to today's log unless a more durable destination is clearly better. +- Update preexisting memory when a new prompt clarifies or corrects something already stored. +- Do not wait for a dedicated sync command if the correct memory update is already obvious. - Do not over-promote uncertain information. Keep uncertain items in the daily log. - When drafting communication, preserve technical meaning and improve clarity in natural US English. diff --git a/.opencode/commands/mattermost-sync.md b/.opencode/commands/mattermost-sync.md index d5e95ac..8e1d363 100644 --- a/.opencode/commands/mattermost-sync.md +++ b/.opencode/commands/mattermost-sync.md @@ -1,8 +1,8 @@ --- -description: Force a Mattermost sync using the configured local script +description: Sync Mattermost context and automatically promote high-confidence project memory --- -Use the configured Mattermost sync command to fetch fresh communication context into the inbox only. +Use the configured Mattermost sync command to fetch fresh communication context and maintain workspace memory automatically. Preferred command sources: @@ -16,14 +16,17 @@ Run the command and use its output as fresh communication context: Then: - if the command fails, stop there and do not edit any workspace files -- if no `ai/inbox/mattermost-latest.md` exists after the sync attempt, do not update project memory -- inspect `ai/inbox/mattermost-latest.md` if it exists -- extract only project-relevant candidate facts -- do not update `ai/logs/`, `ai/state/`, or `ai/context/` in this command -- if important candidate facts are found, summarize them as promotion candidates for a later explicit command +- use `ai/inbox/mattermost-latest.md` if it exists and is non-empty +- otherwise use `scripts/mattermost/generated/mattermost_context.jsonl` if it exists and is non-empty +- apply the memory promotion rules from `knowledge/memory-promotion-rules.md` +- automatically promote explicit, project-relevant, high-confidence facts +- default destination is `ai/logs/$(date +%F).md` +- update `ai/state/current.md` only for facts that materially change the current work window +- do not write tooling noise, sync status, or generic chat chatter into project memory +- if a fact is ambiguous, skip it rather than asking the user what to do Return: 1. What was synchronized -2. Candidate project facts worth promoting -3. What still needs human confirmation +2. Which files were updated +3. Which facts were promoted or intentionally skipped diff --git a/.opencode/commands/promote-project-context.md b/.opencode/commands/promote-project-context.md index bef7f2f..e64da26 100644 --- a/.opencode/commands/promote-project-context.md +++ b/.opencode/commands/promote-project-context.md @@ -11,6 +11,7 @@ Read: @ai/state/current.md @knowledge/workspace-model.md @knowledge/communication-rules.md +@knowledge/memory-promotion-rules.md Today's log, if present: diff --git a/.opencode/commands/sync-context.md b/.opencode/commands/sync-context.md index 78112c1..a3c937c 100644 --- a/.opencode/commands/sync-context.md +++ b/.opencode/commands/sync-context.md @@ -1,5 +1,5 @@ --- -description: Update workspace memory from new facts, corrections, or Mattermost notes +description: Update workspace memory from new facts, corrections, or contextual notes --- Use this command when new information should become part of the persistent workspace context. @@ -13,6 +13,8 @@ Read: @ai/state/current.md @knowledge/workspace-model.md @knowledge/communication-rules.md +@knowledge/agent-memory-rules.md +@knowledge/memory-promotion-rules.md Today's existing log, if present: @@ -34,6 +36,8 @@ Instructions: - If an existing statement became stale, replace or refine it - Do not invent missing facts - Keep uncertain information in the daily log instead of promoting it to stable context +- Do not ask for promotion confirmation when the correct destination is already clear +- Prefer correcting canonical memory over appending duplicate summaries After editing, respond with: diff --git a/.opencode/plugins/mattermost-inbox.js b/.opencode/plugins/mattermost-inbox.js index a698f8d..1288e2c 100644 --- a/.opencode/plugins/mattermost-inbox.js +++ b/.opencode/plugins/mattermost-inbox.js @@ -26,6 +26,15 @@ async function resolveSyncCommand(directory) { } } +async function resolveSyncContent(directory, stdoutText) { + const cleaned = (stdoutText || "").trim() + if (cleaned) return cleaned + + const generatedPath = path.join(directory, "scripts/mattermost/generated/mattermost_context.jsonl") + const generated = await safeRead(generatedPath) + return (generated || "").trim() +} + export const MattermostInbox = async ({ $, directory, client }) => { let lastSyncAt = 0 @@ -54,7 +63,8 @@ export const MattermostInbox = async ({ $, directory, client }) => { try { await mkdir(inboxDir, { recursive: true }) - const output = (await $`bash -lc ${command}`.text()).trim() + const stdoutText = await $`bash -lc ${command}`.text() + const output = await resolveSyncContent(directory, stdoutText) const previous = await safeRead(latestPath) if (output) { diff --git a/AGENTS.md b/AGENTS.md index 6291b64..2ce6760 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -27,9 +27,17 @@ These are also loaded through `opencode.json`. - Assume the workspace may contain stale context until checked. - Before answering questions that depend on current work state, inspect `ai/state/current.md` and the latest relevant log under `ai/logs/`. - If `ai/inbox/mattermost-latest.md` exists, inspect it for fresher communication context before answering standup, status, or manager-message prompts. +- For any meaningful prompt, decide whether the interaction introduces or corrects project memory. - If a sync command, extraction script, or inbox refresh fails, do not update logs, state, or context files from that failed attempt. - Treat sync failures as operational errors, not project context. -- `mattermost-sync` should refresh inbox context only. It must not update `ai/logs/`, `ai/state/`, or stable context files unless the user explicitly asks to promote confirmed project facts. +- `mattermost-sync` should automatically promote high-confidence project facts without asking what to promote. +- Prefer `ai/logs/` as the default destination for new Mattermost-derived facts. +- Promote to `ai/state/current.md` only when the fact materially changes active work over the next few days. +- Promote to `ai/context/project.md` only when the fact changes durable project understanding. +- Never promote tooling chatter, sync status, or generic conversation noise. +- Direct user prompts are also memory sources. Do not limit memory updates to explicit sync commands. +- If a new prompt corrects prior understanding, update the canonical file directly instead of keeping both versions alive. +- Do not ask what should be saved when the correct destination is already clear. - If the user provides durable new facts, update the appropriate context files instead of leaving the new information only in chat history. - If a previous context file is now stale or inaccurate, update that file directly. - Prefer correcting canonical context over appending contradictory notes. diff --git a/ai/AGENTS.md b/ai/AGENTS.md index 919dd53..9a70097 100644 --- a/ai/AGENTS.md +++ b/ai/AGENTS.md @@ -63,12 +63,18 @@ When drafting messages for Jeff: - Treat workspace files as persistent memory, not just reference notes - Before answering prompts about current work, verify `ai/state/current.md` and the latest relevant log in `ai/logs/` - If `ai/inbox/mattermost-latest.md` exists, check it before answering prompts about current status, standups, or supervisor communication +- Treat all meaningful user prompts as potential memory updates, not only explicit sync commands - If a Mattermost sync or other context-ingestion step fails, do not update `ai/logs/`, `ai/state/`, or stable context files based on that failure - Do not record missing dependencies, failed sync attempts, or missing inbox files as project facts unless the user explicitly asks to track the operational issue -- Treat `mattermost-sync` as inbox refresh only. Do not automatically promote synced content into project memory -- Promote Mattermost content only when it is clearly project-relevant, confirmed enough to keep, and the user explicitly asks to sync or promote project context +- Auto-promote Mattermost content when it is clearly project-relevant, explicit, and high-confidence +- Auto-promote direct user-provided project facts when they are clearly project-relevant, explicit, and useful for future sessions +- Default promotion target is today's log +- Promote to `ai/state/current.md` only when the fact changes the active work window +- Promote to `ai/context/project.md` only when the fact is durable beyond the current work window +- Update existing memory when the new information is a correction, clarification, or refinement of something already stored - Prefer updating stable project context over appending generic operational summaries - Do not create daily log entries for tooling activity, sync status, or generic chat noise +- Do not ask the user what should be promoted after a successful sync unless multiple conflicting interpretations are equally plausible - When the user shares relevant new information, update today's log if the information belongs to the daily record - When the user corrects or changes stable context, update the canonical file directly: - `ai/state/current.md` for current focus or active concerns @@ -86,7 +92,7 @@ For day-to-day prompts in this workspace: 1. Verify the latest relevant context. 2. Decide whether the prompt introduces new durable information. -3. Update the workspace when needed, but never from a failed sync or failed tool run, and never auto-promote Mattermost sync results. +3. Update the workspace when needed, whether the source is a normal prompt, a sync, or a drafting conversation, but never from a failed sync or failed tool run. 4. Then answer using the refreshed context. --- diff --git a/knowledge/agent-memory-rules.md b/knowledge/agent-memory-rules.md new file mode 100644 index 0000000..5b1c62b --- /dev/null +++ b/knowledge/agent-memory-rules.md @@ -0,0 +1,116 @@ +# Agent Memory Rules + +## Goal + +Make workspace memory maintenance part of the agent's normal job, not a separate optional workflow. + +--- + +## Default Agent Behavior + +For any meaningful prompt, the agent should decide whether the interaction changes project memory. + +This applies to: + +- direct user prompts +- Mattermost sync results +- translated notes +- standup generation +- manager-update drafting +- debugging discussions +- corrections to previous understanding + +The agent should not wait for a separate promotion command when the right update is already clear. + +--- + +## What Counts As Memory-Worthy + +Capture information automatically when it is: + +- project-relevant +- explicit enough to preserve safely +- likely to matter in a future session +- useful for standups, debugging, or supervisor communication + +Examples: + +- confirmed story creation, points, scope, or priority +- confirmed reproduction constraints +- newly clarified root cause framing +- approved manager guidance that changes work direction +- confirmed version, dependency, or rollout facts tied to current work +- corrections to previously stored project context + +--- + +## What The Agent Must Do + +When new memory-worthy information appears, the agent should: + +1. decide whether it is daily, current-state, durable, or decision-level context +2. update the smallest correct set of files +3. correct stale or conflicting existing statements +4. answer the user using the refreshed context + +Do not ask the user what to promote unless the ambiguity is real and material. + +--- + +## File Selection + +### `ai/logs/YYYY-MM-DD.md` + +Default destination for: + +- same-day progress +- same-day findings +- scoped reproduction notes +- story and approval movement +- context that is important now but may evolve later + +### `ai/state/current.md` + +Use when the fact changes the active work window, including: + +- current priorities +- currently active story scope +- current blockers or debugging constraints +- manager direction that changes the next few days of work + +### `ai/context/project.md` + +Use for durable project knowledge that should survive beyond the current work window. + +### `ai/context/people/jeff.md` + +Use only when a communication preference or manager expectation becomes stable enough to reuse repeatedly. + +### `ai/context/decisions/*.md` + +Use for explicit confirmed decisions with ongoing impact. + +--- + +## What Not To Store + +Do not store: + +- tool failures +- sync attempts +- generic urgency messages +- duplicate paraphrases of the same fact +- weak guesses +- operational chatter that does not change project understanding + +--- + +## Correction Rule + +If new information supersedes old memory: + +- update the existing canonical file +- do not leave stale and corrected versions side by side +- preserve qualifiers if the fact is only partially confirmed + +The agent should behave like a senior engineer maintaining project notes, not like a chat assistant accumulating transcripts. diff --git a/knowledge/memory-promotion-rules.md b/knowledge/memory-promotion-rules.md new file mode 100644 index 0000000..87f31da --- /dev/null +++ b/knowledge/memory-promotion-rules.md @@ -0,0 +1,106 @@ +# Memory Promotion Rules + +## Goal + +Keep workspace memory current automatically without asking the user what to promote after every successful sync. + +--- + +## Default Rule + +When new Mattermost context is explicit, project-relevant, and high-confidence, promote it automatically. + +Do not ask for promotion confirmation by default. + +If a fact is ambiguous, skip it or keep it only in the daily log with appropriate qualifiers. + +--- + +## File Selection + +### Promote to `ai/logs/YYYY-MM-DD.md` + +Use the daily log for: + +- concrete same-day work updates +- story creation, sizing, approval, and scope updates +- manager-approved wording or root-cause framing tied to current work +- confirmed version checks tied to active work +- reproduction findings that are useful now but may still evolve + +Daily logs are the default destination for most promoted Mattermost facts. + +### Promote to `ai/state/current.md` + +Use current state only for facts that materially affect active work over the next few days, such as: + +- approved active story scope +- confirmed current debugging constraints +- current reproduction conditions that change how the work is approached +- near-term priorities confirmed by manager communication + +Do not copy every daily update into current state. + +### Promote to `ai/context/project.md` + +Use project context only for durable project knowledge that should survive beyond the current work window, such as: + +- stable architecture constraints +- recurring debugging truths +- persistent testing limitations +- enduring behavior of REST, GraphQL, XFlow, auth, or entry points + +Do not promote story-specific daily movement into project context unless it changes durable project understanding. + +### Promote to `ai/context/decisions/*.md` + +Use decisions only for explicit confirmed decisions with medium or long-term impact. + +--- + +## Do Not Promote + +Do not record these as project memory: + +- tooling activity +- sync status +- missing dependencies +- empty inbox situations +- reminders or urgency without project substance +- unapproved drafts +- generic chat noise + +--- + +## Confidence Rules + +Auto-promote when the signal is high-confidence, for example: + +- Jeff explicitly approves something +- a Jira story number, title, points, or scope is explicitly confirmed +- a version is stated directly and tied to the active project +- a reproduction condition is clearly stated with scope qualifiers + +If confidence is mixed: + +- prefer the daily log +- preserve qualifiers such as "appears", "currently", or "for authenticated users" +- avoid promoting to stable project context + +--- + +## Example Policy + +Given Mattermost updates like: + +- PDIAP-15836 created and sized at 8 points +- Jeff approved a story title +- REST-removal scope was approved +- XFlowViewMaker 0.5.0 is already in Fid4 +- AO DOB validation issue appears auth-only in TeenIdentityCheck + +Automatic behavior should be: + +- add all of them to today's log if they are relevant to today's work +- promote only the currently actionable subset to `ai/state/current.md` +- keep story-specific details out of `ai/context/project.md` unless they reveal a durable project rule diff --git a/opencode.json b/opencode.json index 75ca570..976a331 100644 --- a/opencode.json +++ b/opencode.json @@ -48,6 +48,8 @@ "./ai/context/decisions/discourse-handling.md", "./ai/AGENTS.md", "./knowledge/workspace-model.md", - "./knowledge/communication-rules.md" + "./knowledge/communication-rules.md", + "./knowledge/agent-memory-rules.md", + "./knowledge/memory-promotion-rules.md" ] } diff --git a/workflows/opencode-entry.md b/workflows/opencode-entry.md index c1b1ea7..c2db202 100644 --- a/workflows/opencode-entry.md +++ b/workflows/opencode-entry.md @@ -32,6 +32,7 @@ Use OpenCode as the daily AI entry point for this workspace without losing proje - Root rules also load automatically from `AGENTS.md`. - The main context command reads the stable workspace files plus today's log. - Mattermost context can be refreshed into `ai/inbox/` using your existing local sync script. +- Direct prompts are also treated as memory opportunities, so the agent can update workspace context during normal conversation. - Daily updates go back into the workspace, so later prompts inherit better context. - The local compaction plugin helps preserve the most important workspace context during long sessions. - This reduces reliance on fragile session memory.