dev: add Pi local-agent workflow
This commit is contained in:
parent
e4675cd60b
commit
148905841f
9 changed files with 570 additions and 0 deletions
7
.pi/.gitignore
vendored
Normal file
7
.pi/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# Pi package runtime — regenerated by `pi install`
|
||||
npm/
|
||||
|
||||
# Temporary/local backups
|
||||
*.bak
|
||||
*.tmp
|
||||
*~
|
||||
55
.pi/APPEND_SYSTEM.md
Normal file
55
.pi/APPEND_SYSTEM.md
Normal file
|
|
@ -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.
|
||||
40
.pi/agents/oracle.md
Normal file
40
.pi/agents/oracle.md
Normal file
|
|
@ -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
|
||||
36
.pi/agents/reviewer.md
Normal file
36
.pi/agents/reviewer.md
Normal file
|
|
@ -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
|
||||
36
.pi/agents/scout.md
Normal file
36
.pi/agents/scout.md
Normal file
|
|
@ -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
|
||||
314
.pi/lardon-profiles.ts
Normal file
314
.pi/lardon-profiles.ts
Normal file
|
|
@ -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<ProfileName, Profile> = {
|
||||
/*
|
||||
* 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<boolean> {
|
||||
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);
|
||||
});
|
||||
}
|
||||
20
.pi/mcp.json
Normal file
20
.pi/mcp.json
Normal file
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
20
.pi/pi-lsp.json
Normal file
20
.pi/pi-lsp.json
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"clangd": {
|
||||
"command": [
|
||||
"clangd",
|
||||
"--background-index",
|
||||
"--clang-tidy"
|
||||
],
|
||||
"extensions": [
|
||||
".c",
|
||||
".h",
|
||||
".cc",
|
||||
".cpp",
|
||||
".cxx",
|
||||
".hh",
|
||||
".hpp",
|
||||
".hxx"
|
||||
],
|
||||
"pullDiagnosticsGraceMs": 5000
|
||||
}
|
||||
}
|
||||
42
.pi/settings.json
Normal file
42
.pi/settings.json
Normal file
|
|
@ -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"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue