Compare commits

...

10 commits

Author SHA1 Message Date
eb817e9539 Add Forgejo CI smoke workflow (enablement template)
All checks were successful
CI Smoke / host-smoke (push) Successful in 1s
CI Smoke / container-smoke (push) Successful in 3s
2026-07-08 12:35:48 +02:00
401e7f9f6b Draft capability entry (reuse-surface REUSE-WP-0017-T04, cohort 3)
Honest first-pass maturity vector grounded in README/docs/tests present
in this repo; no invented evidence. Flagged for human review before
publish. See reuse-surface history/2026-07-06-coverage-classification.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-06 19:50:53 +02:00
8d4f9ad587 Document in-cluster image-build CI evidence for ADR-004 runner
Records successful forgejo-actions-probe image-build workflow and the
static docker-cli + git-clone pattern for non-root host runners.
2026-07-04 00:47:47 +02:00
dc341d7cc6 Point Forgejo runner substrate at in-cluster railiance01 (ADR-004)
Status probe checks k8s runner first; documents retirement of coulombcore
interim host runner.
2026-07-03 22:29:28 +02:00
7aae00e933 Add Forgejo Actions runner substrate and status probe
Documents interim coulombcore org runner for forgejo.coulomb.social and
adds make forgejo-runner-status for operator health checks.
2026-07-03 21:44:57 +02:00
36a3030f78 Regenerate agent instructions: workstream -> workplan terminology
Registration guidance now prescribes file-first + fix-consistency (C-06)
instead of manual create_workplan/create_workstream calls; progress-event
examples use workplan_id; legacy field names annotated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 01:47:46 +02:00
acaef67f4d Archive closed workplans to workplans/archived/ (ADR-001)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 00:25:42 +02:00
effe568e07 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-07-02:
  - update .custodian-brief.md for railiance-forge
2026-07-02 00:24:25 +02:00
a858daf90a Repo hygiene: fill stack-and-commands, normalize workplan statuses
- Fill .claude/rules/stack-and-commands.md (was an empty TODO template)
- Normalize workplan frontmatter statuses to canonical vocabulary
  (completed/done -> finished) per ADR-001

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 00:21:49 +02:00
5a1c1ca629 Normalize agent instructions and workplan frontmatter (STATE-WP-0067)
- Align agent files with on-disk workplan prefixes (infer from workplan ids)
- Set workplan domain to registered domain_slug; add topic_slug where applicable
- Repair frontmatter delimiter formatting; migrate legacy task status literals
- Regenerate AGENTS.md, CLAUDE.md, and .claude/rules from State Hub templates
2026-06-22 23:16:28 +02:00
23 changed files with 649 additions and 99 deletions

20
.claude/rules/agents.md Normal file
View file

@ -0,0 +1,20 @@
## Kaizen Agents
Specialized agent personas available on demand via the state-hub MCP.
**Discover:** `list_kaizen_agents()` — returns all agents with name, description, category
**Load:** `get_kaizen_agent("tdd-workflow")` — returns full instructions; read and follow them
Common agents:
| Agent | Category | When to use |
|-------|----------|-------------|
| `tdd-workflow` | testing | Step-by-step TDD8 workflow for any feature |
| `code-refactoring` | quality | Code quality analysis and safe refactoring |
| `test-maintenance` | testing | Diagnose and fix failing tests |
| `requirements-engineering` | process | Prevent interface/mock mismatches upfront |
| `keepaTodofile` | process | Maintain TODO.md during work |
| `project-management` | process | Track status, determine next steps |
| `datamodel-optimization` | quality | Optimize dataclasses and data structures |
All 17 agents: call `list_kaizen_agents()` for the full list.

View file

@ -0,0 +1,8 @@
## Architecture
<!-- TODO: Describe the key design decisions and component structure.
Key modules, data flows, external integrations, state machines, etc. -->
## Quick Reference
`~/state-hub/mcp_server/TOOLS.md` — MCP tool reference

View file

