feat: bootstrap jetson-ai-ollama from agent-swarm template
Some checks failed
gates / quality (push) Has been cancelled
Some checks failed
gates / quality (push) Has been cancelled
Leader-Bootstrap (Planung) aus Template + Jetson-Meta-Prompt:
- ROADMAP-Board W1-W6 als Abhaengigkeits-DAG (Ready-Set = {W1})
- STATE mit disjunkter Datei-Ownership W2-W6
- CONVENTIONS Projekt-Vertrag (Profile, Pfade, Ports, Daemon-Env, num_ctx, DVC, Scope)
- manifests/requirements.md = kalt verifizierbares Review-Manifest (R-01..R-10)
- REVIEW.md Kalt-Review-Einstieg; ADR 0002 (Ollama-nativ, kein Swapper/Gateway)
- session-prompts/W1..W6 dispatch-fertig; .gitignore um Jetson-Ignores erweitert
- examples/walkthrough entfernt (Projekt hat eigenes gefuelltes Board)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
58
scripts/gate-doc-drift.sh
Executable file
58
scripts/gate-doc-drift.sh
Executable file
@@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env bash
|
||||
# Doku-Drift-Gate: prueft Manifest-Referenzen + STATE-Aktualitaet + Doc-Budget.
|
||||
set -uo pipefail
|
||||
fail=0; man="manifests/requirements.md"
|
||||
|
||||
# Dormant solange das Template nicht initialisiert ist (scripts/init.sh).
|
||||
if grep -q '<id / datum>' STATE.md 2>/dev/null; then
|
||||
echo "[drift] Template noch nicht initialisiert (scripts/init.sh) — uebersprungen."
|
||||
echo "GATE: PASS"; exit 0
|
||||
fi
|
||||
|
||||
echo "[drift] pruefe im Manifest referenzierte Pfade (nur done/in_progress/drift)..."
|
||||
# Nur Pfade aus ERLEDIGTEN Zeilen muessen existieren — 'todo'-Zeilen sind Plan,
|
||||
# ihre Dateien gibt es absichtlich noch nicht. Treffer in eine Datei sammeln,
|
||||
# damit fail=1 nicht in einer Pipe-Subshell verloren geht.
|
||||
miss=$(mktemp)
|
||||
if [ -f "$man" ]; then
|
||||
while IFS= read -r line; do
|
||||
case "$line" in \|*) : ;; *) continue ;; esac # nur Tabellenzeilen
|
||||
status=$(printf '%s' "$line" | sed 's/^|//; s/|[[:space:]]*$//' \
|
||||
| awk -F'|' '{print $NF}' | tr -d ' ' | tr 'A-Z' 'a-z')
|
||||
case "$status" in done|in_progress|drift) : ;; *) continue ;; esac
|
||||
while IFS= read -r tok; do
|
||||
case "$tok" in *" "*|*…*|_*|*path/to*) continue ;; esac
|
||||
case "$tok" in
|
||||
*/*|*.py|*.md|*.sh|*.js|*.ts|*.yml|*.yaml|*.json|*.conf|*.ini|*.txt)
|
||||
[ -e "$tok" ] || echo "$status $tok" >> "$miss" ;;
|
||||
esac
|
||||
done < <(printf '%s\n' "$line" | grep -oE '`[^`]+`' | tr -d '`')
|
||||
done < "$man"
|
||||
fi
|
||||
if [ -s "$miss" ]; then
|
||||
while IFS=" " read -r st p; do echo " - fehlende Referenz (Status $st): $p"; done < "$miss"
|
||||
fail=1
|
||||
fi
|
||||
rm -f "$miss"
|
||||
|
||||
echo "[drift] STATE.md Stale-Check (Commits seit letzter Aenderung)..."
|
||||
last_state=$(git log -1 --format=%H -- STATE.md 2>/dev/null || true)
|
||||
if [ -n "$last_state" ]; then
|
||||
since=$(git rev-list --count "${last_state}..HEAD" 2>/dev/null || echo 0)
|
||||
[ "${since:-0}" -le 3 ] || { echo " - STATE.md seit $since Commits unveraendert"; fail=1; }
|
||||
fi
|
||||
|
||||
echo "[drift] Doc-Groessenbudget (Faustregel < 200 Zeilen)..."
|
||||
while read -r f; do
|
||||
case "$f" in examples/*) continue ;; esac # Beispiele duerfen laenger sein
|
||||
n=$(wc -l < "$f" 2>/dev/null || echo 0)
|
||||
[ "$n" -le 200 ] || echo " - Hinweis: $f hat $n Zeilen (> 200, Drift-Risiko)."
|
||||
done < <(git ls-files 2>/dev/null | grep '\.md$' || true)
|
||||
|
||||
echo "[drift] Code ohne Doc-Aenderung im letzten Commit?"
|
||||
files=$(git show --name-only --pretty= HEAD 2>/dev/null || true)
|
||||
if echo "$files" | grep -qE '\.(py|sh|js|ts)$' && ! echo "$files" | grep -qE '\.md$'; then
|
||||
echo " - Hinweis: Code geaendert, keine Doku angepasst (Drift-Verdacht)."
|
||||
fi
|
||||
|
||||
[ "$fail" -eq 0 ] && echo "GATE: PASS" || { echo "GATE: FAIL"; exit 1; }
|
||||
81
scripts/gate-ownership.sh
Executable file
81
scripts/gate-ownership.sh
Executable file
@@ -0,0 +1,81 @@
|
||||
#!/usr/bin/env bash
|
||||
# Ownership-Gate: kein Paket editiert Dateien eines anderen.
|
||||
# Liest die Ownership-Tabelle aus STATE.md, mappt geaenderte Dateien (Branch vs.
|
||||
# Basis) auf Pakete und FAILt bei Cross-Editing ueber >1 Paket-Grenze hinweg.
|
||||
# Integration (Leader) ist ausgenommen: Branch main/master/integrate/*.
|
||||
# Konvention: Verzeichnis-Pfade in der Tabelle mit Slash beenden (src/api/).
|
||||
# Portabel gehalten (kein mapfile / keine assoziativen Arrays, laeuft auf bash 3.2).
|
||||
set -uo pipefail
|
||||
|
||||
# Dormant solange das Template nicht initialisiert ist.
|
||||
if grep -q '<id / datum>' STATE.md 2>/dev/null; then
|
||||
echo "[ownership] Template noch nicht initialisiert — uebersprungen."
|
||||
echo "GATE: PASS"; exit 0
|
||||
fi
|
||||
|
||||
branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "")
|
||||
case "$branch" in
|
||||
main|master|integrate/*)
|
||||
echo "[ownership] '$branch' ist Integrations-Branch — uebersprungen."
|
||||
echo "GATE: PASS"; exit 0 ;;
|
||||
esac
|
||||
|
||||
# (pkg<TAB>prefix)-Zeilen aus der STATE.md-Ownership-Tabelle ziehen.
|
||||
pairs=$(awk -F'|' '
|
||||
/Datei-Ownership/{f=1; started=0; next}
|
||||
f && started && $0 !~ /^\|/ {f=0} # erst NACH Tabellenbeginn abbrechen
|
||||
f && /^\|/{
|
||||
started=1;
|
||||
pkg=$2; paths=$3;
|
||||
gsub(/^[ \t]+|[ \t]+$/,"",pkg);
|
||||
if(pkg=="" || pkg=="Paket" || pkg ~ /---/ || pkg ~ /…/ || pkg ~ /^_/) next;
|
||||
n=split(paths, a, ",");
|
||||
for(i=1;i<=n;i++){ p=a[i]; gsub(/^[ \t]+|[ \t]+$/,"",p); gsub(/`/,"",p);
|
||||
if(p=="" || p ~ /…/ || p ~ /^_/) continue;
|
||||
print pkg "\t" p }
|
||||
}' STATE.md 2>/dev/null)
|
||||
|
||||
if [ -z "$pairs" ]; then
|
||||
echo "[ownership] keine befuellte Ownership-Tabelle in STATE.md — uebersprungen."
|
||||
echo "GATE: PASS"; exit 0
|
||||
fi
|
||||
|
||||
base=$(git merge-base HEAD main 2>/dev/null || git rev-parse HEAD~1 2>/dev/null || true)
|
||||
[ -n "$base" ] || { echo "[ownership] keine Diff-Basis — uebersprungen."; echo "GATE: PASS"; exit 0; }
|
||||
changed=$(git diff --name-only "$base"...HEAD 2>/dev/null)
|
||||
[ -n "$changed" ] || { echo "[ownership] keine Aenderungen — uebersprungen."; echo "GATE: PASS"; exit 0; }
|
||||
|
||||
hit=""; unowned=""
|
||||
while IFS= read -r f; do
|
||||
[ -n "$f" ] || continue
|
||||
bestpre=""; bestpkg=""
|
||||
while IFS=" " read -r pkg pre; do
|
||||
[ -n "$pre" ] || continue
|
||||
case "$f" in
|
||||
"$pre"|"$pre"*)
|
||||
if [ "${#pre}" -gt "${#bestpre}" ]; then bestpre="$pre"; bestpkg="$pkg"; fi ;;
|
||||
esac
|
||||
done <<EOF
|
||||
$pairs
|
||||
EOF
|
||||
if [ -n "$bestpkg" ]; then
|
||||
hit="$hit$bestpkg
|
||||
"
|
||||
else
|
||||
unowned="$unowned $f"
|
||||
fi
|
||||
done <<EOF
|
||||
$changed
|
||||
EOF
|
||||
|
||||
distinct=$(printf '%s' "$hit" | sed '/^$/d' | sort -u)
|
||||
n=$(printf '%s' "$distinct" | sed '/^$/d' | grep -c . || true)
|
||||
echo "[ownership] Branch '$branch' beruehrt $n Paket(e): $(printf '%s ' $distinct)"
|
||||
[ -n "$unowned" ] && echo "[ownership] Hinweis: ohne Owner in STATE.md:$unowned"
|
||||
|
||||
if [ "${n:-0}" -gt 1 ]; then
|
||||
echo " - FAIL: Aenderungen ueber mehrere Ownership-Grenzen (Cross-Editing)."
|
||||
echo " Worker editieren nur ihr Paket; Integration macht der Leader (Branch integrate/*)."
|
||||
echo "GATE: FAIL"; exit 1
|
||||
fi
|
||||
echo "GATE: PASS"
|
||||
41
scripts/gate-session-hygiene.sh
Executable file
41
scripts/gate-session-hygiene.sh
Executable file
@@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env bash
|
||||
# Session-Hygiene-Gate (Starter — an Repo anpassen).
|
||||
set -uo pipefail
|
||||
fail=0
|
||||
note(){ echo " - $1"; fail=1; }
|
||||
|
||||
# Dormant solange das Template nicht initialisiert ist (scripts/init.sh).
|
||||
if grep -q '<id / datum>' STATE.md 2>/dev/null; then
|
||||
echo "[hygiene] Template noch nicht initialisiert (scripts/init.sh) — uebersprungen."
|
||||
echo "GATE: PASS"; exit 0
|
||||
fi
|
||||
|
||||
echo "[hygiene] pruefe Working Tree..."
|
||||
[ -z "$(git status --porcelain)" ] || note "Working Tree nicht sauber."
|
||||
|
||||
echo "[hygiene] STATE.md im aktuellen Branch aktualisiert?"
|
||||
base=$(git merge-base HEAD main 2>/dev/null || true)
|
||||
head=$(git rev-parse HEAD 2>/dev/null || true)
|
||||
if [ -n "$base" ] && [ "$base" != "$head" ]; then
|
||||
# echte Divergenz (Feature-Branch): Diff gegen Abzweigpunkt
|
||||
git diff --name-only "$base"...HEAD | grep -q '^STATE.md$' || \
|
||||
note "STATE.md im aktuellen Branch nicht aktualisiert."
|
||||
else
|
||||
# auf main/Integration oder Root-Commit: letzten Commit pruefen
|
||||
git log -1 --name-only --pretty= | grep -q '^STATE.md$' || \
|
||||
note "STATE.md im letzten Commit nicht angefasst."
|
||||
fi
|
||||
|
||||
echo "[hygiene] Session-Log vorhanden?"
|
||||
ls sessions/[0-9]*.md >/dev/null 2>&1 || note "Kein Session-Log unter sessions/."
|
||||
|
||||
echo "[hygiene] Conventional Commits?"
|
||||
git log -1 --pretty=%s | grep -Eq '^(feat|fix|docs|test|refactor|chore)(\(.+\))?: ' || \
|
||||
note "Letzter Commit nicht conventional."
|
||||
|
||||
echo "[hygiene] Model-Attribution im letzten Commit?"
|
||||
git log -1 --pretty=%B | grep -q 'Co-Authored-By: Claude' || \
|
||||
echo " - Hinweis: letzter Commit ohne 'Co-Authored-By: Claude <Modell>' (Pflicht nur fuer Agenten-Commits)."
|
||||
|
||||
if [ "$fail" -ne 0 ]; then echo "GATE: FAIL"; exit 1; fi
|
||||
echo "GATE: PASS"
|
||||
60
scripts/init.sh
Executable file
60
scripts/init.sh
Executable file
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env bash
|
||||
# init.sh — ein Template-Klon zu einem konkreten Projekt machen.
|
||||
# Nutzung: bash scripts/init.sh "Mein Projektname"
|
||||
#
|
||||
# Was passiert:
|
||||
# - die Template-README wandert nach docs/about-template.md (Methodik bleibt erhalten)
|
||||
# - eine frische, projektbezogene README.md wird geschrieben
|
||||
# - falls noch kein Git-Repo: git init
|
||||
# - die Gates bleiben DORMANT, bis die erste echte Session STATE.md befuellt
|
||||
# (die Zeile mit '<id / datum>' ersetzt) — danach greifen sie automatisch.
|
||||
#
|
||||
# Naechster Schritt nach init: session-prompts/BOOTSTRAP.md in eine frische
|
||||
# Leader-Session geben, zusammen mit deinem Projekt-Brief.
|
||||
set -euo pipefail
|
||||
|
||||
name="${1:-}"
|
||||
if [ -z "$name" ]; then
|
||||
echo "Nutzung: bash scripts/init.sh \"Projektname\"" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
[ -f AGENTS.md ] || { echo "Bitte aus dem Repo-Root ausfuehren (AGENTS.md nicht gefunden)." >&2; exit 1; }
|
||||
|
||||
if [ -f docs/about-template.md ]; then
|
||||
echo "Bereits initialisiert (docs/about-template.md existiert). Abbruch." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 1) Template-README bewahren, frische Projekt-README schreiben.
|
||||
git mv README.md docs/about-template.md 2>/dev/null || mv README.md docs/about-template.md
|
||||
cat > README.md <<EOF
|
||||
# ${name}
|
||||
|
||||
> Arbeitet nach dem **agent-swarm**-Betriebsmodell. Jeder Agent (Mensch wie KI)
|
||||
> liest zuerst [\`AGENTS.md\`](AGENTS.md). Methodik im Detail:
|
||||
> [\`docs/methodology.md\`](docs/methodology.md). Herkunft des Modells:
|
||||
> [\`docs/about-template.md\`](docs/about-template.md).
|
||||
|
||||
## Schnellstart
|
||||
- **Stand & nächster Schritt:** [\`STATE.md\`](STATE.md)
|
||||
- **Plan / Ready-Set:** [\`ROADMAP.md\`](ROADMAP.md)
|
||||
- **Regeln:** [\`CONVENTIONS.md\`](CONVENTIONS.md)
|
||||
- **Neues Feature anstoßen:** [\`session-prompts/BOOTSTRAP.md\`](session-prompts/BOOTSTRAP.md)
|
||||
EOF
|
||||
|
||||
# 2) Git initialisieren, falls noetig.
|
||||
if ! git rev-parse --git-dir >/dev/null 2>&1; then
|
||||
git init -q
|
||||
echo "[init] leeres Git-Repo angelegt."
|
||||
fi
|
||||
|
||||
echo "[init] '${name}' initialisiert."
|
||||
echo "[init] Template-Overview liegt jetzt unter docs/about-template.md."
|
||||
echo
|
||||
echo "Naechster Schritt:"
|
||||
echo " 1) Projekt-Brief bereithalten (Ziel, Stack, Constraints)."
|
||||
echo " 2) session-prompts/BOOTSTRAP.md in eine frische Session geben (Modell: Sonnet)."
|
||||
echo " 3) Der Leader fuellt ROADMAP/STATE/CONVENTIONS und erzeugt die ersten Session-Prompts."
|
||||
echo
|
||||
echo "Die Gates sind dormant, bis die erste Session STATE.md befuellt."
|
||||
11
scripts/metrics.sh
Executable file
11
scripts/metrics.sh
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env bash
|
||||
# Observability: aggregiert Session-Logs + Git zu metrics/efficiency.csv
|
||||
set -uo pipefail
|
||||
mkdir -p metrics; out="metrics/efficiency.csv"
|
||||
echo "date,sessions,rework_commits,total_commits" > "$out"
|
||||
total=$(git rev-list --count HEAD 2>/dev/null || echo 0)
|
||||
rework=$(git log --pretty=%s | grep -Ec '^(fix|refactor)(\(.+\))?: ' || true)
|
||||
sess=$(ls sessions/[0-9]*.md 2>/dev/null | wc -l | tr -d ' ')
|
||||
echo "$(date +%F),$sess,$rework,$total" >> "$out"
|
||||
echo "[metrics] geschrieben nach $out"
|
||||
echo " Rework-Rate: $rework/$total Commits"
|
||||
Reference in New Issue
Block a user