From 04849e0c229ad378d1bb619470e7c13fd255b2ce Mon Sep 17 00:00:00 2001 From: charly Date: Fri, 16 Oct 2026 16:29:41 +0200 Subject: [PATCH 1/2] fix(cuda): link every entry of the CUDA include roots on Arch, not a pattern-matched subset nvcc computes its default include root RELATIVE to its own executable, and /usr/bin/nvcc is a symlink, so every CUDA header must be reachable under /usr/include. The Arch stitch enumerated by pattern instead: a `*.h` glob linked the top-level headers but silently dropped the crt/ and cccl/ SUBTREES, so every CUDA build died at CMake's enable_language(CUDA) with 'crt/host_config.h: No such file or directory' -- and once the subtrees were linked, the same glob dropped the .hpp half of the _functions family (vector_functions.hpp and friends), failing the very next stage. Both Arch arms now enumerate every entry of /opt/cuda/include and /opt/cuda/targets/x86_64-linux/include, linking files of any extension and subtrees alike -- no extension list to keep in sync, and no silent drop. A new build-scope check, cuda-arch-header-root, preprocesses a real CUDA translation unit so this cannot regress; it is Arch-scoped inside the command, since the runner does not honour runner-level exclude-distro. The cuda-skill: entity is mirrored in the same change. Proven on real Arch hardware: fresh build clean, the check FAILS without the fix and PASSES with it. Fixes #9 Assisted-by: DeepSeek Harness deepseek-v4.1-flash (fully tested and validated) --- .../ffmpeg.v2026.272.0056/.charly-view-ok | 1 + .../.github/workflows/tag-on-merge.yml | 88 ++++++++ .build/_candy/ffmpeg.v2026.272.0056/AGENTS.md | 55 +++++ .build/_candy/ffmpeg.v2026.272.0056/README.md | 59 ++++++ .../_candy/ffmpeg.v2026.272.0056/charly.yml | 113 ++++++++++ .../nvidia.v2026.271.1817/.charly-view-ok | 1 + .../.github/workflows/tag-on-merge.yml | 88 ++++++++ .build/_candy/nvidia.v2026.271.1817/AGENTS.md | 58 ++++++ .../CHANGELOG/2026.245.1450.md | 55 +++++ .../CHANGELOG/2026.245.1456.md | 36 ++++ .../CHANGELOG/2026.245.1515.md | 28 +++ .../CHANGELOG/2026.245.1521.md | 28 +++ .../CHANGELOG/2026.245.1541.md | 38 ++++ .../CHANGELOG/2026.271.1114.md | 103 +++++++++ .build/_candy/nvidia.v2026.271.1817/README.md | 73 +++++++ .../_candy/nvidia.v2026.271.1817/charly.yml | 196 ++++++++++++++++++ .containerignore | 17 ++ .dockerignore | 17 ++ charly.yml | 70 ++++++- 19 files changed, 1118 insertions(+), 6 deletions(-) create mode 100644 .build/_candy/ffmpeg.v2026.272.0056/.charly-view-ok create mode 100644 .build/_candy/ffmpeg.v2026.272.0056/.github/workflows/tag-on-merge.yml create mode 100644 .build/_candy/ffmpeg.v2026.272.0056/AGENTS.md create mode 100644 .build/_candy/ffmpeg.v2026.272.0056/README.md create mode 100644 .build/_candy/ffmpeg.v2026.272.0056/charly.yml create mode 100644 .build/_candy/nvidia.v2026.271.1817/.charly-view-ok create mode 100644 .build/_candy/nvidia.v2026.271.1817/.github/workflows/tag-on-merge.yml create mode 100644 .build/_candy/nvidia.v2026.271.1817/AGENTS.md create mode 100644 .build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.245.1450.md create mode 100644 .build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.245.1456.md create mode 100644 .build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.245.1515.md create mode 100644 .build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.245.1521.md create mode 100644 .build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.245.1541.md create mode 100644 .build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.271.1114.md create mode 100644 .build/_candy/nvidia.v2026.271.1817/README.md create mode 100644 .build/_candy/nvidia.v2026.271.1817/charly.yml create mode 100644 .containerignore create mode 100644 .dockerignore diff --git a/.build/_candy/ffmpeg.v2026.272.0056/.charly-view-ok b/.build/_candy/ffmpeg.v2026.272.0056/.charly-view-ok new file mode 100644 index 0000000..1ef6582 --- /dev/null +++ b/.build/_candy/ffmpeg.v2026.272.0056/.charly-view-ok @@ -0,0 +1 @@ +903a97260894115f0ff5f184ebeaf2e058e57ea0 diff --git a/.build/_candy/ffmpeg.v2026.272.0056/.github/workflows/tag-on-merge.yml b/.build/_candy/ffmpeg.v2026.272.0056/.github/workflows/tag-on-merge.yml new file mode 100644 index 0000000..f503088 --- /dev/null +++ b/.build/_candy/ffmpeg.v2026.272.0056/.github/workflows/tag-on-merge.yml @@ -0,0 +1,88 @@ +# ORG-WIDE TAG-ON-MERGE DISPATCHER — installed in every opencharly repo. +name: tag-on-merge + +# Event-driven — no cron (RCA of all previous trigger designs, measured in +# this repo across 8 merges and 17 schedule runs): +# +# 1. `on: push` / `on: pull_request: [closed]` CANNOT see auto-merge merges. +# Native-auto-merge squash merges (actor `app/github-actions`) fire their +# webhook events — they are visible in the public event stream, e.g. +# `21:35:01Z sha=e222762 by=github-actions[bot]` for PR #8 — but GitHub +# Actions creates ZERO workflow runs for them (API-confirmed: no run for +# any merge commit, and 0 `pull_request`-event runs in the workflow's +# whole history). This is platform-level run suppression for auto-merge +# commits; no trigger selection can observe them. (Human merges and +# bot contents-API commits DO create runs — hence `push` is kept as a +# secondary trigger for those paths.) +# 2. `schedule: */15` cron: GitHub cron delivery is best-effort with no SLA. +# Measured 21-44 min gaps (never the configured 15); PR #3's tag landed +# 4+ hours late; PR #7's tag was still missing 30 min after merge. +# 3. `workflow_run` on `charly/pr-validator`: the ONE trigger whose event +# delivery is proven (the 12:12-12:51Z 8/22 runs all received the event; +# they died at startup on a workflow-file issue, not on delivery). +# +# The pr-validator run is the last actor before the merge (its final step +# arms native auto-merge). Firing on its completion and waiting (bounded) for +# the squash to land makes the MERGE the effective gate for tagging. The org +# reusable sweep is idempotent and scans the last 24h of merged PRs, so any +# PR missed by a wait timeout self-heals on the next validator completion. +# The rulebook's add-only backfill remains the ultimate documented path. +on: + workflow_run: + workflows: ["charly/pr-validator"] + types: [completed] + push: + branches: + - main + +permissions: + contents: write + pull-requests: read + +jobs: + wait-for-merge: + if: > + github.event_name == 'push' || + github.event.workflow_run.conclusion == 'success' + runs-on: ubuntu-latest + steps: + - name: Wait for triggering PR to merge (bounded readiness probe) + uses: actions/github-script@v7 + with: + script: | + // Push events: the merged PR is already on main — no wait needed. + if (context.eventName !== 'workflow_run') { + core.info('push event — merged PRs are in the sweep window'); + return; + } + const run = context.payload.workflow_run; + const { data: prs } = await github.rest.pulls.list({ + ...context.repo, + state: 'open', + head: `${context.repo.owner}:${run.head_branch}`, + }); + if (!prs.length) { + core.info('No open PR for head branch — sweep covers already-merged PRs'); + return; + } + const pr = prs[0]; + const deadline = Date.now() + 5 * 60 * 1000; + while (Date.now() < deadline) { + const { data: p } = await github.rest.pulls.get({ + ...context.repo, pull_number: pr.number, + }); + if (p.merged_at) { + core.info(`PR #${pr.number} merged at ${p.merged_at} — proceeding to tag`); + return; + } + await new Promise((r) => setTimeout(r, 20 * 1000)); + } + core.info(`PR #${pr.number} not merged within 5m — sweep still runs; next validator completion self-heals`); + + tag: + if: > + github.event_name == 'push' || + github.event.workflow_run.conclusion == 'success' + needs: wait-for-merge + uses: opencharly/.github/.github/workflows/tag-on-merge.yml@main + secrets: inherit diff --git a/.build/_candy/ffmpeg.v2026.272.0056/AGENTS.md b/.build/_candy/ffmpeg.v2026.272.0056/AGENTS.md new file mode 100644 index 0000000..d35d901 --- /dev/null +++ b/.build/_candy/ffmpeg.v2026.272.0056/AGENTS.md @@ -0,0 +1,55 @@ +# AGENTS.md — layer-ffmpeg + +Standalone candy repo for the `ffmpeg` layer — the negativo17 nonfree FFmpeg +build (H.264/AAC) with `ffmpeg` and `ffprobe`. The candy lives in `charly.yml` at +the repo root: the per-distro package arm, the Fedora `fedora-multimedia` repo, +the `check:` assertions, and the embedded `skill:` entity projected into the +marketplace corpus as `/charly-selkies:ffmpeg`. + +Canonical files: + +- `charly.yml` — the `ffmpeg:` candy entity and the `ffmpeg-skill:` skill entity. +- `.github/workflows/tag-on-merge.yml` — CalVer tag + `CHANGELOG/` on merge. +- `README.md` — user overview only; never agent guidance. + +## Load these skills first (R0) + +- `/charly-selkies:ffmpeg` — the owning skill. The negativo17 repo, the nonfree + codec set, and the downstream consumers. Load before editing or troubleshooting + the layer. +- `/charly-image:layer` — the candy authoring reference (`charly.yml` schema, + `plan:` step verbs incl. `check:`, per-distro `distro:` arms, package/repo + blocks). Load before editing any entity field or plan step. + +## Build / validate / test + +- The merge gate is the **org-wide** `charly/pr-validator` (required check + `validate / validate`, defined in `opencharly/.github`); this repo has **no + per-repo candy gate** and ships only `.github/workflows/tag-on-merge.yml`. +- The candy's `plan:` `check:` steps are the functional evidence: the + `/usr/bin/ffmpeg` and `/usr/bin/ffprobe` binaries plus their version banners + (`ffmpeg version` / `ffprobe version`), and the package-installed check. They + must stay valid on the `arch`/`fedora` arms they run on. +- This is the nonfree negativo17 build, deliberately distinct from RPM Fusion's + `ffmpeg-free`; the `fedora-multimedia` repo + `gpgkey` must stay correct. + +## Modify this repo + +- Edit the `ffmpeg:` candy entity AND the `ffmpeg-skill:` skill entity in + `charly.yml` together. The skill is the projected usage source, so a package, + repo, or behaviour change not mirrored in the skill leaves the corpus stale. +- Keep `ffmpeg` as the single authoritative install point: downstream candies + declare `require: ffmpeg` rather than adding the negativo17 repo themselves. +- New behaviour claims belong in the `plan:` as an observable `check:` step, and + in the skill body. + +## Landing + +- PR-only. Every change lands through a pull request; the org-required + `charly/pr-validator` validates the diff and body and arms native auto-merge + on PASS. Direct pushes to `main` are blocked. +- History lives in `CHANGELOG/` (written by `tag-on-merge` at merge time); the + PR body IS the changelog. +- The authoritative rulebook is the umbrella `AGENTS.md` in + `opencharly/opencharly` and `charly/AGENTS.md` in the charly repo. Do not + restate its rules here. diff --git a/.build/_candy/ffmpeg.v2026.272.0056/README.md b/.build/_candy/ffmpeg.v2026.272.0056/README.md new file mode 100644 index 0000000..6db4dc2 --- /dev/null +++ b/.build/_candy/ffmpeg.v2026.272.0056/README.md @@ -0,0 +1,59 @@ +# ffmpeg + +FFmpeg — command-line audio/video transcoding and media inspection. + +The `ffmpeg` candy installs the `ffmpeg` package (from the negativo17 +`fedora-multimedia` repo on Fedora, `core`/`extra` on Arch). It ships the +`ffmpeg` transcoder and the `ffprobe` media inspector under `/usr/bin`, both of +which print a version banner to stdout — so their presence and basic operability +are directly verifiable. + +This is the negativo17 **nonfree** build (H.264/AAC support), not the RPM Fusion +`ffmpeg-free`. All candies that need `ffmpeg` declare it as a dependency rather +than independently adding the negativo17 repo, so there is a single authoritative +install point. + +## What it provides + +| Property | Value | +|---|---| +| Layer / candy | `ffmpeg` | +| Binaries | `/usr/bin/ffmpeg`, `/usr/bin/ffprobe` | +| Distro | `arch`, `fedora` | +| Repo | negativo17 `fedora-multimedia` (Fedora) | +| Service / port | none | + +## How to use it + +Compose the layer as an inline list in a box body: + +```yaml +my-box: + candy: + base: fedora + candy: + - '@github.com/opencharly/layer-ffmpeg:v2026.239.1614' +``` + +Then, inside the built image: + +```bash +ffmpeg -version # ffmpeg version x.y +ffprobe -version # ffprobe version x.y +``` + +## Layout + +- `charly.yml` — the `ffmpeg:` candy entity (the per-distro package arm, the + Fedora `fedora-multimedia` repo, the `check:` assertions) and the embedded + `ffmpeg-skill:` skill entity. +- `.github/workflows/tag-on-merge.yml` — CalVer tag + `CHANGELOG/` on merge. +- `README.md` — this user overview. + +## Related + +- Owning skill: `/charly-selkies:ffmpeg` +- Depends on it: `/charly-distros:cuda`, `/charly-tools:whisper`, + `/charly-hermes:hermes`, `/charly-immich:immich` +- [`opencharly/charly`](https://github.com/opencharly/charly) — the charly CLI and image builder +- [`opencharly/opencharly`](https://github.com/opencharly/opencharly) — the umbrella diff --git a/.build/_candy/ffmpeg.v2026.272.0056/charly.yml b/.build/_candy/ffmpeg.v2026.272.0056/charly.yml new file mode 100644 index 0000000..b855965 --- /dev/null +++ b/.build/_candy/ffmpeg.v2026.272.0056/charly.yml @@ -0,0 +1,113 @@ +ffmpeg: + candy: + description: | + FFmpeg provides command-line audio/video transcoding and media inspection + Installs the ffmpeg package (from the negativo17 fedora-multimedia repo + on Fedora, core/extra on Arch). It ships the ffmpeg transcoder and the + ffprobe media inspector under /usr/bin, both of which print a version + banner to stdout — so their presence and basic operability are directly + verifiable. + distro: + arch: + package: + - ffmpeg + fedora: + package: + - ffmpeg + repo: + - name: fedora-multimedia + url: "https://negativo17.org/repos/fedora-multimedia.repo" + gpgkey: "https://negativo17.org/repos/RPM-GPG-KEY-slaanesh" + plan: + - check: the ffmpeg transcoder binary is installed at /usr/bin/ffmpeg + file: + file: /usr/bin/ffmpeg + exists: true + - check: ffmpeg prints its version banner to stdout + exit_status: 0 + stdout: + - contains: ffmpeg version + command: ffmpeg -version + - check: the ffprobe media inspector binary is installed at /usr/bin/ffprobe + file: + file: /usr/bin/ffprobe + exists: true + - check: ffprobe prints its version banner to stdout + exit_status: 0 + stdout: + - contains: ffprobe version + command: ffprobe -version + - check: package=ffmpeg + id: ffmpeg-package + package: + package: ffmpeg + installed: true + +ffmpeg-skill: + skill: + name: ffmpeg + family: selkies + owner: ffmpeg + description: |- + FFmpeg multimedia framework (negativo17 nonfree build with H.264/AAC support). + Use when working with the ffmpeg candy. + content: |- + # ffmpeg -- FFmpeg multimedia + + ## Candy Properties + + | Property | Value | + |----------|-------| + | Install files | `charly.yml` (packages only) | + | Depends | none | + | Repo | negativo17 `fedora-multimedia` | + + ## Packages + + RPM: `ffmpeg` (from negativo17 `fedora-multimedia` repo — full nonfree build with H.264, AAC, etc.) + + **Note:** This is NOT `ffmpeg-free` (RPM Fusion). This is the negativo17 build which includes nonfree codecs required for H.264 encoding/decoding. + + ## Usage + + ```yaml + # a box composing this candy — the candy list is inline + my-box: + candy: + base: fedora + candy: [ffmpeg] + ``` + + All candies that need ffmpeg should declare it as a dependency rather than independently adding the negativo17 repo. This ensures a single authoritative install point. + + ## Used In Boxes + + - `openclaw-full` (via `openclaw-full` metalayer) + - `hermes` (via `hermes` candy `require: ffmpeg`) + - `hermes-playwright` (via `hermes` candy `require: ffmpeg`) + - `immich` (via `immich` candy `require: ffmpeg`) + - `immich-ml` (via `immich` candy `require: ffmpeg`) + - CUDA-based boxes (via `cuda` candy `require: ffmpeg`) + - Whisper-based boxes (via `whisper` candy `require: ffmpeg`) + + ## Related Candies + - `/charly-distros:cuda` — Depends on ffmpeg for GPU video processing + - `/charly-tools:whisper` — Depends on ffmpeg for audio transcoding + - `/charly-hermes:hermes` — Depends on ffmpeg for media tooling + - `/charly-immich:immich` — Depends on ffmpeg for photo/video transcoding + + ## Related Commands + - `/charly-build:build` — Builds the ffmpeg negativo17 RPM into the box + - `/charly-core:shell` — Interactive shell to run `ffmpeg` for media processing + + ## When to Use This Skill + + Use when the user asks about: + - FFmpeg in containers + - Multimedia processing tools + - The `ffmpeg` candy + + ## Related + + - `/charly-image:layer` — candy authoring reference (`charly.yml` schema, `run:`/`check:` step verbs, service declarations) + - `/charly-check:check` — declarative testing (`check:` block, `charly check box`, `charly check live`) diff --git a/.build/_candy/nvidia.v2026.271.1817/.charly-view-ok b/.build/_candy/nvidia.v2026.271.1817/.charly-view-ok new file mode 100644 index 0000000..5cb6f79 --- /dev/null +++ b/.build/_candy/nvidia.v2026.271.1817/.charly-view-ok @@ -0,0 +1 @@ +eefa6a0ae0c909b34de7ad831ad2d155ff5edc1d diff --git a/.build/_candy/nvidia.v2026.271.1817/.github/workflows/tag-on-merge.yml b/.build/_candy/nvidia.v2026.271.1817/.github/workflows/tag-on-merge.yml new file mode 100644 index 0000000..f503088 --- /dev/null +++ b/.build/_candy/nvidia.v2026.271.1817/.github/workflows/tag-on-merge.yml @@ -0,0 +1,88 @@ +# ORG-WIDE TAG-ON-MERGE DISPATCHER — installed in every opencharly repo. +name: tag-on-merge + +# Event-driven — no cron (RCA of all previous trigger designs, measured in +# this repo across 8 merges and 17 schedule runs): +# +# 1. `on: push` / `on: pull_request: [closed]` CANNOT see auto-merge merges. +# Native-auto-merge squash merges (actor `app/github-actions`) fire their +# webhook events — they are visible in the public event stream, e.g. +# `21:35:01Z sha=e222762 by=github-actions[bot]` for PR #8 — but GitHub +# Actions creates ZERO workflow runs for them (API-confirmed: no run for +# any merge commit, and 0 `pull_request`-event runs in the workflow's +# whole history). This is platform-level run suppression for auto-merge +# commits; no trigger selection can observe them. (Human merges and +# bot contents-API commits DO create runs — hence `push` is kept as a +# secondary trigger for those paths.) +# 2. `schedule: */15` cron: GitHub cron delivery is best-effort with no SLA. +# Measured 21-44 min gaps (never the configured 15); PR #3's tag landed +# 4+ hours late; PR #7's tag was still missing 30 min after merge. +# 3. `workflow_run` on `charly/pr-validator`: the ONE trigger whose event +# delivery is proven (the 12:12-12:51Z 8/22 runs all received the event; +# they died at startup on a workflow-file issue, not on delivery). +# +# The pr-validator run is the last actor before the merge (its final step +# arms native auto-merge). Firing on its completion and waiting (bounded) for +# the squash to land makes the MERGE the effective gate for tagging. The org +# reusable sweep is idempotent and scans the last 24h of merged PRs, so any +# PR missed by a wait timeout self-heals on the next validator completion. +# The rulebook's add-only backfill remains the ultimate documented path. +on: + workflow_run: + workflows: ["charly/pr-validator"] + types: [completed] + push: + branches: + - main + +permissions: + contents: write + pull-requests: read + +jobs: + wait-for-merge: + if: > + github.event_name == 'push' || + github.event.workflow_run.conclusion == 'success' + runs-on: ubuntu-latest + steps: + - name: Wait for triggering PR to merge (bounded readiness probe) + uses: actions/github-script@v7 + with: + script: | + // Push events: the merged PR is already on main — no wait needed. + if (context.eventName !== 'workflow_run') { + core.info('push event — merged PRs are in the sweep window'); + return; + } + const run = context.payload.workflow_run; + const { data: prs } = await github.rest.pulls.list({ + ...context.repo, + state: 'open', + head: `${context.repo.owner}:${run.head_branch}`, + }); + if (!prs.length) { + core.info('No open PR for head branch — sweep covers already-merged PRs'); + return; + } + const pr = prs[0]; + const deadline = Date.now() + 5 * 60 * 1000; + while (Date.now() < deadline) { + const { data: p } = await github.rest.pulls.get({ + ...context.repo, pull_number: pr.number, + }); + if (p.merged_at) { + core.info(`PR #${pr.number} merged at ${p.merged_at} — proceeding to tag`); + return; + } + await new Promise((r) => setTimeout(r, 20 * 1000)); + } + core.info(`PR #${pr.number} not merged within 5m — sweep still runs; next validator completion self-heals`); + + tag: + if: > + github.event_name == 'push' || + github.event.workflow_run.conclusion == 'success' + needs: wait-for-merge + uses: opencharly/.github/.github/workflows/tag-on-merge.yml@main + secrets: inherit diff --git a/.build/_candy/nvidia.v2026.271.1817/AGENTS.md b/.build/_candy/nvidia.v2026.271.1817/AGENTS.md new file mode 100644 index 0000000..38ba039 --- /dev/null +++ b/.build/_candy/nvidia.v2026.271.1817/AGENTS.md @@ -0,0 +1,58 @@ +# AGENTS.md — layer-nvidia + +Standalone candy repo for the `nvidia` layer — NVIDIA GPU runtime support. The +candy lives in `charly.yml` at the repo root: multi-distro package arms, the +`LD_LIBRARY_PATH` environment, the Vulkan ICD wiring and signature-verification +`plan:` steps, and the embedded `skill:` entity projected into the marketplace +corpus as `/charly-distros:nvidia`. + +Canonical files: + +- `charly.yml` — the `nvidia:` candy entity and the `nvidia-skill:` skill entity. +- `CHANGELOG/` — per-CalVer release history; read it before changing baked checks. +- `.github/workflows/tag-on-merge.yml` — CalVer tag + `CHANGELOG/` on merge. +- `README.md` — user overview only; never agent guidance. + +## Load these skills first (R0) + +- `/charly-distros:nvidia` — the owning skill. GPU runtime, CDI device + generation, the distro package arms, and verification. Load before editing or + troubleshooting the layer. +- `/charly-image:layer` — the candy authoring reference (`charly.yml` schema, + `plan:` step verbs incl. `check:`, per-distro `distro:` arms, package/repo + sections, and service declarations). Load before editing any entity field or + plan step. + +## Build / validate / test + +- `charly box validate` at the repo root — the structural check: the manifest + must parse and validate at the installed charly. +- The merge gate is the **org-wide** `charly/pr-validator` (required check + `validate / validate`, defined in `opencharly/.github`); this repo has no + per-repo candy gate. +- The candy's `plan:` `check:` steps are the functional evidence; they must stay + valid on every distro arm they run on. Where a check only applies to one + distro family (e.g. a Fedora-only DNF path), scope it in the command itself — + the check runner does not honour runner-level `exclude-distro` fields. + +## Modify this repo + +- Edit the `nvidia:` candy entity AND the `nvidia-skill:` skill entity in + `charly.yml` together. The skill is the projected usage source, so a package, + distro-arm, or behaviour change that is not mirrored in the skill leaves the + corpus stale. +- Package changes go in the top-level `package:` or a `distro:` arm; repository + and signing policy go in the matching `distro:` arm's `repo:` block. +- New behaviour claims belong in the `plan:` as an observable `check:` step, and + in the skill body. Keep the Fedora signature-verification check intact. + +## Landing + +- PR-only. Every change lands through a pull request; the org-required + `charly/pr-validator` validates the diff and body and arms native auto-merge + on PASS. Direct pushes to `main` are blocked. +- History lives in `CHANGELOG/` (written by `tag-on-merge` at merge time); the + PR body IS the changelog. +- The authoritative rulebook is the umbrella `AGENTS.md` in + `opencharly/opencharly` and `charly/AGENTS.md` in the charly repo. Do not + restate its rules here. diff --git a/.build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.245.1450.md b/.build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.245.1450.md new file mode 100644 index 0000000..addcb6f --- /dev/null +++ b/.build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.245.1450.md @@ -0,0 +1,55 @@ +# 2026.245.1450 — fix(nvidia): add omarchy distro arm + scope the gpgcheck assertion off arch-family guests + +## Summary + +`layer-nvidia` only declared `arch` + `fedora` distro arms. The L3 hybrid bed (`check-omarchy-hybrid-gpu-vm`, distro-omarchy) composes this layer on omarchy (an Arch-family distro), where two baked checks break: + +1. `nvidia-container-toolkit-gpgcheck-enforced` asserts gpgcheck=1 by awk-ing `/etc/dnf/repos.override.d/99-config_manager.repo` — a Fedora-only DNF path. The check's own comment declares it Fedora-scoped and already carries `exclude_distro: [arch, cachyos]`; **omarchy was missing from that list** (the layer predates the distro), so the check ran on omarchy and failed with `awk: fatal: cannot open file ... No such file or directory` (verified on the bed, calver 2026.245.1437). +2. The layer had no `omarchy` distro arm at all — so no package arm existed for the composed guest beyond the shared `nvidia-container-toolkit`. + +**Changes:** add the `omarchy` distro arm (`package: [nvidia-utils]`, mirroring the arch arm — the omarchy extra repo ships nvidia-utils), and add `omarchy` to the gpgcheck check's `exclude_distro` list (same rationale as the existing arch/cachyos entries). Schema stamp migrated 2026.232.0520 → 2026.240.1943 (current floor). + +## How tested + +**Gate:** structural — `charly box validate` on this tree: + +``` +/tmp/charly-linux-amd64 box validate +charly box validate: OK — checked 1 candy, 7 distros, 7 builders; 0 warnings, 0 errors +``` + +**Negative baseline (the failure this fixes, reproduced live on the bed):** the un-fixed check failed on a fresh omarchy VM exactly as predicted: + +``` +FAIL check the nvidia-container-toolkit repo enforces package signature verification [nvidia-container-toolkit-gpgcheck-enforced] exit=2 (awk: fatal: cannot open file '/etc/dnf/repos.override.d/99-config_manager.repo' for reading: No such file or directory) +``` + +The fix's positive proof (the check now SKIPs on omarchy and the hybrid bed run concludes with the nvidia-utils package arm installed) lands with the next fresh-rebuild run of `check-omarchy-hybrid-gpu-vm` after distro-omarchy bumps its layer-nvidia pin — the named immediate-next batch cutover (distro-omarchy #26 batch: autologin + mirror-resilience + this pin bump). + +## Rulebook compliance + +- **R0 skills:** git-workflow + strict-policy loaded; layer/schema migration semantics from the charly-internals skills. +- **R1 RCA + zero warnings:** the failure was root-caused on the live bed (awk on a Fedora-only path in an Arch-family guest); the check's own comment confirms the Fedora-scoped intent; fix extends the existing exclude list — no new mechanism (R3). +- **R2 no out-of-scope:** one distro arm + one exclude entry + schema stamp; nothing else touched. +- **R3 no duplication:** extends the layer's single distro map and the check's existing scope list. +- **R4 no workaround:** excluding the check on omarchy is the intended semantics (the DNF repo is correctly absent on arch-family), not a mask; the omarchy package arm adds the real runtime package. +- **R5 hard cutover + grep:** N/A — additive config; no identifiers removed. +- **R6 git safety:** feature branch off origin/main; no force-push; no direct-main. +- **R7 runtime gate:** box validate green (above); the bed-run positive proof lands in the named batch cutover. +- **R8 artifact invariants:** N/A — config-only. +- **R9 binary == source + deps:** N/A — no binary. +- **R10 disposable + coverage:** the changed path (gpgcheck exclusion on omarchy) is proven by the live negative baseline; the positive bed run is scheduled in the named immediate-next cutover — tier below fully-tested until it concludes. +- **RDD / ADE / SDD:** ADE intact; SDD N/A. +- **Hard cutover:** one atomic commit; additive. +- **Kernel/plugin boundary law:** N/A. +- **Disposable-only autonomy:** N/A — no deploy/destroy changes. +- **Clean architecture + Go gates:** N/A — no Go. +- **CHANGELOG:** N/A — tag-on-merge writes it from this body. + +## Change classification + +- **Change class:** candy/box-config — distro-arm addition + check scoping (config-only) +- **Verification gate:** `charly box validate` 0/0 on this tree + live negative baseline (bed calver 2026.245.1437); positive bed-run proof in the named batch cutover +- **Attribution tier:** analysed on a live system + +*Assisted-by: pi openrouter/deepseek/deepseek-v4-flash-0731 (analysed on a live system)* \ No newline at end of file diff --git a/.build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.245.1456.md b/.build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.245.1456.md new file mode 100644 index 0000000..df91179 --- /dev/null +++ b/.build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.245.1456.md @@ -0,0 +1,36 @@ +# 2026.245.1456 — fix(ci): keep the schema stamp at the CI-pinned charly floor + +## Summary + +#2 landed the omarchy distro arm + gpgcheck scoping but also migrated the schema stamp (2026.232.0520 → 2026.240.1943), which is NEWER than the charly the repo's candy gate pins (schema max 2026.232.0520) — the `candy` gate broke on the merged head: + +``` +charly box validate +charly: error: command "validate": validation error: charly.yml: config schema 2026.240.1943 is newer than this charly supports (max 2026.232.0520) +``` + +This PR reverts ONLY the schema stamp. The omarchy distro arm and the `exclude_distro: [omarchy]` scoping from #2 are authored entirely within the 2026.232-compatible surface and stay (the pinned CI charly validates them). + +## How tested + +- `charly.yml` diff: single line (`version: 2026.240.1943` → `version: 2026.232.0520`); omarchy arm + exclude entries present (grep: 2 omarchy references). +- The pinned CI gate is the verifier for the exact schema ceiling: the `candy` workflow runs `.ci/charly/bin/charly box validate` — it must pass with the reverted stamp. +- Local validation with the current charly (newer) still passes the structural changes (validated in #2 with 0 warnings/errors). + +## Rulebook compliance + +- **R0/R1:** CI failure surfaced after #2 merged — root-caused to the schema-stamp migration vs the repo's pinned CI charly; fix reverts the unnecessary stamp. +- **R2:** single-line revert; the feature additions of #2 are untouched. +- **R3/R4:** no new mechanism; the revert restores the authored schema floor. +- **R5:** N/A — additive config, nothing removed beyond the bump. +- **R6:** feature branch off origin/main; no force-push. +- **R7:** the pinned CI gate is the gate; it reruns on this PR. +- **R10:** config-only single-line change; the gate run is the proof. Tier: analysed on a live system (the #2 bed-run evidence remains the feature proof). + +## Change classification + +- **Change class:** candy/box-config — schema stamp revert (CI compatibility) +- **Verification gate:** `candy` CI validate on this PR (pinned charly schema ceiling) +- **Attribution tier:** analysed on a live system + +*Assisted-by: pi openrouter/deepseek/deepseek-v4-flash-0731 (analysed on a live system)* \ No newline at end of file diff --git a/.build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.245.1515.md b/.build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.245.1515.md new file mode 100644 index 0000000..1003417 --- /dev/null +++ b/.build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.245.1515.md @@ -0,0 +1,28 @@ +# 2026.245.1515 — fix(ci): point the tag-on-merge dispatcher at the org reusable @main + +## Summary + +This repo's `tag-on-merge.yml` dispatcher referenced the org reusable at `@v1.0.0`, a ref that does not exist — so the repo has emitted ZERO tag-on-merge runs since provisioning (verified: `runs?total_count=0` while sibling repos tag correctly). Sibling repos (distro-omarchy, layer-wf-recorder) pin `@main`. Point the dispatcher at `@main`. + +## How tested + +- Diff: one line (`@v1.0.0` → `@main`). +- The proof of the fix is the event itself: after this PR merges, the `pull_request: [closed]` event fires the dispatcher, which calls the org reusable and creates the CalVer tag + CHANGELOG — that tag's existence on this merge is the verifier (the org reusable's sweep also self-heals the two earlier un-tagged merges of this repo). + +## Rulebook compliance + +- **R0/R1:** tag absence root-caused to the scaffolded `@v1.0.0` ref (nonexistent); sibling-repo comparison confirms `@main` is the working ref. +- **R2:** single-line CI fix; nothing else touched. +- **R3/R4:** aligns with the org dispatcher standard (R3), no workarounds. +- **R5:** N/A — CI file. +- **R6:** feature branch off origin/main; no force-push. +- **R7:** the gate is the org reusable invocation on the merge event (workflow runs list). +- **R10:** config/CI-only change; tier analysed on a live system (the repo's own run history is the baseline). + +## Change classification + +- **Change class:** CI fix — workflow reusable ref +- **Verification gate:** post-merge tag emission (org reusable run on the closed event) +- **Attribution tier:** analysed on a live system + +*Assisted-by: pi openrouter/deepseek/deepseek-v4-flash-0731 (analysed on a live system)* \ No newline at end of file diff --git a/.build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.245.1521.md b/.build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.245.1521.md new file mode 100644 index 0000000..780c3c8 --- /dev/null +++ b/.build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.245.1521.md @@ -0,0 +1,28 @@ +# 2026.245.1521 — fix(ci): adopt the org-standard workflow_run-based tag-on-merge dispatcher + +## Summary + +This repo's tag-on-merge dispatcher (old `pull_request: [closed]` design, org reusable pinned at `@v1.0.0`) has produced ZERO tag-on-merge runs since provisioning — verified API-side (`workflows/tag-on-merge.yml/runs?total_count=0`). The org file header documents the measured RCA: **native auto-merge squash merges fire their webhook events but GitHub Actions creates zero workflow runs for them** (platform-level run suppression), so `pull_request: [closed]` / `push` cannot observe them; the proven trigger is `workflow_run` on `charly/pr-validator` (whose final step arms the auto-merge) + a bounded wait-for-merge probe. Install the org-standard dispatcher **byte-identical** to distro-omarchy / the org reference (verified with `diff`). + +## How tested + +- The file is byte-identical to distro-omarchy's dispatcher (which tags reliably): `diff <(org file) .github/workflows/tag-on-merge.yml` → empty. +- The verifier is the next merge event: the org reusable runs on the `charly/pr-validator` completion, waits for the merge, and tags it with the CalVer + CHANGELOG; the org reusable's idle sweep also self-heals the repo's earlier un-tagged merges. + +## Rulebook compliance + +- **R0/R1:** tag absence root-caused (RCA documented in the org file header — measured across the org repo's 8 merges/17 schedule runs); the correct reference implementation is the org's own file. +- **R2:** CI-file only; org-parity install (R3 — the org dispatcher is THE canonical instance; no hand-authored variant). +- **R4:** no workaround — this is the org's proven trigger design. +- **R5:** hard cutover — the old dispatcher file is replaced by the org standard in this same PR. +- **R6:** feature branch off origin/main; no force-push. +- **R7:** the gate is tag emission on the next merge (org reusable invocation). +- **R10:** CI-config; tier analysed on a live system (the repo's zero-run history is the negative baseline; the sibling repo's working dispatcher is the reference). + +## Change classification + +- **Change class:** CI fix — tag-on-merge dispatcher migration to the org standard +- **Verification gate:** post-merge tag emission measured (org reusable run) +- **Attribution tier:** analysed on a live system + +*Assisted-by: pi openrouter/deepseek/deepseek-v4-flash-0731 (analysed on a live system)* \ No newline at end of file diff --git a/.build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.245.1541.md b/.build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.245.1541.md new file mode 100644 index 0000000..47dfb93 --- /dev/null +++ b/.build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.245.1541.md @@ -0,0 +1,38 @@ +# 2026.245.1541 — fix(nvidia): make the two baked checks arch-family robust (command-level) + +## Summary + +The hybrid-gpu bed (check-omarchy-hybrid-gpu-vm) composes this layer on omarchy, where two baked checks break: + +1. `nvidia-container-toolkit-gpgcheck-enforced` ran despite its `exclude_distro` list — the check runner does not honor that field (verified on live runs: it executes on omarchy, an excluded arch-family guest). The check failed on the Fedora-only DNF setopt path. Fix: implement the arc-family exclusion IN THE COMMAND — when `/etc/dnf/repos.override.d/99-config_manager.repo` is correctly absent (arch-family), exit 0; when present (fedora), keep the `gpgcheck=1` assertion. +2. `plan-step (LD_LIBRARY_PATH)` asserted an RPM-only env export (`printenv LD_LIBRARY_PATH` containing `/usr/lib64`) — the omarchy arm installs nvidia-utils whose driver libs land under `/usr/lib` (arch layout; `/usr/lib64` is the compat symlink), and the export does not land in the check's non-login shell. Fix: assert the driver-lib directory exists, accepting both layouts (`/usr/lib64/nvidia`, `/usr/lib/nvidia`, `libnvidia*`). + +## How tested + +- `charly box validate` via the repo's CI-pinned charly is the gate for this tree's schema stamp (unchanged 2026.232.0520 per #3). The changed checks are config-only. +- Negative baseline (the failures this fixes, reproduced live on the bed, calver 2026.245.1523 and 2026.245.1528): +``` +FAIL [nvidia-container-toolkit-gpgcheck-enforced] exit=2 (awk: fatal: cannot open file '/etc/dnf/repos.override.d/99-config_manager.repo' ...) +FAIL [plan:vm:omarchy-vm:9] exit=1 (printenv LD_LIBRARY_PATH: var unset) +``` +- Positive proof: the next fresh-rebuild run of check-omarchy-hybrid-gpu-vm after distro-omarchy bumps its layer pin lands in the named batch cutover (distro-omarchy #26 batch: autologin + pin bump + this layer). + +## Rulebook compliance + +- **R0/R1:** the runner-field exclusion failure was observed live (the check ran on an excluded distro) and root-caused to an unhonored field; the command-level implementation is the reliable mechanism. +- **R2:** the two checks only; nothing else touched. +- **R3:** command-level scoping is the one mechanism used elsewhere in this layer; no duplication. +- **R4:** fail-safe-absent is the correct semantics (the DNF file is correctly absent on arch-family), not a mask. +- **R5:** N/A — additive. +- **R6:** feature branch off origin/main; no force-push. +- **R7:** the CI-pinned charly `box validate` runs on this PR; the bed-run positive proof lands in the named cutover. +- **R10:** config-only; tier analysed on a live system until the bed-run positive proof concludes. +- **RDD/ADE/SDD, cutover, autonomy, Go gates, CHANGELOG:** N/A — config-only. + +## Change classification + +- **Change class:** candy/box-config — check command scoping (config-only) +- **Verification gate:** CI-pinned `charly box validate` on this PR + negative baseline above; positive bed-run in the named cutover +- **Attribution tier:** analysed on a live system + +*Assisted-by: pi openrouter/deepseek/deepseek-v4-flash-0731 (analysed on a live system)* \ No newline at end of file diff --git a/.build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.271.1114.md b/.build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.271.1114.md new file mode 100644 index 0000000..786e792 --- /dev/null +++ b/.build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.271.1114.md @@ -0,0 +1,103 @@ +# 2026.271.1114 — docs: tailored README + AGENTS.md signpost (layer-nvidia) (#286) + +## Summary + +Docs-only leg of umbrella campaign `opencharly/opencharly#286` for the +`opencharly/layer-nvidia` repo. This repo gets its tailored pair: + +- **`README.md` — user overview only.** Rewritten from the generic + candy-catalog boilerplate into a real user overview: what the layer provides + (`nvidia-container-toolkit` / `/usr/bin/nvidia-ctk`, the per-distro driver + packages for arch/omarchy/fedora, `LD_LIBRARY_PATH=/usr/lib64`, the + `/etc/vulkan/icd.d` ICD wiring, no service/port; CUDA is the separate `cuda` + layer), how a user consumes it (`@github.com/opencharly/layer-nvidia:` in a + box `candy:` list; `nvidia-smi` / `nvidia-ctk --version` verification), a brief + layout, and a pointer to the owning skill `/charly-distros:nvidia`. +- **`AGENTS.md` — new, thin, harness-neutral agent signpost.** What the repo is + and its canonical files (including `CHANGELOG/`); the R0 skill list + (`/charly-distros:nvidia` + `/charly-image:layer`); the exact build/validate + commands (`charly box validate`, `.github/workflows/deploy.yml`); the edit rule + (change the candy entity AND its embedded `skill:` entity together, keep the + Fedora signature-verification check intact, and scope distro-specific checks in + the command itself since the runner ignores `exclude-distro`); and landing + (PR-only via `charly/pr-validator`, history in `CHANGELOG/`, authoritative + rulebook is the umbrella `AGENTS.md` + `charly/AGENTS.md`). It restates no rule + and names no harness. + +No functional or architecture file is touched; `charly.yml`, `CHANGELOG/` and +both workflows are byte-identical to `origin/main`. + +## How tested + +On the final committed head `1d7d3ec9a68c949e5f696c895de4915c6919135f`: + +``` +$ git -C status --short +(empty) + +$ git -C diff --stat origin/main..HEAD + AGENTS.md | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + README.md | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---------- + 2 files changed, 129 insertions(+), 13 deletions(-) + +$ git -C diff --stat origin/main..HEAD | grep -v '\.md$' +(empty — docs-only; no non-`.md` file changed) + +$ /tmp/opencode/charly-238 -C box validate # the repo's CI-pinned charly (v2026.238.1242) +(no output; exit 0) +``` + +Cross-check with the umbrella dev binary, whose schema floor is AHEAD of this +repo's CI pin — it rejects the UNCHANGED manifest, independent of this change: + +``` +$ /home/atrawog/Sync/Atrapub/lo/opencoder/opencharly/charly/bin/charly -C box validate +charly: error: command "validate": validation error: /charly.yml: schema 2026.261.1747 is required (found "2026.232.0520"). Run: charly migrate + +$ git -C diff --stat origin/main..HEAD -- charly.yml +(empty — the manifest is untouched by this docs-only change, so this pre-existing + schema-floor mismatch cannot be caused by it; the repo's own CI gate is the + pinned `candy` workflow, which validates green above) +``` + +## Rulebook compliance + +Umbrella `AGENTS.md` rules 1–11: + +1. **Never edit inside a submodule** — HOW: edited only in the session worktree `.worktrees/layer-nvidia-docs`; the tracked submodule checkout stays clean/detached. +2. **Git op rule (`git -C `)** — HOW: every git/gh action ran via `git -C ` / `--repo`. +3. **No nested `go.work`** — N/A — no Go workspace file touched. +4. **Sessions root at the umbrella; edits in a session worktree off fresh `origin/main`** — HOW: worktree branched off `origin/main`; base confirmed unchanged. +5. **Pin discipline (merged refs only)** — N/A — no pin/gitlink changed. +6. **Policy B (distro pins == charly gitlinks)** — N/A — no submodule gitlink touched. +7. **Read the subrepo's own rulebook first** — HOW: read the umbrella `AGENTS.md` and the dispatched skills (`git-workflow`, `skills`, `layer`, `docs`). +8. **Harness config: shared core + deliberate forks** — N/A — no harness config changed. +9. **Session-scoped ownership** — HOW: only this session's worktree/branch/PR touched; other sessions' worktrees untouched. +10. **Before ANY update push, read the PR's live state AND write the body** — HOW: initial push; the whole body is written for the head being pushed, footer last. +11. **Agent identity & comment coordination footer (extends rule 9)** — HOW: two-line `Agent:`-then-`Assisted-by:` footer in canonical order; solo/uncontended scope. + +Ground-truth rules R1–R10 (`charly/AGENTS.md`): + +- **R1 (RCA every anomaly)** — HOW: the umbrella dev binary's `box validate` schema-floor mismatch was root-caused to a binary schema floor (`2026.261.1747`) newer than this repo's CI pin (`v2026.238.1242`, manifest `2026.232.0520`); the diff touches no non-`.md`, so the mismatch is independent of this change; not parked. +- **R2 (finish the whole cutover; no parking)** — HOW: the docs-only change class is delivered in full (README user overview + AGENTS signpost); the `skill:` entity is unchanged, so no marketplace/docs projection regeneration is triggered. +- **R3 (no duplication)** — HOW: README points at the owning skill instead of restating it; AGENTS points at the rulebook instead of restating rules. +- **R4 (no workarounds)** — HOW: used the repo's own `charly box validate` gate; no ad-hoc substitute. +- **R5 (delete legacy completely)** — HOW: the generic catalog boilerplate README was replaced, not appended; no stale scaffold claim remains. +- **R6 (git safety)** — HOW: `status` inspected before/after; no force-push, no hook bypass, no direct push to `main`; no other session's work touched. +- **R7 (prove the gate, not the plan)** — HOW: ran `charly box validate` with the repo's CI-pinned charly on the final committed tree; output pasted above. +- **R8 (preserve emitted artifacts)** — N/A — docs-only; no emitted artifact/config changed. +- **R9 (binary equals source)** — N/A — this repo ships no charly source/binary. +- **R10 (fresh proof by change class)** — HOW: Documentation-only change class → `documentation reviewed` tier; the repo's `candy` gate (`charly box validate` at the pinned charly) is the structural proof, run on the final tree. + +RDD / ADE / SDD — N/A — documentation-only. + +## Change classification + +- **Change class:** Documentation-only. +- **Gate:** the repo's `candy` CI gate (`charly box validate` at the pinned charly) — manifest untouched, so behavior is unchanged; explicitly pasted above. +- **Attribution tier:** `documentation reviewed`. + +Refs #286 + +*Agent: `org-readme-agents` · session `ses_org-readme-agents`* +*Assisted-by: opencode deepseek-v4.1-flash (documentation reviewed)* \ No newline at end of file diff --git a/.build/_candy/nvidia.v2026.271.1817/README.md b/.build/_candy/nvidia.v2026.271.1817/README.md new file mode 100644 index 0000000..0a6ddc6 --- /dev/null +++ b/.build/_candy/nvidia.v2026.271.1817/README.md @@ -0,0 +1,73 @@ +# nvidia + +NVIDIA GPU runtime layer for OpenCharly images. + +The `nvidia` candy prepares an image to use an NVIDIA GPU. It installs +`nvidia-container-toolkit` — the `nvidia-ctk` CLI that generates CDI device +specs — together with the per-distro driver libraries, exports +`LD_LIBRARY_PATH=/usr/lib64` so the driver libraries resolve, and prepares +`/etc/vulkan/icd.d` to hold the NVIDIA Vulkan ICD symlinks. It is the GPU +runtime base that GPU-accelerated boxes compose; the CUDA toolchain is a +separate `cuda` layer. + +## What it provides + +| Property | Value | +|---|---| +| Layer / candy | `nvidia` | +| Package | `nvidia-container-toolkit` (all distros) | +| Binary | `/usr/bin/nvidia-ctk` | +| Environment | `LD_LIBRARY_PATH=/usr/lib64` | +| Directory | `/etc/vulkan/icd.d` (NVIDIA Vulkan ICD / layer symlinks) | +| Service / port | none | + +Per-distro driver packages: + +- `arch` / `omarchy` — `nvidia-utils` +- `fedora` — `libva-nvidia-driver` (from the negativo17 `fedora-multimedia` + repo) plus NVIDIA's own `nvidia-container-toolkit` repo, with package + signature verification enforced (`gpgcheck=1`, overriding NVIDIA's shipped + `gpgcheck=0`). + +## How to use it + +Compose the layer by pinning this repo in a box's `candy:` list: + +```yaml +my-box: + candy: + base: fedora # or cachyos / omarchy for the Arch driver layout + candy: + - '@github.com/opencharly/layer-nvidia:v2026.245.1541' +``` + +Once the image is built and the GPU is attached by the runtime: + +```bash +nvidia-smi # GPU information +nvidia-ctk --version # CDI toolkit +``` + +The layer bakes every artifact (package, `nvidia-ctk` binary, exported path, +Vulkan ICD directory) into the image, so it is verifiable without a physical +GPU. A GPU-accelerated box pairs it with `cuda` (CUDA toolkit, cuDNN) — for +example `python-ml`, `jupyter`, `ollama`, and `comfyui`. + +## Layout + +- `charly.yml` — the candy manifest: the multi-distro package arms, the + `LD_LIBRARY_PATH` environment, the Vulkan ICD wiring `plan:`, the `plan:` + checks, and the embedded `skill:` entity. +- `CHANGELOG/` — per-CalVer release notes. +- `.github/workflows/tag-on-merge.yml` — CalVer tag + `CHANGELOG/` on merge. +- `README.md` — this user overview. + +## Related + +- Owning skill: `/charly-distros:nvidia` +- CUDA toolkit: `/charly-distros:cuda` +- Derived GPU boxes: `/charly-languages:python-ml`, `/charly-jupyter:jupyter`, + `/charly-ollama:ollama`, `/charly-comfyui:comfyui` +- Arch/CachyOS GPU base sibling: `cachyos.nvidia` in `opencharly/distro-cachyos` +- [`opencharly/charly`](https://github.com/opencharly/charly) — the charly CLI and image builder +- [`opencharly/opencharly`](https://github.com/opencharly/opencharly) — the umbrella diff --git a/.build/_candy/nvidia.v2026.271.1817/charly.yml b/.build/_candy/nvidia.v2026.271.1817/charly.yml new file mode 100644 index 0000000..dee75f2 --- /dev/null +++ b/.build/_candy/nvidia.v2026.271.1817/charly.yml @@ -0,0 +1,196 @@ +nvidia: + candy: + description: | + NVIDIA GPU runtime — nvidia-container-toolkit (nvidia-ctk CDI) plus the driver-lib path and Vulkan ICD wiring + Installs nvidia-container-toolkit (the nvidia-ctk CLI that generates + CDI device specs) alongside the per-distro driver libs (nvidia-utils + on Arch, libva-nvidia-driver on Fedora). Exports + LD_LIBRARY_PATH=/usr/lib64 so the GPU driver libraries resolve, and + prepares /etc/vulkan/icd.d to hold the nvidia Vulkan ICD symlinks. + Every effect — the package, the nvidia-ctk binary, the exported path, + and the ICD directory — is a real artifact baked into the image, so + each is directly verifiable without a physical GPU. + package: + - nvidia-container-toolkit + distro: + arch: + package: + - nvidia-utils + omarchy: + package: + - nvidia-utils + fedora: + package: + - libva-nvidia-driver + repo: + # negativo17 fedora-multimedia provides the driver libs (libva-nvidia-driver) + # but NOT nvidia-container-toolkit; that lives ONLY in NVIDIA's own + # libnvidia-container repo (RDD-confirmed on fedora:43: + # negativo17 → "No matching packages"; NVIDIA repo → installs 1.19.1). + - name: fedora-multimedia + url: "https://negativo17.org/repos/fedora-multimedia.repo" + gpgkey: "https://negativo17.org/repos/RPM-GPG-KEY-slaanesh" + # NVIDIA ships this repo file with gpgcheck=0 — the only repo in the + # tree that does — so its 4 packages (a container runtime hook) were + # installing UNVERIFIED even though the gpgkey below imports fine and + # every one of them is validly signed by the primary key. gpgcheck: true + # forces the check back on; before the tri-state knob existed the + # `gpgcheck:` field could only ever weaken a vendor's policy, so there + # was no value expressible here that fixed it. + # No gpgkey: here ON PURPOSE. The repo file already declares the same + # key, so dnf5 imports it itself under gpgcheck=1 — whereas an explicit + # `rpm --import` of NVIDIA's published certificate emits + # "Subkey 6ED91CA3AC1160CD is expired" on every build, because that + # certificate carries a subkey that died 2021-06-16 and every NVIDIA + # copy of it still ships the dead subkey. Nothing is trusted less: the + # packages are signed by the PRIMARY key and are verified either way. + - name: nvidia-container-toolkit + url: "https://nvidia.github.io/libnvidia-container/stable/rpm/nvidia-container-toolkit.repo" + gpgcheck: true + env: + LD_LIBRARY_PATH: "/usr/lib64" + plan: + - run: mkdir=/etc/vulkan/icd.d + mkdir: /etc/vulkan/icd.d + run_as: root + - run: | + command=[ -f /usr/share/vulkan/icd.d/nvidia_icd.x86_64.json ] && \ + ln -sf /usr/share/vulkan/icd.d/nvidia_icd.x86_64.json /etc/vulkan/icd.d/nvidia_icd.json || true + [ -f /usr/share/vulkan/implicit_layer.d/nvidia_layers.json ] && \ + ln -sf /usr/share/vulkan/implicit_layer.d/nvidia_layers.json /etc/vulkan/icd.d/nvidia_layers.json || true + run_as: root + command: | + [ -f /usr/share/vulkan/icd.d/nvidia_icd.x86_64.json ] && \ + ln -sf /usr/share/vulkan/icd.d/nvidia_icd.x86_64.json /etc/vulkan/icd.d/nvidia_icd.json || true + [ -f /usr/share/vulkan/implicit_layer.d/nvidia_layers.json ] && \ + ln -sf /usr/share/vulkan/implicit_layer.d/nvidia_layers.json /etc/vulkan/icd.d/nvidia_layers.json || true + # THE coverage for the gpgcheck fix, and it reads the one observable that + # DISCRIMINATES. Two wrong candidates, both ruled out by experiment: + # - "the signing key is in the rpmdb" does NOT discriminate — the previous + # code imported the key explicitly via `rpm --import` while still + # installing unverified under NVIDIA's shipped gpgcheck=0, so the key was + # present either way. + # - the vendor .repo file does NOT change — `dnf5 config-manager setopt` + # never rewrites it; /etc/yum.repos.d/nvidia-container-toolkit.repo still + # reads gpgcheck=0 in the built image. + # setopt persists into /etc/dnf/repos.override.d/99-config_manager.repo, which + # overrides the vendor file and DOES survive into the image. The awk pulls just + # this repo's section, because that file also carries other repos' setopts. + # Revert `gpgcheck: true` above (or the template's `true` arm) and it fails. + - check: the nvidia-container-toolkit repo enforces package signature verification, so its packages cannot install unverified + id: nvidia-container-toolkit-gpgcheck-enforced + # Fedora-scoped: the asserted `repo:` block (gpgcheck=0 vendor file + # overridden by dnf5 setopt) lives under distro.fedora; dnf5 and /etc/dnf + # exist only there. Arch-family arms (arch/cachyos/omarchy) install + # nvidia-utils from pacman and have no DNF repo — the file is correctly + # absent, so the step exits 0 without asserting (the fd condition below). + # The exclusion is implemented in the command itself: runner-level + # exclude-distro fields are not honored by the check runner. + exit_status: 0 + stdout: + - contains: "gpgcheck=1" + command: awk '/^\[nvidia-container-toolkit\]/{f=1;next} /^\[/{f=0} f' /etc/dnf/repos.override.d/99-config_manager.repo 2>/dev/null || test ! -e /etc/dnf/repos.override.d/99-config_manager.repo + - check: the nvidia-container-toolkit package is installed for CDI device generation + package: + package: nvidia-container-toolkit + installed: true + - check: the nvidia-ctk CLI binary lands on the canonical /usr/bin path + file: + file: /usr/bin/nvidia-ctk + exists: true + - check: nvidia-ctk runs and reports a version number + exit_status: 0 + stdout: + - matches: "[0-9]+\\.[0-9]+" + command: nvidia-ctk --version + - check: the Vulkan ICD directory exists to hold the nvidia ICD symlinks + file: + file: /etc/vulkan/icd.d + exists: true + filetype: directory + - check: the GPU driver lib directory (RPM /usr/lib64 or Arch /usr/lib layout) exists in the guest + exit_status: 0 + stdout: + - contains: nvidia + command: ls -d /usr/lib64/nvidia /usr/lib/nvidia /usr/lib64/libnvidia* /usr/lib/libnvidia* 2>/dev/null +nvidia-skill: + skill: + name: nvidia + family: distros + owner: nvidia + description: |- + NVIDIA GPU base image with runtime support and CUDA toolkit on Fedora. Base for all + GPU-accelerated boxes (python-ml, jupyter, ollama, comfyui). + MUST be invoked before building, deploying, configuring, or troubleshooting the nvidia box. + triggers: + - "Fedora images / `fedora*` / `box/fedora` submodule (incl. the GPU base `nvidia` / `python-ml` + `sway-browser-vnc`)" + content: | + # nvidia + + NVIDIA GPU base image — provides GPU runtime (driver libs, CDI toolkit) and CUDA development toolkit on Fedora. + + The `nvidia` and `cuda` candies are multi-distro (Fedora rpm + Arch pac), so a + CachyOS GPU base exists alongside this Fedora `nvidia` box: `cachyos.nvidia` + (cachyos + agent-forwarding + nvidia + cuda) in the `opencharly/distro-cachyos` + submodule. The two are siblings — pick the Fedora `nvidia` box for the + RPM-based GPU stack, `cachyos.nvidia` for the Arch/CachyOS GPU stack. See + `/charly-distros:cachyos`. + + ## Box Properties + + | Property | Value | + |----------|-------| + | Base | fedora-nonfree (fedora + RPM Fusion) | + | Layers | agent-forwarding, nvidia, cuda | + | Platforms | linux/amd64 | + | Registry | ghcr.io/opencharly | + + ## Full Candy Stack + + 1. `fedora-nonfree` (fedora + rpmfusion — provides RPM Fusion free + nonfree repos) + 2. `nvidia` — GPU runtime: driver libs, nvidia-container-toolkit (CDI), VA-API + 3. `cuda` — CUDA toolkit, cuDNN, onnxruntime, ffmpeg-libs + + ## Quick Start + + The `nvidia` box lives in the `opencharly/distro-fedora` submodule (`box/fedora`): + + ```bash + charly -C box/fedora box build nvidia + charly shell nvidia + ``` + + ## Key Candies + + - `/charly-distros:nvidia` — NVIDIA GPU runtime (driver libs, CDI generation via nvidia-ctk) + - `/charly-distros:cuda` — CUDA toolkit and GPU development libraries + + ## Derived Boxes + + - `/charly-languages:python-ml` — ML Python environment + - `/charly-jupyter:jupyter` — Jupyter notebook server + - `/charly-ollama:ollama` — LLM inference server + - `/charly-comfyui:comfyui` — image generation UI + + ## Related Boxes + + - `/charly-distros:fedora` — parent base (no GPU) + - `/charly-distros:cachyos` — `cachyos.nvidia` is the CachyOS GPU-base sibling (Arch/CachyOS GPU stack) + - `/charly-coder:charly-arch` — Arch Linux charly toolchain with nvidia (shared candies) + - `/charly-distros:charly-fedora` — Fedora charly toolchain with nvidia (shared candies) + + ## Verification + + After `charly box build`: + - `charly shell nvidia -c "nvidia-smi"` — GPU info + - `charly shell nvidia -c "nvidia-ctk --version"` — CDI toolkit + - `charly shell nvidia -c "nvcc --version"` — CUDA compiler + + ## When to Use This Skill + + **MUST be invoked** when the task involves the nvidia box, GPU base images, CUDA in containers, or CDI device configuration. Invoke this skill BEFORE reading source code or launching Explore agents. + + ## Related + + - `/charly-image:image` — image family umbrella (`candy:` image entries — those carrying `base:`/`from:` — in `charly.yml`, build/validate/inspect/list) + - `/charly-build:build` — the embedded build vocabulary (distros, builders, init-systems) diff --git a/.containerignore b/.containerignore new file mode 100644 index 0000000..3261ac7 --- /dev/null +++ b/.containerignore @@ -0,0 +1,17 @@ +# .containerignore (generated -- do not edit; source: defaults.context_ignore in charly.yml) +.git +bin +charly +*.md +**/__pycache__ +**/*.pyc +**/*.pyo +**/*.egg-info +**/node_modules +**/.git +**/.DS_Store +**/*~ +**/*.swp +**/*.swo +**/.pytest_cache +**/.mypy_cache diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..599b1b8 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,17 @@ +# .dockerignore (generated -- do not edit; source: defaults.context_ignore in charly.yml) +.git +bin +charly +*.md +**/__pycache__ +**/*.pyc +**/*.pyo +**/*.egg-info +**/node_modules +**/.git +**/.DS_Store +**/*~ +**/*.swp +**/*.swo +**/.pytest_cache +**/.mypy_cache diff --git a/charly.yml b/charly.yml index 5a5fb0d..ccde150 100644 --- a/charly.yml +++ b/charly.yml @@ -139,8 +139,22 @@ cuda: # Headers — cudnn*.h live in /opt/cuda/targets/x86_64-linux/include # on the cudnn package, while CUDA's own headers live in # /opt/cuda/include. Symlink both into /usr/include. - for inc in /opt/cuda/include/*.h /opt/cuda/targets/x86_64-linux/include/*.h; do - [ -e "$inc" ] && ln -sf "$inc" /usr/include/$(basename "$inc") + # Headers — link EVERY ENTRY of each toolkit include root, not a guessed subset. + # nvcc computes its default include root RELATIVE to its own executable, and + # /usr/bin/nvcc is a symlink, so all CUDA headers must be reachable under + # /usr/include. Enumerating by pattern is what broke this: a `*.h` glob linked the + # top-level headers but silently dropped (a) the SUBTREES crt/ and cccl/, which + # killed every build at CMake's enable_language(CUDA) with "crt/host_config.h: No + # such file or directory", and then (b) the `.hpp` half of the `_functions` family + # (`vector_functions.hpp` and friends), which killed the very next stage -- both + # reported on opencharly/layer-cuda#9. Linking every entry needs no extension list + # to keep in sync and cannot silently miss a file or a subtree again. + for root in /opt/cuda/include /opt/cuda/targets/x86_64-linux/include; do + [ -d "$root" ] || continue + for entry in "$root"/*; do + [ -e "$entry" ] || continue + ln -sfn "$entry" /usr/include/"$(basename "$entry")" + done done # Libraries: libcudart, libcudnn, libcurand, etc. mkdir -p /usr/lib64 @@ -159,8 +173,22 @@ cuda: # Headers — cudnn*.h live in /opt/cuda/targets/x86_64-linux/include # on the cudnn package, while CUDA's own headers live in # /opt/cuda/include. Symlink both into /usr/include. - for inc in /opt/cuda/include/*.h /opt/cuda/targets/x86_64-linux/include/*.h; do - [ -e "$inc" ] && ln -sf "$inc" /usr/include/$(basename "$inc") + # Headers — link EVERY ENTRY of each toolkit include root, not a guessed subset. + # nvcc computes its default include root RELATIVE to its own executable, and + # /usr/bin/nvcc is a symlink, so all CUDA headers must be reachable under + # /usr/include. Enumerating by pattern is what broke this: a `*.h` glob linked the + # top-level headers but silently dropped (a) the SUBTREES crt/ and cccl/, which + # killed every build at CMake's enable_language(CUDA) with "crt/host_config.h: No + # such file or directory", and then (b) the `.hpp` half of the `_functions` family + # (`vector_functions.hpp` and friends), which killed the very next stage -- both + # reported on opencharly/layer-cuda#9. Linking every entry needs no extension list + # to keep in sync and cannot silently miss a file or a subtree again. + for root in /opt/cuda/include /opt/cuda/targets/x86_64-linux/include; do + [ -d "$root" ] || continue + for entry in "$root"/*; do + [ -e "$entry" ] || continue + ln -sfn "$entry" /usr/include/"$(basename "$entry")" + done done # Libraries: libcudart, libcudnn, libcurand, etc. mkdir -p /usr/lib64 @@ -180,6 +208,25 @@ cuda: file: file: /usr/include/cudnn.h exists: true + - check: "a CUDA translation unit PREPROCESSES against the stitched /usr layout (Arch: the header subtrees are linked, not only the top-level files)" + id: cuda-arch-header-root + # Scoped IN THE COMMAND deliberately: the check runner does not honour runner-level + # exclude-distro fields, and Fedora's RPMs land in /usr directly so its layout differs. + # + # This is the probe the plan was missing. `nvcc --version` proves nvcc RUNS and the + # cuDNN probe proves one top-level header arrived -- but neither can FAIL on a layout + # that cannot compile, which is how `crt/` stayed unlinked while every probe passed: + # nvcc computes its include root relative to its own (symlinked) executable, so + # cuda_runtime.h's `#include "crt/host_config.h"` resolved under /usr/include and was + # not there. Reproduced end to end on real Arch hardware (opencharly/layer-cuda#9). + command: | + [ -f /etc/arch-release ] || exit 0 + test -f /usr/include/crt/host_config.h || exit 1 + printf 'int main(void){return 0;}\n' > /tmp/chkcuda.cu + nvcc -E -x cu /tmp/chkcuda.cu > /dev/null + rc=$? + rm -f /tmp/chkcuda.cu + exit $rc - check: the CUDA runtime library is linkable from the canonical /usr/lib64 path exit_status: 0 command: ls /usr/lib64/libcudart.so* @@ -244,8 +291,19 @@ cuda-skill: The candy is multi-distro. The `distro.arch` section installs `cuda`, `cudnn`, and `python-onnxruntime-cpu` from the Arch repos. Arch installs CUDA under - `/opt/cuda`, while `CUDA_HOME` is `/usr`, so the Arch path symlinks - `/opt/cuda/*` into `/usr/*` to stitch the Arch layout into the Fedora layout. + `/opt/cuda` — its toolkit headers under `/opt/cuda/targets/x86_64-linux/include/` — + while `CUDA_HOME` is `/usr`, so the Arch path links **every entry of those trees into + `/usr`** — files of any extension and subtrees alike, enumerated rather than + pattern-matched. `nvcc` computes its include root *relative to its own executable*, and + `/usr/bin/nvcc` is a symlink, so anything not reachable under `/usr/include` cannot be + found: `cuda_runtime.h`'s own `#include` fails and every CUDA build dies at CMake's + `enable_language(CUDA)` with "No such file or directory". Matching on patterns produced + both of those failures, on both Arch arms, while every probe in this plan still passed + (opencharly/layer-cuda#9): first a `*.h` glob that linked the top-level headers but not + the `crt/` and `cccl/` subtrees, then the same glob missing the `.hpp` half of the + `_functions` family once the subtrees were linked. The check `cuda-arch-header-root` + preprocesses a real CUDA translation unit to prove the whole header root resolves. + With that stitch in place, the same `nvcc`, header, and library paths resolve identically on Fedora and on Arch/CachyOS. From 3d5faac0a6d0efee3207ffde6f64f5cc47c0d6be Mon Sep 17 00:00:00 2001 From: charly Date: Fri, 16 Oct 2026 16:50:19 +0200 Subject: [PATCH 2/2] chore(cuda): ignore charly's build cache so it cannot land in a PR opencharly/layer-cuda#10 landed 18 build-cache files in a public PR: .build/_candy/{ffmpeg,nvidia}/ (checkouts of two other repos) plus the two generated context-ignore files. Root cause is the missing control, not the slip: this repo had no .gitignore, so nothing stopped a bare 'git add -A' from tracking charly's own local state. This adds the ignore rule for .build/, .containerignore and .dockerignore, and the removal of the tracked copies is in the round's fix commit. Assisted-by: DeepSeek Harness deepseek-v4.1-flash (syntax check only) --- .../ffmpeg.v2026.272.0056/.charly-view-ok | 1 - .../.github/workflows/tag-on-merge.yml | 88 -------- .build/_candy/ffmpeg.v2026.272.0056/AGENTS.md | 55 ----- .build/_candy/ffmpeg.v2026.272.0056/README.md | 59 ------ .../_candy/ffmpeg.v2026.272.0056/charly.yml | 113 ---------- .../nvidia.v2026.271.1817/.charly-view-ok | 1 - .../.github/workflows/tag-on-merge.yml | 88 -------- .build/_candy/nvidia.v2026.271.1817/AGENTS.md | 58 ------ .../CHANGELOG/2026.245.1450.md | 55 ----- .../CHANGELOG/2026.245.1456.md | 36 ---- .../CHANGELOG/2026.245.1515.md | 28 --- .../CHANGELOG/2026.245.1521.md | 28 --- .../CHANGELOG/2026.245.1541.md | 38 ---- .../CHANGELOG/2026.271.1114.md | 103 --------- .build/_candy/nvidia.v2026.271.1817/README.md | 73 ------- .../_candy/nvidia.v2026.271.1817/charly.yml | 196 ------------------ .containerignore | 17 -- .dockerignore | 17 -- .gitignore | 13 ++ 19 files changed, 13 insertions(+), 1054 deletions(-) delete mode 100644 .build/_candy/ffmpeg.v2026.272.0056/.charly-view-ok delete mode 100644 .build/_candy/ffmpeg.v2026.272.0056/.github/workflows/tag-on-merge.yml delete mode 100644 .build/_candy/ffmpeg.v2026.272.0056/AGENTS.md delete mode 100644 .build/_candy/ffmpeg.v2026.272.0056/README.md delete mode 100644 .build/_candy/ffmpeg.v2026.272.0056/charly.yml delete mode 100644 .build/_candy/nvidia.v2026.271.1817/.charly-view-ok delete mode 100644 .build/_candy/nvidia.v2026.271.1817/.github/workflows/tag-on-merge.yml delete mode 100644 .build/_candy/nvidia.v2026.271.1817/AGENTS.md delete mode 100644 .build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.245.1450.md delete mode 100644 .build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.245.1456.md delete mode 100644 .build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.245.1515.md delete mode 100644 .build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.245.1521.md delete mode 100644 .build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.245.1541.md delete mode 100644 .build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.271.1114.md delete mode 100644 .build/_candy/nvidia.v2026.271.1817/README.md delete mode 100644 .build/_candy/nvidia.v2026.271.1817/charly.yml delete mode 100644 .containerignore delete mode 100644 .dockerignore create mode 100644 .gitignore diff --git a/.build/_candy/ffmpeg.v2026.272.0056/.charly-view-ok b/.build/_candy/ffmpeg.v2026.272.0056/.charly-view-ok deleted file mode 100644 index 1ef6582..0000000 --- a/.build/_candy/ffmpeg.v2026.272.0056/.charly-view-ok +++ /dev/null @@ -1 +0,0 @@ -903a97260894115f0ff5f184ebeaf2e058e57ea0 diff --git a/.build/_candy/ffmpeg.v2026.272.0056/.github/workflows/tag-on-merge.yml b/.build/_candy/ffmpeg.v2026.272.0056/.github/workflows/tag-on-merge.yml deleted file mode 100644 index f503088..0000000 --- a/.build/_candy/ffmpeg.v2026.272.0056/.github/workflows/tag-on-merge.yml +++ /dev/null @@ -1,88 +0,0 @@ -# ORG-WIDE TAG-ON-MERGE DISPATCHER — installed in every opencharly repo. -name: tag-on-merge - -# Event-driven — no cron (RCA of all previous trigger designs, measured in -# this repo across 8 merges and 17 schedule runs): -# -# 1. `on: push` / `on: pull_request: [closed]` CANNOT see auto-merge merges. -# Native-auto-merge squash merges (actor `app/github-actions`) fire their -# webhook events — they are visible in the public event stream, e.g. -# `21:35:01Z sha=e222762 by=github-actions[bot]` for PR #8 — but GitHub -# Actions creates ZERO workflow runs for them (API-confirmed: no run for -# any merge commit, and 0 `pull_request`-event runs in the workflow's -# whole history). This is platform-level run suppression for auto-merge -# commits; no trigger selection can observe them. (Human merges and -# bot contents-API commits DO create runs — hence `push` is kept as a -# secondary trigger for those paths.) -# 2. `schedule: */15` cron: GitHub cron delivery is best-effort with no SLA. -# Measured 21-44 min gaps (never the configured 15); PR #3's tag landed -# 4+ hours late; PR #7's tag was still missing 30 min after merge. -# 3. `workflow_run` on `charly/pr-validator`: the ONE trigger whose event -# delivery is proven (the 12:12-12:51Z 8/22 runs all received the event; -# they died at startup on a workflow-file issue, not on delivery). -# -# The pr-validator run is the last actor before the merge (its final step -# arms native auto-merge). Firing on its completion and waiting (bounded) for -# the squash to land makes the MERGE the effective gate for tagging. The org -# reusable sweep is idempotent and scans the last 24h of merged PRs, so any -# PR missed by a wait timeout self-heals on the next validator completion. -# The rulebook's add-only backfill remains the ultimate documented path. -on: - workflow_run: - workflows: ["charly/pr-validator"] - types: [completed] - push: - branches: - - main - -permissions: - contents: write - pull-requests: read - -jobs: - wait-for-merge: - if: > - github.event_name == 'push' || - github.event.workflow_run.conclusion == 'success' - runs-on: ubuntu-latest - steps: - - name: Wait for triggering PR to merge (bounded readiness probe) - uses: actions/github-script@v7 - with: - script: | - // Push events: the merged PR is already on main — no wait needed. - if (context.eventName !== 'workflow_run') { - core.info('push event — merged PRs are in the sweep window'); - return; - } - const run = context.payload.workflow_run; - const { data: prs } = await github.rest.pulls.list({ - ...context.repo, - state: 'open', - head: `${context.repo.owner}:${run.head_branch}`, - }); - if (!prs.length) { - core.info('No open PR for head branch — sweep covers already-merged PRs'); - return; - } - const pr = prs[0]; - const deadline = Date.now() + 5 * 60 * 1000; - while (Date.now() < deadline) { - const { data: p } = await github.rest.pulls.get({ - ...context.repo, pull_number: pr.number, - }); - if (p.merged_at) { - core.info(`PR #${pr.number} merged at ${p.merged_at} — proceeding to tag`); - return; - } - await new Promise((r) => setTimeout(r, 20 * 1000)); - } - core.info(`PR #${pr.number} not merged within 5m — sweep still runs; next validator completion self-heals`); - - tag: - if: > - github.event_name == 'push' || - github.event.workflow_run.conclusion == 'success' - needs: wait-for-merge - uses: opencharly/.github/.github/workflows/tag-on-merge.yml@main - secrets: inherit diff --git a/.build/_candy/ffmpeg.v2026.272.0056/AGENTS.md b/.build/_candy/ffmpeg.v2026.272.0056/AGENTS.md deleted file mode 100644 index d35d901..0000000 --- a/.build/_candy/ffmpeg.v2026.272.0056/AGENTS.md +++ /dev/null @@ -1,55 +0,0 @@ -# AGENTS.md — layer-ffmpeg - -Standalone candy repo for the `ffmpeg` layer — the negativo17 nonfree FFmpeg -build (H.264/AAC) with `ffmpeg` and `ffprobe`. The candy lives in `charly.yml` at -the repo root: the per-distro package arm, the Fedora `fedora-multimedia` repo, -the `check:` assertions, and the embedded `skill:` entity projected into the -marketplace corpus as `/charly-selkies:ffmpeg`. - -Canonical files: - -- `charly.yml` — the `ffmpeg:` candy entity and the `ffmpeg-skill:` skill entity. -- `.github/workflows/tag-on-merge.yml` — CalVer tag + `CHANGELOG/` on merge. -- `README.md` — user overview only; never agent guidance. - -## Load these skills first (R0) - -- `/charly-selkies:ffmpeg` — the owning skill. The negativo17 repo, the nonfree - codec set, and the downstream consumers. Load before editing or troubleshooting - the layer. -- `/charly-image:layer` — the candy authoring reference (`charly.yml` schema, - `plan:` step verbs incl. `check:`, per-distro `distro:` arms, package/repo - blocks). Load before editing any entity field or plan step. - -## Build / validate / test - -- The merge gate is the **org-wide** `charly/pr-validator` (required check - `validate / validate`, defined in `opencharly/.github`); this repo has **no - per-repo candy gate** and ships only `.github/workflows/tag-on-merge.yml`. -- The candy's `plan:` `check:` steps are the functional evidence: the - `/usr/bin/ffmpeg` and `/usr/bin/ffprobe` binaries plus their version banners - (`ffmpeg version` / `ffprobe version`), and the package-installed check. They - must stay valid on the `arch`/`fedora` arms they run on. -- This is the nonfree negativo17 build, deliberately distinct from RPM Fusion's - `ffmpeg-free`; the `fedora-multimedia` repo + `gpgkey` must stay correct. - -## Modify this repo - -- Edit the `ffmpeg:` candy entity AND the `ffmpeg-skill:` skill entity in - `charly.yml` together. The skill is the projected usage source, so a package, - repo, or behaviour change not mirrored in the skill leaves the corpus stale. -- Keep `ffmpeg` as the single authoritative install point: downstream candies - declare `require: ffmpeg` rather than adding the negativo17 repo themselves. -- New behaviour claims belong in the `plan:` as an observable `check:` step, and - in the skill body. - -## Landing - -- PR-only. Every change lands through a pull request; the org-required - `charly/pr-validator` validates the diff and body and arms native auto-merge - on PASS. Direct pushes to `main` are blocked. -- History lives in `CHANGELOG/` (written by `tag-on-merge` at merge time); the - PR body IS the changelog. -- The authoritative rulebook is the umbrella `AGENTS.md` in - `opencharly/opencharly` and `charly/AGENTS.md` in the charly repo. Do not - restate its rules here. diff --git a/.build/_candy/ffmpeg.v2026.272.0056/README.md b/.build/_candy/ffmpeg.v2026.272.0056/README.md deleted file mode 100644 index 6db4dc2..0000000 --- a/.build/_candy/ffmpeg.v2026.272.0056/README.md +++ /dev/null @@ -1,59 +0,0 @@ -# ffmpeg - -FFmpeg — command-line audio/video transcoding and media inspection. - -The `ffmpeg` candy installs the `ffmpeg` package (from the negativo17 -`fedora-multimedia` repo on Fedora, `core`/`extra` on Arch). It ships the -`ffmpeg` transcoder and the `ffprobe` media inspector under `/usr/bin`, both of -which print a version banner to stdout — so their presence and basic operability -are directly verifiable. - -This is the negativo17 **nonfree** build (H.264/AAC support), not the RPM Fusion -`ffmpeg-free`. All candies that need `ffmpeg` declare it as a dependency rather -than independently adding the negativo17 repo, so there is a single authoritative -install point. - -## What it provides - -| Property | Value | -|---|---| -| Layer / candy | `ffmpeg` | -| Binaries | `/usr/bin/ffmpeg`, `/usr/bin/ffprobe` | -| Distro | `arch`, `fedora` | -| Repo | negativo17 `fedora-multimedia` (Fedora) | -| Service / port | none | - -## How to use it - -Compose the layer as an inline list in a box body: - -```yaml -my-box: - candy: - base: fedora - candy: - - '@github.com/opencharly/layer-ffmpeg:v2026.239.1614' -``` - -Then, inside the built image: - -```bash -ffmpeg -version # ffmpeg version x.y -ffprobe -version # ffprobe version x.y -``` - -## Layout - -- `charly.yml` — the `ffmpeg:` candy entity (the per-distro package arm, the - Fedora `fedora-multimedia` repo, the `check:` assertions) and the embedded - `ffmpeg-skill:` skill entity. -- `.github/workflows/tag-on-merge.yml` — CalVer tag + `CHANGELOG/` on merge. -- `README.md` — this user overview. - -## Related - -- Owning skill: `/charly-selkies:ffmpeg` -- Depends on it: `/charly-distros:cuda`, `/charly-tools:whisper`, - `/charly-hermes:hermes`, `/charly-immich:immich` -- [`opencharly/charly`](https://github.com/opencharly/charly) — the charly CLI and image builder -- [`opencharly/opencharly`](https://github.com/opencharly/opencharly) — the umbrella diff --git a/.build/_candy/ffmpeg.v2026.272.0056/charly.yml b/.build/_candy/ffmpeg.v2026.272.0056/charly.yml deleted file mode 100644 index b855965..0000000 --- a/.build/_candy/ffmpeg.v2026.272.0056/charly.yml +++ /dev/null @@ -1,113 +0,0 @@ -ffmpeg: - candy: - description: | - FFmpeg provides command-line audio/video transcoding and media inspection - Installs the ffmpeg package (from the negativo17 fedora-multimedia repo - on Fedora, core/extra on Arch). It ships the ffmpeg transcoder and the - ffprobe media inspector under /usr/bin, both of which print a version - banner to stdout — so their presence and basic operability are directly - verifiable. - distro: - arch: - package: - - ffmpeg - fedora: - package: - - ffmpeg - repo: - - name: fedora-multimedia - url: "https://negativo17.org/repos/fedora-multimedia.repo" - gpgkey: "https://negativo17.org/repos/RPM-GPG-KEY-slaanesh" - plan: - - check: the ffmpeg transcoder binary is installed at /usr/bin/ffmpeg - file: - file: /usr/bin/ffmpeg - exists: true - - check: ffmpeg prints its version banner to stdout - exit_status: 0 - stdout: - - contains: ffmpeg version - command: ffmpeg -version - - check: the ffprobe media inspector binary is installed at /usr/bin/ffprobe - file: - file: /usr/bin/ffprobe - exists: true - - check: ffprobe prints its version banner to stdout - exit_status: 0 - stdout: - - contains: ffprobe version - command: ffprobe -version - - check: package=ffmpeg - id: ffmpeg-package - package: - package: ffmpeg - installed: true - -ffmpeg-skill: - skill: - name: ffmpeg - family: selkies - owner: ffmpeg - description: |- - FFmpeg multimedia framework (negativo17 nonfree build with H.264/AAC support). - Use when working with the ffmpeg candy. - content: |- - # ffmpeg -- FFmpeg multimedia - - ## Candy Properties - - | Property | Value | - |----------|-------| - | Install files | `charly.yml` (packages only) | - | Depends | none | - | Repo | negativo17 `fedora-multimedia` | - - ## Packages - - RPM: `ffmpeg` (from negativo17 `fedora-multimedia` repo — full nonfree build with H.264, AAC, etc.) - - **Note:** This is NOT `ffmpeg-free` (RPM Fusion). This is the negativo17 build which includes nonfree codecs required for H.264 encoding/decoding. - - ## Usage - - ```yaml - # a box composing this candy — the candy list is inline - my-box: - candy: - base: fedora - candy: [ffmpeg] - ``` - - All candies that need ffmpeg should declare it as a dependency rather than independently adding the negativo17 repo. This ensures a single authoritative install point. - - ## Used In Boxes - - - `openclaw-full` (via `openclaw-full` metalayer) - - `hermes` (via `hermes` candy `require: ffmpeg`) - - `hermes-playwright` (via `hermes` candy `require: ffmpeg`) - - `immich` (via `immich` candy `require: ffmpeg`) - - `immich-ml` (via `immich` candy `require: ffmpeg`) - - CUDA-based boxes (via `cuda` candy `require: ffmpeg`) - - Whisper-based boxes (via `whisper` candy `require: ffmpeg`) - - ## Related Candies - - `/charly-distros:cuda` — Depends on ffmpeg for GPU video processing - - `/charly-tools:whisper` — Depends on ffmpeg for audio transcoding - - `/charly-hermes:hermes` — Depends on ffmpeg for media tooling - - `/charly-immich:immich` — Depends on ffmpeg for photo/video transcoding - - ## Related Commands - - `/charly-build:build` — Builds the ffmpeg negativo17 RPM into the box - - `/charly-core:shell` — Interactive shell to run `ffmpeg` for media processing - - ## When to Use This Skill - - Use when the user asks about: - - FFmpeg in containers - - Multimedia processing tools - - The `ffmpeg` candy - - ## Related - - - `/charly-image:layer` — candy authoring reference (`charly.yml` schema, `run:`/`check:` step verbs, service declarations) - - `/charly-check:check` — declarative testing (`check:` block, `charly check box`, `charly check live`) diff --git a/.build/_candy/nvidia.v2026.271.1817/.charly-view-ok b/.build/_candy/nvidia.v2026.271.1817/.charly-view-ok deleted file mode 100644 index 5cb6f79..0000000 --- a/.build/_candy/nvidia.v2026.271.1817/.charly-view-ok +++ /dev/null @@ -1 +0,0 @@ -eefa6a0ae0c909b34de7ad831ad2d155ff5edc1d diff --git a/.build/_candy/nvidia.v2026.271.1817/.github/workflows/tag-on-merge.yml b/.build/_candy/nvidia.v2026.271.1817/.github/workflows/tag-on-merge.yml deleted file mode 100644 index f503088..0000000 --- a/.build/_candy/nvidia.v2026.271.1817/.github/workflows/tag-on-merge.yml +++ /dev/null @@ -1,88 +0,0 @@ -# ORG-WIDE TAG-ON-MERGE DISPATCHER — installed in every opencharly repo. -name: tag-on-merge - -# Event-driven — no cron (RCA of all previous trigger designs, measured in -# this repo across 8 merges and 17 schedule runs): -# -# 1. `on: push` / `on: pull_request: [closed]` CANNOT see auto-merge merges. -# Native-auto-merge squash merges (actor `app/github-actions`) fire their -# webhook events — they are visible in the public event stream, e.g. -# `21:35:01Z sha=e222762 by=github-actions[bot]` for PR #8 — but GitHub -# Actions creates ZERO workflow runs for them (API-confirmed: no run for -# any merge commit, and 0 `pull_request`-event runs in the workflow's -# whole history). This is platform-level run suppression for auto-merge -# commits; no trigger selection can observe them. (Human merges and -# bot contents-API commits DO create runs — hence `push` is kept as a -# secondary trigger for those paths.) -# 2. `schedule: */15` cron: GitHub cron delivery is best-effort with no SLA. -# Measured 21-44 min gaps (never the configured 15); PR #3's tag landed -# 4+ hours late; PR #7's tag was still missing 30 min after merge. -# 3. `workflow_run` on `charly/pr-validator`: the ONE trigger whose event -# delivery is proven (the 12:12-12:51Z 8/22 runs all received the event; -# they died at startup on a workflow-file issue, not on delivery). -# -# The pr-validator run is the last actor before the merge (its final step -# arms native auto-merge). Firing on its completion and waiting (bounded) for -# the squash to land makes the MERGE the effective gate for tagging. The org -# reusable sweep is idempotent and scans the last 24h of merged PRs, so any -# PR missed by a wait timeout self-heals on the next validator completion. -# The rulebook's add-only backfill remains the ultimate documented path. -on: - workflow_run: - workflows: ["charly/pr-validator"] - types: [completed] - push: - branches: - - main - -permissions: - contents: write - pull-requests: read - -jobs: - wait-for-merge: - if: > - github.event_name == 'push' || - github.event.workflow_run.conclusion == 'success' - runs-on: ubuntu-latest - steps: - - name: Wait for triggering PR to merge (bounded readiness probe) - uses: actions/github-script@v7 - with: - script: | - // Push events: the merged PR is already on main — no wait needed. - if (context.eventName !== 'workflow_run') { - core.info('push event — merged PRs are in the sweep window'); - return; - } - const run = context.payload.workflow_run; - const { data: prs } = await github.rest.pulls.list({ - ...context.repo, - state: 'open', - head: `${context.repo.owner}:${run.head_branch}`, - }); - if (!prs.length) { - core.info('No open PR for head branch — sweep covers already-merged PRs'); - return; - } - const pr = prs[0]; - const deadline = Date.now() + 5 * 60 * 1000; - while (Date.now() < deadline) { - const { data: p } = await github.rest.pulls.get({ - ...context.repo, pull_number: pr.number, - }); - if (p.merged_at) { - core.info(`PR #${pr.number} merged at ${p.merged_at} — proceeding to tag`); - return; - } - await new Promise((r) => setTimeout(r, 20 * 1000)); - } - core.info(`PR #${pr.number} not merged within 5m — sweep still runs; next validator completion self-heals`); - - tag: - if: > - github.event_name == 'push' || - github.event.workflow_run.conclusion == 'success' - needs: wait-for-merge - uses: opencharly/.github/.github/workflows/tag-on-merge.yml@main - secrets: inherit diff --git a/.build/_candy/nvidia.v2026.271.1817/AGENTS.md b/.build/_candy/nvidia.v2026.271.1817/AGENTS.md deleted file mode 100644 index 38ba039..0000000 --- a/.build/_candy/nvidia.v2026.271.1817/AGENTS.md +++ /dev/null @@ -1,58 +0,0 @@ -# AGENTS.md — layer-nvidia - -Standalone candy repo for the `nvidia` layer — NVIDIA GPU runtime support. The -candy lives in `charly.yml` at the repo root: multi-distro package arms, the -`LD_LIBRARY_PATH` environment, the Vulkan ICD wiring and signature-verification -`plan:` steps, and the embedded `skill:` entity projected into the marketplace -corpus as `/charly-distros:nvidia`. - -Canonical files: - -- `charly.yml` — the `nvidia:` candy entity and the `nvidia-skill:` skill entity. -- `CHANGELOG/` — per-CalVer release history; read it before changing baked checks. -- `.github/workflows/tag-on-merge.yml` — CalVer tag + `CHANGELOG/` on merge. -- `README.md` — user overview only; never agent guidance. - -## Load these skills first (R0) - -- `/charly-distros:nvidia` — the owning skill. GPU runtime, CDI device - generation, the distro package arms, and verification. Load before editing or - troubleshooting the layer. -- `/charly-image:layer` — the candy authoring reference (`charly.yml` schema, - `plan:` step verbs incl. `check:`, per-distro `distro:` arms, package/repo - sections, and service declarations). Load before editing any entity field or - plan step. - -## Build / validate / test - -- `charly box validate` at the repo root — the structural check: the manifest - must parse and validate at the installed charly. -- The merge gate is the **org-wide** `charly/pr-validator` (required check - `validate / validate`, defined in `opencharly/.github`); this repo has no - per-repo candy gate. -- The candy's `plan:` `check:` steps are the functional evidence; they must stay - valid on every distro arm they run on. Where a check only applies to one - distro family (e.g. a Fedora-only DNF path), scope it in the command itself — - the check runner does not honour runner-level `exclude-distro` fields. - -## Modify this repo - -- Edit the `nvidia:` candy entity AND the `nvidia-skill:` skill entity in - `charly.yml` together. The skill is the projected usage source, so a package, - distro-arm, or behaviour change that is not mirrored in the skill leaves the - corpus stale. -- Package changes go in the top-level `package:` or a `distro:` arm; repository - and signing policy go in the matching `distro:` arm's `repo:` block. -- New behaviour claims belong in the `plan:` as an observable `check:` step, and - in the skill body. Keep the Fedora signature-verification check intact. - -## Landing - -- PR-only. Every change lands through a pull request; the org-required - `charly/pr-validator` validates the diff and body and arms native auto-merge - on PASS. Direct pushes to `main` are blocked. -- History lives in `CHANGELOG/` (written by `tag-on-merge` at merge time); the - PR body IS the changelog. -- The authoritative rulebook is the umbrella `AGENTS.md` in - `opencharly/opencharly` and `charly/AGENTS.md` in the charly repo. Do not - restate its rules here. diff --git a/.build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.245.1450.md b/.build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.245.1450.md deleted file mode 100644 index addcb6f..0000000 --- a/.build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.245.1450.md +++ /dev/null @@ -1,55 +0,0 @@ -# 2026.245.1450 — fix(nvidia): add omarchy distro arm + scope the gpgcheck assertion off arch-family guests - -## Summary - -`layer-nvidia` only declared `arch` + `fedora` distro arms. The L3 hybrid bed (`check-omarchy-hybrid-gpu-vm`, distro-omarchy) composes this layer on omarchy (an Arch-family distro), where two baked checks break: - -1. `nvidia-container-toolkit-gpgcheck-enforced` asserts gpgcheck=1 by awk-ing `/etc/dnf/repos.override.d/99-config_manager.repo` — a Fedora-only DNF path. The check's own comment declares it Fedora-scoped and already carries `exclude_distro: [arch, cachyos]`; **omarchy was missing from that list** (the layer predates the distro), so the check ran on omarchy and failed with `awk: fatal: cannot open file ... No such file or directory` (verified on the bed, calver 2026.245.1437). -2. The layer had no `omarchy` distro arm at all — so no package arm existed for the composed guest beyond the shared `nvidia-container-toolkit`. - -**Changes:** add the `omarchy` distro arm (`package: [nvidia-utils]`, mirroring the arch arm — the omarchy extra repo ships nvidia-utils), and add `omarchy` to the gpgcheck check's `exclude_distro` list (same rationale as the existing arch/cachyos entries). Schema stamp migrated 2026.232.0520 → 2026.240.1943 (current floor). - -## How tested - -**Gate:** structural — `charly box validate` on this tree: - -``` -/tmp/charly-linux-amd64 box validate -charly box validate: OK — checked 1 candy, 7 distros, 7 builders; 0 warnings, 0 errors -``` - -**Negative baseline (the failure this fixes, reproduced live on the bed):** the un-fixed check failed on a fresh omarchy VM exactly as predicted: - -``` -FAIL check the nvidia-container-toolkit repo enforces package signature verification [nvidia-container-toolkit-gpgcheck-enforced] exit=2 (awk: fatal: cannot open file '/etc/dnf/repos.override.d/99-config_manager.repo' for reading: No such file or directory) -``` - -The fix's positive proof (the check now SKIPs on omarchy and the hybrid bed run concludes with the nvidia-utils package arm installed) lands with the next fresh-rebuild run of `check-omarchy-hybrid-gpu-vm` after distro-omarchy bumps its layer-nvidia pin — the named immediate-next batch cutover (distro-omarchy #26 batch: autologin + mirror-resilience + this pin bump). - -## Rulebook compliance - -- **R0 skills:** git-workflow + strict-policy loaded; layer/schema migration semantics from the charly-internals skills. -- **R1 RCA + zero warnings:** the failure was root-caused on the live bed (awk on a Fedora-only path in an Arch-family guest); the check's own comment confirms the Fedora-scoped intent; fix extends the existing exclude list — no new mechanism (R3). -- **R2 no out-of-scope:** one distro arm + one exclude entry + schema stamp; nothing else touched. -- **R3 no duplication:** extends the layer's single distro map and the check's existing scope list. -- **R4 no workaround:** excluding the check on omarchy is the intended semantics (the DNF repo is correctly absent on arch-family), not a mask; the omarchy package arm adds the real runtime package. -- **R5 hard cutover + grep:** N/A — additive config; no identifiers removed. -- **R6 git safety:** feature branch off origin/main; no force-push; no direct-main. -- **R7 runtime gate:** box validate green (above); the bed-run positive proof lands in the named batch cutover. -- **R8 artifact invariants:** N/A — config-only. -- **R9 binary == source + deps:** N/A — no binary. -- **R10 disposable + coverage:** the changed path (gpgcheck exclusion on omarchy) is proven by the live negative baseline; the positive bed run is scheduled in the named immediate-next cutover — tier below fully-tested until it concludes. -- **RDD / ADE / SDD:** ADE intact; SDD N/A. -- **Hard cutover:** one atomic commit; additive. -- **Kernel/plugin boundary law:** N/A. -- **Disposable-only autonomy:** N/A — no deploy/destroy changes. -- **Clean architecture + Go gates:** N/A — no Go. -- **CHANGELOG:** N/A — tag-on-merge writes it from this body. - -## Change classification - -- **Change class:** candy/box-config — distro-arm addition + check scoping (config-only) -- **Verification gate:** `charly box validate` 0/0 on this tree + live negative baseline (bed calver 2026.245.1437); positive bed-run proof in the named batch cutover -- **Attribution tier:** analysed on a live system - -*Assisted-by: pi openrouter/deepseek/deepseek-v4-flash-0731 (analysed on a live system)* \ No newline at end of file diff --git a/.build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.245.1456.md b/.build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.245.1456.md deleted file mode 100644 index df91179..0000000 --- a/.build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.245.1456.md +++ /dev/null @@ -1,36 +0,0 @@ -# 2026.245.1456 — fix(ci): keep the schema stamp at the CI-pinned charly floor - -## Summary - -#2 landed the omarchy distro arm + gpgcheck scoping but also migrated the schema stamp (2026.232.0520 → 2026.240.1943), which is NEWER than the charly the repo's candy gate pins (schema max 2026.232.0520) — the `candy` gate broke on the merged head: - -``` -charly box validate -charly: error: command "validate": validation error: charly.yml: config schema 2026.240.1943 is newer than this charly supports (max 2026.232.0520) -``` - -This PR reverts ONLY the schema stamp. The omarchy distro arm and the `exclude_distro: [omarchy]` scoping from #2 are authored entirely within the 2026.232-compatible surface and stay (the pinned CI charly validates them). - -## How tested - -- `charly.yml` diff: single line (`version: 2026.240.1943` → `version: 2026.232.0520`); omarchy arm + exclude entries present (grep: 2 omarchy references). -- The pinned CI gate is the verifier for the exact schema ceiling: the `candy` workflow runs `.ci/charly/bin/charly box validate` — it must pass with the reverted stamp. -- Local validation with the current charly (newer) still passes the structural changes (validated in #2 with 0 warnings/errors). - -## Rulebook compliance - -- **R0/R1:** CI failure surfaced after #2 merged — root-caused to the schema-stamp migration vs the repo's pinned CI charly; fix reverts the unnecessary stamp. -- **R2:** single-line revert; the feature additions of #2 are untouched. -- **R3/R4:** no new mechanism; the revert restores the authored schema floor. -- **R5:** N/A — additive config, nothing removed beyond the bump. -- **R6:** feature branch off origin/main; no force-push. -- **R7:** the pinned CI gate is the gate; it reruns on this PR. -- **R10:** config-only single-line change; the gate run is the proof. Tier: analysed on a live system (the #2 bed-run evidence remains the feature proof). - -## Change classification - -- **Change class:** candy/box-config — schema stamp revert (CI compatibility) -- **Verification gate:** `candy` CI validate on this PR (pinned charly schema ceiling) -- **Attribution tier:** analysed on a live system - -*Assisted-by: pi openrouter/deepseek/deepseek-v4-flash-0731 (analysed on a live system)* \ No newline at end of file diff --git a/.build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.245.1515.md b/.build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.245.1515.md deleted file mode 100644 index 1003417..0000000 --- a/.build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.245.1515.md +++ /dev/null @@ -1,28 +0,0 @@ -# 2026.245.1515 — fix(ci): point the tag-on-merge dispatcher at the org reusable @main - -## Summary - -This repo's `tag-on-merge.yml` dispatcher referenced the org reusable at `@v1.0.0`, a ref that does not exist — so the repo has emitted ZERO tag-on-merge runs since provisioning (verified: `runs?total_count=0` while sibling repos tag correctly). Sibling repos (distro-omarchy, layer-wf-recorder) pin `@main`. Point the dispatcher at `@main`. - -## How tested - -- Diff: one line (`@v1.0.0` → `@main`). -- The proof of the fix is the event itself: after this PR merges, the `pull_request: [closed]` event fires the dispatcher, which calls the org reusable and creates the CalVer tag + CHANGELOG — that tag's existence on this merge is the verifier (the org reusable's sweep also self-heals the two earlier un-tagged merges of this repo). - -## Rulebook compliance - -- **R0/R1:** tag absence root-caused to the scaffolded `@v1.0.0` ref (nonexistent); sibling-repo comparison confirms `@main` is the working ref. -- **R2:** single-line CI fix; nothing else touched. -- **R3/R4:** aligns with the org dispatcher standard (R3), no workarounds. -- **R5:** N/A — CI file. -- **R6:** feature branch off origin/main; no force-push. -- **R7:** the gate is the org reusable invocation on the merge event (workflow runs list). -- **R10:** config/CI-only change; tier analysed on a live system (the repo's own run history is the baseline). - -## Change classification - -- **Change class:** CI fix — workflow reusable ref -- **Verification gate:** post-merge tag emission (org reusable run on the closed event) -- **Attribution tier:** analysed on a live system - -*Assisted-by: pi openrouter/deepseek/deepseek-v4-flash-0731 (analysed on a live system)* \ No newline at end of file diff --git a/.build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.245.1521.md b/.build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.245.1521.md deleted file mode 100644 index 780c3c8..0000000 --- a/.build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.245.1521.md +++ /dev/null @@ -1,28 +0,0 @@ -# 2026.245.1521 — fix(ci): adopt the org-standard workflow_run-based tag-on-merge dispatcher - -## Summary - -This repo's tag-on-merge dispatcher (old `pull_request: [closed]` design, org reusable pinned at `@v1.0.0`) has produced ZERO tag-on-merge runs since provisioning — verified API-side (`workflows/tag-on-merge.yml/runs?total_count=0`). The org file header documents the measured RCA: **native auto-merge squash merges fire their webhook events but GitHub Actions creates zero workflow runs for them** (platform-level run suppression), so `pull_request: [closed]` / `push` cannot observe them; the proven trigger is `workflow_run` on `charly/pr-validator` (whose final step arms the auto-merge) + a bounded wait-for-merge probe. Install the org-standard dispatcher **byte-identical** to distro-omarchy / the org reference (verified with `diff`). - -## How tested - -- The file is byte-identical to distro-omarchy's dispatcher (which tags reliably): `diff <(org file) .github/workflows/tag-on-merge.yml` → empty. -- The verifier is the next merge event: the org reusable runs on the `charly/pr-validator` completion, waits for the merge, and tags it with the CalVer + CHANGELOG; the org reusable's idle sweep also self-heals the repo's earlier un-tagged merges. - -## Rulebook compliance - -- **R0/R1:** tag absence root-caused (RCA documented in the org file header — measured across the org repo's 8 merges/17 schedule runs); the correct reference implementation is the org's own file. -- **R2:** CI-file only; org-parity install (R3 — the org dispatcher is THE canonical instance; no hand-authored variant). -- **R4:** no workaround — this is the org's proven trigger design. -- **R5:** hard cutover — the old dispatcher file is replaced by the org standard in this same PR. -- **R6:** feature branch off origin/main; no force-push. -- **R7:** the gate is tag emission on the next merge (org reusable invocation). -- **R10:** CI-config; tier analysed on a live system (the repo's zero-run history is the negative baseline; the sibling repo's working dispatcher is the reference). - -## Change classification - -- **Change class:** CI fix — tag-on-merge dispatcher migration to the org standard -- **Verification gate:** post-merge tag emission measured (org reusable run) -- **Attribution tier:** analysed on a live system - -*Assisted-by: pi openrouter/deepseek/deepseek-v4-flash-0731 (analysed on a live system)* \ No newline at end of file diff --git a/.build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.245.1541.md b/.build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.245.1541.md deleted file mode 100644 index 47dfb93..0000000 --- a/.build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.245.1541.md +++ /dev/null @@ -1,38 +0,0 @@ -# 2026.245.1541 — fix(nvidia): make the two baked checks arch-family robust (command-level) - -## Summary - -The hybrid-gpu bed (check-omarchy-hybrid-gpu-vm) composes this layer on omarchy, where two baked checks break: - -1. `nvidia-container-toolkit-gpgcheck-enforced` ran despite its `exclude_distro` list — the check runner does not honor that field (verified on live runs: it executes on omarchy, an excluded arch-family guest). The check failed on the Fedora-only DNF setopt path. Fix: implement the arc-family exclusion IN THE COMMAND — when `/etc/dnf/repos.override.d/99-config_manager.repo` is correctly absent (arch-family), exit 0; when present (fedora), keep the `gpgcheck=1` assertion. -2. `plan-step (LD_LIBRARY_PATH)` asserted an RPM-only env export (`printenv LD_LIBRARY_PATH` containing `/usr/lib64`) — the omarchy arm installs nvidia-utils whose driver libs land under `/usr/lib` (arch layout; `/usr/lib64` is the compat symlink), and the export does not land in the check's non-login shell. Fix: assert the driver-lib directory exists, accepting both layouts (`/usr/lib64/nvidia`, `/usr/lib/nvidia`, `libnvidia*`). - -## How tested - -- `charly box validate` via the repo's CI-pinned charly is the gate for this tree's schema stamp (unchanged 2026.232.0520 per #3). The changed checks are config-only. -- Negative baseline (the failures this fixes, reproduced live on the bed, calver 2026.245.1523 and 2026.245.1528): -``` -FAIL [nvidia-container-toolkit-gpgcheck-enforced] exit=2 (awk: fatal: cannot open file '/etc/dnf/repos.override.d/99-config_manager.repo' ...) -FAIL [plan:vm:omarchy-vm:9] exit=1 (printenv LD_LIBRARY_PATH: var unset) -``` -- Positive proof: the next fresh-rebuild run of check-omarchy-hybrid-gpu-vm after distro-omarchy bumps its layer pin lands in the named batch cutover (distro-omarchy #26 batch: autologin + pin bump + this layer). - -## Rulebook compliance - -- **R0/R1:** the runner-field exclusion failure was observed live (the check ran on an excluded distro) and root-caused to an unhonored field; the command-level implementation is the reliable mechanism. -- **R2:** the two checks only; nothing else touched. -- **R3:** command-level scoping is the one mechanism used elsewhere in this layer; no duplication. -- **R4:** fail-safe-absent is the correct semantics (the DNF file is correctly absent on arch-family), not a mask. -- **R5:** N/A — additive. -- **R6:** feature branch off origin/main; no force-push. -- **R7:** the CI-pinned charly `box validate` runs on this PR; the bed-run positive proof lands in the named cutover. -- **R10:** config-only; tier analysed on a live system until the bed-run positive proof concludes. -- **RDD/ADE/SDD, cutover, autonomy, Go gates, CHANGELOG:** N/A — config-only. - -## Change classification - -- **Change class:** candy/box-config — check command scoping (config-only) -- **Verification gate:** CI-pinned `charly box validate` on this PR + negative baseline above; positive bed-run in the named cutover -- **Attribution tier:** analysed on a live system - -*Assisted-by: pi openrouter/deepseek/deepseek-v4-flash-0731 (analysed on a live system)* \ No newline at end of file diff --git a/.build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.271.1114.md b/.build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.271.1114.md deleted file mode 100644 index 786e792..0000000 --- a/.build/_candy/nvidia.v2026.271.1817/CHANGELOG/2026.271.1114.md +++ /dev/null @@ -1,103 +0,0 @@ -# 2026.271.1114 — docs: tailored README + AGENTS.md signpost (layer-nvidia) (#286) - -## Summary - -Docs-only leg of umbrella campaign `opencharly/opencharly#286` for the -`opencharly/layer-nvidia` repo. This repo gets its tailored pair: - -- **`README.md` — user overview only.** Rewritten from the generic - candy-catalog boilerplate into a real user overview: what the layer provides - (`nvidia-container-toolkit` / `/usr/bin/nvidia-ctk`, the per-distro driver - packages for arch/omarchy/fedora, `LD_LIBRARY_PATH=/usr/lib64`, the - `/etc/vulkan/icd.d` ICD wiring, no service/port; CUDA is the separate `cuda` - layer), how a user consumes it (`@github.com/opencharly/layer-nvidia:` in a - box `candy:` list; `nvidia-smi` / `nvidia-ctk --version` verification), a brief - layout, and a pointer to the owning skill `/charly-distros:nvidia`. -- **`AGENTS.md` — new, thin, harness-neutral agent signpost.** What the repo is - and its canonical files (including `CHANGELOG/`); the R0 skill list - (`/charly-distros:nvidia` + `/charly-image:layer`); the exact build/validate - commands (`charly box validate`, `.github/workflows/deploy.yml`); the edit rule - (change the candy entity AND its embedded `skill:` entity together, keep the - Fedora signature-verification check intact, and scope distro-specific checks in - the command itself since the runner ignores `exclude-distro`); and landing - (PR-only via `charly/pr-validator`, history in `CHANGELOG/`, authoritative - rulebook is the umbrella `AGENTS.md` + `charly/AGENTS.md`). It restates no rule - and names no harness. - -No functional or architecture file is touched; `charly.yml`, `CHANGELOG/` and -both workflows are byte-identical to `origin/main`. - -## How tested - -On the final committed head `1d7d3ec9a68c949e5f696c895de4915c6919135f`: - -``` -$ git -C status --short -(empty) - -$ git -C diff --stat origin/main..HEAD - AGENTS.md | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ - README.md | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---------- - 2 files changed, 129 insertions(+), 13 deletions(-) - -$ git -C diff --stat origin/main..HEAD | grep -v '\.md$' -(empty — docs-only; no non-`.md` file changed) - -$ /tmp/opencode/charly-238 -C box validate # the repo's CI-pinned charly (v2026.238.1242) -(no output; exit 0) -``` - -Cross-check with the umbrella dev binary, whose schema floor is AHEAD of this -repo's CI pin — it rejects the UNCHANGED manifest, independent of this change: - -``` -$ /home/atrawog/Sync/Atrapub/lo/opencoder/opencharly/charly/bin/charly -C box validate -charly: error: command "validate": validation error: /charly.yml: schema 2026.261.1747 is required (found "2026.232.0520"). Run: charly migrate - -$ git -C diff --stat origin/main..HEAD -- charly.yml -(empty — the manifest is untouched by this docs-only change, so this pre-existing - schema-floor mismatch cannot be caused by it; the repo's own CI gate is the - pinned `candy` workflow, which validates green above) -``` - -## Rulebook compliance - -Umbrella `AGENTS.md` rules 1–11: - -1. **Never edit inside a submodule** — HOW: edited only in the session worktree `.worktrees/layer-nvidia-docs`; the tracked submodule checkout stays clean/detached. -2. **Git op rule (`git -C `)** — HOW: every git/gh action ran via `git -C ` / `--repo`. -3. **No nested `go.work`** — N/A — no Go workspace file touched. -4. **Sessions root at the umbrella; edits in a session worktree off fresh `origin/main`** — HOW: worktree branched off `origin/main`; base confirmed unchanged. -5. **Pin discipline (merged refs only)** — N/A — no pin/gitlink changed. -6. **Policy B (distro pins == charly gitlinks)** — N/A — no submodule gitlink touched. -7. **Read the subrepo's own rulebook first** — HOW: read the umbrella `AGENTS.md` and the dispatched skills (`git-workflow`, `skills`, `layer`, `docs`). -8. **Harness config: shared core + deliberate forks** — N/A — no harness config changed. -9. **Session-scoped ownership** — HOW: only this session's worktree/branch/PR touched; other sessions' worktrees untouched. -10. **Before ANY update push, read the PR's live state AND write the body** — HOW: initial push; the whole body is written for the head being pushed, footer last. -11. **Agent identity & comment coordination footer (extends rule 9)** — HOW: two-line `Agent:`-then-`Assisted-by:` footer in canonical order; solo/uncontended scope. - -Ground-truth rules R1–R10 (`charly/AGENTS.md`): - -- **R1 (RCA every anomaly)** — HOW: the umbrella dev binary's `box validate` schema-floor mismatch was root-caused to a binary schema floor (`2026.261.1747`) newer than this repo's CI pin (`v2026.238.1242`, manifest `2026.232.0520`); the diff touches no non-`.md`, so the mismatch is independent of this change; not parked. -- **R2 (finish the whole cutover; no parking)** — HOW: the docs-only change class is delivered in full (README user overview + AGENTS signpost); the `skill:` entity is unchanged, so no marketplace/docs projection regeneration is triggered. -- **R3 (no duplication)** — HOW: README points at the owning skill instead of restating it; AGENTS points at the rulebook instead of restating rules. -- **R4 (no workarounds)** — HOW: used the repo's own `charly box validate` gate; no ad-hoc substitute. -- **R5 (delete legacy completely)** — HOW: the generic catalog boilerplate README was replaced, not appended; no stale scaffold claim remains. -- **R6 (git safety)** — HOW: `status` inspected before/after; no force-push, no hook bypass, no direct push to `main`; no other session's work touched. -- **R7 (prove the gate, not the plan)** — HOW: ran `charly box validate` with the repo's CI-pinned charly on the final committed tree; output pasted above. -- **R8 (preserve emitted artifacts)** — N/A — docs-only; no emitted artifact/config changed. -- **R9 (binary equals source)** — N/A — this repo ships no charly source/binary. -- **R10 (fresh proof by change class)** — HOW: Documentation-only change class → `documentation reviewed` tier; the repo's `candy` gate (`charly box validate` at the pinned charly) is the structural proof, run on the final tree. - -RDD / ADE / SDD — N/A — documentation-only. - -## Change classification - -- **Change class:** Documentation-only. -- **Gate:** the repo's `candy` CI gate (`charly box validate` at the pinned charly) — manifest untouched, so behavior is unchanged; explicitly pasted above. -- **Attribution tier:** `documentation reviewed`. - -Refs #286 - -*Agent: `org-readme-agents` · session `ses_org-readme-agents`* -*Assisted-by: opencode deepseek-v4.1-flash (documentation reviewed)* \ No newline at end of file diff --git a/.build/_candy/nvidia.v2026.271.1817/README.md b/.build/_candy/nvidia.v2026.271.1817/README.md deleted file mode 100644 index 0a6ddc6..0000000 --- a/.build/_candy/nvidia.v2026.271.1817/README.md +++ /dev/null @@ -1,73 +0,0 @@ -# nvidia - -NVIDIA GPU runtime layer for OpenCharly images. - -The `nvidia` candy prepares an image to use an NVIDIA GPU. It installs -`nvidia-container-toolkit` — the `nvidia-ctk` CLI that generates CDI device -specs — together with the per-distro driver libraries, exports -`LD_LIBRARY_PATH=/usr/lib64` so the driver libraries resolve, and prepares -`/etc/vulkan/icd.d` to hold the NVIDIA Vulkan ICD symlinks. It is the GPU -runtime base that GPU-accelerated boxes compose; the CUDA toolchain is a -separate `cuda` layer. - -## What it provides - -| Property | Value | -|---|---| -| Layer / candy | `nvidia` | -| Package | `nvidia-container-toolkit` (all distros) | -| Binary | `/usr/bin/nvidia-ctk` | -| Environment | `LD_LIBRARY_PATH=/usr/lib64` | -| Directory | `/etc/vulkan/icd.d` (NVIDIA Vulkan ICD / layer symlinks) | -| Service / port | none | - -Per-distro driver packages: - -- `arch` / `omarchy` — `nvidia-utils` -- `fedora` — `libva-nvidia-driver` (from the negativo17 `fedora-multimedia` - repo) plus NVIDIA's own `nvidia-container-toolkit` repo, with package - signature verification enforced (`gpgcheck=1`, overriding NVIDIA's shipped - `gpgcheck=0`). - -## How to use it - -Compose the layer by pinning this repo in a box's `candy:` list: - -```yaml -my-box: - candy: - base: fedora # or cachyos / omarchy for the Arch driver layout - candy: - - '@github.com/opencharly/layer-nvidia:v2026.245.1541' -``` - -Once the image is built and the GPU is attached by the runtime: - -```bash -nvidia-smi # GPU information -nvidia-ctk --version # CDI toolkit -``` - -The layer bakes every artifact (package, `nvidia-ctk` binary, exported path, -Vulkan ICD directory) into the image, so it is verifiable without a physical -GPU. A GPU-accelerated box pairs it with `cuda` (CUDA toolkit, cuDNN) — for -example `python-ml`, `jupyter`, `ollama`, and `comfyui`. - -## Layout - -- `charly.yml` — the candy manifest: the multi-distro package arms, the - `LD_LIBRARY_PATH` environment, the Vulkan ICD wiring `plan:`, the `plan:` - checks, and the embedded `skill:` entity. -- `CHANGELOG/` — per-CalVer release notes. -- `.github/workflows/tag-on-merge.yml` — CalVer tag + `CHANGELOG/` on merge. -- `README.md` — this user overview. - -## Related - -- Owning skill: `/charly-distros:nvidia` -- CUDA toolkit: `/charly-distros:cuda` -- Derived GPU boxes: `/charly-languages:python-ml`, `/charly-jupyter:jupyter`, - `/charly-ollama:ollama`, `/charly-comfyui:comfyui` -- Arch/CachyOS GPU base sibling: `cachyos.nvidia` in `opencharly/distro-cachyos` -- [`opencharly/charly`](https://github.com/opencharly/charly) — the charly CLI and image builder -- [`opencharly/opencharly`](https://github.com/opencharly/opencharly) — the umbrella diff --git a/.build/_candy/nvidia.v2026.271.1817/charly.yml b/.build/_candy/nvidia.v2026.271.1817/charly.yml deleted file mode 100644 index dee75f2..0000000 --- a/.build/_candy/nvidia.v2026.271.1817/charly.yml +++ /dev/null @@ -1,196 +0,0 @@ -nvidia: - candy: - description: | - NVIDIA GPU runtime — nvidia-container-toolkit (nvidia-ctk CDI) plus the driver-lib path and Vulkan ICD wiring - Installs nvidia-container-toolkit (the nvidia-ctk CLI that generates - CDI device specs) alongside the per-distro driver libs (nvidia-utils - on Arch, libva-nvidia-driver on Fedora). Exports - LD_LIBRARY_PATH=/usr/lib64 so the GPU driver libraries resolve, and - prepares /etc/vulkan/icd.d to hold the nvidia Vulkan ICD symlinks. - Every effect — the package, the nvidia-ctk binary, the exported path, - and the ICD directory — is a real artifact baked into the image, so - each is directly verifiable without a physical GPU. - package: - - nvidia-container-toolkit - distro: - arch: - package: - - nvidia-utils - omarchy: - package: - - nvidia-utils - fedora: - package: - - libva-nvidia-driver - repo: - # negativo17 fedora-multimedia provides the driver libs (libva-nvidia-driver) - # but NOT nvidia-container-toolkit; that lives ONLY in NVIDIA's own - # libnvidia-container repo (RDD-confirmed on fedora:43: - # negativo17 → "No matching packages"; NVIDIA repo → installs 1.19.1). - - name: fedora-multimedia - url: "https://negativo17.org/repos/fedora-multimedia.repo" - gpgkey: "https://negativo17.org/repos/RPM-GPG-KEY-slaanesh" - # NVIDIA ships this repo file with gpgcheck=0 — the only repo in the - # tree that does — so its 4 packages (a container runtime hook) were - # installing UNVERIFIED even though the gpgkey below imports fine and - # every one of them is validly signed by the primary key. gpgcheck: true - # forces the check back on; before the tri-state knob existed the - # `gpgcheck:` field could only ever weaken a vendor's policy, so there - # was no value expressible here that fixed it. - # No gpgkey: here ON PURPOSE. The repo file already declares the same - # key, so dnf5 imports it itself under gpgcheck=1 — whereas an explicit - # `rpm --import` of NVIDIA's published certificate emits - # "Subkey 6ED91CA3AC1160CD is expired" on every build, because that - # certificate carries a subkey that died 2021-06-16 and every NVIDIA - # copy of it still ships the dead subkey. Nothing is trusted less: the - # packages are signed by the PRIMARY key and are verified either way. - - name: nvidia-container-toolkit - url: "https://nvidia.github.io/libnvidia-container/stable/rpm/nvidia-container-toolkit.repo" - gpgcheck: true - env: - LD_LIBRARY_PATH: "/usr/lib64" - plan: - - run: mkdir=/etc/vulkan/icd.d - mkdir: /etc/vulkan/icd.d - run_as: root - - run: | - command=[ -f /usr/share/vulkan/icd.d/nvidia_icd.x86_64.json ] && \ - ln -sf /usr/share/vulkan/icd.d/nvidia_icd.x86_64.json /etc/vulkan/icd.d/nvidia_icd.json || true - [ -f /usr/share/vulkan/implicit_layer.d/nvidia_layers.json ] && \ - ln -sf /usr/share/vulkan/implicit_layer.d/nvidia_layers.json /etc/vulkan/icd.d/nvidia_layers.json || true - run_as: root - command: | - [ -f /usr/share/vulkan/icd.d/nvidia_icd.x86_64.json ] && \ - ln -sf /usr/share/vulkan/icd.d/nvidia_icd.x86_64.json /etc/vulkan/icd.d/nvidia_icd.json || true - [ -f /usr/share/vulkan/implicit_layer.d/nvidia_layers.json ] && \ - ln -sf /usr/share/vulkan/implicit_layer.d/nvidia_layers.json /etc/vulkan/icd.d/nvidia_layers.json || true - # THE coverage for the gpgcheck fix, and it reads the one observable that - # DISCRIMINATES. Two wrong candidates, both ruled out by experiment: - # - "the signing key is in the rpmdb" does NOT discriminate — the previous - # code imported the key explicitly via `rpm --import` while still - # installing unverified under NVIDIA's shipped gpgcheck=0, so the key was - # present either way. - # - the vendor .repo file does NOT change — `dnf5 config-manager setopt` - # never rewrites it; /etc/yum.repos.d/nvidia-container-toolkit.repo still - # reads gpgcheck=0 in the built image. - # setopt persists into /etc/dnf/repos.override.d/99-config_manager.repo, which - # overrides the vendor file and DOES survive into the image. The awk pulls just - # this repo's section, because that file also carries other repos' setopts. - # Revert `gpgcheck: true` above (or the template's `true` arm) and it fails. - - check: the nvidia-container-toolkit repo enforces package signature verification, so its packages cannot install unverified - id: nvidia-container-toolkit-gpgcheck-enforced - # Fedora-scoped: the asserted `repo:` block (gpgcheck=0 vendor file - # overridden by dnf5 setopt) lives under distro.fedora; dnf5 and /etc/dnf - # exist only there. Arch-family arms (arch/cachyos/omarchy) install - # nvidia-utils from pacman and have no DNF repo — the file is correctly - # absent, so the step exits 0 without asserting (the fd condition below). - # The exclusion is implemented in the command itself: runner-level - # exclude-distro fields are not honored by the check runner. - exit_status: 0 - stdout: - - contains: "gpgcheck=1" - command: awk '/^\[nvidia-container-toolkit\]/{f=1;next} /^\[/{f=0} f' /etc/dnf/repos.override.d/99-config_manager.repo 2>/dev/null || test ! -e /etc/dnf/repos.override.d/99-config_manager.repo - - check: the nvidia-container-toolkit package is installed for CDI device generation - package: - package: nvidia-container-toolkit - installed: true - - check: the nvidia-ctk CLI binary lands on the canonical /usr/bin path - file: - file: /usr/bin/nvidia-ctk - exists: true - - check: nvidia-ctk runs and reports a version number - exit_status: 0 - stdout: - - matches: "[0-9]+\\.[0-9]+" - command: nvidia-ctk --version - - check: the Vulkan ICD directory exists to hold the nvidia ICD symlinks - file: - file: /etc/vulkan/icd.d - exists: true - filetype: directory - - check: the GPU driver lib directory (RPM /usr/lib64 or Arch /usr/lib layout) exists in the guest - exit_status: 0 - stdout: - - contains: nvidia - command: ls -d /usr/lib64/nvidia /usr/lib/nvidia /usr/lib64/libnvidia* /usr/lib/libnvidia* 2>/dev/null -nvidia-skill: - skill: - name: nvidia - family: distros - owner: nvidia - description: |- - NVIDIA GPU base image with runtime support and CUDA toolkit on Fedora. Base for all - GPU-accelerated boxes (python-ml, jupyter, ollama, comfyui). - MUST be invoked before building, deploying, configuring, or troubleshooting the nvidia box. - triggers: - - "Fedora images / `fedora*` / `box/fedora` submodule (incl. the GPU base `nvidia` / `python-ml` + `sway-browser-vnc`)" - content: | - # nvidia - - NVIDIA GPU base image — provides GPU runtime (driver libs, CDI toolkit) and CUDA development toolkit on Fedora. - - The `nvidia` and `cuda` candies are multi-distro (Fedora rpm + Arch pac), so a - CachyOS GPU base exists alongside this Fedora `nvidia` box: `cachyos.nvidia` - (cachyos + agent-forwarding + nvidia + cuda) in the `opencharly/distro-cachyos` - submodule. The two are siblings — pick the Fedora `nvidia` box for the - RPM-based GPU stack, `cachyos.nvidia` for the Arch/CachyOS GPU stack. See - `/charly-distros:cachyos`. - - ## Box Properties - - | Property | Value | - |----------|-------| - | Base | fedora-nonfree (fedora + RPM Fusion) | - | Layers | agent-forwarding, nvidia, cuda | - | Platforms | linux/amd64 | - | Registry | ghcr.io/opencharly | - - ## Full Candy Stack - - 1. `fedora-nonfree` (fedora + rpmfusion — provides RPM Fusion free + nonfree repos) - 2. `nvidia` — GPU runtime: driver libs, nvidia-container-toolkit (CDI), VA-API - 3. `cuda` — CUDA toolkit, cuDNN, onnxruntime, ffmpeg-libs - - ## Quick Start - - The `nvidia` box lives in the `opencharly/distro-fedora` submodule (`box/fedora`): - - ```bash - charly -C box/fedora box build nvidia - charly shell nvidia - ``` - - ## Key Candies - - - `/charly-distros:nvidia` — NVIDIA GPU runtime (driver libs, CDI generation via nvidia-ctk) - - `/charly-distros:cuda` — CUDA toolkit and GPU development libraries - - ## Derived Boxes - - - `/charly-languages:python-ml` — ML Python environment - - `/charly-jupyter:jupyter` — Jupyter notebook server - - `/charly-ollama:ollama` — LLM inference server - - `/charly-comfyui:comfyui` — image generation UI - - ## Related Boxes - - - `/charly-distros:fedora` — parent base (no GPU) - - `/charly-distros:cachyos` — `cachyos.nvidia` is the CachyOS GPU-base sibling (Arch/CachyOS GPU stack) - - `/charly-coder:charly-arch` — Arch Linux charly toolchain with nvidia (shared candies) - - `/charly-distros:charly-fedora` — Fedora charly toolchain with nvidia (shared candies) - - ## Verification - - After `charly box build`: - - `charly shell nvidia -c "nvidia-smi"` — GPU info - - `charly shell nvidia -c "nvidia-ctk --version"` — CDI toolkit - - `charly shell nvidia -c "nvcc --version"` — CUDA compiler - - ## When to Use This Skill - - **MUST be invoked** when the task involves the nvidia box, GPU base images, CUDA in containers, or CDI device configuration. Invoke this skill BEFORE reading source code or launching Explore agents. - - ## Related - - - `/charly-image:image` — image family umbrella (`candy:` image entries — those carrying `base:`/`from:` — in `charly.yml`, build/validate/inspect/list) - - `/charly-build:build` — the embedded build vocabulary (distros, builders, init-systems) diff --git a/.containerignore b/.containerignore deleted file mode 100644 index 3261ac7..0000000 --- a/.containerignore +++ /dev/null @@ -1,17 +0,0 @@ -# .containerignore (generated -- do not edit; source: defaults.context_ignore in charly.yml) -.git -bin -charly -*.md -**/__pycache__ -**/*.pyc -**/*.pyo -**/*.egg-info -**/node_modules -**/.git -**/.DS_Store -**/*~ -**/*.swp -**/*.swo -**/.pytest_cache -**/.mypy_cache diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index 599b1b8..0000000 --- a/.dockerignore +++ /dev/null @@ -1,17 +0,0 @@ -# .dockerignore (generated -- do not edit; source: defaults.context_ignore in charly.yml) -.git -bin -charly -*.md -**/__pycache__ -**/*.pyc -**/*.pyo -**/*.egg-info -**/node_modules -**/.git -**/.DS_Store -**/*~ -**/*.swp -**/*.swo -**/.pytest_cache -**/.mypy_cache diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3b8f34c --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +# charly local state — never commit +# +# `.build/` is the build cache: generated candy checkouts (`_candy/`) of THIS +# repo's dependencies, recreated by every `charly box validate`/`generate`/`build`. +# `.containerignore` and `.dockerignore` are generated context-ignore files +# (gitignored org-wide by the shared ignore rules). +# +# Without this file a `git add -A` silently lands all of it in a PR — which is +# exactly what happened in opencharly/layer-cuda#10, where 18 of 19 changed files +# were this cache rather than the change. +.build/ +.containerignore +.dockerignore