@ -20,7 +20,7 @@ Requires the `warden` CLI from `~/ops-warden` (`uv tool install .` or `uv run wa
| Agent runtime | How to orient |
| --- | --- |
| **Codex / Grok** (shell, HTTP State Hub) | `warden route` commands above; inbox `to_agent=railiance-forge` is for coordination, not secret vending |
| **Claude Code** (MCP when available) | `get_domain_summary("custodian")` for workstreams; **still** use `warden route` for credential ownership |
| **Claude Code** (MCP when available) | `get_domain_summary("custodian")` for workplans; **still** use `warden route` for credential ownership |
| **llm-connect** (inference service) | Never put secret retrieval in prompts; route custody to OpenBao/operator paths surfaced by `warden route` |
### Quick routing table

View file

@ -0,0 +1,42 @@
## First Session Protocol
Triggered when `get_domain_summary("financials")` shows **no workplans**.
The project is registered but work has not yet been structured.
**Step 1 — Read, don't write**
- `~/the-custodian/canon/projects/financials/project_charter_v0.1.md` — purpose, scope
- `~/the-custodian/canon/projects/financials/roadmap_v0.1.md` — planned phases
- Scan repo root: README, directory structure, existing code or docs
**Step 2 — Survey in-progress work**
Look for TODOs, open branches, half-finished files. Note done vs. started but incomplete.
**Step 3 — Propose workplans to Bernd**
Propose 13 workplans — each a coherent strand, weeks to months, anchored to a
roadmap phase. **Wait for approval before creating.**
**Step 4 — Write the workplan file; fix-consistency registers it (ADR-001)**
```
workplans/RAILIANCE-WP-NNNN-<slug>.md ← write this, commit it
```
Then register by running the consistency check — do **not** call
`create_workplan`/`create_task` (or legacy `create_workstream`) yourself;
manual registration duplicates what C-06 creates from the file:
```bash
statehub fix-consistency --repo railiance-forge
```
C-06 creates the hub workplan + tasks and writes `state_hub_workstream_id` /
`state_hub_task_id` back into the file (legacy field names, kept for
compatibility — they hold workplan/task IDs).
**Step 5 — Record the setup**
```
add_progress_event(
summary="First session: structured financials into N workplans, M tasks",
event_type="milestone",
topic_id="ca369340-a64e-442e-98f1-a4fa7dc74a38",
detail={"workplans": [...], "tasks_created": M}
)
```
<!-- Delete or archive this file once past first session -->

View file

@ -0,0 +1,8 @@
## Repo boundary
This repo owns **railiance-forge** only. It does not own:
<!-- TODO: List what belongs in adjacent repos, e.g.:
- SSH key management → railiance-infra/
- State hub code → state-hub/
-->

View file

@ -0,0 +1,5 @@
**Purpose:** Railiance forge and artifact infrastructure: current Gitea operation, future Forgejo migration, container/package registries, runner substrate, artifact lifecycle, and forge operating evidence.
**Domain:** financials
**Repo slug:** railiance-forge
**Topic ID:** ca369340-a64e-442e-98f1-a4fa7dc74a38

View file

@ -0,0 +1,94 @@
## Session Protocol
Dev Hub (State Hub API): http://127.0.0.1:8000
MCP server name in `~/.claude.json`: `dev-hub`
**Step 1 — Orient**
Read the offline-safe brief first — it works without a live hub connection:
```bash
cat .custodian-brief.md
```
Then call the MCP tool for richer cross-domain context when MCP tools are exposed:
```
get_domain_summary("financials")
```
If MCP tools are unavailable in the current agent session, use the REST API:
```bash
curl -s "http://127.0.0.1:8000/state/summary" | python3 -m json.tool
```
If the hub is offline: `cd ~/state-hub && make api`
**Step 2 — Check inbox**
With MCP tools:
```
get_messages(to_agent="railiance-forge", unread_only=True)
```
Mark read with `mark_message_read(message_id)`. Reply or act on coordination
requests before proceeding.
Without MCP tools:
```bash
curl -s "http://127.0.0.1:8000/messages/?to_agent=railiance-forge&unread_only=true" \
| python3 -m json.tool
curl -s -X PATCH "http://127.0.0.1:8000/messages/<id>/read" \
-H "Content-Type: application/json" -d '{}'
```
**Step 3 — Scan workplans**
```bash
ls workplans/
```
For each file with `status: ready`, `active`, or `blocked`, note pending
`wait`/`todo`/`progress` tasks.
**Step 4 — Present brief**
1. **Active workplans** for `financials` — title, task counts, blocking decisions
2. **Pending tasks** from `workplans/` + any `[repo:railiance-forge]` hub tasks
3. **Goal guidance** — if `goal_guidance` in summary:
- `needs_workplan`: surface as top action — *"Repo goal '{title}' has no workplan yet"*
- `alignment_warnings`: flag if active work is not aligned with current goal
4. **Suggested next action** — highest-priority open item
5. **SBOM status** — flag if `last_sbom_at` is unset for this repo
If no workplans: follow First Session Protocol (`first-session.md`).
**During work:** `record_decision()` · `add_progress_event()` · `resolve_decision()`
> State Hub is a *read model*. **Never register workplans or tasks by hand**
> (`create_workplan`, `create_task`, or the legacy `create_workstream`) — write
> the workplan file in `workplans/` and run `fix-consistency`; its C-06 check
> registers the workplan and its tasks in the hub and writes the IDs back into
> the file. Manual registration creates duplicates the moment fix-consistency
> runs. Work structure belongs in repo files (ADR-001).
>
> Terminology: "workstream" is the legacy name for workplan. Some API/frontmatter
> field names keep it for compatibility (`state_hub_workstream_id`,
> `workstream_id` params) — treat them as workplan IDs.
**Session close:**
With MCP tools:
```
add_progress_event(summary="...", topic_id="ca369340-a64e-442e-98f1-a4fa7dc74a38", workplan_id="<uuid>")
```
Without MCP tools:
```bash
curl -s -X POST http://127.0.0.1:8000/progress/ \
-H "Content-Type: application/json" \
-d '{"topic_id":"ca369340-a64e-442e-98f1-a4fa7dc74a38","workplan_id":"<uuid>","event_type":"note","summary":"what changed","author":"codex"}'
```
If workplan files were modified, ensure the local copy is up to date first,
then sync from the repo checkout:
```bash
git pull --ff-only
statehub fix-consistency
```
For repos where implementation runs on a remote machine (e.g. CoulombCore),
use the pull-before-fix mode from any shell with the State Hub CLI:
```bash
statehub fix-consistency --repo railiance-forge --remote
```
**C-15** (DB task ahead of file) is normal in multi-machine workflows — writeback
will sync the file to match DB. **C-16** (repo behind remote) blocks all writes
until you pull — intentional to prevent clobbering remote progress.

View file

@ -0,0 +1,18 @@
## Stack
- **Language:** Helm values + Kubernetes manifests, Bash Make targets
- **Key deps:** Gitea (current forge runtime), Actions runner substrate, SOPS/age; runs against the S2 cluster on railiance01
## Dev Commands
```bash
make help # list all targets
make check-tools && make check-sops # preflight (read-only)
make gitea-status # forge runtime + database state (read-only)
make runner-status # Actions runner / registry probes (read-only)
make registry-docs | evidence-docs | runner-docs # print canonical docs
make gitea-deploy | gitea-ingress-deploy # production-touching
```
`gitea-deploy` / `gitea-ingress-deploy` change the production forge —
operator approval required. Status and docs targets are read-only.

View file

@ -0,0 +1,45 @@
## Workplan Convention (ADR-001)
File location: `workplans/RAILIANCE-WP-NNNN-<slug>.md`
ID prefix: `RAILIANCE-WP-`
Work items originate as files in this repo **before** being registered in the hub.
Canonical workplan frontmatter statuses are:
`proposed`, `ready`, `active`, `blocked`, `backlog`, `finished`, `archived`.
Use `proposed` for a newly drafted plan, `ready` after review against current
repo state, and `finished` when implementation is complete. `stalled` and
`needs_review` are derived health labels, not stored statuses.
Closed workplans may be moved to `workplans/archived/` with a completion-date
prefix: `YYMMDD-RAILIANCE-WP-NNNN-<slug>.md`. The frontmatter id remains
unchanged; the prefix is only for quick visual reference.
Small opportunistic tasks discovered during another session use **Ad Hoc Tasks**:
`workplans/ADHOC-YYYY-MM-DD.md`, workplan slug `adhoc-YYYY-MM-DD`, and task ids
`ADHOC-YYYY-MM-DD-T01`, `T02`, etc. Use adhocs only for low-risk work completed
directly. Promote anything requiring analysis, design, approval, dependencies, or
multiple planned phases into a normal workplan.
Ecosystem todos from other agents arrive as `[repo:railiance-forge]` hub tasks —
visible at session start. Pick one up by creating the workplan file, committing,
and running `statehub fix-consistency` — C-06 registers the workplan in the hub.
Never register by hand with `create_workplan`/`create_workstream`.
Task blocks use this shape:
```task
id: RAILIANCE-WP-NNNN-T01
status: wait | todo | progress | done | cancel
priority: high | medium | low
state_hub_task_id: "<uuid>" # written by fix-consistency — do not edit
```
Status progression is `todo``progress``done`; use `wait` for waiting or
blocked work and `cancel` for stopped work.
Workplan frontmatter carries `state_hub_workstream_id` — a legacy field name
kept for compatibility ("workstream" is the old term for workplan); it holds
the hub workplan id and is written by fix-consistency. Do not edit or rename it.
<!-- Ralph Loop rules and HEUREKA sequence: ~/.claude/CLAUDE.md — do not duplicate here -->

View file

@ -1,8 +1,8 @@
<!-- custodian-brief: generated by fix-consistency — do not edit manually -->
# Custodian Brief — railiance-forge
**Domain:** railiance
**Last synced:** 2026-06-08 08:14 UTC
**Domain:** financials
**Last synced:** 2026-07-01 22:24 UTC
**State Hub:** http://127.0.0.1:8000 *(adjust if running on a remote machine)*
## Active Workstreams
@ -13,6 +13,6 @@
## MCP Orientation (when available)
If the state-hub MCP server is reachable, call:
`get_domain_summary("railiance")`
`get_domain_summary("financials")`
This provides richer cross-domain context.
If the MCP call fails, use this file as your orientation source.

View file

@ -0,0 +1,29 @@
# Canonical CI smoke template (tier 1 routing drill).
# Copy to: .forgejo/workflows/ci-smoke.yaml in consumer repos.
name: CI Smoke
on:
push:
branches:
- main
workflow_dispatch:
jobs:
host-smoke:
runs-on: self-hosted
steps:
- name: Routing probe (host runner)
run: |
set -eu
echo "repository=${GITHUB_REPOSITORY:-unknown}"
echo "sha=${GITHUB_SHA:-unknown}"
echo "runner=${RUNNER_NAME:-unknown}"
uname -a
container-smoke:
runs-on: ubuntu-latest
steps:
- name: Routing probe (container label)
run: |
set -eu
echo "container-smoke ok for ${GITHUB_REPOSITORY:-unknown}"

156
AGENTS.md
View file

@ -1,48 +1,54 @@
# railiance-forge - Agent Instructions
# railiance-forge Agent Instructions
## Repo Identity
**Purpose:** Railiance forge and artifact infrastructure - source forge runtime,
container/package registries, forge-backed runner substrate, artifact lifecycle,
and future Forgejo migration.
**Purpose:** Railiance forge and artifact infrastructure: current Gitea operation, future Forgejo migration, container/package registries, runner substrate, artifact lifecycle, and forge operating evidence.
**Domain:** railiance
**Domain:** financials
**Repo slug:** railiance-forge
**Topic ID:** `ca369340-a64e-442e-98f1-a4fa7dc74a38`
**Workplan prefix:** `FORGE-WP-`
**Workplan prefix:** `RAILIANCE-WP-`
---
## State Hub Integration
The Custodian State Hub tracks work across all domains. Interact via HTTP REST -
The Custodian State Hub tracks work across all domains. Interact via HTTP REST
there is no MCP server for Codex agents.
| Context | URL |
|---------|-----|
| Local workstation | `http://127.0.0.1:8000` |
| Remote via tunnel | `http://127.0.0.1:18000` |
| Optional local edge relay | http://127.0.0.1:18080 |
When an operator has enabled the edge relay, set API_BASE to the relay URL.
Queueable writes return an explicit queued receipt if the central hub is
unreachable. Treat that as pending local evidence, then ask the operator to run
statehub outbox status/replay after connectivity returns.
### Orient at session start
```bash
# Offline brief — works without hub connection
cat .custodian-brief.md
curl -s "http://127.0.0.1:8000/workstreams/?topic_id=ca369340-a64e-442e-98f1-a4fa7dc74a38&status=active" \
# Active workplans for this domain
curl -s "http://127.0.0.1:8000/workplans/?topic_id=ca369340-a64e-442e-98f1-a4fa7dc74a38&status=active" \
| python3 -m json.tool
# Check inbox
curl -s "http://127.0.0.1:8000/messages/?to_agent=railiance-forge&unread_only=true" \
| python3 -m json.tool
```
Mark a message read:
```bash
curl -s -X PATCH "http://127.0.0.1:8000/messages/<id>/read" \
-H "Content-Type: application/json" -d '{}'
```
### Log progress at session close
### Log progress (required at session close)
```bash
curl -s -X POST http://127.0.0.1:8000/progress/ \
@ -51,12 +57,12 @@ curl -s -X POST http://127.0.0.1:8000/progress/ \
"summary": "what was done",
"event_type": "note",
"author": "codex",
"workstream_id": "<uuid>",
"workplan_id": "<uuid>",
"task_id": "<uuid>"
}'
```
Omit `workstream_id` / `task_id` when not applicable.
Omit `workplan_id` / `task_id` when not applicable.
### Update task status
@ -64,10 +70,9 @@ Omit `workstream_id` / `task_id` when not applicable.
curl -s -X PATCH "http://127.0.0.1:8000/tasks/<task_id>" \
-H "Content-Type: application/json" \
-d '{"status": "progress"}'
# values: wait | todo | progress | done | cancel
```
Canonical task values: `wait | todo | progress | done | cancel`.
### Flag a task for human review
```bash
@ -81,46 +86,24 @@ curl -s -X PATCH "http://127.0.0.1:8000/tasks/<task_id>" \
## Session Protocol
**Start:**
1. `cat .custodian-brief.md` - domain goal and open workstreams.
2. Check inbox:
`GET /messages/?to_agent=railiance-forge&unread_only=true`; mark read.
3. Scan workplans: `ls workplans/` and note `ready`, `active`, or `blocked`
workplans and open tasks.
4. Check blocked tasks: `GET /tasks/?needs_human=true`.
1. `cat .custodian-brief.md` — domain goal and open workplans (offline-safe)
2. Check inbox: `GET /messages/?to_agent=railiance-forge&unread_only=true`; mark read
3. Scan workplans: `ls workplans/` — note `status: ready`, `active`, or `blocked` files and open tasks
4. Check human-needed tasks: `GET /tasks/?needs_human=true`
**During work:**
- Update task statuses in workplan files as tasks progress.
- Record significant decisions via `POST /decisions/`.
- Keep forge responsibilities separate from S4 templates and S5 app releases.
## Verification Commands
This repo currently contains documentation, workplans, and read-only operator
entry points. There is no app build, package install, or unit-test command yet.
Use these checks for ordinary edits:
```bash
git diff --check
make registry-docs
make check-tools
make -C /home/worsch/state-hub fix-consistency REPO=railiance-forge
```
`make gitea-status` is read-only but requires a kubeconfig pointed at a
representative Railiance cluster.
- Update task statuses in workplan files as tasks progress
- Record significant decisions via `POST /decisions/`
**Close:**
1. Update workplan file task statuses.
2. Log progress with `POST /progress/`.
3. After workplan file changes, run from `~/state-hub`:
1. Update workplan file task statuses to reflect progress
2. Log: `POST /progress/` with a summary of what changed
3. After workplan file changes, run:
```bash
make fix-consistency REPO=railiance-forge
statehub fix-consistency
```
Coding agents should run this directly; ask the operator only if the CLI or
State Hub API is unavailable. This syncs task status from files into the hub DB.
---
@ -146,7 +129,7 @@ Requires the `warden` CLI from `~/ops-warden` (`uv tool install .` or `uv run wa
| Agent runtime | How to orient |
| --- | --- |
| **Codex / Grok** (shell, HTTP State Hub) | `warden route` commands above; inbox `to_agent=railiance-forge` is for coordination, not secret vending |
| **Claude Code** (MCP when available) | `get_domain_summary("custodian")` for workstreams; **still** use `warden route` for credential ownership |
| **Claude Code** (MCP when available) | `get_domain_summary("custodian")` for workplans; **still** use `warden route` for credential ownership |
| **llm-connect** (inference service) | Never put secret retrieval in prompts; route custody to OpenBao/operator paths surfaced by `warden route` |
### Quick routing table
@ -174,70 +157,69 @@ every repo's agent instructions because it is high-frequency, high-risk, and eas
get wrong.
**Canon:** `~/ops-warden/wiki/CredentialRouting.md` · catalog `~/ops-warden/registry/routing/catalog.yaml`
<!-- REPO-AGENTS-EXTENSIONS -->
<!-- Append repo-specific agent instructions below this marker.
The state-hub template sync preserves content after this line. -->
---
## Workplan Convention
## Workplan Convention (ADR-001)
Work items originate as files in this repo. State Hub indexes those files as
workstreams and task blocks.
Work items originate as files in this repo — not in the hub. The hub is a
read/cache/index layer that rebuilds from files.
**File location:** `workplans/FORGE-WP-NNNN-<slug>.md`
**File location:** `workplans/RAILIANCE-WP-NNNN-<slug>.md`
**Archived location:** `workplans/archived/YYMMDD-FORGE-WP-NNNN-<slug>.md`
**Archived location:** finished workplans may move to
`workplans/archived/YYMMDD-RAILIANCE-WP-NNNN-<slug>.md`. The `YYMMDD` prefix is
the completion/archive date; the frontmatter `id` does not change.
**Ad Hoc Tasks:** small opportunistic fixes discovered during a session use
`workplans/ADHOC-YYYY-MM-DD.md` with task ids `ADHOC-YYYY-MM-DD-T01`, etc. Use
this only for low-risk work completed directly; create a normal workplan for
anything needing analysis, design, approval, dependencies, or multiple phases.
**Frontmatter:**
```yaml
---
id: FORGE-WP-NNNN
id: RAILIANCE-WP-NNNN
type: workplan
title: "..."
domain: railiance
domain: financials
repo: railiance-forge
status: proposed | ready | active | blocked | backlog | finished | archived
owner: codex
topic_slug: railiance
topic_slug: ...
created: "YYYY-MM-DD"
updated: "YYYY-MM-DD"
state_hub_workstream_id: "<uuid>" # written by fix-consistency - do not edit
state_hub_workstream_id: "<uuid>" # written by fix-consistency do not edit
---
```
**Task block format:**
Use `proposed` for a new draft, `ready` after review against current repo
state, and `finished` after implementation. `stalled` and `needs_review` are
derived health labels, not frontmatter statuses.
````text
**Task block format** (one per `##` section):
```
## Task Title
```task
id: FORGE-WP-NNNN-T01
status: todo | progress | done | wait | cancel
` ` `task
id: RAILIANCE-WP-NNNN-T01
status: wait | todo | progress | done | cancel
priority: high | medium | low
state_hub_task_id: "<uuid>" # written by fix-consistency - do not edit
```
state_hub_task_id: "<uuid>" # written by fix-consistency do not edit
` ` `
Task description text.
````
```
Status progression: `todo` -> `progress` -> `done`, or `wait` / `cancel`.
Status progression: `todo` `progress``done`; use `wait` for waiting/blocked work and `cancel` for stopped work.
To create a new workplan:
1. Write the file following the format above.
2. Run from `~/state-hub`:
```bash
make fix-consistency REPO=railiance-forge
```
---
## Repository Boundaries
This repo owns forge runtime and artifact infrastructure. It does not own:
- OS/host provisioning (`railiance-infra`);
- Kubernetes runtime primitives (`railiance-cluster`);
- shared database/storage/secret platforms (`railiance-platform`);
- generic CI/CD templates and developer portal paths (`railiance-enablement`);
- user-facing application releases (`railiance-apps`);
- source application code.
1. Write the file following the format above
2. Notify the custodian operator to run `make fix-consistency REPO=railiance-forge`
(or send a message to the hub agent via `POST /messages/`)

12
CLAUDE.md Normal file
View file

@ -0,0 +1,12 @@
# railiance-forge — Claude Code Instructions
@SCOPE.md
@.claude/rules/repo-identity.md
@.claude/rules/session-protocol.md
@.claude/rules/first-session.md
@.claude/rules/workplan-convention.md
@.claude/rules/stack-and-commands.md
@.claude/rules/architecture.md
@.claude/rules/repo-boundary.md
@.claude/rules/credential-routing.md
@.claude/rules/agents.md

View file

@ -59,6 +59,9 @@ runner-docs: ## Print Gitea Actions runner substrate docs and evidence
runner-status: ## Read-only Actions runner, host, and inter-hub registry probes
bash tools/gitea-runner-status.sh
forgejo-runner-status: ## Read-only Forgejo Actions runner and endpoint probes
bash tools/forgejo-runner-status.sh
check-runner-tools: ## Check local tools used by runner inspection targets
@missing=0; \
for tool in curl ssh docker; do \
@ -109,4 +112,4 @@ help: ## Show this help
/^[a-zA-Z0-9_-]+:.*?##/ { printf " \033[36m%-20s\033[0m %s\n", $$1, $$2 } \
/^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) }' $(MAKEFILE_LIST)
.PHONY: check-tools check-sops registry-docs evidence-docs runner-docs runner-status check-runner-tools gitea-deploy gitea-ingress-deploy gitea-status help
.PHONY: check-tools check-sops registry-docs evidence-docs runner-docs runner-status forgejo-runner-status check-runner-tools gitea-deploy gitea-ingress-deploy gitea-status help

