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, 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 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 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 restent sur OpenCV L2. Track Model/Builder, les primitives géométriques Gate C
SfM sont implémentés ; le solveur Sparse SfM complet, le DAG, le viewer et les et le noyau Sparse SfM incrémental Gate D sont implémentés ; BA, l'orchestration
étapes denses restent des tickets séparés planifiés. Le Resource Governor ne 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. constitue pas un Resource System générique : voir la décision darchitecture.
## Licence ## Licence

View file

@ -120,8 +120,8 @@ les Feature Sets persistés.
**IMPLEMENTED** — vérification géométrique et tracks. **Sparse SfM Gate A **IMPLEMENTED** — vérification géométrique et tracks. **Sparse SfM Gate A
PASS**, the Sparse SfM v16 persistence model is **FROZEN** after Gate B; PASS**, the Sparse SfM v16 persistence model is **FROZEN** after Gate B;
the numerical solver and reconstruction pipeline remain **PLANNED** until later Gate C geometry and the synchronous in-memory Gate D incremental core are
implementation gates. **IMPLEMENTED / PASS**. BA and project/task orchestration remain **PLANNED**.
## Extension v2 multi-descriptor ## 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; 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. 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 **PLANNED** — dépendances d'artefacts, graphe géométrique et orchestration
reconstruction incrémentale. 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 **Statut :** COMPLETED/FROZEN — le Track Builder v1 direct et durable est
implémenté dans Project DB v15 (`track_sets`, `tracks`, `track_observations` et 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 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. 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 **Sparse SfM Gate A : PASS.** Le contrat géométrique, la stratégie
incremental, la triangulation candidate, le gauge, les conventions de pose, incremental, la triangulation candidate, le gauge, les conventions de pose,
les limites BA et l'enveloppe matérielle sont documentés dans les limites BA et l'enveloppe matérielle sont documentés dans
`architecture/sparse_sfm.md`. Le solveur Sparse SfM reste `architecture/sparse_sfm.md`. Ses primitives pures calibrées Gate C sont
**NOT_IMPLEMENTED** jusqu'aux Gates DG; ses primitives pures calibrées sont **IMPLEMENTED / PASS** et son noyau incrémental synchrone en mémoire Gate D est
implémentées en Gate C, tandis que sa persistance v16 et ses lecteurs bornés **IMPLEMENTED / PASS**. BA et orchestration restent **PLANNED**, tandis que sa
restent ceux de B2. 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 Gate D consumes exactly one immutable Track Set, one immutable calibration
scope, finite calibration values for participating images, bounded keypoint scope, finite calibration values for participating images, bounded keypoint
coordinates addressed by `(feature_set_id, feature_index)`, and explicit 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 ### Algorithm
@ -592,9 +593,9 @@ policy loop performs a `limit + 1` attempt.
## Out of scope ## Out of scope
No production Sparse SfM, triangulator, camera solver, BA, Project DB v16, Beyond the Gate D incremental core, no BA, Project DB integration, metric
metric alignment, control-point scale, dense/MVS, mesh, texturing, Vulkan SfM, alignment, control-point scale, dense/MVS, mesh, texturing, Vulkan SfM, GPU BA,
GPU BA, network/distributed scheduling or UI workflow is implemented here. network/distributed scheduling or UI workflow is implemented here.
## Gate B — model and persistence contract ## 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 **IMPLEMENTED** — paires candidates, matching, vérification géométrique et
Track Model / Track Builder v1 peuvent consommer le catalogue et ses assets. 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 **PLANNED** — BA, orchestration Sparse SfM, MVS et relations géométriques
ScanSets. La vérification/scrub des assets et la réconciliation globale restent entre ScanSets. La vérification/scrub des assets et la réconciliation globale
également NOT_YET_WIRED. 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 - ✅ Candidate Pair Generator
- ✅ Matching et vérification géométrique - ✅ Matching et vérification géométrique
- ✅ Track Model / Track Builder v1 - ✅ 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) ### Phase 5 : Reconstruction (PLANNED)
- 📋 Reconstruction incrémentale - 📋 Orchestration de reconstruction incrémentale
- 📋 MVS / dense - 📋 MVS / dense
- 📋 Mesh - 📋 Mesh
- 📋 Contraintes externes - 📋 Contraintes externes