add CI images to repo
Some checks failed
/ check (push) Successful in 2m44s
/ nvim-bundle (nvim) (push) Failing after 14m17s

This commit is contained in:
iofq 2026-02-28 00:01:58 -06:00
parent abce966b76
commit 817aa75f84
16 changed files with 386 additions and 54 deletions

View file

@ -0,0 +1,12 @@
on:
push:
branches: [main]
jobs:
check:
runs-on: nix-upstream-latest
steps:
- run: echo "experimental-features = nix-command flakes" >> /etc/nix/nix.conf
- run: nix-env -i nodejs
- uses: actions/checkout@v4
- name: nix flake check
run: nix flake check

View file

@ -1,33 +0,0 @@
name: build
on:
push:
branches:
- main
jobs:
build:
runs-on: nix-latest
strategy:
matrix:
package_name: ["nvim"]
steps:
- uses: actions/checkout@v4
- uses: DeterminateSystems/nix-installer-action@main
- name: check
run: nix flake check
- name: Run `nix bundle`
if: github.ref == 'refs/heads/main'
id: build
run: |
nix bundle \
-o ${{ matrix.package_name }}.AppImage \
--bundler github:ralismark/nix-appimage \
--extra-experimental-features nix-command \
--extra-experimental-features flakes .#${{ matrix.package_name }}
echo "Done building AppImage for ${{ matrix.package_name }}"
- name: Upload bundle to release
if: github.ref == 'refs/heads/main'
uses: https://data.forgejo.org/forgejo/upload-artifact@v4
with:
path: "${{ matrix.package_name }}.AppImage"
name: "${{ matrix.package_name }}-x86_64-linux.AppImage"

View file

@ -0,0 +1,24 @@
on:
push:
paths:
- 'pkgs/nvim/**'
jobs:
nvim-bundle:
runs-on: nix-upstream-latest
if: github.ref == 'refs/heads/main'
strategy:
matrix:
package_name: ["nvim"]
steps:
- run: echo "experimental-features = nix-command flakes" >> /etc/nix/nix.conf
- run: nix-env -i nodejs
- uses: actions/checkout@v4
- name: Run `nix bundle`
run: |
path="${{ matrix.package_name }}.AppImage"
nix bundle --bundler github:ralismark/nix-appimage \
-o "$path" \
.#${{ matrix.package_name }}
curl --user "${{ secrets.FJ_USER }}:${{ secrets.FJ_PASS }}" \
--upload-file "$path" \
"${{ forge.api_url }}/packages/${{ secrets.FJ_USER }}/generic/${{ matrix.package_name }}/latest/$path"

View file

@ -0,0 +1,66 @@
---
name: commit
description: Generate commit messages and PR descriptions from implementation.
---
# Commit Skill
Generates commit messages from completed implementation.
## Inputs
Read these files:
- **DESIGN.md** (design contract)
- **IMPLEMENTATION.md** (if exists; provides decisions log, deviations)
- **run `jj diff`** (actual changes)
## Process
### 1. Review Changes
Examine diff to understand what changed. Cross-reference with DESIGN.md to understand why.
### 2. Generate Commit Message
**Format: Conventional Commits**
```
brief description
Detailed body explaining:
- What changed
- Why (reference DESIGN.md problem/solution)
```
**Types**: `feat`, `fix`, `refactor`, `docs`, `test`, `chore`
**Example**:
```
feat: add support for nested JSON
Changes:
- Added parseNestedJSON() to handle nested patterns
- Updated JSONParser.java to consume new patterns.
```
**Guidelines**:
- One commit for the entire feature (per DESIGN.md)
- Accurate, complete: human will edit further
**Note**: IMPLEMENTATION.md should be deleted
## Output
Present to user:
```
=== COMMIT MESSAGE ===
[Generated message]
```
Prompt user if they would like to commit using the message. If so, use `jj desc -m '<commit message>'`
## Philosophy
Your output is a **draft** for human editing. Optimize for accuracy and completeness, not polish. Provide context reviewers need:
Good commit/PR messages make review faster and preserve project history.

