{
 "_doc": "Inventaire machine du projet Blueprint Factory (Kage Games). Généré par src/handoff/build_context.py — ne pas éditer à la main. Lire d'abord handoff.md.",
 "project": "Blueprint Factory",
 "language": "fr",
 "entry_point": "https://kg.g.caute.re/factory/",
 "entry_point_note": "La page /factory/ contient le handoff complet (27 sections) en HTML statique, lisible sans JavaScript ; handoff.md, llms.txt et context.json en sont des versions alternatives.",
 "handoff": "https://kg.g.caute.re/factory/handoff.md",
 "llms_txt": "https://kg.g.caute.re/factory/llms.txt",
 "state_as_of": "2026-11-10T23:00+01:00",
 "repo": {
  "name": "blueprint-factory",
  "remote": null,
  "note": "dépôt git local sans remote ; demander l'accès au propriétaire"
 },
 "hard_rules": [
  "Aucun vert (teinte 70–170° avec s ≥ 0,25 et v ≥ 0,15) dans l'art, l'UI, les SVG et les matériaux",
  "Aucun secret dans le chat, les logs, git ou les pages",
  "Ne jamais déployer soi-même : livrer un overlay, un opérateur le fusionne",
  "Overlays en ajout ou remplacement seulement (préfixe launcher/site/…) ; jamais build-site.sh complet ; jamais le Caddyfile",
  "Ne jamais toucher DNS, edge, VPN ni ACL",
  "Ne pas câbler jobs.json",
  "Unreal Engine exclu ; moteur cible Godot 4.7.2",
  "Steamworks : réservé au propriétaire",
  "Documenter chaque étape ; vérifier chaque affirmation (lint, test, HTTP 200)"
 ],
 "urls": {
  "factory_home": "https://kg.g.caute.re/factory/",
  "referential": "https://kg.g.caute.re/factory/referential/",
  "kit_kx": "https://kg.g.caute.re/factory/kit/",
  "configurator": "https://kg.g.caute.re/factory/kit/configurator/",
  "variants": "https://kg.g.caute.re/factory/kit/variants/",
  "chain": "https://kg.g.caute.re/factory/chain/",
  "outpost_ox": "https://kg.g.caute.re/factory/outpost/",
  "grid_gx": "https://kg.g.caute.re/factory/grid/",
  "handoff_md": "https://kg.g.caute.re/factory/handoff.md",
  "llms_txt": "https://kg.g.caute.re/factory/llms.txt",
  "context_json": "https://kg.g.caute.re/factory/context.json",
  "data": {
   "kit_catalog": "https://kg.g.caute.re/factory/assets/kit/kit.json",
   "kit_config": "https://kg.g.caute.re/factory/assets/kit/config.json",
   "ox_catalog": "https://kg.g.caute.re/factory/outpost/data/ox.json",
   "gx_catalog": "https://kg.g.caute.re/factory/assets/grid/grid.json",
   "gx_palette_gpl": "https://kg.g.caute.re/factory/assets/grid/gx_palette.gpl",
   "v1_buildings": "https://kg.g.caute.re/factory/assets/buildings.json",
   "chain_artifacts": [
    "https://kg.g.caute.re/factory/chain/artifacts/ax02-mixte.brief.txt",
    "https://kg.g.caute.re/factory/chain/artifacts/ax02-mixte.spec.json",
    "https://kg.g.caute.re/factory/chain/artifacts/asm_mixte.json",
    "https://kg.g.caute.re/factory/chain/artifacts/hull_m.json",
    "https://kg.g.caute.re/factory/chain/artifacts/asm_mixte.svg",
    "https://kg.g.caute.re/factory/chain/artifacts/wear_seed.json",
    "https://kg.g.caute.re/factory/chain/artifacts/id_legend.json",
    "https://kg.g.caute.re/factory/chain/artifacts/qa_report.txt",
    "https://kg.g.caute.re/factory/chain/artifacts/kit_lint.txt",
    "https://kg.g.caute.re/factory/chain/artifacts/asm_mixte.tscn",
    "https://kg.g.caute.re/factory/chain/artifacts/asm_mixte.gameplay.json",
    "https://kg.g.caute.re/factory/chain/artifacts/godot-check.txt"
   ],
   "style_kit": "https://kg.g.caute.re/factory/chain/artifacts/style-kit.json"
  },
  "deep_city_context": {
   "v0.1": "https://kg.g.caute.re/play/deep-city/",
   "v0.2": "https://kg.g.caute.re/play/deep-city-v2/",
   "v0.3_kepler_ombre": "https://kg.g.caute.re/play/deep-city-v3/",
   "love2d": "https://kg.g.caute.re/play/deep-city-love2d/",
   "raylib": "https://kg.g.caute.re/play/deep-city-raylib/",
   "phaser": "https://kg.g.caute.re/play/deep-city-phaser/",
   "vanilla": "https://kg.g.caute.re/play/deep-city-vanilla/"
  },
  "deep_links": {
   "home": "/factory/#<habitat_s|command_hq|landing_pad>/<wire|solid|tex>",
   "kit": "/factory/kit/#<components|modules|hulls|assemblies>/<id>/<wire|solid|tex>",
   "outpost": "/factory/outpost/#<components|buildings|plots|assemblies>/<id>/<wire|solid|tex>",
   "grid": "/factory/grid/#<components|modules|hulls|assemblies>/<id> | #methods",
   "configurator": "/factory/kit/configurator/#h=<s|m|l>&f=<slot-module[-r],…>&sn=<immat>&w=<0-3>&st=<bande>",
   "variants": "/factory/kit/variants/?base=<seed>&n=<count> | ?sheet&mode=tex"
  }
 },
 "glossary": {
  "U": "0,25 m (grille KX) ; u = U/5 = 0,05 m",
  "g": "1 voxel GX = U/2 = 0,125 m (G8) ; G4 = 1 vox = U (LOD dérivé)",
  "C1": "slot 3,00 × 2,00 × 2,00 m (12U × 8U × 8U)",
  "C2": "slot 6,25 × 2,00 × 2,00 m = 2 × C1 + nervure 0,25 ; accepte 1 × C2 ou 2 × C1 (sous-slots a/b à ±1,625)",
  "KX-4": "interface : 8 coins KXC, 4 verrous KXL, 4 bras KXB, 1 ombilicale UMB (2 sur C2)",
  "KX": "kit cargo spatial",
  "HX": "coque KX",
  "AX": "assemblage KX",
  "OX": "kit avant-poste minier sur astéroïde",
  "PX": "parcelle OX",
  "OA": "assemblage OX",
  "F1": "emprise OX 4,00 × 4,00 m",
  "F2": "emprise OX 10,00 × 4,00 m = 2 × F1 + couloir 2,00",
  "OX-4": "socle commun OX (ANC, LEG, plancher +0,70, UMB↔HUB)",
  "GX": "KX quantifié voxel pour pixel art",
  "GH": "coque GX",
  "GA": "assemblage GX",
  "slot": "emplacement vide : seules les interfaces sont dessinées"
 },
 "kits": {
  "v1": {
   "spec_paths": [
    "specs/habitat_s.json",
    "specs/command_hq.json",
    "specs/landing_pad.json"
   ],
   "buildings": [
    {
     "id": "habitat_s",
     "name": "Module habitat S",
     "code": "HAB-S"
    },
    {
     "id": "command_hq",
     "name": "Centre de commandement",
     "code": "CMD-HQ"
    },
    {
     "id": "landing_pad",
     "name": "Aire d'atterrissage",
     "code": "PAD-L"
    }
   ],
   "build": "./build.sh",
   "page": "https://kg.g.caute.re/factory/"
  },
  "kx": {
   "charter": "specs/kit/style-kit.json",
   "charter_version": "1.0",
   "stats": {
    "modules": {
     "mod_liq": {
      "tare_t": 2.2,
      "load_t": 8.0,
      "cap": 8000,
      "unit": "L",
      "power_kw": 0.5,
      "label": "Liquides"
     },
     "mod_box": {
      "tare_t": 2.4,
      "load_t": 6.0,
      "cap": 10.0,
      "unit": "m³",
      "power_kw": 0.0,
      "label": "Fret sec"
     },
     "mod_ore": {
      "tare_t": 3.1,
      "load_t": 14.0,
      "cap": 6.0,
      "unit": "m³",
      "power_kw": 0.0,
      "label": "Minerai"
     },
     "mod_cryo": {
      "tare_t": 3.4,
      "load_t": 4.5,
      "cap": 6.5,
      "unit": "m³",
      "power_kw": 6.0,
      "label": "Cryogénie"
     },
     "mod_bio": {
      "tare_t": 6.8,
      "load_t": 7.0,
      "cap": 22.0,
      "unit": "m³",
      "power_kw": 9.0,
      "label": "Vivant"
     }
    },
    "hulls": {
     "hull_s": {
      "dry_t": 18.0,
      "payload_t": 24.0,
      "power_kw": 8.0,
      "crew": 2
     },
     "hull_m": {
      "dry_t": 34.0,
      "payload_t": 80.0,
      "power_kw": 16.0,
      "crew": 3
     },
     "hull_l": {
      "dry_t": 46.0,
      "payload_t": 90.0,
      "power_kw": 24.0,
      "crew": 4
     }
    },
    "rules": {
     "masse": "masse totale = coque à vide + Σ (tare + charge pleine) des modules",
     "charge_utile": "Σ (tare + charge) des modules ≤ payload_t de la coque, sinon assemblage refusé",
     "energie": "Σ power_kw des modules ≤ power_kw de la coque (bus ombilical), sinon refusé",
     "slots": "C1 → slot C1, ou demi-slot a/b d'un C2 ; C2 → slot C2 entier ; slot vide autorisé ; rotZ ∈ {0, 180}"
    },
    "generator": {
     "hull_weights": {
      "hull_s": 3,
      "hull_m": 4,
      "hull_l": 3
     },
     "p_empty": 0.12,
     "p_rot180": 0.4,
     "p_bio": {
      "mission": 0.8,
      "autres": 0.15,
      "_doc": "probabilité qu'un slot C2 reçoive 1 × KX-BIO (sinon 2 × C1)"
     },
     "missions": {
      "Citernier": {
       "mod_liq": 6,
       "mod_box": 1,
       "mod_cryo": 1
      },
      "Vraquier": {
       "mod_ore": 6,
       "mod_box": 1,
       "mod_liq": 1
      },
      "Frigorifique": {
       "mod_cryo": 5,
       "mod_box": 2,
       "mod_liq": 1
      },
      "Mixte": {
       "mod_liq": 2,
       "mod_box": 2,
       "mod_ore": 2,
       "mod_cryo": 2
      },
      "Bétailler": {
       "mod_bio": 6,
       "mod_cryo": 2,
       "mod_box": 1,
       "mod_liq": 1
      }
     }
    }
   },
   "spec_dirs": {
    "modules": "specs/kit/modules/",
    "hulls": "specs/kit/hulls/",
    "assemblies": "specs/kit/assemblies/"
   },
   "metrics": {
    "grid": {
     "U": 0.25,
     "u": 0.05,
     "_rule": "Toute cote structurelle (enveloppe, slot, plaque, nervure, cadre) est un multiple de u = U/5. Les têtes de rivets et biseaux XS sont des exceptions micro listées ici."
    },
    "slots": {
     "C1": {
      "L": 3.0,
      "W": 2.0,
      "H": 2.0,
      "label": "Slot simple C1 (12U × 8U × 8U)"
     },
     "C2": {
      "L": 6.25,
      "W": 2.0,
      "H": 2.0,
      "label": "Slot double C2 (25U × 8U × 8U) = 2 × C1 + 1 nervure"
     },
     "clearance": 0.05,
     "rib_gap": 0.25,
     "_rule": "Un module occupe le slot moins le jeu (0,05 m par face). Deux slots C1 consécutifs sont séparés d'une nervure de 1U ; C2 = 2 × C1 + 1U, donc un C2 remplace exactement deux C1 alignés."
    },
    "interface": {
     "name": "KX-4",
     "casting": {
      "size": 0.2,
      "bevel": 0.025,
      "slot_hole": [
       0.1,
       0.05
      ]
     },
     "twistlock_inset": 0.1,
     "umbilical": {
      "r": 0.15,
      "bolts": 6,
      "pos": [
       0,
       0
      ]
     },
     "plate_t": 0.05,
     "_rule": "8 pièces de coin KX (cube 0,20 biseauté) aux coins de l'enveloppe module. 4 verrous tournants au plancher du slot sous les coins bas (retrait 0,10), 4 bras de serrage en tête sous les coins hauts, 1 prise ombilicale Ø0,30 au centre du plancher."
    },
    "rivet": {
     "micro": {
      "d": 0.03,
      "h": 0.012,
      "pitch": 0.15,
      "edge": 0.05,
      "segs": 6
     },
     "macro": {
      "d": 0.06,
      "h": 0.02,
      "pitch": 0.3,
      "edge": 0.1,
      "segs": 6
     },
     "_rule": "Rangée centrée : n = floor((L − 2·edge)/pitch) + 1, pas constant, marge ≥ edge. Macro = micro × 2 (coques)."
    },
    "bevel": {
     "XXS": 0.01,
     "XS": 0.025,
     "S": 0.05,
     "M": 0.1,
     "L": 0.2,
     "XL": 0.4
    },
    "plates": {
     "module": 0.5,
     "hull": 1.0,
     "seam_w": 0.01,
     "_rule": "Joints de bordé tous les 2U sur les modules, 4U sur les coques ; joints alignés sur la grille d'origine de la pièce."
    },
    "frame": {
     "rail": 0.1,
     "rail_bevel": 0.025,
     "rib_t": 0.1,
     "rib_d": 0.2,
     "rib_pitch": 0.5
    },
    "markings": {
     "band_h": 0.15,
     "band_z": 1.45,
     "hazard_w": 0.1,
     "id_h": 0.2
    }
   },
   "palette": {
    "bg": "#0a1a33",
    "ink": "#eef7ff",
    "cyan": "#62d6ff",
    "dim": "#7fd6ff",
    "muted": "#7f9cc4",
    "marking": "#ffad5c",
    "slot": "#ff9a3c",
    "cut": "#ff6f61",
    "hull": "#c9ccd2",
    "frame": "#3a3f4a",
    "plate": "#9aa3b0",
    "iface": "#f2b705",
    "rock": "#4a3f36",
    "codes": {
     "LIQ": "#2f7fd0",
     "BOX": "#e0573a",
     "ORE": "#c8962e",
     "CRYO": "#8fd3ff",
     "BIO": "#b06ad8"
    },
    "_rule": "Aucun vert (teinte 70°–170°) nulle part : art, UI, SVG. Vérifié par kit_lint."
   },
   "budget_triangles": {
    "component": 2500,
    "module": 20000,
    "hull": 45000,
    "assembly": 100000
   },
   "gameplay": {
    "units": {
     "mass": "t",
     "volume": "m³",
     "density": "t/m³",
     "cost": "cr"
    },
    "cargo": {
     "LIQ": {
      "density": 1.0,
      "label": "liquides"
     },
     "BOX": {
      "density": 0.6,
      "label": "fret sec"
     },
     "ORE": {
      "density": 2.33,
      "label": "minerai"
     },
     "CRYO": {
      "density": 0.69,
      "label": "cryogénie"
     },
     "BIO": {
      "density": 0.32,
      "label": "vivant"
     }
    },
    "modules": {
     "mod_liq": {
      "usable": 0.75,
      "tare_t": 2.2,
      "cost_cr": 700
     },
     "mod_box": {
      "usable": 0.935,
      "tare_t": 2.4,
      "cost_cr": 900
     },
     "mod_ore": {
      "usable": 0.56,
      "tare_t": 3.1,
      "cost_cr": 500
     },
     "mod_cryo": {
      "usable": 0.61,
      "tare_t": 3.4,
      "cost_cr": 1800
     },
     "mod_bio": {
      "usable": 0.975,
      "tare_t": 6.8,
      "cost_cr": 3200
     }
    },
    "hulls": {
     "hull_s": {
      "dry_t": 18.0,
      "cost_cr": 7000
     },
     "hull_m": {
      "dry_t": 34.0,
      "cost_cr": 12000
     },
     "hull_l": {
      "dry_t": 46.0,
      "cost_cr": 19000
     }
    }
   },
   "components": [
    {
     "id": "cmp_rvt",
     "code": "RVT",
     "name": "Rangée de rivets",
     "triangles": 108
    },
    {
     "id": "cmp_bvl",
     "code": "BVL",
     "name": "Profil biseauté",
     "triangles": 28
    },
    {
     "id": "cmp_pnl",
     "code": "PNL",
     "name": "Plaque de bordé",
     "triangles": 228
    },
    {
     "id": "cmp_rib",
     "code": "RIB",
     "name": "Nervure de renfort",
     "triangles": 252
    },
    {
     "id": "cmp_kxc",
     "code": "KXC",
     "name": "Pièce de coin KX",
     "triangles": 104
    },
    {
     "id": "cmp_kxl",
     "code": "KXL",
     "name": "Verrou tournant KX",
     "triangles": 224
    },
    {
     "id": "cmp_kxb",
     "code": "KXB",
     "name": "Bras de serrage KX",
     "triangles": 268
    },
    {
     "id": "cmp_umb",
     "code": "UMB",
     "name": "Prise ombilicale KX",
     "triangles": 376
    },
    {
     "id": "cmp_ifp",
     "code": "IFP",
     "name": "Plaque d'interface de slot",
     "triangles": 2076
    },
    {
     "id": "cmp_vnt",
     "code": "VNT",
     "name": "Grille d'aération",
     "triangles": 200
    },
    {
     "id": "cmp_rng",
     "code": "RNG",
     "name": "Poignée / échelon",
     "triangles": 200
    },
    {
     "id": "cmp_bcn",
     "code": "BCN",
     "name": "Feu balise",
     "triangles": 162
    },
    {
     "id": "cmp_pip",
     "code": "PIP",
     "name": "Raccord de tuyauterie",
     "triangles": 480
    },
    {
     "id": "cmp_dor",
     "code": "DOR",
     "name": "Porte cargo",
     "triangles": 1168
    }
   ],
   "modules": [
    {
     "id": "mod_bio",
     "code": "KX-BIO",
     "name": "Module vivarium",
     "cls": "C2",
     "triangles": 16880
    },
    {
     "id": "mod_box",
     "code": "KX-BOX",
     "name": "Module conteneur sec",
     "cls": "C1",
     "triangles": 11200
    },
    {
     "id": "mod_cryo",
     "code": "KX-CRY",
     "name": "Module cryogénique",
     "cls": "C1",
     "triangles": 8456
    },
    {
     "id": "mod_liq",
     "code": "KX-LIQ",
     "name": "Module citerne",
     "cls": "C1",
     "triangles": 5430
    },
    {
     "id": "mod_ore",
     "code": "KX-ORE",
     "name": "Module vrac minerai",
     "cls": "C1",
     "triangles": 5164
    }
   ],
   "hulls": [
    {
     "id": "hull_l",
     "code": "HX-L",
     "name": "Coque long-courrier",
     "triangles": 41076
    },
    {
     "id": "hull_m",
     "code": "HX-M",
     "name": "Coque cargo moyen",
     "triangles": 32744
    },
    {
     "id": "hull_s",
     "code": "HX-S",
     "name": "Coque caboteur",
     "triangles": 16924
    }
   ],
   "assemblies": [
    {
     "id": "asm_caboteur",
     "code": "AX-01",
     "name": "Caboteur citerne + fret",
     "hull": "hull_s",
     "triangles": 33554,
     "fill": [
      {
       "slot": "S1",
       "module": "mod_liq"
      },
      {
       "slot": "S2",
       "module": "mod_box",
       "rot": 180
      }
     ]
    },
    {
     "id": "asm_longcourrier",
     "code": "AX-04",
     "name": "Long-courrier vivarium",
     "hull": "hull_l",
     "triangles": 96928,
     "fill": [
      {
       "slot": "S1",
       "module": "mod_bio"
      },
      {
       "slot": "S2",
       "module": "mod_cryo"
      },
      {
       "slot": "S3",
       "module": "mod_box"
      },
      {
       "slot": "S4",
       "module": "mod_liq",
       "sub": "a"
      },
      {
       "slot": "S4",
       "module": "mod_liq",
       "sub": "b",
       "rot": 180
      },
      {
       "slot": "S5",
       "module": "mod_cryo"
      }
     ]
    },
    {
     "id": "asm_minerai",
     "code": "AX-03",
     "name": "Minéralier partiel",
     "hull": "hull_m",
     "triangles": 58830,
     "fill": [
      {
       "slot": "S1",
       "module": "mod_liq"
      },
      {
       "slot": "S3",
       "module": "mod_ore"
      },
      {
       "slot": "S4",
       "module": "mod_ore",
       "rot": 180
      },
      {
       "slot": "S5",
       "module": "mod_ore"
      },
      {
       "slot": "S6",
       "module": "mod_ore",
       "rot": 180
      }
     ]
    },
    {
     "id": "asm_mixte",
     "code": "AX-02",
     "name": "Cargo moyen mixte",
     "hull": "hull_m",
     "triangles": 76614,
     "fill": [
      {
       "slot": "S1",
       "module": "mod_cryo"
      },
      {
       "slot": "S2",
       "module": "mod_cryo"
      },
      {
       "slot": "S3",
       "module": "mod_box"
      },
      {
       "slot": "S4",
       "module": "mod_liq",
       "rot": 180
      },
      {
       "slot": "S5",
       "module": "mod_ore"
      },
      {
       "slot": "S6",
       "module": "mod_ore",
       "rot": 180
      }
     ]
    }
   ],
   "lint": {
    "tool": "tools/kit_lint.py",
    "ok": 119,
    "total": 119
   },
   "build": "./build-kit.sh (FAST=1 sans Blender)",
   "tests": [
    "tools/test-kit.mjs",
    "tools/test-kit-config.mjs",
    "tools/test-kit-nav.mjs"
   ],
   "pages": [
    "https://kg.g.caute.re/factory/kit/",
    "https://kg.g.caute.re/factory/kit/configurator/",
    "https://kg.g.caute.re/factory/kit/variants/"
   ],
   "doc": "docs/kit/README.md"
  },
  "ox": {
   "charter": "specs/outpost/style-outpost.json",
   "charter_version": "0.1",
   "extends": "specs/kit/style-kit.json",
   "inherits": [
    "grid",
    "rivet",
    "bevel",
    "plates",
    "frame",
    "markings",
    "strokes",
    "type",
    "palette"
   ],
   "spec_dirs": {
    "buildings": "specs/outpost/buildings/",
    "plots": "specs/outpost/plots/",
    "assemblies": "specs/outpost/assemblies/"
   },
   "metrics": {
    "lattice": {
     "pitch": 6.0,
     "corridor": 2.0
    },
    "footprints": {
     "F1": {
      "L": 4.0,
      "W": 4.0,
      "label": "Emprise simple F1 (16U × 16U)"
     },
     "F2": {
      "L": 10.0,
      "W": 4.0,
      "label": "Emprise double F2 (40U × 16U) = 2 × F1 + 1 couloir"
     },
     "clearance": 0.25
    },
    "socle": {
     "name": "OX-4",
     "anchor_inset": 0.1,
     "anchor_head": [
      0.4,
      0.4,
      0.05
     ],
     "pile": {
      "d": 0.1,
      "depth": 1.2,
      "helix_d": 0.3,
      "helices": 3
     },
     "leg_h": 0.5,
     "leg_stroke": 0.1,
     "frame_sec": 0.2,
     "deck_z": 0.7,
     "hub_top": 0.426,
     "umb_gap": [
      0.05,
      0.1
     ],
     "slab_t": 0.05
    },
    "port": {
     "z": 1.75,
     "tube_d": 1.5,
     "flange_d": 1.8,
     "collar": 0.25,
     "bolts": 16,
     "segment": 0.5
    },
    "terrain": {
     "cell": 1.0,
     "terrace_z": 1.2,
     "terrace_margin": 1.0,
     "rim": 5.0
    }
   },
   "families": {
    "VIE": {
     "label": "Vie / équipage",
     "mat": "k_liq"
    },
    "EXT": {
     "label": "Extraction",
     "mat": "k_box"
    },
    "TRT": {
     "label": "Traitement / stockage",
     "mat": "k_ore"
    },
    "NRJ": {
     "label": "Énergie",
     "mat": "k_cryo"
    },
    "COM": {
     "label": "Communication",
     "mat": "k_bio"
    }
   },
   "budget_triangles": null,
   "components": [
    {
     "id": "oxc_anc",
     "code": "ANC",
     "name": "Ancrage régolithe",
     "triangles": 372
    },
    {
     "id": "oxc_leg",
     "code": "LEG",
     "name": "Vérin de nivellement",
     "triangles": 402
    },
    {
     "id": "oxc_hub",
     "code": "HUB",
     "name": "Borne de service",
     "triangles": 536
    },
    {
     "id": "oxc_spd",
     "code": "SPD",
     "name": "Semelle de slot",
     "triangles": 2948
    },
    {
     "id": "oxc_prt",
     "code": "PRT",
     "name": "Port de liaison",
     "triangles": 816
    },
    {
     "id": "oxc_tub",
     "code": "TUB",
     "name": "Tube de liaison",
     "triangles": 1412
    },
    {
     "id": "oxc_sup",
     "code": "SUP",
     "name": "Tréteau de tube",
     "triangles": 128
    },
    {
     "id": "oxc_mms",
     "code": "MMS",
     "name": "Blindage Whipple",
     "triangles": 532
    },
    {
     "id": "oxc_rad",
     "code": "RAD",
     "name": "Radiateur",
     "triangles": 520
    },
    {
     "id": "oxc_sol",
     "code": "SOL",
     "name": "Panneau solaire",
     "triangles": 732
    },
    {
     "id": "oxc_ant",
     "code": "ANT",
     "name": "Antenne",
     "triangles": 478
    },
    {
     "id": "oxc_sas",
     "code": "SAS",
     "name": "Sas d'accès",
     "triangles": 1542
    }
   ],
   "inherited_kx_components": [
    "RVT",
    "BVL",
    "RIB",
    "KXC",
    "UMB",
    "VNT",
    "RNG",
    "BCN",
    "PIP",
    "DOR"
   ],
   "buildings": [
    {
     "id": "bld_com",
     "code": "OX-COM",
     "name": "Relais de communication",
     "cls": "F1",
     "family": "COM",
     "triangles": 9346
    },
    {
     "id": "bld_drl",
     "code": "OX-DRL",
     "name": "Foreuse",
     "cls": "F1",
     "family": "EXT",
     "triangles": 8686
    },
    {
     "id": "bld_hab",
     "code": "OX-HAB",
     "name": "Habitat pressurisé",
     "cls": "F1",
     "family": "VIE",
     "triangles": 9166
    },
    {
     "id": "bld_hgr",
     "code": "OX-HGR",
     "name": "Hangar à engins",
     "cls": "F2",
     "family": "VIE",
     "triangles": 16692
    },
    {
     "id": "bld_pwr",
     "code": "OX-PWR",
     "name": "Centrale solaire",
     "cls": "F1",
     "family": "NRJ",
     "triangles": 7014
    },
    {
     "id": "bld_ref",
     "code": "OX-REF",
     "name": "Raffinerie",
     "cls": "F2",
     "family": "TRT",
     "triangles": 16316
    },
    {
     "id": "bld_sil",
     "code": "OX-SIL",
     "name": "Silo à minerai",
     "cls": "F1",
     "family": "TRT",
     "triangles": 8846
    }
   ],
   "plots": [
    {
     "id": "plot_l",
     "code": "PX-L",
     "name": "Parcelle de base",
     "triangles": 40234
    },
    {
     "id": "plot_m",
     "code": "PX-M",
     "name": "Parcelle d'exploitation",
     "triangles": 23820
    },
    {
     "id": "plot_s",
     "code": "PX-S",
     "name": "Parcelle de prospection",
     "triangles": 14070
    }
   ],
   "assemblies": [
    {
     "id": "oa_base",
     "code": "OA-03",
     "name": "Base minière complète",
     "plot": "plot_l",
     "triangles": 143872,
     "fill": [
      {
       "slot": "S1",
       "building": "bld_com"
      },
      {
       "slot": "S2",
       "building": "bld_hab"
      },
      {
       "slot": "S3",
       "building": "bld_hab"
      },
      {
       "slot": "S4",
       "building": "bld_drl"
      },
      {
       "slot": "S5",
       "building": "bld_hgr"
      },
      {
       "slot": "S6",
       "building": "bld_ref"
      },
      {
       "slot": "S7",
       "sub": "b",
       "building": "bld_pwr"
      },
      {
       "slot": "S7",
       "sub": "a",
       "building": "bld_hab",
       "rot": 180
      },
      {
       "slot": "S8",
       "building": "bld_sil"
      }
     ],
     "links": [
      [
       "S2",
       "E",
       "S3",
       "W"
      ],
      [
       "S3",
       "E",
       "S4",
       "W"
      ],
      [
       "S2",
       "N",
       "S5",
       "Sa"
      ],
      [
       "S5",
       "E",
       "S6",
       "W"
      ],
      [
       "S3",
       "N",
       "S6",
       "Sb"
      ],
      [
       "S7a",
       "N",
       "S5",
       "Na"
      ]
     ]
    },
    {
     "id": "oa_exploitation",
     "code": "OA-02",
     "name": "Exploitation minière",
     "plot": "plot_m",
     "triangles": 80140,
     "fill": [
      {
       "slot": "S1",
       "building": "bld_drl",
       "rot": 180
      },
      {
       "slot": "S2",
       "building": "bld_hab"
      },
      {
       "slot": "S3",
       "building": "bld_drl"
      },
      {
       "slot": "S4",
       "building": "bld_ref"
      },
      {
       "slot": "S5",
       "building": "bld_sil"
      }
     ],
     "links": [
      [
       "S1",
       "W",
       "S2",
       "W"
      ],
      [
       "S2",
       "E",
       "S3",
       "W"
      ],
      [
       "S2",
       "N",
       "S4",
       "Sa"
      ]
     ]
    },
    {
     "id": "oa_prospection",
     "code": "OA-01",
     "name": "Avant-poste de prospection",
     "plot": "plot_s",
     "triangles": 40476,
     "fill": [
      {
       "slot": "S1",
       "building": "bld_hab"
      },
      {
       "slot": "S2",
       "building": "bld_drl"
      },
      {
       "slot": "S3",
       "building": "bld_pwr"
      }
     ],
     "links": [
      [
       "S1",
       "E",
       "S2",
       "W"
      ]
     ]
    }
   ],
   "lint": {
    "tool": "tools/ox_lint.py",
    "ok": 150,
    "total": 150
   },
   "build": "./build-outpost.sh (FAST=1 sans Blender)",
   "tests": [
    "tools/test-outpost.mjs"
   ],
   "pages": [
    "https://kg.g.caute.re/factory/outpost/"
   ],
   "doc": "docs/outpost/README.md"
  },
  "gx": {
   "charter": "specs/grid/grid-kit.json",
   "charter_version": "0.1",
   "spec_dirs": {
    "modules": "specs/grid/modules/",
    "hulls": "specs/grid/hulls/",
    "assemblies": "specs/grid/assemblies/"
   },
   "metrics": {
    "grid": {
     "g": 0.125,
     "per_U": 2,
     "lod": {
      "G8": 1,
      "G4": 2
     }
    },
    "slots": {
     "C1": {
      "L": 24,
      "W": 16,
      "H": 16
     },
     "C2": {
      "L": 50,
      "W": 16,
      "H": 16
     },
     "rib_gap": 2,
     "clearance": 1,
     "lock_layer": 1
    },
    "render_iso_P": [
     [
      -2,
      2,
      0
     ],
     [
      1,
      1,
      -2
     ]
    ],
    "render_oblique_P": [
     [
      -2,
      0,
      0
     ],
     [
      0,
      2,
      -2
     ]
    ]
   },
   "palette_colors": 53,
   "verdict": {
    "retained": "A : géométrie née sur la grille, raster entier voxel par voxel en Python (src/grid/gx_raster.py)",
    "blender_ortho_B": "seulement pour 8 directions / caméra libre, retouches à prévoir (~82 % pixels exacts)",
    "G4": "LOD pour vues lointaines et icônes",
    "smooth_KX_B_prime": "0 % pixels exacts : un modèle lisse ne donne pas du pixel art lisible",
    "C_live": "outil de cadrage seulement"
   },
   "components": [
    {
     "id": "gx_crn",
     "code": "GX-CRN",
     "name": "Coin d'interface",
     "dims": [
      2,
      2,
      2
     ],
     "voxels": 8
    },
    {
     "id": "gx_lck",
     "code": "GX-LCK",
     "name": "Verrou tournant",
     "dims": [
      4,
      4,
      1
     ],
     "voxels": 16
    },
    {
     "id": "gx_arm",
     "code": "GX-ARM",
     "name": "Bras de serrage",
     "dims": [
      4,
      6,
      10
     ],
     "voxels": 64
    },
    {
     "id": "gx_umb",
     "code": "GX-UMB",
     "name": "Ombilicale mâle / femelle",
     "dims": [
      10,
      4,
      2
     ],
     "voxels": 32
    },
    {
     "id": "gx_rvt",
     "code": "GX-RVT",
     "name": "Règle de rivetage",
     "dims": [
      17,
      3,
      7
     ],
     "voxels": 306
    },
    {
     "id": "gx_bvl",
     "code": "GX-BVL",
     "name": "Règle de chanfrein",
     "dims": [
      36,
      16,
      16
     ],
     "voxels": 4165
    },
    {
     "id": "gx_pnl",
     "code": "GX-PNL",
     "name": "Bordé à joints",
     "dims": [
      17,
      2,
      9
     ],
     "voxels": 256
    },
    {
     "id": "gx_rib",
     "code": "GX-RIB",
     "name": "Nervure",
     "dims": [
      13,
      4,
      12
     ],
     "voxels": 408
    },
    {
     "id": "gx_vnt",
     "code": "GX-VNT",
     "name": "Évent",
     "dims": [
      6,
      2,
      6
     ],
     "voxels": 52
    },
    {
     "id": "gx_bcn",
     "code": "GX-BCN",
     "name": "Balise",
     "dims": [
      1,
      1,
      2
     ],
     "voxels": 2
    },
    {
     "id": "gx_pip",
     "code": "GX-PIP",
     "name": "Tuyau à brides",
     "dims": [
      14,
      6,
      10
     ],
     "voxels": 72
    },
    {
     "id": "gx_dor",
     "code": "GX-DOR",
     "name": "Porte",
     "dims": [
      8,
      2,
      12
     ],
     "voxels": 162
    },
    {
     "id": "gx_win",
     "code": "GX-WIN",
     "name": "Hublot",
     "dims": [
      6,
      2,
      6
     ],
     "voxels": 52
    },
    {
     "id": "gx_haz",
     "code": "GX-HAZ",
     "name": "Bande de danger",
     "dims": [
      16,
      1,
      2
     ],
     "voxels": 32
    },
    {
     "id": "gx_ifp",
     "code": "GX-IFP",
     "name": "Plaque d'interface de slot C1",
     "dims": [
      24,
      16,
      1
     ],
     "voxels": 384
    }
   ],
   "modules": [
    {
     "id": "gmod_bio",
     "code": "GX-BIO",
     "name": "Vivarium",
     "cls": "C2",
     "dims": [
      48,
      14,
      14
     ],
     "voxels": 7548
    },
    {
     "id": "gmod_box",
     "code": "GX-BOX",
     "name": "Conteneur sec",
     "cls": "C1",
     "dims": [
      22,
      14,
      14
     ],
     "voxels": 3146
    },
    {
     "id": "gmod_cryo",
     "code": "GX-CRY",
     "name": "Cuves cryo",
     "cls": "C1",
     "dims": [
      22,
      14,
      14
     ],
     "voxels": 2270
    },
    {
     "id": "gmod_liq",
     "code": "GX-LIQ",
     "name": "Citerne",
     "cls": "C1",
     "dims": [
      22,
      14,
      14
     ],
     "voxels": 2492
    },
    {
     "id": "gmod_ore",
     "code": "GX-ORE",
     "name": "Trémie à minerai",
     "cls": "C1",
     "dims": [
      22,
      14,
      14
     ],
     "voxels": 2648
    }
   ],
   "hulls": [
    {
     "id": "ghull_l",
     "code": "GH-L",
     "name": "Coque long-courrier",
     "dims": [
      257,
      20,
      44
     ],
     "voxels": 51938
    },
    {
     "id": "ghull_m",
     "code": "GH-M",
     "name": "Coque cargo moyen",
     "dims": [
      147,
      38,
      45
     ],
     "voxels": 70236
    },
    {
     "id": "ghull_s",
     "code": "GH-S",
     "name": "Coque caboteur",
     "dims": [
      107,
      20,
      42
     ],
     "voxels": 26056
    }
   ],
   "assemblies": [
    {
     "id": "gasm_caboteur",
     "code": "GA-01",
     "name": "Caboteur citerne + fret",
     "dims": [
      107,
      20,
      42
     ],
     "voxels": 31694
    },
    {
     "id": "gasm_longcourrier",
     "code": "GA-04",
     "name": "Long-courrier vivarium",
     "dims": [
      257,
      20,
      44
     ],
     "voxels": 72156
    },
    {
     "id": "gasm_minerai",
     "code": "GA-03",
     "name": "Minéralier partiel",
     "dims": [
      147,
      38,
      45
     ],
     "voxels": 83320
    },
    {
     "id": "gasm_mixte",
     "code": "GA-02",
     "name": "Cargo moyen mixte",
     "dims": [
      147,
      38,
      45
     ],
     "voxels": 85710
    }
   ],
   "lint": {
    "tool": "tools/grid_lint.py",
    "ok": 107,
    "total": 107
   },
   "build": "./build-grid.sh (FAST=1 sans Blender)",
   "tests": [
    "tools/test-grid.mjs"
   ],
   "pages": [
    "https://kg.g.caute.re/factory/grid/"
   ],
   "doc": "docs/grid/README.md"
  }
 },
 "chain_9_steps": {
  "subject": "AX-02 asm_mixte",
  "page": "https://kg.g.caute.re/factory/chain/",
  "doc": "docs/chain/README.md",
  "wear_seed": 4471,
  "steps": [
   {
    "n": 1,
    "name": "Brief",
    "source": "specs/briefs/ax02-mixte.brief.txt"
   },
   {
    "n": 2,
    "name": "Spec JSON",
    "cmd": "python3 src/chain/brief_to_spec.py specs/briefs/ax02-mixte.brief.txt --check specs/kit/assemblies/asm_mixte.json"
   },
   {
    "n": 3,
    "name": "Blockout",
    "cmd": "xvfb-run -a $BLENDER --background --python src/chain/chain_blender.py -- --pass blockout --out build/chain --seed 4471"
   },
   {
    "n": 4,
    "name": "Plan SVG",
    "cmd": "python3 src/kit_build.py"
   },
   {
    "n": 5,
    "name": "Kitbash 3D",
    "cmd": "src/blender_bridge.py (via ./build-kit.sh)"
   },
   {
    "n": 6,
    "name": "Usure",
    "cmd": "chain_blender.py --pass wear --seed 4471"
   },
   {
    "n": 7,
    "name": "Bake",
    "cmd": "chain_blender.py --pass ao_bake ; src/bake_textures.py ; chain_blender.py --pass id_bake"
   },
   {
    "n": 8,
    "name": "QA",
    "cmd": "python3 src/chain/chain_qa.py"
   },
   {
    "n": 9,
    "name": "Export Godot",
    "cmd": "python3 src/chain/chain_gameplay.py && python3 src/chain/chain_tscn.py ; godot --headless -s check.gd"
   }
  ],
  "gameplay_ax02": {
   "capacity_m3": 43.1,
   "load_t": 51.0,
   "mass_t": 102.5,
   "cost_cr": 18200,
   "source": "build/chain/godot/asm_mixte.gameplay.json"
  },
  "godot_check": "TSCN_OK AX-02 meshes=1 collisions=9 ancres=6 masse_t=102.5 cout_cr=18200"
 },
 "tests": {
  "playwright": [
   "tools/test-viewer.mjs",
   "tools/test-kit.mjs",
   "tools/test-kit-config.mjs",
   "tools/test-kit-nav.mjs",
   "tools/test-chain.mjs",
   "tools/test-outpost.mjs",
   "tools/test-grid.mjs",
   "tools/test-factory-home.mjs"
  ],
  "usage": "python3 -m http.server 8782 -d viewer & node tools/<test>.mjs http://127.0.0.1:8782/ [outdir]",
  "lints": [
   "python3 tools/kit_lint.py",
   "python3 tools/ox_lint.py",
   "python3 tools/grid_lint.py",
   "python3 src/chain/chain_qa.py"
  ]
 },
 "export": {
  "blender": "src/blender_bridge.py (contrôle cotes, GLB/FBX/_wire.glb, rendus)",
  "bake": "src/bake_textures.py",
  "web_glb": "src/kit_web_glb.py (Draco, --jpeg pour _tex)",
  "loader": "viewer/kit/kgltf.js (un seul DRACOLoader)",
  "godot": "Godot 4.7.2 headless (src/godot_check.gd, build/chain/godot/check.gd)"
 },
 "known_issues": [
  {
   "id": 1,
   "title": "Badge kit LINT 110/110 au lieu de 119/119",
   "cause": "viewer/assets/kit/kit.json embarque un lint.json antérieur aux contrôles configurateur",
   "status": "ouvert"
  },
  {
   "id": 2,
   "title": "Usure peu visible en vue d'ensemble",
   "status": "ouvert"
  },
  {
   "id": 3,
   "title": "OOM Draco galerie → configurateur",
   "status": "corrigé (2700872)"
  },
  {
   "id": 4,
   "title": "Cache navigateur sur /factory/* après mise en ligne",
   "status": "contourné par rechargement forcé"
  },
  {
   "id": 5,
   "title": "launcher/scripts/add-factory.sh efface site/factory et embarque le Caddyfile",
   "status": "ne pas utiliser en prod"
  },
  {
   "id": 6,
   "title": "OX sans budget triangles (OA-03 = 143 872)",
   "status": "question ouverte"
  },
  {
   "id": 7,
   "title": "build/kit/lint.json suivi par git, réécrit à chaque lint",
   "status": "ouvert"
  },
  {
   "id": 8,
   "title": "Dépôt sans remote",
   "status": "ouvert"
  },
  {
   "id": 9,
   "title": "Ancien overlay référentiel au préfixe factory/ au lieu de launcher/site/",
   "status": "historique"
  },
  {
   "id": 10,
   "title": "viewer/index.html du dépôt en retard sur la prod (nav)",
   "status": "corrigé par le commit handoff"
  },
  {
   "id": 11,
   "title": "Carte de normales GX avec teintes cyan-vert (technique)",
   "status": "exception documentée"
  },
  {
   "id": 12,
   "title": "Pas de booléens, SVG = sortie, collisions Godot seulement AX-02",
   "status": "limites connues"
  },
  {
   "id": 13,
   "title": "build/chain/ et build/grid/ non suivis et non ignorés",
   "status": "ouvert"
  }
 ],
 "decisions": [
  "Spec JSON = source de vérité ; SVG = sortie",
  "Mêmes sommets SVG/Blender + triple vérification des cotes",
  "3e dièdre, calques Inkscape, data-part",
  "m, Z-up, export Y-up",
  "Aucun vert, éclairage neutre/froid",
  "habitat_s en 2×2 tuiles (échelle humaine)",
  "Charte mesurée + composants communs + lint",
  "Coques/parcelles à slots vides ; assemblage = données",
  "Filaire côté client, Draco + JPEG, occlusion SVG",
  "Rendus Blender prioritaires si l'IA dévie",
  "OX étend KX sans copie ; couleur = famille",
  "GX : méthode A ; B pour 8 directions ; G4 pour lointain/icônes",
  "Brief → spec sans IA",
  "Densités calées sur le configurateur (≤ 0,37 %)",
  "Variantes generate(seed) mulberry32, correction plutôt que rejet",
  "Un seul DRACOLoader partagé + dispose",
  "Déploiement par overlays via opérateur",
  "Godot 4.7.2 cible, Unreal exclu",
  "Handoff rendu en entier dans /factory/ (index.html généré, ne pas éditer à la main)"
 ],
 "open_questions": [
  "Quel jeu consomme les kits ?",
  "3D ou pixel art à terme ?",
  "Budget triangles OX ?",
  "Édition inverse SVG → spec ou éditeur web de spec ?",
  "Étendre la chaîne 9 étapes à tous les AX/OA et à GX ?",
  "Accès au dépôt (remote) pour l'agent entrant ?"
 ],
 "conventions": {
  "commit": "« <Périmètre> : <résumé dense avec chiffres vérifiés> », corps = cause + correctif, en français",
  "overlay": "launcher-factory-<sujet>-overlay.tar.gz, chemins launcher/site/…, ajout/remplacement seulement, taille + sha256 + liste fournis, fusion par un opérateur",
  "verify": "lint du kit + test Playwright de la page + HTTP 200 après mise en ligne",
  "document": "README du kit + captures docs/ + handoff.md + context.json"
 },
 "commits": [
  {
   "commit": "396e5ee",
   "date_paris": "2026-11-10 23:54",
   "subject": "Handoff : context.json régénéré (commits jusqu'à l'accueil v2)"
  },
  {
   "commit": "acebdee",
   "date_paris": "2026-11-10 23:54",
   "subject": "Accueil factory v2 : handoff complet rendu en HTML statique dans /factory/ (27/27 sections lisibles sans JS)"
  },
  {
   "commit": "8b7432b",
   "date_paris": "2026-11-10 23:29",
   "subject": "Accueil factory : handoff agent IA — bandeau « commence par handoff.md », section #contexte, handoff.md (27 sections), llms.txt, context.json généré (src/handof"
  },
  {
   "commit": "2700872",
   "date_paris": "2026-11-10 22:14",
   "subject": "Kit KX/OX : libérer Draco et le contexte WebGL avant de quitter la page"
  },
  {
   "commit": "94009ef",
   "date_paris": "2026-11-10 17:36",
   "subject": "Kit OX : avant-poste minier sur astéroïde dérivé de KX — 12 composants OX + 10 KX hérités, 7 bâtiments F1/F2 sur socle OX-4, 3 parcelles à slots vides + couloir"
  },
  {
   "commit": "477f208",
   "date_paris": "2026-11-10 17:34",
   "subject": "Kit KX : configurateur (coque + modules par glisser-déposer/clic, validation live taille/KX-4/budgets, résumé masse/coût/énergie, habillage, export/import forma"
  },
  {
   "commit": "1278dc3",
   "date_paris": "2026-11-10 17:22",
   "subject": "Kit GX : kit KX quantifié sur grille voxel (g = U/2) pour rendu pixel art — 15 composants, 5 modules, 3 coques à slots vides, 4 assemblages, raster entier (A) v"
  },
  {
   "commit": "8c6bb9c",
   "date_paris": "2026-11-10 17:21",
   "subject": "Chaîne 9 étapes 9/9 réel : brief→spec déterministe, carte ID cuite, fiche gameplay calculée (densités/coûts dans style-kit.json), plafonds triangles, page /fact"
  },
  {
   "commit": "51bbbde",
   "date_paris": "2026-11-10 17:10",
   "subject": "Chaîne factory 9 étapes illustrée sur AX-02 : blockout, usure par seed, bake AO, QA, export .tscn Godot, planche + vignettes"
  },
  {
   "commit": "0da1d14",
   "date_paris": "2026-11-10 11:06",
   "subject": "Kit KX : 10 rendus PNG (Cycles hangar + versions cinématiques) et planche contact"
  },
  {
   "commit": "85673ea",
   "date_paris": "2026-11-10 10:21",
   "subject": "Kit KX : charte de style mesurée, 14 composants, 5 modules cargo, 3 coques à slots vides, 4 assemblages, lint (110), visionneuse /factory/kit/ 4 niveaux (Draco)"
  },
  {
   "commit": "75fc04d",
   "date_paris": "2026-11-09 21:54",
   "subject": "Visionneuse 3D web (Three.js) + textures cuites <id>_tex.glb ; build.sh : bake + viewer/assets"
  },
  {
   "commit": "87098a6",
   "date_paris": "2026-11-09 21:37",
   "subject": "Blueprint factory V1: spec JSON -> plans SVG cotés + Blender filaire/plein/texturé (habitat_s, command_hq, landing_pad)"
  }
 ]
}
