feat: public example of life-project gates system

Public demo of Factory 4 Life project management:

- Gate definitions S0 (spec), S1 (build), S2
  (integration), S3 (production ready)
- Hardware project template with PlatformIO,
  KiCad CI, and Makefile for fab packages
- JSON schema for .kill-life.yaml manifest
- CLI scripts: create-project, validate-gates,
  dashboard with color-coded status output
- Example project: led-controller (S0+S1 passed,
  S2 in progress)
This commit is contained in:
2026-04-07 15:39:30 +02:00
commit 8ae0eb239a
18 changed files with 820 additions and 0 deletions
+5
View File
@@ -0,0 +1,5 @@
.DS_Store
*.swp
*.swo
tmp/
.omc/
+67
View File
@@ -0,0 +1,67 @@
# life-project-example
Example repo for Factory 4 Life project management: gates S0-S3, templates, cross-repo orchestration.
> This is a **public demo** of the project management system. See the gate definitions, templates, and scripts below.
## Concept
Chaque projet hardware/firmware/software suit un pipeline de **gates** (S0 -> S3) inspiré du stage-gate process. Ce repo centralise :
- **Gates** : definitions, criteres, checklists (`gates/`)
- **Schemas** : validation YAML des manifests `.kill-life.yaml` (`schemas/`)
- **Templates** : squelettes de repos prets a l'emploi (`templates/`)
- **Scripts** : outils CLI pour creer, valider et suivre les projets (`scripts/`)
- **Projects** : registre des projets actifs (`projects/`)
## Pipeline de gates
| Gate | Nom | Objectif |
|------|-----|----------|
| **S0** | Spec Ready | Specs testables, architecture definie, plan de validation |
| **S1** | Build OK | Firmware compile, ERC/DRC green, tests unitaires passent |
| **S2** | Integration | Tests integration, BOM valide, prototype fonctionnel |
| **S3** | Production Ready | Fab package complet, compliance, documentation livree |
## Structure d'un projet
Chaque repo projet contient un `.kill-life.yaml` a la racine :
```yaml
kill_life:
version: 1
project: "mon-projet"
client: "client-name"
gates:
s0: { status: passed, date: "2026-03-15" }
s1: { status: in_progress }
s2: { status: pending }
s3: { status: pending }
hardware:
pcb_dir: hardware/pcb
bom_dir: hardware/bom
firmware:
framework: platformio
src_dir: firmware/src
```
## Utilisation
```bash
# Creer un nouveau projet depuis le template
./scripts/create-project.sh mon-projet electron-rare
# Valider les gates d'un projet
./scripts/validate-gates.sh electron-rare/mon-projet
# Dashboard de tous les projets
./scripts/dashboard.sh
```
## Repos exemple
- [electron-rare/hypnoled](https://github.com/electron-rare/hypnoled) — HypnoLED animations LED ESP32
## License
MIT
+43
View File
@@ -0,0 +1,43 @@
# Gate S0 — Spec Ready
## Objectif
Valider que les specifications sont completes, testables, et que l'architecture est definie.
## Criteres obligatoires
- [ ] `docs/specs/01_spec.md` existe avec des criteres d'acceptation testables
- [ ] `docs/specs/02_arch.md` definit les interfaces et contrats
- [ ] `docs/specs/03_plan.md` liste les commandes de validation et l'evidence attendue
- [ ] `constraints.yaml` present et valide (si applicable)
- [ ] `.kill-life.yaml` present a la racine avec `version: 1`
## Criteres optionnels
- [ ] Diagramme d'architecture (Excalidraw, Draw.io, ou Mermaid)
- [ ] Estimation de BOM preliminaire
- [ ] Identification des risques techniques
## Artifacts produits
| Artifact | Chemin | Format |
|----------|--------|--------|
| Spec | `docs/specs/01_spec.md` | Markdown |
| Architecture | `docs/specs/02_arch.md` | Markdown |
| Plan de validation | `docs/specs/03_plan.md` | Markdown |
| Contraintes | `constraints.yaml` | YAML |
## Validation automatique
```bash
# Verifie la presence des fichiers requis
./scripts/validate-gates.sh <org>/<repo> --gate s0
```
## Passage de gate
Le passage de S0 est formalise par :
1. Une PR avec label `gate:s0`
2. Review par au moins 1 personne
3. Tous les checks CI passent
4. Mise a jour du `.kill-life.yaml` : `s0.status: passed`
+49
View File
@@ -0,0 +1,49 @@
# Gate S1 — Build OK
## Objectif
Valider que le projet compile, que les checks hardware passent, et que les tests unitaires sont en place.
## Criteres par type
### Firmware (si `firmware/` existe)
- [ ] `pio run` compile sans erreur (au moins 1 environment)
- [ ] `pio test -e native` passe (ou justification documentee)
- [ ] Pas de warnings critiques (-Werror ou equivalent)
### Hardware (si `hardware/` existe)
- [ ] ERC (Electrical Rules Check) green — artifact JSON
- [ ] DRC (Design Rules Check) green — artifact JSON
- [ ] Netlist exportable
- [ ] BOM genere (`hardware/bom/`)
### Software (si pas firmware/hardware)
- [ ] Build reussi (`npm run build` / `cargo build` / etc.)
- [ ] Tests unitaires passent
- [ ] Linter/formatter OK
## Criteres communs
- [ ] CI GitHub Actions configure et green
- [ ] README.md a jour avec instructions de build
- [ ] Gate S0 passee
## Validation automatique
```bash
./scripts/validate-gates.sh <org>/<repo> --gate s1
```
Le workflow `.github/workflows/kill-life-ci.yml` execute automatiquement :
- ERC/DRC via `kicad-cli` (container `ghcr.io/inti-cmnb/kicad8_auto`)
- Build firmware via PlatformIO
- Validation BOM
## Passage de gate
1. CI green sur `main`
2. PR avec label `gate:s1`
3. Mise a jour `.kill-life.yaml` : `s1.status: passed`
+45
View File
@@ -0,0 +1,45 @@
# Gate S2 — Integration
## Objectif
Valider que les composants (firmware + hardware + software) fonctionnent ensemble sur un prototype.
## Criteres obligatoires
- [ ] Gate S1 passee
- [ ] Prototype physique assemble et fonctionnel
- [ ] Tests d'integration documentes et passes
- [ ] Communication inter-composants validee (I2C, SPI, UART, WiFi...)
- [ ] Consommation electrique mesuree et dans les specs
### Hardware
- [ ] PCB fabrique et assemble (au moins 1 exemplaire)
- [ ] Tous les composants soudes et testes
- [ ] Photos/videos du prototype dans `docs/prototype/`
### Firmware
- [ ] Flash reussi sur le hardware reel
- [ ] Tests fonctionnels sur cible (pas seulement native)
- [ ] OTA fonctionnel (si applicable)
### Software
- [ ] Integration API/backend testee end-to-end
- [ ] Deployment staging fonctionnel
## Artifacts produits
| Artifact | Chemin | Format |
|----------|--------|--------|
| Rapport d'integration | `docs/integration_report.md` | Markdown |
| Photos prototype | `docs/prototype/` | Images |
| Mesures electriques | `docs/measurements/` | CSV/Markdown |
| Test results | `tests/integration/` | Code + logs |
## Passage de gate
1. PR avec label `gate:s2`
2. Review incluant validation physique (photos/videos)
3. Mise a jour `.kill-life.yaml` : `s2.status: passed`
+54
View File
@@ -0,0 +1,54 @@
# Gate S3 — Production Ready
## Objectif
Valider que le projet est pret pour la fabrication en serie / le deploiement en production.
## Criteres obligatoires
- [ ] Gate S2 passee
- [ ] Fab package complet et valide
### Fab Package (hardware)
- [ ] Gerbers exportes et verifies
- [ ] Drill files generes
- [ ] BOM finale avec references fournisseurs et prix
- [ ] Pick & place file (si SMD)
- [ ] `acceptance_gates` dans `.kill-life.yaml` : `erc_ok`, `drc_ok`, `bom_review_ok`, `artifacts_complete`
### Firmware release
- [ ] Version taguee (semver)
- [ ] Binary release sur GitHub Releases
- [ ] Changelog a jour
- [ ] OTA path teste depuis version N-1 (si applicable)
### Documentation
- [ ] Guide utilisateur (`docs/user_guide.md`)
- [ ] Procedure de fabrication (`docs/manufacturing.md`)
- [ ] Nomenclature complete et a jour
- [ ] Licences verifiees (SPDX)
### Compliance
- [ ] Conformite CE / FCC documentee (si applicable)
- [ ] Tests EMC references (si applicable)
- [ ] WEEE / RoHS compliance (si applicable)
## Artifacts produits
| Artifact | Chemin | Format |
|----------|--------|--------|
| Fab package | `releases/<version>/` | Gerbers, drill, BOM, netlist |
| Firmware binary | GitHub Release | `.bin` / `.uf2` |
| User guide | `docs/user_guide.md` | Markdown |
| Manufacturing guide | `docs/manufacturing.md` | Markdown |
## Passage de gate
1. PR avec label `gate:s3`
2. Review par au moins 2 personnes
3. Tag de release cree
4. Mise a jour `.kill-life.yaml` : `s3.status: passed`
+16
View File
@@ -0,0 +1,16 @@
kill_life:
version: 1
project: "example-led-controller"
repo: "electron-rare/life-project-example"
client: "demo"
gates:
s0: { status: passed, date: "2026-03-01" }
s1: { status: passed, date: "2026-03-15" }
s2: { status: in_progress }
s3: { status: pending }
hardware:
pcb_dir: hardware/pcb
bom_dir: hardware/bom
firmware:
framework: platformio
src_dir: firmware/src
+81
View File
@@ -0,0 +1,81 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "kill-life.yaml",
"description": "Manifest de projet Factory 4 Life",
"type": "object",
"required": ["kill_life"],
"properties": {
"kill_life": {
"type": "object",
"required": ["version", "project"],
"properties": {
"version": { "type": "integer", "const": 1 },
"project": { "type": "string", "minLength": 1 },
"client": { "type": "string" },
"mascarade_url": { "type": "string", "format": "uri" },
"agents": {
"type": "array",
"items": { "type": "string" }
},
"mcp_servers": {
"type": "array",
"items": { "type": "string" }
},
"gates": {
"type": "object",
"properties": {
"s0": { "$ref": "#/$defs/gate_status" },
"s1": { "$ref": "#/$defs/gate_status" },
"s2": { "$ref": "#/$defs/gate_status" },
"s3": { "$ref": "#/$defs/gate_status" }
}
},
"acceptance_gates": {
"type": "object",
"properties": {
"erc_ok": { "type": "boolean" },
"drc_ok": { "type": "boolean" },
"bom_review_ok": { "type": "boolean" },
"artifacts_complete": { "type": "boolean" }
}
},
"hardware": {
"type": "object",
"properties": {
"pcb_dir": { "type": "string" },
"simulation_dir": { "type": "string" },
"bom_dir": { "type": "string" }
}
},
"firmware": {
"type": "object",
"properties": {
"framework": { "type": "string", "enum": ["platformio", "esp-idf", "arduino", "zephyr"] },
"src_dir": { "type": "string" }
}
},
"software": {
"type": "object",
"properties": {
"framework": { "type": "string" },
"src_dir": { "type": "string" }
}
}
}
}
},
"$defs": {
"gate_status": {
"type": "object",
"required": ["status"],
"properties": {
"status": {
"type": "string",
"enum": ["pending", "in_progress", "passed", "blocked", "skipped"]
},
"date": { "type": "string", "format": "date" },
"notes": { "type": "string" }
}
}
}
}
+95
View File
@@ -0,0 +1,95 @@
#!/usr/bin/env bash
set -euo pipefail
# Create a new Factory 4 Life project from template
# Usage: ./scripts/create-project.sh <project-name> <github-org> [--client <name>]
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(dirname "$SCRIPT_DIR")"
TEMPLATE_DIR="${REPO_ROOT}/templates/hardware-project"
usage() {
cat <<'EOF'
Usage: create-project.sh <project-name> <github-org> [options]
Options:
--client <name> Client name for the project
--public Create as public repo (default: private)
--no-clone Don't clone locally after creation
-h, --help Show this help
Example:
./scripts/create-project.sh my-led-project electron-rare --client acme
EOF
}
PROJECT=""
ORG=""
CLIENT=""
VISIBILITY="--private"
CLONE=true
while [[ $# -gt 0 ]]; do
case "$1" in
--client) CLIENT="$2"; shift 2 ;;
--public) VISIBILITY="--public"; shift ;;
--no-clone) CLONE=false; shift ;;
-h|--help) usage; exit 0 ;;
*)
if [[ -z "$PROJECT" ]]; then PROJECT="$1"
elif [[ -z "$ORG" ]]; then ORG="$1"
else usage >&2; exit 2
fi
shift ;;
esac
done
[[ -n "$PROJECT" ]] || { echo "Error: project name required" >&2; usage >&2; exit 1; }
[[ -n "$ORG" ]] || { echo "Error: github org required" >&2; usage >&2; exit 1; }
echo "Creating project: ${ORG}/${PROJECT}"
# Create GitHub repo
gh repo create "${ORG}/${PROJECT}" ${VISIBILITY} \
--description "Factory 4 Life project — ${PROJECT}" \
--clone
cd "${PROJECT}"
# Copy template
cp -r "${TEMPLATE_DIR}/"* .
cp -r "${TEMPLATE_DIR}/".[!.]* . 2>/dev/null || true
# Generate .kill-life.yaml
cat > .kill-life.yaml <<YAML
kill_life:
version: 1
project: "${PROJECT}"
client: "${CLIENT:-tbd}"
gates:
s0: { status: in_progress }
s1: { status: pending }
s2: { status: pending }
s3: { status: pending }
agents:
- forge
- firmware-agent
- qa-agent
mcp_servers:
- kicad
hardware:
pcb_dir: hardware/pcb
bom_dir: hardware/bom
firmware:
framework: platformio
src_dir: firmware/src
YAML
# Initial commit
git add -A
git commit -m "feat: init ${PROJECT} from life-project template"
git push -u origin main
echo ""
echo "Project created: https://github.com/${ORG}/${PROJECT}"
echo "Next: edit .kill-life.yaml and start working on S0 specs"
+51
View File
@@ -0,0 +1,51 @@
#!/usr/bin/env bash
set -euo pipefail
# Display dashboard of all Factory 4 Life projects
# Reads project registry from projects/ directory
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(dirname "$SCRIPT_DIR")"
PROJECTS_DIR="${REPO_ROOT}/projects"
echo "============================================"
echo " Factory 4 Life — Project Dashboard"
echo " $(date '+%Y-%m-%d %H:%M')"
echo "============================================"
echo ""
printf "%-25s %-10s %-10s %-10s %-10s %-12s\n" "PROJECT" "S0" "S1" "S2" "S3" "CLIENT"
printf "%-25s %-10s %-10s %-10s %-10s %-12s\n" "-------" "--" "--" "--" "--" "------"
for project_file in "${PROJECTS_DIR}"/*.yaml; do
[[ -f "$project_file" ]] || continue
name=$(grep 'project:' "$project_file" | head -1 | awk '{print $2}' | tr -d '"')
client=$(grep 'client:' "$project_file" | head -1 | awk '{print $2}' | tr -d '"')
# Parse inline YAML: s0: { status: passed, date: "..." }
extract_status() { grep " $1:" "$2" | sed 's/.*status: *//;s/[,} ].*//' | tr -d '"'; }
s0=$(extract_status s0 "$project_file")
s1=$(extract_status s1 "$project_file")
s2=$(extract_status s2 "$project_file")
s3=$(extract_status s3 "$project_file")
# Color-code status
format_status() {
case "$1" in
passed) printf "\033[32m%-10s\033[0m" "PASSED" ;;
in_progress) printf "\033[33m%-10s\033[0m" "WIP" ;;
blocked) printf "\033[31m%-10s\033[0m" "BLOCKED" ;;
skipped) printf "\033[90m%-10s\033[0m" "SKIP" ;;
*) printf "%-10s" "PENDING" ;;
esac
}
printf "%-25s " "${name:-unknown}"
format_status "$s0"
format_status "$s1"
format_status "$s2"
format_status "$s3"
printf "%-12s\n" "${client:-}"
done
echo ""
+147
View File
@@ -0,0 +1,147 @@
#!/usr/bin/env bash
set -euo pipefail
# Validate gate criteria for a Factory 4 Life project
# Usage: ./scripts/validate-gates.sh <org/repo> [--gate s0|s1|s2|s3] [--local <path>]
usage() {
cat <<'EOF'
Usage: validate-gates.sh <org/repo> [options]
Options:
--gate <s0|s1|s2|s3> Validate specific gate (default: all)
--local <path> Use local directory instead of cloning
--json Output as JSON
-h, --help Show this help
Example:
./scripts/validate-gates.sh electron-rare/hypnoled --gate s1
./scripts/validate-gates.sh electron-rare/hypnoled --local ~/hypnoled
EOF
}
REPO=""
GATE=""
LOCAL_PATH=""
JSON_OUTPUT=false
while [[ $# -gt 0 ]]; do
case "$1" in
--gate) GATE="$2"; shift 2 ;;
--local) LOCAL_PATH="$2"; shift 2 ;;
--json) JSON_OUTPUT=true; shift ;;
-h|--help) usage; exit 0 ;;
*) REPO="$1"; shift ;;
esac
done
[[ -n "$REPO" ]] || { echo "Error: repo required" >&2; usage >&2; exit 1; }
# Get project directory
if [[ -n "$LOCAL_PATH" ]]; then
PROJECT_DIR="$LOCAL_PATH"
else
TMPDIR=$(mktemp -d)
trap "rm -rf $TMPDIR" EXIT
gh repo clone "$REPO" "$TMPDIR/repo" -- --depth 1 2>/dev/null
PROJECT_DIR="$TMPDIR/repo"
fi
PASS=0
FAIL=0
WARN=0
check() {
local gate="$1" desc="$2" result="$3"
if [[ "$result" == "pass" ]]; then
echo " [PASS] $desc"
((PASS++))
elif [[ "$result" == "warn" ]]; then
echo " [WARN] $desc"
((WARN++))
else
echo " [FAIL] $desc"
((FAIL++))
fi
}
validate_s0() {
echo "=== Gate S0: Spec Ready ==="
check s0 ".kill-life.yaml exists" \
"$([[ -f "$PROJECT_DIR/.kill-life.yaml" ]] && echo pass || echo fail)"
check s0 "docs/specs/01_spec.md exists" \
"$([[ -f "$PROJECT_DIR/docs/specs/01_spec.md" ]] && echo pass || echo fail)"
check s0 "docs/specs/02_arch.md exists" \
"$([[ -f "$PROJECT_DIR/docs/specs/02_arch.md" ]] && echo pass || echo fail)"
check s0 "docs/specs/03_plan.md exists" \
"$([[ -f "$PROJECT_DIR/docs/specs/03_plan.md" ]] && echo pass || echo fail)"
check s0 "README.md exists" \
"$([[ -f "$PROJECT_DIR/README.md" ]] && echo pass || echo fail)"
}
validate_s1() {
echo "=== Gate S1: Build OK ==="
# Firmware checks
if [[ -f "$PROJECT_DIR/firmware/platformio.ini" ]]; then
check s1 "platformio.ini exists" pass
check s1 "firmware/src/ has source files" \
"$(find "$PROJECT_DIR/firmware/src" -name '*.cpp' -o -name '*.c' -o -name '*.h' 2>/dev/null | head -1 | grep -q . && echo pass || echo fail)"
fi
# Hardware checks
if [[ -d "$PROJECT_DIR/hardware/pcb" ]]; then
check s1 "KiCad schematic exists" \
"$(find "$PROJECT_DIR/hardware/pcb" -name '*.kicad_sch' 2>/dev/null | head -1 | grep -q . && echo pass || echo fail)"
check s1 "KiCad PCB exists" \
"$(find "$PROJECT_DIR/hardware/pcb" -name '*.kicad_pcb' 2>/dev/null | head -1 | grep -q . && echo pass || echo fail)"
check s1 "BOM exists" \
"$([[ -d "$PROJECT_DIR/hardware/bom" ]] && find "$PROJECT_DIR/hardware/bom" -name '*.csv' 2>/dev/null | head -1 | grep -q . && echo pass || echo warn)"
fi
# CI check
check s1 "GitHub Actions CI configured" \
"$(find "$PROJECT_DIR/.github/workflows" -name '*.yml' -o -name '*.yaml' 2>/dev/null | head -1 | grep -q . && echo pass || echo fail)"
}
validate_s2() {
echo "=== Gate S2: Integration ==="
check s2 "Integration report exists" \
"$([[ -f "$PROJECT_DIR/docs/integration_report.md" ]] && echo pass || echo fail)"
check s2 "Prototype documentation exists" \
"$([[ -d "$PROJECT_DIR/docs/prototype" ]] && echo pass || echo warn)"
check s2 "Integration tests exist" \
"$(find "$PROJECT_DIR/tests/integration" -type f 2>/dev/null | head -1 | grep -q . && echo pass || echo warn)"
}
validate_s3() {
echo "=== Gate S3: Production Ready ==="
check s3 "User guide exists" \
"$([[ -f "$PROJECT_DIR/docs/user_guide.md" ]] && echo pass || echo fail)"
check s3 "Manufacturing guide exists" \
"$([[ -f "$PROJECT_DIR/docs/manufacturing.md" ]] && echo pass || echo warn)"
check s3 "Release directory exists" \
"$([[ -d "$PROJECT_DIR/releases" ]] && echo pass || echo fail)"
if [[ -d "$PROJECT_DIR/hardware/pcb" ]]; then
check s3 "Gerbers generated" \
"$(find "$PROJECT_DIR/releases" -name '*.gbr' -o -name '*.gtl' 2>/dev/null | head -1 | grep -q . && echo pass || echo fail)"
fi
}
# Run validations
echo "Validating: $REPO"
echo ""
case "$GATE" in
s0) validate_s0 ;;
s1) validate_s0; validate_s1 ;;
s2) validate_s0; validate_s1; validate_s2 ;;
s3) validate_s0; validate_s1; validate_s2; validate_s3 ;;
"") validate_s0; validate_s1; validate_s2; validate_s3 ;;
*) echo "Unknown gate: $GATE" >&2; exit 1 ;;
esac
echo ""
echo "Results: ${PASS} passed, ${FAIL} failed, ${WARN} warnings"
[[ "$FAIL" -eq 0 ]] && exit 0 || exit 1
@@ -0,0 +1,58 @@
name: Kill_LIFE CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
erc-drc:
name: KiCad ERC/DRC
runs-on: ubuntu-latest
if: hashFiles('hardware/pcb/*.kicad_sch') != ''
container:
image: ghcr.io/inti-cmnb/kicad8_auto:latest
steps:
- uses: actions/checkout@v4
- name: Run ERC
run: |
for sch in $(find hardware/pcb -name '*.kicad_sch' -not -path '*/libs/*'); do
echo "--- ERC: $sch ---"
kicad-cli sch erc --exit-code-violations "$sch" || exit 1
done
- name: Run DRC
run: |
for pcb in $(find hardware/pcb -name '*.kicad_pcb'); do
echo "--- DRC: $pcb ---"
kicad-cli pcb drc --exit-code-violations "$pcb" || exit 1
done
bom-check:
name: BOM Validation
runs-on: ubuntu-latest
if: hashFiles('hardware/bom/*.csv') != ''
steps:
- uses: actions/checkout@v4
- name: Validate BOM
run: |
if [ -f hardware/bom/bom.csv ]; then
echo "BOM found: $(wc -l < hardware/bom/bom.csv) lines"
else
echo "WARNING: No BOM at hardware/bom/bom.csv"
fi
firmware-build:
name: Firmware Build
runs-on: ubuntu-latest
if: hashFiles('firmware/platformio.ini') != ''
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- run: pip install platformio
- name: Build firmware
run: cd firmware && pio run
@@ -0,0 +1,21 @@
kill_life:
version: 1
project: "TEMPLATE"
client: "tbd"
gates:
s0: { status: in_progress }
s1: { status: pending }
s2: { status: pending }
s3: { status: pending }
agents:
- forge
- firmware-agent
- qa-agent
mcp_servers:
- kicad
hardware:
pcb_dir: hardware/pcb
bom_dir: hardware/bom
firmware:
framework: platformio
src_dir: firmware/src
+32
View File
@@ -0,0 +1,32 @@
PROJECT_DIR := hardware/pcb
TS ?= $(shell date +%Y%m%d-%H%M%S)
REL := releases/$(TS)
.PHONY: kicad-check kicad-fab firmware-build
kicad-check:
@command -v kicad-cli >/dev/null || (echo "kicad-cli manquant" && exit 1)
@for sch in $$(find $(PROJECT_DIR) -name '*.kicad_sch' -not -path '*/libs/*'); do \
echo "--- ERC: $$sch ---"; \
kicad-cli sch erc "$$sch"; \
done
@for pcb in $$(find $(PROJECT_DIR) -name '*.kicad_pcb'); do \
echo "--- DRC: $$pcb ---"; \
kicad-cli pcb drc "$$pcb"; \
done
kicad-fab:
@command -v kicad-cli >/dev/null || (echo "kicad-cli manquant" && exit 1)
mkdir -p "$(REL)/gerbers" "$(REL)/drill" "$(REL)/bom" "$(REL)/netlist"
@for pcb in $$(find $(PROJECT_DIR) -name '*.kicad_pcb'); do \
kicad-cli pcb export gerbers "$$pcb" --output "$(REL)/gerbers"; \
kicad-cli pcb export drill "$$pcb" --output "$(REL)/drill"; \
done
@for sch in $$(find $(PROJECT_DIR) -name '*.kicad_sch' -maxdepth 1); do \
kicad-cli sch export bom "$$sch" --output "$(REL)/bom/bom.csv"; \
kicad-cli sch export netlist "$$sch" --output "$(REL)/netlist/project.net"; \
done
@echo "Artefacts dans $(REL)"
firmware-build:
cd firmware && pio run
+38
View File
@@ -0,0 +1,38 @@
# PROJECT_NAME
> Factory 4 Life project — description here
## Structure
```
.kill-life.yaml # Project manifest & gate status
firmware/ # ESP32 firmware (PlatformIO)
hardware/
pcb/ # KiCad schematics & PCB
bom/ # Bill of Materials
docs/
specs/ # Specifications (S0 gate)
releases/ # Fab packages & binaries
```
## Gates
| Gate | Status |
|------|--------|
| S0 — Spec Ready | in_progress |
| S1 — Build OK | pending |
| S2 — Integration | pending |
| S3 — Production Ready | pending |
## Build
```bash
# Firmware
cd firmware && pio run
# Hardware checks
make kicad-check
# Fab package
make kicad-fab
```
@@ -0,0 +1,8 @@
[env:esp32]
platform = espressif32
board = esp32dev
framework = arduino
monitor_speed = 115200
[env:native]
platform = native
@@ -0,0 +1,10 @@
#include <Arduino.h>
void setup() {
Serial.begin(115200);
Serial.println("Factory 4 Life — Project init");
}
void loop() {
// TODO: implement
}