View file

@ -0,0 +1,114 @@
---
name: design
description: Design features collaboratively to create exhaustive DESIGN.md doc. Triggers on "rubber duck", "help me design", "write a design doc".
---
# Design Skill
Creates exhaustive design documents with zero ambiguity. All architectural decisions happen here: implementation is mechanical execution.
## Core Principle
**Minimal Agency**: Surface decisions, never make them silently. If unclear, ask. The human decides architecture; you structure and formalize.
**Critical**: DESIGN.md must be SO explicit that implementation is mechanical. If implementer needs to make design decisions, the design is incomplete.
## Process
### 1. Ingest
User provides raw notes/requirements. Treat as authoritative even if informal/incomplete.
### 2. Discovery
Before designing, **explore the codebase**:
- `grep`/`find`/`read` to locate files, classes, functions user mentioned.
- Understand existing patterns, conventions, architecture
- Identify which files will be touched
- Read relevant code for context
Factor discoveries into design and respect existing patterns.
### 3. Collaborative Design
**Rubber duck mode**. Your job:
- Ask clarifying questions until no ambiguities remain
- Surface implicit assumptions, probe edge cases
- Structure and formalize, but **never decide architecture unilaterally**
- When decision needed and user hasn't made it: **explicitly surface as open question**
### 4. Generate DESIGN.md
Output to `DESIGN.md` with this **exact structure**:
```markdown
# Problem
Clear statement of what needs solving and why.
## Non-goals
Explicit list of what this does NOT address.
# Solution
High-level approach description.
## Architecture
How components fit together, data flow, key patterns.
- Exact code samples for key abstractions
## Files to be Modified
- `path/to/file` - Brief description of changes
## Files to be Created
- `path/to/file` - Purpose
## Data Structures
Exact type definitions, schemas, interfaces with code samples.
## Interfaces & APIs
Exact function signatures, class definitions with code samples.
Include parameters, return types, behavior.
## Algorithms & Logic
Pseudocode or explicit descriptions of non-trivial logic.
## Error Handling
How errors detected, propagated, handled.
# Test Cases
Explicit scenarios with:
- **Setup**: Preconditions, input
- **Action**: What happens
- **Expected**: Outcome/output
Include edge cases and failure modes.
# Implementation Notes
Constraints, ordering requirements, gotchas.
## Assumptions & Constraints
Explicit list of assumptions.
# Considered but Not Implemented
Alternative approaches and why rejected.
```
### 5. Approval Gate
**HARD GATE**: DESIGN.md must be approved before `/implement`. State:
```
DESIGN.md complete. Review and approve before running /implement.
If incomplete or needs changes, let me know and I'll update.
```
Do not proceed without explicit approval.
## Philosophy
A good DESIGN.md reads like executable specification. Every conditional, every data structure, every interface is decided. Implementation maps spec to code with zero interpretation.
**Why exhaustive design?**
- Prevents mid-implementation thrashing
- Human makes hard decisions with full context
- Agent executes without architectural judgment calls
- Design document becomes PR review artifact
## Artifact Lifecycle
DESIGN.md is **permanent** committed to repo, included in PRs for reviewers.

View file

