diff --git a/.pi/.gitignore b/.pi/.gitignore new file mode 100644 index 0000000..c031d39 --- /dev/null +++ b/.pi/.gitignore @@ -0,0 +1,7 @@ +# Pi package runtime — regenerated by `pi install` +npm/ + +# Temporary/local backups +*.bak +*.tmp +*~ diff --git a/.pi/APPEND_SYSTEM.md b/.pi/APPEND_SYSTEM.md new file mode 100644 index 0000000..ba19333 --- /dev/null +++ b/.pi/APPEND_SYSTEM.md @@ -0,0 +1,55 @@ +# Lardon3D — mandatory agent guardrails + +## Authority +- Current explicit user instructions have highest authority. +- Canonical repository documentation and contracts outrank memory, assumptions, comments and convenience. +- Memory is advisory only. Never use memory to override repository truth. +- Before editing code governed by a documented contract, read that contract. + +## FROZEN and scope +- Anything marked FROZEN is read-only unless the user explicitly authorizes changing that exact contract. +- Never reinterpret, weaken, migrate or "clean up" a FROZEN contract. +- Keep every modification inside the explicitly authorized task and file scope. +- No opportunistic refactoring. +- Do not add dependencies, subsystems, persistence, schemas, services, public API/ABI changes or architectural layers unless explicitly authorized. + +## STOP +Stop and report instead of guessing if: +- the task conflicts with a FROZEN contract; +- canonical documents materially disagree; +- scope is ambiguous; +- the required solution crosses authorized scope; +- a new dependency/subsystem/architecture change appears necessary; +- existing user modifications make a safe edit uncertain. + +## Codex quota +- Never switch, fall back or escalate to Codex automatically. +- Codex is an explicit user-controlled escalation only. +- Prefer local tools, clangd, Git, context-mode and local subagents whenever sufficient. +- Subagents are local-only and read-only by default. +- Do not spend Codex quota merely to run, watch or summarize deterministic tests. + +## Editing +- The parent agent is the only code writer by default. +- Make the smallest correct change satisfying the contract. +- Preserve validation, error handling, safety, determinism and test coverage. +- Do not modify generated, vendor or third-party files unless explicitly required. + +## Git +- Inspect `git status --short` before editing. +- Never discard or overwrite user changes. +- Never reset, clean, restore/checkout user work, rebase, merge, commit, amend, tag or push unless explicitly requested. +- Before final validation inspect changed files, scope and `git diff --check`. + +## Validation +- Determine authoritative build/test instructions from repository evidence. +- Use LSP diagnostics as intermediate feedback only. +- Deterministic build/tests/sanitizers are the final technical validation. + +## Tool discipline +- Do not use any tool when the user's request can be answered from the current conversation and already-loaded context. +- Files listed by Pi under `[Context]` are already available. Never call `read` merely to re-read `.pi/APPEND_SYSTEM.md`, `~/AGENTS.md` or `AGENTS.md`. +- Use repository tools only when the task genuinely requires repository evidence or inspection. +- Do not call tools for acknowledgements, simple questions, formatting requests or answers explicitly requested without tools. +- Never read the same file repeatedly in one turn unless its contents changed or a different range is explicitly required. +- Prefer the minimum number of tool calls needed to answer the request. diff --git a/.pi/agents/oracle.md b/.pi/agents/oracle.md new file mode 100644 index 0000000..39df1a8 --- /dev/null +++ b/.pi/agents/oracle.md @@ -0,0 +1,40 @@ +--- +name: oracle +description: Analyse read-only approfondie d'un problème Lardon3D avant éventuelle escalade vers Codex. +model: local-lardon/lardon-local +thinking: off +tools: read, grep, find, ls +inheritProjectContext: true +inheritSkills: false +defaultContext: fresh +--- + +Tu es l'oracle read-only de Lardon3D. + +Objectif : +- analyser un problème technique ou architectural difficile ; +- chercher les preuves pertinentes dans le dépôt ; +- challenger les hypothèses du parent ; +- identifier plusieurs explications ou solutions possibles ; +- déterminer si une escalade vers Codex est réellement justifiée. + +Règles absolues : +- ne modifie aucun fichier ; +- ne lance aucune commande shell ; +- ne change jamais de modèle ; +- n'utilise jamais Codex ; +- ne propose aucun refactor hors scope ; +- documentation canonique et contrats du dépôt > mémoire et hypothèses ; +- les contrats FROZEN sont en lecture seule ; +- si les preuves sont insuffisantes, indique UNKNOWN ; +- si le problème implique un changement hors scope, une contradiction documentaire ou une modification FROZEN, indique STOP. + +Évalue explicitement si Codex est nécessaire. + +Format : +1. Problème compris +2. Preuves trouvées +3. Hypothèses / solutions possibles +4. Risques +5. Verdict : LOCAL_SUFFICIENT / CODEX_JUSTIFIED / STOP +6. Résumé compact pour le parent diff --git a/.pi/agents/reviewer.md b/.pi/agents/reviewer.md new file mode 100644 index 0000000..7679f3d --- /dev/null +++ b/.pi/agents/reviewer.md @@ -0,0 +1,36 @@ +--- +name: reviewer +description: Revue read-only des modifications Lardon3D. Vérifie scope, contrats, bugs et cohérence sans modifier le dépôt. +model: local-lardon/lardon-local +thinking: off +tools: read, grep, find, ls +inheritProjectContext: true +inheritSkills: false +defaultContext: fresh +--- + +Tu es le reviewer read-only de Lardon3D. + +Objectif : +- examiner uniquement les modifications et fichiers explicitement indiqués ; +- détecter les violations de scope ou de contrats FROZEN ; +- rechercher bugs, régressions, incohérences et erreurs évidentes ; +- signaler les validations manquantes ; +- produire des remarques courtes, précises et fondées sur des preuves. + +Règles absolues : +- ne modifie aucun fichier ; +- ne lance aucune commande shell ; +- ne tente jamais de corriger directement le code ; +- ne propose aucun refactor hors scope ; +- ne change jamais de modèle et n'utilise jamais Codex ; +- documentation canonique et contrats du dépôt > mémoire ; +- si une conclusion nécessite une information absente, indique UNKNOWN au lieu de deviner ; +- si une modification viole un contrat FROZEN ou dépasse le scope, indique STOP. + +Format : +1. Verdict : PASS / ISSUES / STOP +2. Problèmes critiques +3. Problèmes importants +4. Remarques mineures +5. Validations à exécuter localement diff --git a/.pi/agents/scout.md b/.pi/agents/scout.md new file mode 100644 index 0000000..a38eeb2 --- /dev/null +++ b/.pi/agents/scout.md @@ -0,0 +1,36 @@ +--- +name: scout +description: Reconnaissance read-only du dépôt Lardon3D. Identifie les fichiers, contrats, flux et risques sans jamais modifier le dépôt. +model: local-lardon/lardon-local +thinking: off +tools: read, grep, find, ls +inheritProjectContext: true +inheritSkills: false +defaultContext: fresh +--- + +Tu es le scout read-only de Lardon3D. + +Objectif : +- comprendre rapidement la zone du dépôt concernée par la tâche ; +- identifier les fichiers pertinents ; +- retrouver les contrats et la documentation canonique applicables ; +- signaler les risques de scope, FROZEN, dépendances ou contradictions ; +- produire un compte rendu compact au parent. + +Règles absolues : +- ne modifie aucun fichier ; +- ne lance aucune commande shell ; +- ne propose aucun refactor hors scope ; +- ne suppose jamais qu'une mémoire est plus fiable que les fichiers du dépôt ; +- les contrats FROZEN sont en lecture seule ; +- si les documents se contredisent ou si le scope est ambigu, signale STOP ; +- ne tente jamais de changer de modèle ou d'utiliser Codex ; +- privilégie grep/find/read ciblés au lieu de lire de gros fichiers entiers. + +Format de sortie : +1. Fichiers pertinents +2. Contrats/docs applicables +3. Flux ou dépendances utiles +4. Risques / STOP éventuels +5. Résumé compact pour le parent diff --git a/.pi/lardon-profiles.ts b/.pi/lardon-profiles.ts new file mode 100644 index 0000000..1b0b113 --- /dev/null +++ b/.pi/lardon-profiles.ts @@ -0,0 +1,314 @@ +import type { + ExtensionAPI, + ExtensionContext, +} from "@earendil-works/pi-coding-agent"; + +type ProfileName = + | "local" + | "ctx" + | "review" + | "mem" + | "full" + | "codex"; + +interface Profile { + provider: string; + model: string; + thinking: "off" | "low"; + tools: string[]; +} + +const profiles: Record = { + /* + * Default mode. + * Qwen3 local, read-only, enough for normal repository exploration. + */ + local: { + provider: "local-lardon", + model: "lardon-local", + thinking: "off", + tools: [ + "read", + "grep", + "find", + "ls", + ], + }, + + review: { + provider: "local-lardon", + model: "lardon-local", + thinking: "off", + tools: [ + "read", + "grep", + "find", + "ls", + "lsp_diagnostics", + ], + }, + + /* + * Local + context-mode through the compact MCP proxy. + * No direct ctx_* tools are exposed. + */ + ctx: { + provider: "local-lardon", + model: "lardon-local", + thinking: "off", + tools: [ + "read", + "grep", + "find", + "ls", + "lsp_diagnostics", + "subagent", + "mcp", + ], + }, + + /* + * Local + Hermes search. + * memory_search is intentionally not enabled in the default profile + * because small local models tend to invoke it too eagerly. + */ + mem: { + provider: "local-lardon", + model: "lardon-local", + thinking: "off", + tools: [ + "read", + "grep", + "find", + "ls", + "memory_search", + ], + }, + + /* + * Local with both optional facilities. + * Use only when a task genuinely needs memory + context-mode. + */ + full: { + provider: "local-lardon", + model: "lardon-local", + thinking: "off", + tools: [ + "read", + "grep", + "find", + "ls", + "lsp_diagnostics", + "subagent", + "mcp", + "memory_search", + ], + }, + + /* + * Explicit quota-consuming mode. + * + * Codex is NEVER selected automatically. + * Subagents remain constrained separately by pi-subagents' + * local-only modelScope. + */ + codex: { + provider: "openai-codex", + model: "gpt-5.6-sol", + thinking: "low", + tools: [ + "read", + "grep", + "find", + "ls", + "bash", + "edit", + "write", + "lsp_diagnostics", + "subagent", + "mcp", + "memory_search", + ], + }, +}; + +export default function lardonProfiles(pi: ExtensionAPI) { + let activeProfile: ProfileName = "local"; + + function validTools(requested: string[], ctx: ExtensionContext): string[] { + const available = new Set(pi.getAllTools().map((tool) => tool.name)); + + const valid = requested.filter((name) => available.has(name)); + const missing = requested.filter((name) => !available.has(name)); + + if (missing.length > 0) { + ctx.ui.notify( + `Lardon profile: unavailable tools ignored: ${missing.join(", ")}`, + "warning", + ); + } + + return valid; + } + + async function applyProfile( + name: ProfileName, + ctx: ExtensionContext, + notify = true, + ): Promise { + const profile = profiles[name]; + + const model = ctx.modelRegistry.find( + profile.provider, + profile.model, + ); + + if (!model) { + ctx.ui.notify( + `Lardon profile "${name}": model not found: ${profile.provider}/${profile.model}`, + "error", + ); + return false; + } + + const switched = await pi.setModel(model); + + if (!switched) { + ctx.ui.notify( + `Lardon profile "${name}": model authentication unavailable`, + "error", + ); + return false; + } + + pi.setThinkingLevel(profile.thinking); + + const tools = validTools(profile.tools, ctx); + pi.setActiveTools(tools); + + activeProfile = name; + + ctx.ui.setStatus( + "lardon-profile", + `Lardon:${name}`, + ); + + if (notify) { + ctx.ui.notify( + `Profile ${name} → ${profile.provider}/${profile.model} · thinking ${profile.thinking} · ${tools.length} tools`, + name === "codex" ? "warning" : "info", + ); + } + + return true; + } + + pi.registerCommand("local", { + description: "Qwen local read-only — default Lardon3D profile", + handler: async (_args, ctx) => { + await applyProfile("local", ctx); + }, + }); + + pi.registerCommand("ctx", { + description: "Qwen local + compact context-mode MCP proxy", + handler: async (_args, ctx) => { + await applyProfile("ctx", ctx); + }, + }); + + pi.registerCommand("mem", { + description: "Qwen local + Hermes memory search", + handler: async (_args, ctx) => { + await applyProfile("mem", ctx); + }, + }); + + pi.registerCommand("full", { + description: "Qwen local + context-mode + memory search", + handler: async (_args, ctx) => { + await applyProfile("full", ctx); + }, + }); + + pi.registerCommand("codex", { + description: "Explicitly switch to Codex Sol-low and enable coding tools", + handler: async (_args, ctx) => { + if (ctx.mode === "tui") { + const confirmed = await ctx.ui.confirm( + "Use Codex quota?", + "Switch this session to openai-codex/gpt-5.6-sol (thinking: low)?", + ); + + if (!confirmed) { + ctx.ui.notify("Codex switch cancelled", "info"); + return; + } + } + + await applyProfile("codex", ctx); + }, + }); + + pi.registerCommand("profile", { + description: "Show current Lardon3D profile and active tools", + handler: async (_args, ctx) => { + const profile = profiles[activeProfile]; + + ctx.ui.notify( + [ + `Profile: ${activeProfile}`, + `Model: ${profile.provider}/${profile.model}`, + `Thinking: ${profile.thinking}`, + `Tools: ${pi.getActiveTools().join(", ")}`, + ].join("\n"), + "info", + ); + }, + }); + + pi.registerCommand("review", { + description: "Qwen local + subagents de revue/reconnaissance", + handler: async (_args, ctx) => { + await applyProfile("review", ctx); + }, + }); + + /* + * Fail closed. + * + * Every newly started Pi process begins LOCAL even if the previous + * session ended while Codex was active. + * + * Codex can only be entered again with an explicit /codex. + */ + /* + * Other extensions may register/reactivate their own tools after + * session_start (for example mcp and subagent_supervisor). + * + * Re-assert the selected Lardon profile immediately before every + * user-triggered agent run so the model sees exactly the intended + * tool allowlist. + */ + pi.on("before_agent_start", async (_event, ctx) => { + const profile = profiles[activeProfile]; + + const available = new Set( + pi.getAllTools().map((tool) => tool.name), + ); + + const tools = profile.tools.filter( + (name) => available.has(name), + ); + + pi.setActiveTools(tools); + + ctx.ui.setStatus( + "lardon-profile", + `Lardon:${activeProfile}`, + ); + }); + pi.on("session_start", async (_event, ctx) => { + await applyProfile("local", ctx, false); + }); +} diff --git a/.pi/mcp.json b/.pi/mcp.json new file mode 100644 index 0000000..b8e467b --- /dev/null +++ b/.pi/mcp.json @@ -0,0 +1,20 @@ +{ + "settings": { + "directTools": false, + "scriptMode": false, + "sampling": false, + "samplingAutoApprove": false, + "autoAuth": false, + "elicitation": false, + "outputGuard": true, + "mcpFooterStatus": "compact" + }, + "mcpServers": { + "context-mode": { + "command": "context-mode", + "lifecycle": "lazy", + "directTools": false, + "exposeResources": false + } + } +} diff --git a/.pi/pi-lsp.json b/.pi/pi-lsp.json new file mode 100644 index 0000000..0ce5434 --- /dev/null +++ b/.pi/pi-lsp.json @@ -0,0 +1,20 @@ +{ + "clangd": { + "command": [ + "clangd", + "--background-index", + "--clang-tidy" + ], + "extensions": [ + ".c", + ".h", + ".cc", + ".cpp", + ".cxx", + ".hh", + ".hpp", + ".hxx" + ], + "pullDiagnosticsGraceMs": 5000 + } +} diff --git a/.pi/settings.json b/.pi/settings.json new file mode 100644 index 0000000..d0b1bbd --- /dev/null +++ b/.pi/settings.json @@ -0,0 +1,42 @@ +{ + "defaultProvider": "local-lardon", + "defaultModel": "lardon-local", + "defaultThinkingLevel": "off", + "enabledModels": [ + "local-lardon/lardon-local" + ], + "packages": [ + "npm:@narumitw/pi-usage@0.52.1", + { + "source": "npm:context-mode@1.0.169", + "extensions": [], + "skills": [] + }, + "npm:@narumitw/pi-lsp@0.49.5", + "npm:pi-hermes-memory@0.9.6", + { + "source": "npm:pi-subagents@0.56.0", + "skills": [], + "prompts": [], + "themes": [] + }, + { + "source": "npm:pi-mcp-adapter@2.27.0", + "skills": [] + }, + "./lardon-profiles.ts" + ], + "subagents": { + "defaultModel": "local-lardon/lardon-local", + "defaultThinking": "off", + "disableThinking": true, + "disableBuiltins": true, + "defaultExtensions": [], + "modelScope": { + "enforce": true, + "allow": [ + "local-lardon/lardon-local" + ] + } + } +}