Two additions to fleet/ohm.yaml's includes for the bes2600 driver scope:
1. driver/bes2600/tx-sdio-dma-oob-danctnix/ — already on disk from
ka#17 but not previously included. The cumulative-c5x-danctnix
shipped in pkgrel=3 did NOT have this fix; pkgrel=4 per-series
regressed because the staging-prep series was excluded. KFENCE
caught the OOB during pkgrel=4 soak; pkgrel=5 included it.
2. driver/bes2600/join-confirm-reset-danctnix/ — NEW scope.
cw1200 ancestor port (sta.c:1339-1344) with bes2600-specific
PASSIVE-gate compensation in bes2600_unjoin_work. Closes
besser#25. Verified pkgrel=6 srcversion 0E16463F: cascade gone,
periodic ~600ms latency jitter also gone (same root cause).
Status note: per-series reconstruction is now converged. The
cumulative-c5x-danctnix entry is left as historical fallback;
ka#29's blocker (per-series mirrors not applying cleanly) was
resolved by manually reconstructing the per-series in
marfrit/bes2600-dkms bes2600/join-confirm-failure-reset (top
commit 3d833f8).
Build still hand-managed via boltzmann:~/src/besser/marfrit-besser/
danctnix-besser-pkgbuild/kernel/PKGBUILD; ka-promote / ka-build
template rendering still pending per the original TODOs.
Signed-off-by: Claude (noether) <claude@reauktion.de>
Resolves the conflict-window between the PR's "switch bes2600 to
cumulative-c5x interim" intent and main's incremental per-patch
evolution.
Resolution per discussion:
- fleet/ohm.yaml: keep PR's cumulative-c5x layout (replaces per-patch
list) but rename arch/arm64 include to main's canonical
'scs-arm-neon-build-fix/' (branch's renamed dir dropped).
- patches/driver/bes2600/queue-pending-record-lock-bh-danctnix/
0001-*.patch: take main's (= identical content + the git-format-patch
trailer that the branch's earlier add omitted).
- patches/driver/bes2600/scan-filter-5ghz-danctnix/: drop branch's
older '0001-...-allow-single-channel.patch' variant; keep main's
newer '0001-...-filter-at-driver-boundary.patch' to avoid 0001-*
collisions in ka-promote's series-dir resolver.
- patches/arch/arm64/xor-neon-ffixed-x18-scs-build-fix-danctnix/:
dropped (= duplicate of main's scs-arm-neon-build-fix/).
- All other main additions (rkvdec vp9 patches, scan-filter-5ghz/,
fleet/ampere.yaml updates) auto-merged cleanly.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
a840f76 changed @@ from -9,6 +9,10 to -9,7 +9,12 but overshot by 1.
Actual hunk is 6 context + 5 add = -9,6 +9,11. Wrong counts were
silently masked in pkgrel=4 build #4 by the trailer-stripped EOF
letting patch fuzz recover. pkgrel=5 with besser#18 after SCS
exposes it as 'malformed patch at line N: 2.54.0'.
Cumulative b2sum: ceec602afa8574c74354... -> 50397711a6a3ba522283...
Size unchanged 162 716.
When the SCS patch was the LAST patch in ohm's cumulative, the
trailing '-- \n2.54.0\n' git-format-patch sentinel was an orphan that
patch(1) read as a malformed header — fixed in 84734ba by stripping
the trailer.
Now besser#18 (queue-pending-record-lock-bh-danctnix) is added at the
end of ohm.yaml's includes. SCS is no longer last. Without its
trailer to mark end-of-patch, patch(1) reads straight into besser#18's
'From d95453c... Mon Sep 17 00:00:00 2001' line and errors as
'malformed patch at line N: From ...'.
Restoring the trailer makes the separator unambiguous again.
Cumulative b2sum: 0eb091ddaba4a8f1c3c2a78... -> ceec602afa8574c74354...
Size: 162 704 -> 162 716 (+12 = the trailer bytes).
This rule — 'only the LAST patch must lack a trailer; all others must
keep theirs' — is sensitive to ohm.yaml include ordering, which is
brittle. Filed as a kernel-agent followup: ka-promote should rewrite
trailers automatically (always add to non-last, always strip from
last) so source patches don't need to be ordering-aware.
Pulls the besser#18 lockdep fix (originally on
noether/bes2600-pending-record-lock-bh / PR #30) into this PR so the
ohm migration ships a single self-consistent pkgrel that contains all
three goal components: kernel-agent flow + Patch I + besser#18 fix
(plus the GCC 15 SCS Makefile workaround, no-op while SCS=n).
ohm.yaml includes now resolve to 4 patches:
1. driver/bes2600/cumulative-c5x-danctnix/ (148 149 B)
2. driver/bes2600/scan-filter-5ghz-danctnix/ ( 7 735 B)
3. arch/arm64/xor-neon-ffixed-x18-scs-build-fix-danctnix/ (1 562 B)
4. driver/bes2600/queue-pending-record-lock-bh-danctnix/ (5 258 B)
----
cumulative.patch (162 704 B)
b2sum 0eb091ddaba4a8f1c3c2a78eb8c621cdc6e6dfed6c43f7dac03e508a05b...
Trailer-strip applied to the besser#18 patch source for the same
reason as the SCS patch — it's now the last in the concatenated
cumulative, and patch(1) errors on the orphan '-- \n2.54.0\n' EOF
sentinel. Same gotcha documented in 84734ba.
PR #30 (the standalone besser#18 mirror PR) becomes superfluous
once this lands; close it as 'bundled into #28'.
The '-- \n2.54.0\n\n' trailer added in 989b884 was wrong. The
underlying problem was the malformed @@ hunk counts (off by 1 in
both old and new), fixed in a840f76. With correct @@ counts, patch(1)
processes the hunk fully and then sees the orphan trailer at EOF —
which it tries to parse as the start of a new patch header
('malformed patch at line N: 2.54.0').
The original (no-trailer) shape works correctly in the concatenated
cumulative as long as the @@ counts are right. Removing the trailer
brings the file back to the original 1562-byte size and the
cumulative b2sum to 334c37b5d37067982bd9... (size unchanged 157 458 ->
157 446 since the 12 byte trailer is gone).
Lesson for ka-promote: when concatenating patches as a stream for
patch(1), the LAST patch must not carry a trailing '-- \n<version>\n'
sentinel — the previous patches' sentinels are fine because they are
followed by 'From <sha>' headers that patch(1) recognises as the next
patch boundary. Documented in series-dir README as a gotcha.
Single-patch series-dir, mirror of the Markus-authored commit d95453c
on marfrit/bes2600-dkms branch bes2600/queue-pending-record-lock-bh-fix
(PR #11). Paths rewritten from DKMS-style (bes2600/foo.c) to in-tree
staging (drivers/staging/bes2600/foo.c) via sed -- this is the
in-tree variant.
Fix: convert plain spin_lock(&pending_record_lock) to spin_lock_bh()
at the 5 sites where it's taken in non-BH-disabled contexts
(queue.c:832/839/844, tx_loop.c:112/114). queue.c:289/295 stays as
plain spin_lock because BH is already disabled by the outer
queue->lock_bh acquired at queue.c:285.
Eliminates the SOFTIRQ-safe -> SOFTIRQ-unsafe lockdep warning
reported in besser#18 (PROVE_LOCKING-only -- non-fatal on production
builds where lockdep is off, but real AB-BA window between
bes2600_join_work workqueue context and bes2600_tx softirq context).
This commit does NOT add the include to fleet/ohm.yaml. The patch
will be wired into ohm's manifest in a follow-up commit (or this
branch's PR can extend with the ohm.yaml change once the migration
PR #28 lands and the bes2600-dkms PR #11 is reviewed).
Closes: besser#18
Refs: marfrit/bes2600-dkms #11 (source-of-truth PR)
The hunk header @@ -9,6 +9,10 @@ understated both old (actual 7) and
new (actual 12) line counts by 1. patch(1) standalone tolerates this
via fuzz, but in the concatenated cumulative the wrong counts cause
patch to mis-judge the hunk boundary and read the trailing context
line ('lib-...uaccess_flushcache.o') as the start of a new patch
header — 'malformed patch at line 4526'.
Cumulative b2sum: bd42cd39106298879eeb... -> ad9e2cb533957f218058...
(size unchanged at 157 458; only the @@ counts in the SCS patch
differ)
The SCS-build-fix patch was missing the standard '-- \n2.54.0\n'
trailer that git format-patch emits between patches. Without it,
BSD-flavour patch(1) in makepkg's prepare() reads the trailing context
line of the @@ hunk as the start of a new patch header and dies with
'malformed patch at line N'. Affects builds where ka-promote
concatenates this series with any others. Reproduced 2026-05-18 on
the first attempted ohm pkgrel=4 build.
Cumulative b2sum changes accordingly:
a807297b25be... -> bd42cd39106298879eeb...
(size 157446 -> 157458; 12 bytes for the trailer)
Audit during ohm pkgrel=4 migration found the per-series -danctnix
mirrors merged in #17 do NOT apply against the linux-pinetab2 baseline:
all 17 of them use DKMS-style root paths (bes2600/foo.c) rather than
in-tree staging paths (drivers/staging/bes2600/foo.c), and at least one
has a corrupted mixed-prefix header
(a/drivers/staging/bes2600/... b/bes2600/...).
ka-promote ohm with those includes produced a 172 644-byte cumulative
touching 27 file paths, of which 11 are bogus. The hand-curated
0001-bes2600-besser-cumulative-series.patch from the working
danctnix-besser-pkgbuild flow on boltzmann (148 149 bytes, 48 in-tree
staging files) is what pkgrel=3 actually builds with.
Until the per-series mirrors are reconstructed (followup issue to be
opened separately), the bes2600 driver scope is satisfied here by
staging that hand-curated cumulative as a single-file series-dir
patches/driver/bes2600/cumulative-c5x-danctnix/. ohm.yaml drops the
broken per-series includes in favour of:
- driver/bes2600/cumulative-c5x-danctnix/
- driver/bes2600/scan-filter-5ghz-danctnix/ (closes besser#1)
- arch/arm64/xor-neon-ffixed-x18-scs-build-fix-danctnix/
ka-promote ohm now produces a self-consistent 157 446-byte cumulative
(148 149 + 7 735 + 1 562 = exact byte arithmetic) with b2sum
a807297b25be... which is what the new
marfrit-packages/arch/linux-pinetab2-danctnix-besser PKGBUILD pkgrel=4
pins.
Also fixes fleet/ohm.yaml YAML parse error: bar5_burn_in had a scalar
value followed by a sub-list, which ka-promote (PyYAML) refused to
parse. The whole manifest had never parsed cleanly since #18 landed.
Refs: #5 (migrate PKGBUILD), #2 (mirror besser series — needs per-series
rewrite followup), besser#1 (Patch I).
Updates both flavors with the n_channels > 1 refinement (was > 0).
The original guard refused ALL 5 GHz scans which broke 5 GHz
association via NM band=a profiles (NM iterates freq_list per
channel, single-channel scans were also refused).
Tightened: only multi-channel 5 GHz scans (the per-band-sweep
that triggers the firmware storm) are refused; single-channel
5 GHz scans pass through so NM/wpa_supplicant can find and
associate to 5 GHz BSSes.
Verified on ohm with locally-built pkgrel=3 (srcversion
BEB625FA7443171EA8D55F7): associated to 5 GHz BSSID
c0:25:06:e6:5b:33 on 5240 MHz / ch.48, 150 Mbit/s MCS 7
40MHz short-GI; Pattern A still 0 since boot.
Patch file is now a concatenation of two commits from
marfrit/bes2600-dkms bes2600/scan-filter-5ghz branch:
093a503 (original Patch I)
8cd10f4 (this refinement)
patch -Np1 applies them sequentially -> net effect = single squash.
Refs: besser#1 (closed), PKGBUILD update at marfrit/besser
claude-noether-14 commit 122582e (pkgrel=3 deployed to ohm
on 2026-05-18 same session).
Patch I closes besser#1 — the wsm_generic_confirm 0x0007 dmesg storm.
One-line guard in bes2600_hw_scan() refuses the 5 GHz iteration of
mac80211's per-band hw_scan loop with -EOPNOTSUPP, so the firmware
never sees the scan request that would be rejected with status 2 →
-EINVAL cascade. Phase 7 verified 2026-05-18 on ohm running pkgrel=2:
Pattern A 14.3/h → 0/h over 30-min window, no WARN/BUG, single-band
2.4 GHz scans still return BSSes cleanly.
Two flavors imported (scan-filter-5ghz and scan-filter-5ghz-danctnix)
matching the convention of other bes2600 series — the code path
doesn't touch timer APIs so the two are byte-identical for now;
flavor separation is kept to preserve consistency in ohm.yaml.
The arm64 scs-arm-neon-build-fix series is a build-environment
workaround: GCC 15.2.1 strictly validates that -fsanitize=shadow-
call-stack requires -ffixed-x18, and arm_neon.h's #pragma target/
push/pop blocks lose x18 fixing inside the wrapped section. The
Makefile tweak re-adds -ffixed-x18 explicitly for xor-neon.o. It's
a no-op when SCS is off (current pkgrel=2 ohm config) and unblocks
SCS=y once GCC upstream is fixed.
ohm.yaml gains a CONFIG_SHADOW_CALL_STACK=n config override with a
pointer to besser#20 (the re-enable tracking issue) so future
manifest-driven kconfig generation honors the workaround without
silently dropping it.
Source-of-truth commit for Patch I:
marfrit/bes2600-dkms branch bes2600/scan-filter-5ghz sha 093a503
PKGBUILD-side (already deployed to ohm via pkgrel=2):
marfrit/besser branch claude-noether-14 sha ae175f9
Refs: besser#1 (closed), besser#20, kernel-agent#5
Three patches from D.V.A.B. Sarma adding VP9 decode support to the
VDPU381 variant of rkvdec (RK3588 generation). Combined ~1500 LOC,
5 new files in drivers/media/platform/rockchip/rkvdec/.
Provenance: github.com/dvab-sarma/android_kernel_rk_opi branch
add-rkvdec-vdpu381-vp9-v8. Collabora's blog cites the work but it
hasn't reached linux-media patchwork yet (Collabora: "v1 series
needs to be sent for review soon"). Casanova's underlying
VDPU381/VDPU383 H.264+HEVC base IS in mainline 7.0 release.
Tested by author on Orange Pi 5 Pro (RK3588) with AOSP 16 + FFMPEG,
Profile 0 + Profile 2.
Tested in our fleet 2026-05-18: cherry-picks cleanly on top of
ampere-minimal-devices, full kernel build (KERNELRELEASE
7.0.0-rc3-vp9-test+) succeeds clean with GCC 16.1.1. Image + DTB +
modules + initramfs installed under -vp9-test+ suffix on ampere
without touching the running -devices+ kernel; new extlinux label
arch_vp9_test added (default unchanged at arch_devices). End-to-end
VP9 decode verification pending operator reboot into the new label.
Patches NOT yet referenced from fleet/ampere.yaml — that bump is
the operator's call (manifest preamble currently scopes VP9 out per
issue #6). Once verified, ampere.yaml can add these three under the
scope-tagged patch list in apply order 0001→0002→0003.
Cross-reference: marfrit/kernel-agent#12.
Add coolpi-cm5-genbook DTS patch that mirrors vendor coolpi-kernel
audio routing for the internal microphone:
routing = "MIC1", "Main Mic",
"MIC2", "Headset Mic";
Necessary-but-not-sufficient: the ES8316 RX aif_out widget power-up
chain is still broken on mainline (separate issue, not addressed
here); a future codec/audio-graph-card driver fix can complete the
capture path once the topology is correct.
Include in ampere fleet manifest.
Mirrors all 30 BES2600 patch series from marfrit/besser/patches/ into
the kernel-agent scope-tagged tree under patches/driver/bes2600/.
15 base series + 15 -danctnix siblings = 45 .patch files including
cover letters.
Per-series promotion eligibility tracked in the README (default
unset → ka-promote asks before including in a build). Markus to
update as series mature.
DKMS-to-in-tree transition path documented (drop bes2600-dkms
once series lands in mainline / DanctNIX base).
Cumulative-patch ordering caveat captured: existing order is NOT
alphabetical (A,B,C v3,F,G,D,E,C2,c5.x,c6.x,c7,H). ka-promote
needs an explicit apply_order field, not a series-name sort.
Surface when fleet/ohm.yaml lands in #5.
Acceptance criteria from #2:
[x] All series present under driver/bes2600/
[x] Promotion eligibility per series (table in README, defaults unset for Markus to fill)
[ ] Manifest for ohm references driver:bes2600 scope (deferred to #5)
[x] DKMS-to-in-tree transition path documented
Generated-by: Claude Opus 4.7 <claude@reauktion.de>
Closes the migration started in #8. The 6 active ampere patches (pwm15,
pwm-fan, RK806 power-controller, speaker, USB-C PD, lid switch) landed
in #8 under soc/rockchip/rk3588/, module/coolpi-cm5/, and
board/coolpi-cm5-genbook/. This commit migrates the remaining 3:
* `0006 arm64 Kconfig: do not select HAVE_GCC_PLUGINS`
→ patches/arch/arm64/. NOT for upstream — local build workaround;
README explains the proper fix is gcc-plugin-devel install.
* `0009 Bluetooth: btrtl: make RTL_SEC_PROJ read non-fatal`
→ patches/driver/bluetooth/btrtl/. Benefits ampere (RTL8852BE) and
boltzmann (same M.2 family). Cross-host driver/ scope.
* `0010 gpio/drm/mfd/input/dts: fix suspend/resume and wakeup on RK3588`
→ SPLIT into 5 scope-tagged sub-patches as the issue required
("0010 split into ≥2 patches by scope"):
- patches/driver/gpio/rockchip/0010a-gpio-rockchip-propagate-irq_set_wake-to-parent-GIC.patch
- patches/driver/gpu/drm/bridge/analogix/0010b-drm-bridge-analogix-dp-disable-IRQ-before-clock-gating-in-suspend.patch
- patches/driver/mfd/rk8xx/0010c-mfd-rk8xx-spi-add-PM-ops-and-shutdown-callback.patch
- patches/driver/input/misc/0010d-input-rk805-pwrkey-register-wake-IRQ-via-dev_pm_set_wake_irq.patch
- patches/board/coolpi-cm5-genbook/0010e-arm64-dts-rockchip-rk3588-coolpi-cm5-genbook-add-NPU-power-domain-and-touchpad-wakeup.patch
The split is byte-identical to the original 0010 (verified on
decompose-0010 branch in marfrit/linux-rk3588-marfrit — sha256 of
the combined diff matches the monolithic 0010 commit).
All 0010 sub-patches marked WIP in their README and explicitly NOT
added to fleet/ampere.yaml includes — suspend/resume thread is still
open and Markus hasn't decided the upstream-targeting shape.
READMEs added at each new directory documenting per-patch context.
Acceptance criteria from #1:
[x] Each patch lives at narrowest correct scope
[x] 0010 split into ≥2 patches by scope (5 sub-patches)
[x] Per-host manifest for ampere references the right scopes + explicit includes (already #8)
[ ] github.com/marfrit/misc_patches retained as historical mirror — Markus to decide
[x] working-tree dirty state on boltzmann reconciled (decompose-0010 + ampere-minimal-devices branches captured)
Generated-by: Claude Opus 4.7 <claude@reauktion.de>
Brings the second customized fleet host into kernel-agent's
scope-tagged tree. Sibling PR coming in marfrit-packages with the
arch/linux-ampere-fourier/ PKGBUILD + flat patch + config + extlinux
hook (build-tree-ready form).
Issue #6 ask #1 only — VP9 enablement (ask #2) and AV1 dec integration
(ask #3) are explicitly deferred to a separate session per the user's
direction. The ampere.yaml manifest documents what's excluded and why.
## Patches promoted
Six patches from boltzmann:~/src/misc_patches/genbook/kernel/ get
scope-tagged into kernel-agent's tree:
soc/rockchip/rk3588/
0001-...Add-pwm15-pinctrl-entries.patch (prereq for 0002)
module/coolpi-cm5/
0003-...Fix-power-off-by-enabling-RK806-as-system-power-controller.patch
board/coolpi-cm5-genbook/
0002-...Add-pwm-fan.patch
0004-...Enable-speaker-output-via-audio-graph-card.patch
0005-...Enable-USB-C-PD-charging-via-FUSB302.patch
0008-...Add-lid-switch-and-USB3-PHY-lane-config.patch
Each new scope dir gets a README.md documenting what it carries and
why the scope-level granularity makes sense (pwm15 is SoC-wide,
RK806 power-off is SoM-level not board-level, the rest are
board-specific GenBook quirks).
Note on uncommitted-modifications flag in issue body: patches 0001-0004
have working-tree-only changes in misc_patches that fix malformed
'From: PATCH 000X/000Y' headers (placeholder text instead of an
RFC-2822 author identity). The working-tree versions with proper
'From: Markus Fritsche <mfritsche@localhost>' headers are what we ship
here — the unfixed-on-disk variants would fail patch -i header parsing
on stricter implementations and are user-side cleanup that hasn't been
committed back to misc_patches yet. Markus can commit the cleanup
to that personal repo separately; this PR's ingestion does not depend
on it.
Patches 0006 (HAVE_GCC_PLUGINS Kconfig), 0009 (Bluetooth btrtl),
0010 (multi-driver suspend/wakeup) from the misc_patches series are
intentionally NOT promoted here — they need different scope tags
(arch/arm64/, driver/bluetooth/, soc/rockchip/rk3588/ + driver/ split)
and will follow when their respective campaigns demand them. The
ampere.yaml manifest documents the explicit-defer for each.
## fleet/ampere.yaml manifest
Same shape as fleet/fresnel.yaml. Baseline pinned at marfrit/linux-rockchip
branch linux-rk3588-marfrit @ f8f3ad934433 (the working tree on
boltzmann; 18 commits ahead of v7.0-rc3, current 2026-05-15 tip).
Six scope-tagged patch includes per the apply-order in the package
(pwm15 pinctrl must precede the pwm-fan node consumer).
## ampere-specific bootloader path
Documented in manifest. ampere boots from /boot/firmware/ (vfat
partition on mmcblk0p1), not /boot/ (root partition) like fresnel.
The marfrit-packages PKGBUILD's extlinux-add hook needs to write to
/boot/firmware/extlinux/extlinux.conf, not /boot/extlinux/.
## ampere as 2nd aarch64 build host
Per the README update in PR #7, ampere is now a secondary aarch64
build host. The manifest's build_host: section pins ampere as
self-hosting primary for its own kernel, with boltzmann as secondary
and fermi as fallback. This is the first manifest that has its own
host listed as the primary build target — not ideologically pretty,
but pragmatic: native arch, same uarch, full RAM, no cross-compile
step, no need to wake another 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).