docs(sparse-sfm): close Gate D

This commit is contained in:
fy59 2026-08-24 18:40:58 +02:00
parent 148905841f
commit 835d96f8c4
16 changed files with 29 additions and 592 deletions

7
.pi/.gitignore vendored
View file

@ -1,7 +0,0 @@
# Pi package runtime — regenerated by `pi install`
npm/
# Temporary/local backups
*.bak
*.tmp
*~

View file

@ -1,55 +0,0 @@
# 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.

View file

@ -1,40 +0,0 @@
---
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

View file

@ -1,36 +0,0 @@
---
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

View file

@ -1,36 +0,0 @@
---
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

View file

@ -1,314 +0,0 @@
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);
});
}

View file

@ -1,20 +0,0 @@
{
"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
}
}
}

View file

@ -1,20 +0,0 @@
{
"clangd": {
"command": [
"clangd",
"--background-index",
"--clang-tidy"
],
"extensions": [
".c",
".h",
".cc",
".cpp",
".cxx",
".hh",
".hpp",
".hxx"
],
"pullDiagnosticsGraceMs": 5000
}
}

View file

@ -1,42 +0,0 @@
{
"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"
]
}
}
}

View file

@ -165,9 +165,10 @@ Matcher v1, Geometric Verification Model v1 et Geometric Verifier Fundamental v1
sont implémentés. Le runtime Feature + Matcher + Verifier emploie des tâches durables,
de petits lots, le Resource Governor interactif et un hot path Vulkan ORB exact avec
fallback CPU. La feasibility Vulkan SIFT/RootSIFT a été rejetée ; ces deux matchers
restent sur OpenCV L2. Track Model/Builder et les primitives géométriques Sparse
SfM sont implémentés ; le solveur Sparse SfM complet, le DAG, le viewer et les
étapes denses restent des tickets séparés planifiés. Le Resource Governor ne
restent sur OpenCV L2. Track Model/Builder, les primitives géométriques Gate C
et le noyau Sparse SfM incrémental Gate D sont implémentés ; BA, l'orchestration
Sparse SfM, le DAG, le viewer et les étapes denses restent des tickets séparés
planifiés. Le Resource Governor ne
constitue pas un Resource System générique : voir la décision darchitecture.
## Licence

View file

@ -120,8 +120,8 @@ les Feature Sets persistés.
**IMPLEMENTED** — vérification géométrique et tracks. **Sparse SfM Gate A
PASS**, the Sparse SfM v16 persistence model is **FROZEN** after Gate B;
the numerical solver and reconstruction pipeline remain **PLANNED** until later
implementation gates.
Gate C geometry and the synchronous in-memory Gate D incremental core are
**IMPLEMENTED / PASS**. BA and project/task orchestration remain **PLANNED**.
## Extension v2 multi-descriptor

View file

@ -798,5 +798,7 @@ orphelins et compaction Visual Index. Feature Store et Visual Index v1 sont impl
Visual Index v1 borne un index à 256 segments de 16 memberships, soit 4096 Feature Sets;
la couverture de 50 000 Feature Sets nécessitera la compaction ou une évolution v2.
**PLANNED** — dépendances d'artefacts, graphe géométrique et
reconstruction incrémentale.
**PLANNED** — dépendances d'artefacts, graphe géométrique et orchestration
projet/tâche de la reconstruction incrémentale. Le noyau Sparse SfM
incrémental synchrone en mémoire Gate D est **IMPLEMENTED / PASS** hors
Project DB v16.

View file

@ -125,16 +125,17 @@ USAC/MAGSAC avec configuration, seed et fingerprint déterministes.
**Statut :** COMPLETED/FROZEN — le Track Builder v1 direct et durable est
implémenté dans Project DB v15 (`track_sets`, `tracks`, `track_observations` et
le payload de tâche). Les primitives de géométrie calibrée Gate C sont
implémentées; le solveur incrémental complet et l'orchestration restent PLANNED.
implémentées et le noyau Sparse SfM incrémental Gate D est IMPLEMENTED / PASS ;
l'orchestration projet et tâche reste PLANNED.
Le modèle de persistance Sparse SfM v16 est gelé après Gate B.
**Sparse SfM Gate A : PASS.** Le contrat géométrique, la stratégie
incremental, la triangulation candidate, le gauge, les conventions de pose,
les limites BA et l'enveloppe matérielle sont documentés dans
`architecture/sparse_sfm.md`. Le solveur Sparse SfM reste
**NOT_IMPLEMENTED** jusqu'aux Gates DG; ses primitives pures calibrées sont
implémentées en Gate C, tandis que sa persistance v16 et ses lecteurs bornés
restent ceux de B2.
`architecture/sparse_sfm.md`. Ses primitives pures calibrées Gate C sont
**IMPLEMENTED / PASS** et son noyau incrémental synchrone en mémoire Gate D est
**IMPLEMENTED / PASS**. BA et orchestration restent **PLANNED**, tandis que sa
persistance v16 et ses lecteurs bornés restent ceux de B2.
---

View file

@ -450,7 +450,8 @@ Governor and persistence publication.
Gate D consumes exactly one immutable Track Set, one immutable calibration
scope, finite calibration values for participating images, bounded keypoint
coordinates addressed by `(feature_set_id, feature_index)`, and explicit
fingerprinted parameters. The Track Set is never mutated.
parameters immutable during execution. Gate D neither computes nor carries the
future parameter fingerprint. The Track Set is never mutated.
### Algorithm
@ -592,9 +593,9 @@ policy loop performs a `limit + 1` attempt.
## Out of scope
No production Sparse SfM, triangulator, camera solver, BA, Project DB v16,
metric alignment, control-point scale, dense/MVS, mesh, texturing, Vulkan SfM,
GPU BA, network/distributed scheduling or UI workflow is implemented here.
Beyond the Gate D incremental core, no BA, Project DB integration, metric
alignment, control-point scale, dense/MVS, mesh, texturing, Vulkan SfM, GPU BA,
network/distributed scheduling or UI workflow is implemented here.
## Gate B — model and persistence contract

View file

@ -121,8 +121,9 @@ des images de ScanSets différents sans dépendre de leur nom ou ordre.
**IMPLEMENTED** — paires candidates, matching, vérification géométrique et
Track Model / Track Builder v1 peuvent consommer le catalogue et ses assets.
Les primitives géométriques Sparse SfM sont implémentées par Gate C.
Les primitives géométriques Sparse SfM Gate C et le noyau incrémental
synchrone en mémoire Gate D sont **IMPLEMENTED / PASS**.
**PLANNED** — solveur Sparse SfM complet, MVS et relations géométriques entre
ScanSets. La vérification/scrub des assets et la réconciliation globale restent
également NOT_YET_WIRED.
**PLANNED** — BA, orchestration Sparse SfM, MVS et relations géométriques
entre ScanSets. La vérification/scrub des assets et la réconciliation globale
restent également NOT_YET_WIRED.

View file

@ -50,10 +50,11 @@ Lardon3D suit une feuille de route ordonnée qui privilégie la stabilité et la
- ✅ Candidate Pair Generator
- ✅ Matching et vérification géométrique
- ✅ Track Model / Track Builder v1
- 🔄 Sparse SfM : primitives géométriques Gate C implémentées ; solveur complet planifié
- ✅ Sparse SfM : primitives géométriques Gate C et noyau incrémental Gate D
implémentés
### Phase 5 : Reconstruction (PLANNED)
- 📋 Reconstruction incrémentale
- 📋 Orchestration de reconstruction incrémentale
- 📋 MVS / dense
- 📋 Mesh
- 📋 Contraintes externes