View file

@ -0,0 +1,80 @@
# Forgejo Actions Runner Substrate
Last reviewed: 2026-07-03
Status: **in-cluster runner on railiance01** (ADR-004). Supersedes interim coulombcore
host runner.
## Purpose
Forge-owned Actions runner for `https://forgejo.coulomb.social` so `coulomb`
organization repos build and publish without workstation or legacy-host Docker.
Label contract aligns with `docs/gitea-actions-runner-substrate.md` and
`docs/ci-runner-actions-gitops-ownership.md`.
## Production Runner (ADR-004)
| Field | Value |
| --- | --- |
| Runner name | `railiance01-build-01` |
| Scope | `coulomb` organization |
| Placement | `forgejo` namespace, railiance01 k3s |
| Manifest | `railiance-apps/manifests/forgejo-runner.yaml` |
| Images | `code.forgejo.org/forgejo/runner:6.3.1`, `docker:27-dind` |
| Job runtime | DinD sidecar (`DOCKER_HOST=tcp://127.0.0.1:2375`) |
| State PVC | `forgejo-runner-data` |
| Cluster deploy authority | Not included |
### Labels
```text
self-hosted:host,linux:host,linux_amd64:host,container-build:host,registry-publish:host,railiance01:host,ubuntu-latest:docker://node:20-bookworm,docker:docker://node:20-bookworm
```
## Operator Commands
```bash
# S5 deploy (railiance-apps)
cd ~/railiance-apps
make forgejo-runner-registration-deploy # after SOPS encrypt
make forgejo-runner-deploy
make forgejo-runner-status
# Endpoint smoke
make forgejo-smoke
# Generate registration token (in cluster; do not log token)
KUBECONFIG=~/.kube/config-hosteurope kubectl exec -n forgejo deploy/forgejo-gitea -- \
forgejo actions generate-runner-token --scope coulomb
```
## Secret Boundaries
- `forgejo-runner-registration` Kubernetes Secret — registration token only.
- Repo/org registry credentials — Forgejo Actions secrets, not in Git.
- No kubeconfig or OpenBao tokens on the runner pod by default.
## Retired: Interim coulombcore Host Runner
`railiance-coulombcore-build-01` on coulombcore was a scheduling proof only.
Disable after in-cluster runner is healthy:
```bash
ssh coulombcore 'sudo systemctl disable --now forgejo-runner'
```
## Evidence
- Host probe (2026-07-03): `coulomb/forgejo-actions-probe` workflow `success`.
- In-cluster (2026-07-03): `railiance01-build-01` 2/2 Ready; `container-probe`
and `image-build` workflows `success`. Image-build uses static docker-cli on
the non-root runner host + `DOCKER_HOST=tcp://127.0.0.1:2375` (DinD); org
secrets `REGISTRY_USER` / `REGISTRY_TOKEN`; pushes to
`forgejo.coulomb.social/coulomb/forgejo-actions-probe`.
- `actions/checkout@v4` failed on the host runner — use `git clone` in job steps
until checkout action compatibility is confirmed.
## References
- `railiance-infra/docs/adr/ADR-004-forgejo-in-cluster-actions-runner.md`
- [Forgejo runner installation](https://forgejo.org/docs/v11.0/admin/actions/runner-installation/)

View file

@ -0,0 +1,129 @@
---
id: capability.railiance.forge-infrastructure
name: Railiance Forge And Artifact Infrastructure
summary: Source forge, registry, and automation-runner infrastructure for Railiance, separated out from
railiance-apps/railiance-enablement; covers current Gitea operation, the Forgejo migration, container/package
registries, and Actions runner substrate.
owner: railiance-forge
status: draft
domain: financials
tags:
- railiance
- forgejo
- forge
- ci-runner
maturity:
discovery:
current: D3
target: D5
confidence: medium
rationale: README and SCOPE.md explicitly name 'current Gitea operation, future Forgejo migration,
container and package registries, Actions runner substrate, artifact lifecycle' as the scope; status
noted as 'active forge extraction' with canonical registry operation docs already landed.
availability:
current: A1
target: A3
confidence: medium
rationale: README explicitly states 'no live Helm deploy or Kubernetes apply was run as part of the
move' — documentation and operator targets exist, but this repo is mid-extraction; has .gitea CI
(not yet migrated to .forgejo itself, notably, despite owning the migration).
external_evidence:
completeness:
level: C1
confidence: low
basis: scope_vs_intent_and_consumer_expectations
satisfied_expectations:
- scope separation from railiance-apps/railiance-enablement documented
- canonical registry operation docs and runner ownership contracts
broken_expectations: []
out_of_scope_expectations: []
reliability:
level: R0
confidence: low
basis: consumer_quality_signals
known_reliability_risks:
- repo is actively being founded/extracted; no live deploy yet by its own account
- directly relevant to REUSE-WP-0019 but hasn't migrated its own CI to .forgejo/ yet
discovery:
intent: Own source forge, artifact registry, and CI runner substrate responsibilities for Railiance,
separated from application (railiance-apps) and enablement (railiance-enablement) concerns, across
the Gitea-to-Forgejo transition.
includes:
- forge operation (current Gitea, migrating to Forgejo)
- container/package registries
- Actions runner substrate
- artifact lifecycle
excludes:
- application workload deployment (railiance-apps)
- CI/CD templates for consuming repos (railiance-enablement)
assumptions: []
use_cases: []
research_memos: []
availability:
current_level: A1
target_level: A3
current_artifacts:
- operator docs and tools/ (extraction in progress)
target_artifacts: []
consumption_modes:
- cli (operator tooling)
- documentation/runbooks
relations:
depends_on: []
supports: []
related_to: []
evidence:
documentation:
- README.md
- SCOPE.md
tests: []
consumer_feedback: []
bug_reports: []
incidents: []
consumer_guidance:
recommended_for:
- Railiance operators managing forge/registry/runner infrastructure, especially during the Gitea-to-Forgejo
transition
not_recommended_for:
- treating this as production-stable — the repo's own README states the extraction is active and no
live deploy has run yet
known_limitations:
- actively being founded; no live Helm/k8s deploy has run as part of the extraction yet; own CI still
under .gitea/ pending its own Forgejo migration
promotion_history: []
---
# Railiance Forge And Artifact Infrastructure
## Overview
`railiance-forge` is being founded to separate source forge, artifact registry, and CI/Actions runner responsibilities from `railiance-apps` and `railiance-enablement`. It directly owns the current Gitea operation and the future Forgejo migration — of particular relevance to REUSE-WP-0019 — though by its own account no live deploy has run yet.
## Assessment notes
### Discovery
README and SCOPE.md explicitly name 'current Gitea operation, future Forgejo migration, container and package registries, Actions runner substrate, artifact lifecycle' as the scope; status noted as 'active forge extraction' with canonical registry operation docs already landed.
### Availability
README explicitly states 'no live Helm deploy or Kubernetes apply was run as part of the move' — documentation and operator targets exist, but this repo is mid-extraction; has .gitea CI (not yet migrated to .forgejo itself, notably, despite owning the migration).
### Completeness
First-pass honest assessment from the REUSE-WP-0017 coverage campaign
(reuse-surface). No external consumer feedback exists yet; levels reflect
scope-vs-intent documentation quality, not internal code quality.
### Reliability
No production consumer telemetry exists yet; reliability level is
intentionally conservative pending REUSE-WP-0019 reuse-telemetry evidence.
## Promotion checklist
- [x] ID follows `capability.<domain>.<name>` pattern
- [x] Maturity enums match `specs/CapabilityMaturityStandard.md`
- [x] `external_evidence` is populated separately from `maturity`
- [ ] Relations reference valid capability IDs (none yet)
- [x] Index entry added in `registry/indexes/capabilities.yaml`

View file

@ -1,4 +1,22 @@
version: 1
updated: '2026-06-16'
updated: '2026-07-06'
domain: helix_forge
capabilities: []
capabilities:
- id: capability.railiance.forge-infrastructure
name: Railiance Forge And Artifact Infrastructure
summary: Source forge, registry, and automation-runner infrastructure for Railiance, separated out from
railiance-apps/railiance-enablement; covers current Gitea operation, the Forgejo migration, container/package
registries, and Actions runner substrate.
vector: D3 / A1 / C1 / R0
domain: financials
status: draft
owner: railiance-forge
path: registry/capabilities/capability.railiance.forge-infrastructure.md
tags:
- railiance
- forgejo
- forge
- ci-runner
consumption_modes:
- cli (operator tooling)
- documentation/runbooks

57
tools/forgejo-runner-status.sh Executable file
View file

@ -0,0 +1,57 @@
#!/usr/bin/env bash
set -u
FORGEJO_URL="${FORGEJO_URL:-https://forgejo.coulomb.social}"
FORGEJO_KUBECONFIG="${FORGEJO_KUBECONFIG:-${HOME}/.kube/config-hosteurope}"
RUNNER_HOST="${RUNNER_HOST:-}"
RUNNER_SSH_USER="${RUNNER_SSH_USER:-}"
RUNNER_SSH_KEY="${RUNNER_SSH_KEY:-}"
SSH_CONNECT_TIMEOUT="${SSH_CONNECT_TIMEOUT:-5}"
section() { printf '\n## %s\n' "$1"; }
have() { command -v "$1" >/dev/null 2>&1; }
http_code() { curl -sS -m 8 -o /dev/null -w '%{http_code}' "$1" 2>/dev/null || printf 'error'; }
section "Tool availability"
for tool in curl ssh; do
if have "$tool"; then printf 'ok: %s\n' "$tool"; else printf 'missing: %s\n' "$tool"; fi
done
section "Forgejo endpoint checks"
if have curl; then
printf 'forgejo root: %s\n' "$(http_code "${FORGEJO_URL}/")"
printf 'forgejo api version: %s\n' "$(http_code "${FORGEJO_URL}/api/v1/version")"
printf 'forgejo registry /v2 (GET): %s\n' "$(curl -sS -m 8 -o /dev/null -w '%{http_code}' -X GET "${FORGEJO_URL}/v2/")"
else
echo "curl missing; skipping endpoint checks"
fi
section "In-cluster runner (railiance01)"
if have kubectl && [ -r "${FORGEJO_KUBECONFIG}" ]; then
KUBECONFIG="${FORGEJO_KUBECONFIG}" kubectl get deploy,pods,pvc -n forgejo -l app.kubernetes.io/name=forgejo-runner --ignore-not-found 2>/dev/null || true
KUBECONFIG="${FORGEJO_KUBECONFIG}" kubectl logs -n forgejo deploy/forgejo-runner -c runner --tail=5 2>/dev/null || true
else
echo "kubectl or kubeconfig missing; skipping in-cluster probe"
fi
section "Legacy host runner probe (optional)"
if [ -n "${RUNNER_HOST}" ] && have ssh; then
ssh_target="${RUNNER_HOST}"
if [ -n "${RUNNER_SSH_USER}" ]; then ssh_target="${RUNNER_SSH_USER}@${RUNNER_HOST}"; fi
ssh_args=(-o BatchMode=yes -o ConnectTimeout="${SSH_CONNECT_TIMEOUT}")
if [ -n "${RUNNER_SSH_KEY}" ]; then ssh_args+=(-i "${RUNNER_SSH_KEY}"); fi
ssh "${ssh_args[@]}" "${ssh_target}" '
set -u
echo "host=$(hostname)"
if command -v forgejo-runner >/dev/null 2>&1; then forgejo-runner -v || true; else echo "missing: forgejo-runner"; fi
if command -v docker >/dev/null 2>&1; then docker --version || true; else echo "missing: docker"; fi
if command -v systemctl >/dev/null 2>&1; then
systemctl is-active forgejo-runner 2>/dev/null || true
fi
if [ -f /var/lib/forgejo-runner/.runner ]; then echo "ok: /var/lib/forgejo-runner/.runner present"; fi
'
elif [ -n "${RUNNER_HOST}" ]; then
echo "ssh missing; skipping legacy host probe"
else
echo "RUNNER_HOST unset; skipping legacy host probe"
fi

View file

@ -2,7 +2,7 @@
id: FORGE-WP-0001
type: workplan
title: "railiance-forge repository foundation"
domain: railiance
domain: financials
repo: railiance-forge
status: finished
owner: codex

View file

@ -2,7 +2,7 @@
id: FORGE-WP-0002
type: workplan
title: "Canonical registry docs and read-only forge operations"
domain: railiance
domain: financials
repo: railiance-forge
status: finished
owner: codex

View file

@ -2,7 +2,7 @@
id: FORGE-WP-0003
type: workplan
title: "Gitea Actions runner substrate for Railiance workloads"
domain: railiance
domain: financials
repo: railiance-forge
status: finished
owner: codex

View file

@ -2,7 +2,7 @@
id: FORGE-WP-0004
type: workplan
title: "Standard public Gitea HTTPS root endpoint"
domain: railiance
domain: financials
repo: railiance-forge
status: finished
owner: codex

View file

@ -2,7 +2,7 @@
id: FORGE-WP-0005
type: workplan
title: "Remove public Gitea NodePort side door"
domain: railiance
domain: financials
repo: railiance-forge
status: finished
owner: codex