@ -0,0 +1,129 @@
---
name: implement
description: Mechanically execute approved design. Creates tasks, writes tests first, implements feature.
---
# Implement Skill
Mechanical execution of DESIGN.md. No architectural decisions, only code that maps directly to specs.
## Core Principle
**Implementation is execution, not planning**. If you need to make a design decision, the design is incomplete. STOP and surface it.
## Startup
**MUST run on startup**:
1. Read `DESIGN.md` from current directory
2. If missing: STOP, instruct user to run `/design` first
## Process
### 1. Task Decomposition
Create `IMPLEMENTATION.md` with ordered task list.
**Task list structure**:
```markdown
# Task List
## Status: [In Progress / Complete]
- [ ] Task 1: Write tests for [feature area]
- Files: `tests/feature.test.c`
- Creates test cases from DESIGN.md § Test Cases
- [ ] Task 2: Implement [interfaces]
- Files: `src/interfaces.c`
- Functions: `funcName()`
- Implements DESIGN.md § Interfaces & APIs
- [ ] Task 3: Integrate [parts]
- Files: `src/main.c`, `src/util.c`
- Connects components per DESIGN.md § Architecture
- [ ] Task 4: End-to-end validation
- Run all tests, verify feature works
# Decisions Log
Description of any deviation from DESIGN.md, with rationale. Remember that any deviation should be surfaced to the user.
# Notes
Any implementation context, gotchas encountered, etc.
```
**Task requirements**:
- **First tasks write tests** from DESIGN.md test cases, provides feedback loops
- Each task = one logical unit of diff
- Specify: what changes, which files, which functions
- Order to minimize conflicts/dependencies
- Include end-to-end validation
**Purpose**: State tracking across sessions. Prevents losing track when resuming. NOT for planning, all planning in DESIGN.md.
### 2. Implementation
Execute tasks in order. Update checkboxes as completed.
**Rules**:
- Map DESIGN.md specs directly to code
- **Tests first**: run tests, fix failures, proceed
- Do not introduce scope beyond DESIGN.md
- **Minimal comments**: Only when drastically improving clarity. Prefer self-documenting code (clear names, small functions, obvious structure)
- Mark tasks complete: `- [x] Task 1: ...`
**Failure mode handling**:
If task requires decision not in DESIGN.md:
1. **STOP immediately**
2. Surface ambiguity to user: "DESIGN.md doesn't specify [X]. Options: [A], [B]. Which should I use?"
3. Recommend updating DESIGN.md
4. User updates DESIGN.md → restart `/implement` from fresh session
**Never make architectural decisions silently.**
### 3. Test Feedback Loops
- Run tests after implementing all functionality
### 4. Decisions Log
If any deviations from DESIGN.md occur (even minor), log in IMPLEMENTATION.md
Examples:
- Changed file structure slightly for [reason]
- Added helper function not in DESIGN.md for [reason]
- Adjusted error handling approach because [reason]
## Code Style
- **Self-documenting code**: Clear variable/function names, small focused functions
- **Comments**: Rare. Only for non-obvious "why" (never "what")
- Follow existing codebase patterns discovered during `/design`
## Context Management
For very large implementations: break into sub-sessions or delegate to subagents. Maintain coherence via shared DESIGN.md and IMPLEMENTATION.md.
## Commit Scope
**One feature = one commit**. Complete all tasks before invoking `/commit`.
## Completion
When all tasks complete:
```
Implementation complete. Ready for /commit to generate commit message and PR description.
```
## Artifact Lifecycle
**IMPLEMENTATION.md is ephemeral** and deleted before commit. Only DESIGN.md is committed.
## Philosophy
You are a compiler: DESIGN.md → working code. The better the design, the more mechanical your work. If you're making judgment calls, something's wrong upstream - STOP.
**Why mechanical execution?**
- Prevents scope creep and ensures design intent preserved
- Human made hard decisions with full context
- Agent executes reliably without interpretation

View file

@ -22,7 +22,7 @@
docker-compose docker-compose
tmux tmux
]; ];
system-net.openssh.ports = [2022]; machine.net.openssh.ports = [2022];
systemd.services.k3s = { systemd.services.k3s = {
preStart = '' preStart = ''
until ${pkgs.tailscale}/bin/tailscale status; do until ${pkgs.tailscale}/bin/tailscale status; do
@ -107,7 +107,7 @@
]; ];
}; };
}; };
system-sys = { machine.sys = {
zram = false; zram = false;
swapSize = 16; swapSize = 16;
}; };

View file

