phase 1: promote vb2_dma_resv RFC v2 + add ka-status + ampere as 2nd aarch64 host
Three changes that together flip kernel-agent from spec'd to operational
in the manual-orchestrated form. Real ka-* CLI verbs come in later phases;
this commit gets a first iteration through the pipeline and proves the
flow at the artifact level.
1. Promote vb2_dma_resv RFC v2 series into the scope-tagged tree
Markus iterated v2 locally on boltzmann (kernel-agent-bootstrap dir,
reaching linux-fresnel-fourier pkgrel=14). v2 attaches the producer
fence at device_run in slept-OK context per Dufresne's v1 review on
linux-media. The three patches land under
patches/subsystem/media/videobuf2/dma-resv-release-fence/:
- 0004 (helper) — opt-in vb2 dma_resv producer-fence helper
- 0005 (driver opt-in) — hantro device_run attach
- 0006 (driver opt-in) — rockchip-rga device_run attach
Numbered 4/5/6 because the fresnel build PKGBUILD applies them after
the three 0001/0002/0003 PBP DTS patches; this directory's numbering
follows that apply-order, not the upstream lore series numbering.
README at the scope dir documents fleet eligibility, decision history,
and the v1 → v2 design pivot.
2. Update fleet/fresnel.yaml to include the v2 series
Pre-v2 manifest had a comment block 'Explicitly NOT included … vb2
dma-resv-release-fence … defer until v2 lands'. v2 has landed. Move
those three lines from 'excluded' to 'includes', annotate the decision
inline.
3. README updates
- Build hosts table: add ampere (CoolPi GenBook, RK3588 32GB) as
secondary aarch64 host. Same uarch as boltzmann, on-demand wake via
His. Gives the fleet a second native build target for when boltzmann
is busy (e.g. carrying a firefox-fourier 4h build).
- 'Out of scope this round' bootstrap section: mark vb2_dma_resv as
resolved 2026-05-15, keep panfrost IOMMU_CACHE deferred.
4. First ka-* CLI verb implemented: bin/ka-status
bash, ~120 lines. Reads fleet/*.yaml manifests, queries Gitea for
open [ka:*] issues, probes each reachable host for the installed
kernel-package version. Read-only — no sudo, no host writes. Picks
GITEA_TOKEN from /opt/herding/etc/claude-identities/<host>.creds or
env override.
Proves the agent's Gitea-API + manifest-parsing skeleton works
end-to-end without committing to a full ka-promote/build/install
implementation. Smoke-tested locally:
$ bin/ka-status
kernel-agent status (repo: marfrit/kernel-agent)
open [ka:*] issues total: 1
══ fresnel ══
manifest: arch=arm64 soc=rockchip/rk3399 board=pinebook-pro
package: linux-fresnel-fourier
installed: host-down # (fresnel is currently powered off)
open ka-issues: (none for this host)
No PKGBUILD update in this PR — that lives in marfrit-packages and
ships as a sibling PR (the actual linux-fresnel-fourier-7.0-14 publish).
This commit is contained in:
Executable
+136
@@ -0,0 +1,136 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# ka-status — per-host kernel-agent state summary.
|
||||
#
|
||||
# Reads fleet/*.yaml manifests + queries Gitea for open [ka:*] issues +
|
||||
# probes each host (where reachable) for the installed kernel-package
|
||||
# version. Designed to give a first-look "what's the state" before any
|
||||
# ka-promote / ka-install action.
|
||||
#
|
||||
# Usage:
|
||||
# ka-status # summary across all manifests
|
||||
# ka-status <host> # detail for one host
|
||||
#
|
||||
# Read-only. Never mutates state. No sudo. No SSH-into-host writes.
|
||||
#
|
||||
# Phase 1 deliverable. Future ka-* CLI verbs (ka-promote / ka-close /
|
||||
# ka-install) build on the same Gitea-API + manifest-parsing skeleton.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
GITEA_URL="${GITEA_URL:-https://git.reauktion.de}"
|
||||
REPO="${KERNEL_AGENT_REPO:-marfrit/kernel-agent}"
|
||||
TOKEN_FILE="${KERNEL_AGENT_TOKEN_FILE:-/opt/herding/etc/claude-identities/noether.creds}"
|
||||
|
||||
# Resolve token from per-host claude-identity creds, or env override.
|
||||
token=""
|
||||
if [ -n "${GITEA_TOKEN:-}" ]; then
|
||||
token="$GITEA_TOKEN"
|
||||
elif [ -r "$TOKEN_FILE" ]; then
|
||||
token="$(grep -E '^GITEA_TOKEN=' "$TOKEN_FILE" | head -1 | cut -d= -f2)"
|
||||
fi
|
||||
|
||||
# Locate fleet/ — script lives in bin/ next to fleet/.
|
||||
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
fleet_dir="${script_dir}/../fleet"
|
||||
[ -d "$fleet_dir" ] || { echo "fleet/ not found relative to $script_dir" >&2; exit 2; }
|
||||
|
||||
api_get() {
|
||||
local path="$1"
|
||||
local args=(--silent --show-error --max-time 15)
|
||||
[ -n "$token" ] && args+=(-H "Authorization: token $token")
|
||||
curl "${args[@]}" "${GITEA_URL}/api/v1/${path}"
|
||||
}
|
||||
|
||||
# Open ka-prefixed issues, JSON array on stdout.
|
||||
fetch_ka_issues() {
|
||||
api_get "repos/${REPO}/issues?state=open&type=issues&limit=50" \
|
||||
| python3 -c '
|
||||
import json, sys
|
||||
issues = json.load(sys.stdin)
|
||||
def kind(t):
|
||||
if not t.startswith("["): return None
|
||||
p = t.find("]")
|
||||
return t[1:p] if p > 0 else None
|
||||
out = [{
|
||||
"number": i["number"],
|
||||
"title": i["title"],
|
||||
"kind": kind(i["title"]),
|
||||
} for i in issues if kind(i["title"]) and kind(i["title"]).startswith("ka:")]
|
||||
print(json.dumps(out))
|
||||
' 2>/dev/null || echo "[]"
|
||||
}
|
||||
|
||||
# Parse a fleet/<host>.yaml manifest (very-narrow YAML subset).
|
||||
manifest_field() {
|
||||
local file="$1" key="$2"
|
||||
grep -E "^[[:space:]]*${key}:" "$file" | head -1 | sed -E "s/^[^:]*:[[:space:]]*//; s/[[:space:]]+#.*//; s/^[\"']//; s/[\"']$//"
|
||||
}
|
||||
|
||||
manifest_pkgname() {
|
||||
local file="$1"
|
||||
awk '/^package:/{p=1; next} p && /^[a-z]/{p=0} p && /^[[:space:]]+name:/{sub(/^[[:space:]]+name:[[:space:]]*/,""); print; exit}' "$file"
|
||||
}
|
||||
|
||||
# Probe a host for installed kernel-package version (best-effort, non-blocking).
|
||||
probe_installed() {
|
||||
local host="$1" pkg="$2"
|
||||
ssh -o ConnectTimeout=3 -o BatchMode=yes -o StrictHostKeyChecking=accept-new \
|
||||
"${host}.fritz.box" "pacman -Q '$pkg' 2>/dev/null || dpkg-query -W -f='\${Package} \${Version}\n' '$pkg' 2>/dev/null || echo 'host-up:not-installed'" 2>/dev/null \
|
||||
|| echo "host-down"
|
||||
}
|
||||
|
||||
issues_json="$(fetch_ka_issues)"
|
||||
|
||||
# Per-host issue grouping — match on title containing the host name (cheap heuristic;
|
||||
# proper kernel-agent will tag issues with a host label).
|
||||
issues_for_host() {
|
||||
local host="$1"
|
||||
echo "$issues_json" | python3 -c "
|
||||
import json, sys
|
||||
host = '$host'
|
||||
issues = json.load(sys.stdin)
|
||||
hits = [i for i in issues if host in i['title'].lower()]
|
||||
for h in hits:
|
||||
print(f\" #{h['number']} [{h['kind']}] {h['title']}\")
|
||||
" 2>/dev/null
|
||||
}
|
||||
|
||||
print_host() {
|
||||
local file="$1"
|
||||
local host pkg
|
||||
host="$(basename "$file" .yaml)"
|
||||
pkg="$(manifest_pkgname "$file")"
|
||||
local arch="$(manifest_field "$file" arch)"
|
||||
local soc="$(manifest_field "$file" soc)"
|
||||
local board="$(manifest_field "$file" board)"
|
||||
|
||||
printf '\n══ %s ══\n' "$host"
|
||||
printf ' manifest: arch=%s soc=%s board=%s\n' "$arch" "$soc" "$board"
|
||||
printf ' package: %s\n' "$pkg"
|
||||
if [ -n "$pkg" ]; then
|
||||
printf ' installed: %s\n' "$(probe_installed "$host" "$pkg")"
|
||||
fi
|
||||
|
||||
local n=0
|
||||
while IFS= read -r line; do
|
||||
[ -z "$line" ] && continue
|
||||
if [ $n -eq 0 ]; then printf ' open ka-issues:\n'; fi
|
||||
printf '%s\n' "$line"
|
||||
n=$((n+1))
|
||||
done < <(issues_for_host "$host")
|
||||
[ $n -eq 0 ] && printf ' open ka-issues: (none for this host)\n'
|
||||
}
|
||||
|
||||
if [ $# -ge 1 ]; then
|
||||
f="${fleet_dir}/${1}.yaml"
|
||||
[ -r "$f" ] || { echo "no manifest for host '$1'" >&2; exit 2; }
|
||||
print_host "$f"
|
||||
else
|
||||
printf 'kernel-agent status (repo: %s)\n' "$REPO"
|
||||
printf 'open [ka:*] issues total: %s\n' "$(echo "$issues_json" | python3 -c 'import json,sys; print(len(json.load(sys.stdin)))')"
|
||||
for f in "$fleet_dir"/*.yaml; do
|
||||
[ -e "$f" ] || continue
|
||||
print_host "$f"
|
||||
done
|
||||
fi
|
||||
Reference in New Issue
Block a user