feat(provider): move system prompt block to file and add pre-save quality gate master
authorSvjatoslav Agejenko <svjatoslav@svjatoslav.eu>
Sun, 12 Jul 2026 12:51:59 +0000 (15:51 +0300)
committerSvjatoslav Agejenko <svjatoslav@svjatoslav.eu>
Sun, 12 Jul 2026 12:51:59 +0000 (15:51 +0300)
Move the inline string concatenation from system_prompt_block() into
src/retinue/system_prompt_block.txt so the Python source is readable
and the discipline text is editable without code changes.

Add a pre-save quality gate to the discipline text:
- search existing memories before adding,
- fresh-session test before saving,
- quote file paths that contain spaces,
- name all referents,
- avoid bare pronouns,
- one fact per memory.

Bump plugin version to 1.1.0.

plugin.yaml
src/retinue/provider.py
src/retinue/system_prompt_block.txt [new file with mode: 0644]

index c81f1b4..5c63698 100644 (file)
@@ -1,5 +1,5 @@
 name: retinue
 name: retinue
-version: 1.0.0
+version: 1.1.0
 description: "Semantic memory provider for Hermes Agent using model2vec and sqlite-vec."
 hooks:
   - sync_turn
 description: "Semantic memory provider for Hermes Agent using model2vec and sqlite-vec."
 hooks:
   - sync_turn
index 2554409..8ff39b4 100644 (file)
@@ -114,47 +114,7 @@ class RetinueMemoryProvider(MemoryProvider):
     # System prompt guidance
     # ------------------------------------------------------------------
     def system_prompt_block(self) -> str:
     # System prompt guidance
     # ------------------------------------------------------------------
     def system_prompt_block(self) -> str:
-        return (
-            "Memory discipline\n\n"
-            "Retinue semantic memory is available and cheap. Use it eagerly.\n\n"
-            "Before doing anything substantive -- answering questions, writing code, debugging, planning -- "
-            "search memory first with retinue_memory_search. Retinue is semantic, so \"Vehicle\" matches \"Volvo\" "
-            "and \"deployment\" matches \"install\". If memory has partial info, use it; if not, fill the gap "
-            "after you find the answer.\n\n"
-            "After every task, before your final reply, run retinue_memory_add if any of these are true:\n"
-            "- search returned nothing useful AND an external source (docs, files, URLs, CLI output) gave the answer.\n"
-            "- you discovered a stable identifier the next session will need: URL, path, hostname, port, env var, version, command flag.\n"
-            "- you learned a person's role / handle, or a system's alias / nickname.\n"
-            "- a task succeeded via a non-obvious path, or you had to back out of a wrong first attempt.\n"
-            "- the user corrected a fact, preference, or process.\n"
-            "Memories MUST be self-contained. You will work on many projects across many sessions, and a memory "
-            "written today may be retrieved months later with no surrounding context. If a memory relies on context "
-            "that is only obvious right now, it becomes a landmine. Before saving, re-read the memory as if you had "
-            "never seen this conversation and ask: \"Could a fresh session correctly understand and apply this fact?\" "
-            "If not, rewrite it.\n\n"
-            "Memory hygiene -- clean proactively, do not ask for permission.\n"
-            "Whenever you list or search memories, inspect the results for quality problems and fix them immediately:\n"
-            "- Delete exact or near-duplicate memories (keep the newest / most complete one).\n"
-            "- Delete stale or obsolete memories (paths that moved, versions that changed, preferences that were corrected, bugs that were fixed).\n"
-            "- Merge several overlapping memories into one self-contained entry by deleting the fragments and adding a consolidated memory.\n"
-            "- Update a memory when the underlying fact changes.\n"
-            "If a cleanup is obvious, do it silently and briefly report what changed. Only ask the user when the correct action is genuinely ambiguous.\n\n"
-            "Always make explicit in the content:\n"
-            "- project / repository (full name, e.g. sixth-3d, not \"the project\")\n"
-            "- file or path (absolute or repo-relative, e.g. src/retinue/provider.py, not \"that script\")\n"
-            "- tool / library / version (e.g. sqlite-vec 0.1.x, not \"the vec extension\")\n"
-            "- environment / host (e.g. Linux host \"jupiter\", not \"this machine\")\n\n"
-            "Never use bare pronouns (\"it\", \"this\", \"here\", \"the file\", \"the project\", \"the user\") without "
-            "naming the referent in the same memory.\n\n"
-            "Bad (context-dependent, misleading later):\n"
-            "- \"the build fails on Java 21 -- use 17 instead\"\n"
-            "- \"user prefers tabs\"\n\n"
-            "Good (self-contained, safe to retrieve in any future session):\n"
-            "- \"sixth-3d (pom.xml): toolchain pinned to Java Language Version of 21 "
-            "'unsupported class file version' usually means the daemon is running an older JDK -- run with JAVA_HOME "
-            "pointing to JDK 21.\"\n"
-            "- \"User John prefers plain text output, not markdown tables.\""
-        )
+        return Path(__file__).with_name("system_prompt_block.txt").read_text()
 
     # ------------------------------------------------------------------
     # Tool interface
 
     # ------------------------------------------------------------------
     # Tool interface
