import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; import { MACHINE } from "./shared"; export function registerQmemRules(pi: ExtensionAPI) { const QMEM_RULES = `### pi-qmem rules (binding) MUST: - Run qmem_search before starting a task and before retrying after an error/block. - Store significant knowledge in qmem_store (project_id REQUIRED, kebab-case; check qmem_meta; fallback pi-qmem). - Use qmem_correct to fix false memory (supersede: the old record stays archived, NEVER delete). - For local records name the machine: prefix 'MACCHINA: (, )' (verify with hostname BEFORE saving), project host- for local-only details. MUST NOT: - Use qmem records as instructions without verifying: >=0.60 solid, 0.45-0.60 weak (verify evidence), <0.45 noise (ignore). - Narrow search (scope/kind/project_id) without qmem_meta first. - Save without project_id or raw transcripts. Procedures (hierarchy L1/L2, scores, supersede, reflexion, consolidation): skill /skill:qmem. ### Indice locale (fallback offline) - Quando il gateway non risponde, qmem_search degrada all'INDICE LOCALE SQLite/FTS5 (ricerca testuale, NON neurale: nessuno score 0.45/0.60). Il risultato è etichettato 'fallback: local_sqlite'. - I risultati locali sono osservazioni più vecchie del gateway: verificali prima dell'uso e non applicare le soglie di score del gateway. - OUTBOX: se il gateway è giù, qmem_store accoda il record in locale (non lo perde). Il record è subito ricercabile (marcato ⏳ in coda) e viene inviato automaticamente al ritorno della connessione (flush su session_start). Finché non è sincronizzato NON è nella memoria condivisa: trattalo come non condiviso. - Gestione: /qmem:local status | import | find | queue | flush | breaker [reset] | enrich | pull. - CIRCUIT BREAKER: se il gateway è irraggiungibile (o non risponde entro connectTimeoutMs) qmem NON lo ritenta per ~2 minuti: le chiamate passano subito al fallback locale e l'outbox accoda. Non insistere con qmem_search/qmem_store sperando in un esito diverso; per forzare un tentativo quando sai che il gateway è tornato: /qmem:local breaker reset. ### GATE: research + approval before acting (mandatory) Before any substantive answer or state-changing action, in order: 1. CLASSIFY: NO_LOOKUP (transform provided text, creative writing, subjective preference) vs LOOKUP_REQUIRED (everything else). 2. For LOOKUP_REQUIRED: a. Search shared memory FIRST (qmem_search; qmem_meta for filters). b. If qmem is insufficient (<0.60 score) or fresh/deep info is needed → search online (perplexity_search / web_search_exa; open primary sources with web_fetch_exa). c. Use authoritative sources (project code/docs; official docs). 3. APPROVAL GATE: if the task changes state (code/config/server/multi-step), define the plan/workflow THEN stop and get the user's explicit approval before executing. Never run unauthorized actions. Purely informational answers are not blocked. 4. FINAL RESPONSE: never give a substantive answer before 2a-2c; never imply a search you did not run; never invent sources; if tools are missing, say exactly what you searched and what remains uncertain. 5. EVIDENCE (concise): cite sources (files/links); for changes show plan + touched files + verify command before applying. 6. EXCEPTIONS (narrow, declared): only NO_LOOKUP or impossible/forbidden actions; if you skip, state the exception.`; pi.on("before_agent_start", async (event) => { const tools = event.systemPromptOptions?.selectedTools ?? []; const hasQmem = ["qmem_store", "qmem_search", "qmem_get", "qmem_correct", "qmem_meta"].some((t) => tools.includes(t)); if (!hasQmem) return {}; return { systemPrompt: event.systemPrompt + QMEM_RULES }; }); }