@ -1,6 +1,6 @@
{ host, pkgs, config, lib, ...}: { host, pkgs, config, lib, ...}:
let cfg = config.system-net; in { let cfg = config.machine.net; in {
options.system-net = { options.machine.net = {
enable = lib.mkOption { enable = lib.mkOption {
type = lib.types.bool; type = lib.types.bool;
default = true; default = true;

View file

@ -1,6 +1,6 @@
{ host, pkgs, config, lib, ...}: { host, pkgs, config, lib, ...}:
let cfg = config.system-nix; in { let cfg = config.machine.nix; in {
options.system-nix = { options.machine.nix = {
enable = lib.mkOption { enable = lib.mkOption {
type = lib.types.bool; type = lib.types.bool;
default = true; default = true;

View file

@ -1,6 +1,6 @@
{ pkgs, config, lib, ...}: { pkgs, config, lib, ...}:
let cfg = config.system-pkgs; in { let cfg = config.machine.pkgs; in {
options.system-pkgs = { options.machine.pkgs = {
enable = lib.mkOption { enable = lib.mkOption {
type = lib.types.bool; type = lib.types.bool;
default = true; default = true;

View file

@ -5,10 +5,10 @@
... ...
}: }:
let let
cfg = config.system-sys; cfg = config.machine.sys;
in in
{ {
options.system-sys = { options.machine.sys = {
enable = lib.mkOption { enable = lib.mkOption {
type = lib.types.bool; type = lib.types.bool;
default = true; default = true;

View file

@ -8,7 +8,7 @@
"net.ipv4.ip_forward" = 1; "net.ipv4.ip_forward" = 1;
"net.ipv6.conf.all.forwarding" = 1; "net.ipv6.conf.all.forwarding" = 1;
}; };
system-net.openssh.ports = [22 2022]; machine.net.openssh.ports = [22 2022];
networking = { networking = {
hostId = "00238132"; hostId = "00238132";
firewall = { firewall = {

View file

@ -83,10 +83,10 @@ in
]; ];
}; };
}; };
system-net.nfs = true; machine.net.nfs = true;
system-sys.zram = true; machine.sys.zram = true;
system-sys.swap = false; machine.sys.swap = false;
system-sys.documentation = true; machine.sys.documentation = true;
hardware = { hardware = {
graphics = { graphics = {
enable = true; enable = true;

View file

@ -1,4 +1,9 @@
{ host, config, pkgs, ... }: {
host,
config,
pkgs,
...
}:
{ {
imports = [ imports = [
./hardware-configuration.nix ./hardware-configuration.nix
@ -11,27 +16,42 @@
sopsFile = ../../secrets/forgejo-runner.yaml; sopsFile = ../../secrets/forgejo-runner.yaml;
}; };
}; };
system-sys.zram = false; machine.sys.zram = false;
networking = { networking = {
hostId = "81238132"; hostId = "81238132";
firewall = { firewall = {
allowedTCPPorts = [ allowedTCPPorts = [
22 22
10250 10250
25565 #mc 25565 # mc
25566 #mc 25566 # mc
]; ];
interfaces."podman+" = {
allowedTCPPorts = [ 33393 ];
}; };
}; };
virtualisation.docker = { };
virtualisation.podman = {
enable = true; enable = true;
extraOptions = "--dns 1.1.1.1";
}; };
services.gitea-actions-runner = { services.gitea-actions-runner = {
package = pkgs.forgejo-runner; package = pkgs.forgejo-runner;
instances.default = { instances.default = {
enable = true; enable = true;
name = host.hostName; name = host.hostName;
settings = {
runner = {
capacity = 3;
};
cache = {
enable = true;
host = "host.containers.internal";
port = 33393;
};
container = {
force_pull = true;
};
};
url = "https://git.10110110.xyz"; url = "https://git.10110110.xyz";
tokenFile = config.sops.secrets.forgejo-runner.path; tokenFile = config.sops.secrets.forgejo-runner.path;
labels = [ labels = [