diff --git a/src/retinue/system_prompt_block.txt b/src/retinue/system_prompt_block.txt
new file mode 100644 (file)
index 0000000..93ccd61
--- /dev/null
@@ -0,0 +1,86 @@
+Memory discipline
+
+Retinue semantic memory is available and cheap. Use it eagerly.
+
+Before doing anything substantive -- answering questions, writing
+code, debugging, planning -- search memory first with
+retinue_memory_search. Retinue is semantic, so "Vehicle" matches
+"Volvo" and "deployment" matches "install". If memory has partial
+info, use it; if not, fill the gap after you find the answer.
+
+After every task, before your final reply, run retinue_memory_add if
+any of these are true:
+- search returned nothing useful AND an external source (docs, files,
+  URLs, CLI output) gave the answer.
+- you discovered a stable identifier the next session will need: URL,
+  path, hostname, port, env var, version, command flag.
+- you learned a person's role / handle, or a system's alias /
+  nickname.
+- a task succeeded via a non-obvious path, or you had to back out of a
+  wrong first attempt.
+- the user corrected a fact, preference, or process.
+
+Pre-save quality gate
+
+Before saving any memory, run this checklist. If any check fails,
+rewrite the memory before saving.
+1. Search first. Use retinue_memory_search for related concepts. If an
+   existing memory already covers the fact, merge or replace it
+   instead of adding a fragment.
+2. Fresh-session test. Read the candidate memory verbatim and ask: "If
+   I had never seen this conversation, could I correctly understand
+   and act on this fact?" If not, rewrite it.
+3. Quote paths with spaces. Every file path that contains spaces or
+   shell-special characters must be enclosed in double quotes, e.g.,
+   "/home/n0/data/projects/Internet hosting/apache2 setup.org". Paths
+   with no spaces may be quoted too.
+4. Name the referents. Include project/repository full name, file or
+   path, tool/library/version, and environment/host where relevant.
+5. No bare pronouns. Remove "it", "this", "here", "the file", "the
+   project", "the user" without naming the referent in the same
+   sentence.
+6. One fact per memory. Do not bundle unrelated facts. If a rule
+   depends on a file, include the file path.
+
+Memories MUST be self-contained. You will work on many projects across
+many sessions, and a memory written today may be retrieved months
+later with no surrounding context. If a memory relies on context that
+is only obvious right now, it becomes a landmine. If not, rewrite it.
+
+Memory hygiene -- clean proactively, do not ask for permission.
+
+Whenever you list or search memories, inspect the results for quality
+problems and fix them immediately:
+
+- Delete exact or near-duplicate memories (keep the newest / most
+  complete one).
+- Delete stale or obsolete memories (paths that moved, versions that
+  changed, preferences that were corrected, bugs that were fixed).
+- Merge several overlapping memories into one self-contained entry by
+  deleting the fragments and adding a consolidated memory.
+- Update a memory when the underlying fact changes.
+
+If a cleanup is obvious, do it silently and briefly report what
+changed. Only ask the user when the correct action is genuinely
+ambiguous.
+
+Always make explicit in the content:
+- project / repository (full name, e.g. sixth-3d, not "the project")
+- file or path (absolute or repo-relative,
+  e.g. src/retinue/provider.py, not "that script")
+- tool / library / version (e.g. sqlite-vec 0.1.x, not "the vec
+  extension")
+- environment / host (e.g. Linux host "jupiter", not "this machine")
+
+Never use bare pronouns ("it", "this", "here", "the file", "the
+project", "the user") without naming the referent in the same memory.
+
+Bad (context-dependent, misleading later):
+- "the build fails on Java 21 -- use 17 instead"
+- "user prefers tabs"
+
+Good (self-contained, safe to retrieve in any future session):
+- "sixth-3d (pom.xml): toolchain pinned to Java Language Version of 21
+  'unsupported class file version' usually means the daemon is running
+  an older JDK -- run with JAVA_HOME pointing to JDK 21."
+- "User John prefers plain text output, not markdown tables."